pwiz/pwiz/utility/findmf/base/resample/utilities/determinebinwidth.hpp0000664000175100017510000000500112664775615030464 0ustar teamcityteamcity00000000000000// // $Id: determinebinwidth.hpp 5313 2013-12-17 18:06:54Z chambm $ // // // Original author: Witold Wolski // // Copyright : ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef DETERMINEBINWIDTHUTILITIES_H #define DETERMINEBINWIDTHUTILITIES_H #include #include #include namespace ralab { namespace base { namespace resample { typedef boost::int32_t int32_t; namespace utilities{ template struct meanfunctor : std::binary_function{ T operator()(const T & x, const T& y){ return (x+y)/2.; } }; template < typename InputIterator, typename OutputIterator, typename TN //= int32_t > OutputIterator summ ( InputIterator begin, //!< [in] begin InputIterator end, //!< [in] end OutputIterator destBegin, //!< [out] dest begin TN lag = 1//!< [in] an integer indicating which lag to use. ) { return( std::transform(begin + lag , end , begin , destBegin , meanfunctor()) ); } template double determine(TRealI begin, TRealI end,double maxj=5.){ //BOOST_ASSERT(!boost::range::is_sorted(begin,end)); double j = 1.; double average = *begin; double sum = average; int32_t i = 1; for(; begin != end ; ++begin, ++i){ while(*begin > (j+0.5) *average){ ++j; } if(j > maxj){ break; } sum += *begin/j; average = sum/static_cast(i); } return average; } } } } } #endif pwiz/pwiz/data/vendor_readers/Waters/ChromatogramList_Waters.hpp0000664000175100017510000000366512664775617027260 0ustar teamcityteamcity00000000000000// // $Id: ChromatogramList_Waters.hpp 2640 2011-04-18 20:23:31Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/ChromatogramListBase.hpp" #include "Reader_Waters_Detail.hpp" #include "pwiz/utility/misc/Once.hpp" namespace pwiz { namespace msdata { namespace detail { class PWIZ_API_DECL ChromatogramList_Waters : public ChromatogramListBase { public: virtual size_t size() const; virtual const ChromatogramIdentity& chromatogramIdentity(size_t index) const; virtual size_t find(const std::string& id) const; virtual ChromatogramPtr chromatogram(size_t index, bool getBinaryData) const; #ifdef PWIZ_READER_WATERS ChromatogramList_Waters(RawDataPtr rawdata); private: RawDataPtr rawdata_; mutable size_t size_; mutable util::once_flag_proxy indexInitialized_; struct IndexEntry : public ChromatogramIdentity { CVID chromatogramType; int function; int offset; float Q1, Q3; }; mutable std::vector index_; mutable std::map idToIndexMap_; void createIndex() const; #endif // PWIZ_READER_WATERS }; } // detail } // msdata } // pwiz pwiz/pwiz/data/vendor_readers/Waters/SpectrumList_Waters.cpp0000664000175100017510000005477212664775617026437 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_Waters.cpp 9095 2015-11-01 01:14:24Z pcbrefugee $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_Waters.hpp" #ifdef PWIZ_READER_WATERS #include "pwiz/utility/misc/SHA1Calculator.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include "Reader_Waters_Detail.hpp" #include #include "boost/foreach_field.hpp" namespace pwiz { namespace msdata { namespace detail { using namespace Waters; SpectrumList_Waters::SpectrumList_Waters(MSData& msd, RawDataPtr rawdata, const Reader::Config& config) : msd_(msd), rawdata_(rawdata), config_(config) { createIndex(); } PWIZ_API_DECL size_t SpectrumList_Waters::size() const { return size_; } PWIZ_API_DECL const SpectrumIdentity& SpectrumList_Waters::spectrumIdentity(size_t index) const { if (index>size_) throw runtime_error("[SpectrumList_Waters::spectrumIdentity()] Bad index: " + lexical_cast(index)); return index_[index]; } PWIZ_API_DECL size_t SpectrumList_Waters::find(const string& id) const { map::const_iterator scanItr = idToIndexMap_.find(id); if (scanItr == idToIndexMap_.end()) return size_; return scanItr->second; } PWIZ_API_DECL SpectrumPtr SpectrumList_Waters::spectrum(size_t index, bool getBinaryData) const { return spectrum(index, getBinaryData ? DetailLevel_FullData : DetailLevel_FullMetadata, 0.0, 0.0, 0.0); } PWIZ_API_DECL SpectrumPtr SpectrumList_Waters::spectrum(size_t index, DetailLevel detailLevel) const { return spectrum(index, detailLevel, 0.0, 0.0, 0.0); } PWIZ_API_DECL SpectrumPtr SpectrumList_Waters::spectrum(size_t index, bool getBinaryData, double lockmassMzPosScans, double lockmassMzNegScans, double lockmassTolerance) const { return spectrum(index, getBinaryData ? DetailLevel_FullData : DetailLevel_FullMetadata, lockmassMzPosScans, lockmassMzNegScans, lockmassTolerance); } PWIZ_API_DECL SpectrumPtr SpectrumList_Waters::spectrum(size_t index, DetailLevel detailLevel, double lockmassMzPosScans, double lockmassMzNegScans, double lockmassTolerance) const { boost::lock_guard lock(readMutex); // lock_guard will unlock mutex when out of scope or when exception thrown (during destruction) if (index >= size_) throw runtime_error("[SpectrumList_Waters::spectrum()] Bad index: " + lexical_cast(index)); // allocate a new Spectrum SpectrumPtr result(new Spectrum); if (!result.get()) throw runtime_error("[SpectrumList_Waters::spectrum()] Allocation error."); IndexEntry& ie = index_[index]; result->index = ie.index; result->id = ie.id; // TODO: fix Serializer_mzXML so it supports non-default sourceFilePtrs //size_t sourceFileIndex = ie.functionPtr->getFunctionNumber() - 1; //result->sourceFilePtr = msd_.fileDescription.sourceFilePtrs[sourceFileIndex]; /*float laserAimX = pExScanStats_->LaserAimXPos; float laserAimY = pExScanStats_->LaserAimYPos; //if (scanInfo->ionizationType() == IonizationType_MALDI) { result->spotID = (format("%dx%d") % laserAimX % laserAimY).str(); }*/ result->scanList.set(MS_no_combination); result->scanList.scans.push_back(Scan()); Scan& scan = result->scanList.scans[0]; scan.instrumentConfigurationPtr = msd_.run.defaultInstrumentConfigurationPtr; //scan.instrumentConfigurationPtr = //findInstrumentConfiguration(msd_, translate(scanInfo->massAnalyzerType())); int msLevel; CVID spectrumType; translateFunctionType(WatersToPwizFunctionType(rawdata_->Info.GetFunctionType(ie.function)), msLevel, spectrumType); result->set(spectrumType); result->set(MS_ms_level, msLevel); scan.set(MS_preset_scan_configuration, ie.function+1); if (detailLevel == DetailLevel_InstantMetadata) return result; using ::Waters::Lib::MassLynxRaw::MSScanStats; const MSScanStats& scanStats = rawdata_->GetScanStats(ie.function, ie.block >= 0 ? ie.block : ie.scan); scan.set(MS_scan_start_time, scanStats.rt, UO_minute); PwizPolarityType polarityType = WatersToPwizPolarityType(rawdata_->Info.GetIonMode(ie.function)); if (polarityType != PolarityType_Unknown) result->set(translate(polarityType)); double lockmassMz = (polarityType == PolarityType_Negative) ? lockmassMzNegScans : lockmassMzPosScans; if (scanStats.isContinuumScan) result->set(MS_profile_spectrum); else result->set(MS_centroid_spectrum); // block >= 0 is ion mobility if (ie.block < 0) { // scanStats values don't match the ion mobility data arrays // CONSIDER: in the ion mobility case, get these values from the actual data arrays result->set(MS_base_peak_m_z, scanStats.basePeakMass); result->set(MS_base_peak_intensity, scanStats.basePeakIntensity); result->set(MS_total_ion_current, scanStats.tic); result->defaultArrayLength = scanStats.peaksInScan; } else result->defaultArrayLength = 0; float minMZ, maxMZ; rawdata_->Info.GetAcquisitionMassRange(ie.function, minMZ, maxMZ); scan.scanWindows.push_back(ScanWindow(minMZ, maxMZ, MS_m_z)); if (detailLevel < DetailLevel_FastMetadata) return result; const RawData::ExtendedScanStatsByName& extendedScanStatsByName = rawdata_->GetExtendedScanStats(ie.function); // block >= 0 is ion mobility if (ie.block >= 0) { double driftTime = rawdata_->GetDriftTime(ie.function, ie.block, ie.scan); scan.set(MS_ion_mobility_drift_time, driftTime, UO_millisecond); } if (msLevel > 1) { RawData::ExtendedScanStatsByName::const_iterator setMassItr = extendedScanStatsByName.find("Set Mass"); if (setMassItr != extendedScanStatsByName.end()) { size_t tofScanIndex = ie.block >= 0 ? std::min(setMassItr->second.size()-1, (size_t) ie.block) : ie.scan; float setMass = boost::any_cast(setMassItr->second[tofScanIndex]); if (setMass > 0) { Precursor precursor; SelectedIon selectedIon(setMass); precursor.isolationWindow.set(MS_isolation_window_target_m_z, setMass, MS_m_z); precursor.activation.set(MS_beam_type_collision_induced_dissociation); // AFAIK there is no Waters instrument with a trap collision cell RawData::ExtendedScanStatsByName::const_iterator ceItr = extendedScanStatsByName.find("Collision Energy"); if (ceItr != extendedScanStatsByName.end() && boost::any_cast(ceItr->second[tofScanIndex]) > 0) precursor.activation.set(MS_collision_energy, boost::any_cast(ceItr->second[tofScanIndex]), UO_electronvolt); precursor.selectedIons.push_back(selectedIon); result->precursors.push_back(precursor); } } } if (detailLevel < DetailLevel_FullMetadata) return result; if (detailLevel == DetailLevel_FullData || detailLevel == DetailLevel_FullMetadata) { if (ie.block >= 0) { int axisLength = 0, nonZeroDataPoints = 0; const CompressedDataCluster& cdc = rawdata_->GetCompressedDataClusterForBlock(ie.function, ie.block); vector& imsMasses = imsMasses_; vector& massIndices = massIndices_; vector& imsIntensities = imsIntensities_; // CDC masses are uncalibrated, so we have to get calibration coefficients and do it ourselves initializeCoefficients(); cdc.getMassAxisLength(axisLength); if (axisLength != (int) imsMasses.size()) { imsMasses_.resize(axisLength); imsCalibratedMasses_.resize(axisLength); cdc.getMassAxis(&imsMasses[0]); massIndices.resize(axisLength); imsIntensities.resize(axisLength); std::fill(massIndices.begin(), massIndices.end(), 0.0f); std::fill(imsIntensities.begin(), imsIntensities.end(), 0.0f); for (int index = 0; index < imsCalibratedMasses_.size(); index++) imsCalibratedMasses_[index] = calibrate(imsMasses_[index]); } cdc.getScan(ie.block, ie.scan, &massIndices[0], &imsIntensities[0], nonZeroDataPoints); if (detailLevel == DetailLevel_FullMetadata) { result->defaultArrayLength = nonZeroDataPoints; if (nonZeroDataPoints > 0) { result->defaultArrayLength = 2; // flanking zero samples for (int i=0, end=nonZeroDataPoints; i < end; ++i) { if (i > 0 && massIndices[i-1] != massIndices[i]-1) ++result->defaultArrayLength; ++result->defaultArrayLength; if (i+1 < end && massIndices[i+1] != massIndices[i]+1) ++result->defaultArrayLength; } } return result; } // get actual data arrays vector masses, intensities; result->defaultArrayLength = nonZeroDataPoints; if (nonZeroDataPoints > 0) { masses.resize(2 + (nonZeroDataPoints * 3)); // worst case size intensities.resize(2 + (nonZeroDataPoints * 3)); // worst case size int count = 0; masses[count] = imsCalibratedMasses_[massIndices[0] - 1]; intensities[count++] = 0; for (int i=0, end=nonZeroDataPoints; i < end; ++i) { if (i > 0 && massIndices[i-1] != massIndices[i]-1) { masses[count] = imsCalibratedMasses_[massIndices[i] - 1]; intensities[count++] = 0; } masses[count] = imsCalibratedMasses_[massIndices[i]]; intensities[count++] = imsIntensities[i]; if (i+1 < end && massIndices[i+1] != massIndices[i]+1) { masses[count] = imsCalibratedMasses_[massIndices[i] + 1]; intensities[count++] = 0; } } masses[count] = imsCalibratedMasses_[massIndices[nonZeroDataPoints - 1] + 1]; intensities[count++] = 0; masses.resize(count); intensities.resize(count); } std::fill_n(massIndices.begin(), nonZeroDataPoints, 0.0f); std::fill_n(imsIntensities.begin(), nonZeroDataPoints, 0.0f); result->swapMZIntensityArrays(masses, intensities, MS_number_of_detector_counts); // Donate mass and intensity buffers to result vectors return result; } vector masses, intensities; if (detailLevel != DetailLevel_FullMetadata) { if (lockmassMz == 0.0) rawdata_->ScanReader.readSpectrum(ie.function, ie.scan, masses, intensities); else rawdata_->ScanReader.readSpectrum(ie.function, ie.scan, (float)lockmassMz, (float)lockmassTolerance, masses, intensities); } vector mzArray(masses.begin(), masses.end()); vector intensityArray(intensities.begin(), intensities.end()); result->swapMZIntensityArrays(mzArray, intensityArray, MS_number_of_detector_counts); // Donate mass and intensity buffers to result vectors } return result; } PWIZ_API_DECL void SpectrumList_Waters::initializeCoefficients() const { if (calibrationCoefficients_.empty()) { // the header property is something like: 6.08e-3,9.99e-1,-2.84e-6,7.63e-8,-6.91e-10,T1 string coefficients = rawdata_->GetHeaderProp("Cal Function 1"); vector tokens; bal::split(tokens, coefficients, bal::is_any_of(",")); if (tokens.size() < 5) // I don't know what the T1 is for, but it doesn't seem important throw runtime_error("[SpectrumList_Waters::spectrum()] error parsing calibration coefficients: " + coefficients); calibrationCoefficients_.resize(5); try { for (size_t i=0; i < 5; ++i) calibrationCoefficients_[i] = lexical_cast(tokens[i]); } catch (bad_lexical_cast&) { throw runtime_error("[SpectrumList_Waters::spectrum()] error parsing calibration coefficients: " + coefficients); } } } PWIZ_API_DECL double SpectrumList_Waters::calibrate(const double& mz) const { const vector& c = calibrationCoefficients_; double sqrtMz = sqrt(mz); double x = c[0] + c[1]*sqrtMz + c[2]*mz + c[3]*mz*sqrtMz + c[4]*mz*mz; return x*x; } PWIZ_API_DECL pwiz::analysis::Spectrum3DPtr SpectrumList_Waters::spectrum3d(double scanStartTime, const boost::icl::interval_set& driftTimeRanges) const { pwiz::analysis::Spectrum3DPtr result(new pwiz::analysis::Spectrum3D); if (scanTimeToFunctionAndBlockMap_.empty()) // implies no ion mobility data return result; boost::container::flat_map > >::const_iterator findItr = scanTimeToFunctionAndBlockMap_.lower_bound(floor(scanStartTime * 1e6) / 1e6); if (findItr == scanTimeToFunctionAndBlockMap_.end() || findItr->first - 1e-6 > scanStartTime) return result; for (size_t pair = 0; pair < findItr->second.size(); ++pair) { int function = findItr->second[pair].first; int block = findItr->second[pair].first; int axisLength = 0, nonZeroDataPoints = 0, numScansInBlock = 0; const CompressedDataCluster& cdc = rawdata_->GetCompressedDataClusterForBlock(function, block); vector& imsMasses = imsMasses_; vector& massIndices = massIndices_; vector& imsIntensities = imsIntensities_; // CDC masses are uncalibrated, so we have to get calibration coefficients and do it ourselves initializeCoefficients(); cdc.getMassAxisLength(axisLength); if (axisLength != (int) imsMasses.size()) { imsMasses_.resize(axisLength); imsCalibratedMasses_.resize(axisLength); cdc.getMassAxis(&imsMasses[0]); massIndices.resize(axisLength); imsIntensities.resize(axisLength); std::fill(massIndices.begin(), massIndices.end(), 0.0f); std::fill(imsIntensities.begin(), imsIntensities.end(), 0.0f); for (int index = 0; index < imsCalibratedMasses_.size(); index++) imsCalibratedMasses_[index] = calibrate(imsMasses_[index]); } cdc.getScansInBlock(numScansInBlock); for (int scan = 0; scan < numScansInBlock; ++scan) { double driftTime = rawdata_->GetDriftTime(function, block, scan); if (driftTimeRanges.find(driftTime) == driftTimeRanges.end()) continue; cdc.getScan(block, scan, &massIndices[0], &imsIntensities[0], nonZeroDataPoints); if (nonZeroDataPoints == 0) continue; boost::container::flat_map& driftSpectrum = (*result)[driftTime]; driftSpectrum[imsCalibratedMasses_[massIndices[0] - 1]] = 0; for (int i = 0, end = nonZeroDataPoints; i < end; ++i) { if (i > 0 && massIndices[i - 1] != massIndices[i] - 1) { driftSpectrum[imsCalibratedMasses_[massIndices[i] - 1]] = 0; } driftSpectrum[imsCalibratedMasses_[massIndices[i]]] = imsIntensities[i]; if (i + 1 < end && massIndices[i + 1] != massIndices[i] + 1) { driftSpectrum[imsCalibratedMasses_[massIndices[i] + 1]] = 0; } } driftSpectrum[imsCalibratedMasses_[massIndices[nonZeroDataPoints - 1] + 1]] = 0; std::fill_n(massIndices.begin(), nonZeroDataPoints, 0.0f); std::fill_n(imsIntensities.begin(), nonZeroDataPoints, 0.0f); } } return result; } PWIZ_API_DECL void SpectrumList_Waters::createIndex() { using namespace boost::spirit::karma; map > functionAndScanByRetentionTime; int numScansInBlock = 0; // number of scans per compressed block int numBlocks = 0; // number of blocks BOOST_FOREACH(int function, rawdata_->FunctionIndexList()) { int msLevel; CVID spectrumType; try { translateFunctionType(WatersToPwizFunctionType(rawdata_->Info.GetFunctionType(function)), msLevel, spectrumType); } catch(...) // unable to translate function type { cerr << "[SpectrumList_Waters::createIndex] Unable to translate function type \"" + rawdata_->Info.GetFunctionTypeString(function) + "\"" << endl; continue; } if (spectrumType == MS_SRM_spectrum || spectrumType == MS_SIM_spectrum || spectrumType == MS_constant_neutral_loss_spectrum || spectrumType == MS_constant_neutral_gain_spectrum) continue; int scanCount = rawdata_->Info.GetScansInFunction(function); const vector& scanStats = rawdata_->GetAllScanStatsForFunction(function); if (scanStats.size() != scanCount) throw runtime_error("[SpectrumList_Waters::createIndex] scanStats.size() not equal to scanCount"); if (!config_.combineIonMobilitySpectra && rawdata_->IonMobilityByFunctionIndex()[function]) { const CompressedDataCluster& cdc = rawdata_->GetCompressedDataClusterForBlock(function, 0); cdc.getNumberOfBlocks(numBlocks); cdc.getScansInBlock(numScansInBlock); if (scanCount != numBlocks) throw runtime_error("[SpectrumList_Waters::createIndex] numBlocks from CDC is not equal to scanCount from MassLynxRaw"); scanTimeToFunctionAndBlockMap_.reserve(numBlocks); for (int i=0; i < numBlocks; ++i) scanTimeToFunctionAndBlockMap_[scanStats[i].rt * 60].push_back(make_pair(function, i)); } else { for (int i=0; i < scanCount; ++i) functionAndScanByRetentionTime[scanStats[i].rt] = make_pair(function, i); } } typedef pair FunctionScanPair; BOOST_FOREACH_FIELD((double rt)(const FunctionScanPair& functionScanPair), functionAndScanByRetentionTime) { index_.push_back(IndexEntry()); IndexEntry& ie = index_.back(); ie.function = functionScanPair.first; ie.process = 0; ie.block = -1; // block < 0 is not ion mobility ie.scan = functionScanPair.second; ie.index = index_.size() - 1; std::back_insert_iterator sink(ie.id); generate(sink, "function=" << int_ << " process=" << int_ << " scan=" << int_, (ie.function + 1), ie.process, (ie.scan + 1)); idToIndexMap_[ie.id] = ie.index; } BOOST_FOREACH_FIELD((double rt)(const vector& functionBlockPairs), scanTimeToFunctionAndBlockMap_) { BOOST_FOREACH(const FunctionScanPair& functionBlockPair, functionBlockPairs) { for (int j = 0; j < numScansInBlock; ++j) { index_.push_back(IndexEntry()); IndexEntry& ie = index_.back(); ie.function = functionBlockPair.first; ie.process = 0; ie.block = functionBlockPair.second; ie.scan = j; ie.index = index_.size() - 1; std::back_insert_iterator sink(ie.id); generate(sink, "function=" << int_ << " process=" << int_ << " scan=" << int_, (ie.function + 1), ie.process, ((numScansInBlock*ie.block) + ie.scan + 1)); idToIndexMap_[ie.id] = ie.index; } } } size_ = index_.size(); } } // detail } // msdata } // pwiz #else // PWIZ_READER_WATERS // // non-MSVC implementation // namespace pwiz { namespace msdata { namespace detail { namespace {const SpectrumIdentity emptyIdentity;} size_t SpectrumList_Waters::size() const {return 0;} const SpectrumIdentity& SpectrumList_Waters::spectrumIdentity(size_t index) const {return emptyIdentity;} size_t SpectrumList_Waters::find(const std::string& id) const {return 0;} SpectrumPtr SpectrumList_Waters::spectrum(size_t index, bool getBinaryData) const {return SpectrumPtr();} SpectrumPtr SpectrumList_Waters::spectrum(size_t index, DetailLevel detailLevel) const { return SpectrumPtr(); } SpectrumPtr SpectrumList_Waters::spectrum(size_t index, bool getBinaryData, double lockmassMzPosScans, double lockmassMzNegScans, double lockmassTolerance) const { return SpectrumPtr(); } SpectrumPtr SpectrumList_Waters::spectrum(size_t index, DetailLevel detailLevel, double lockmassMzPosScans, double lockmassMzNegScans, double lockmassTolerance) const { return SpectrumPtr(); } PWIZ_API_DECL pwiz::analysis::Spectrum3DPtr SpectrumList_Waters::spectrum3d(double scanStartTime, const boost::icl::interval_set& driftTimeRanges) const { return pwiz::analysis::Spectrum3DPtr(); } } // detail } // msdata } // pwiz #endif // PWIZ_READER_WATERS pwiz/pwiz/data/vendor_readers/Waters/Reader_Waters.cpp0000664000175100017510000001737712664775617025203 0ustar teamcityteamcity00000000000000// // $Id: Reader_Waters.cpp 8961 2015-10-08 15:03:23Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Reader_Waters.hpp" #include "pwiz/utility/misc/DateTime.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/String.hpp" #include "pwiz/data/msdata/Version.hpp" // A Waters RAW source (representing a "run") is actually a directory // It may have multiple functions (scan events), e.g. _FUNC001.DAT, _FUNC002.DAT, etc. // It may also contain some useful metadata in _extern.inf PWIZ_API_DECL std::string pwiz::msdata::Reader_Waters::identify(const std::string& filename, const std::string& head) const { std::string result; // Make sure target "filename" is actually a directory if (!bfs::is_directory(filename)) return result; // Count the number of _FUNC[0-9]{3}.DAT files, starting with _FUNC001.DAT string functionPathmask = filename + "/_FUNC*.DAT"; vector functionFilepaths; pwiz::util::expand_pathmask(functionPathmask, functionFilepaths); if (!functionFilepaths.empty()) result = getType(); return result; } #ifdef PWIZ_READER_WATERS #include "pwiz/utility/misc/SHA1Calculator.hpp" //#include #include "Reader_Waters_Detail.hpp" #include "SpectrumList_Waters.hpp" #include "ChromatogramList_Waters.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace msdata { using namespace pwiz::util; using namespace pwiz::msdata::detail; using namespace pwiz::msdata::detail::Waters; // // Reader_Waters // namespace { void fillInMetadata(const string& rawpath, RawDataPtr rawdata, MSData& msd) { msd.cvs = defaultCVList(); string functionPathmask = rawpath + "/_FUNC*.DAT"; vector functionFilepaths; expand_pathmask(functionPathmask, functionFilepaths); // first list all the function DAT files as sources for (size_t i=0; i < functionFilepaths.size(); ++i) { bfs::path sourcePath = functionFilepaths[i]; SourceFilePtr sourceFile(new SourceFile); sourceFile->id = BFS_STRING(sourcePath.leaf()); sourceFile->name = BFS_STRING(sourcePath.leaf()); sourceFile->location = "file://" + BFS_COMPLETE(sourcePath.branch_path()).string(); sourceFile->set(MS_Waters_nativeID_format); sourceFile->set(MS_Waters_raw_format); msd.fileDescription.sourceFilePtrs.push_back(sourceFile); } if (!functionFilepaths.empty()) msd.run.defaultSourceFilePtr = msd.fileDescription.sourceFilePtrs.front(); // next iterate over any other files bfs::path p(rawpath); for (bfs::directory_iterator itr(p); itr != bfs::directory_iterator(); ++itr) { // skip the function filepaths if (find(functionFilepaths.begin(), functionFilepaths.end(), itr->path()) != functionFilepaths.end()) continue; // skip lockmass cache if (bal::iends_with(itr->path().string(), "lmgt.inf")) continue; bfs::path sourcePath = itr->path(); SourceFilePtr sourceFile(new SourceFile); sourceFile->id = BFS_STRING(sourcePath.leaf()); sourceFile->name = BFS_STRING(sourcePath.leaf()); sourceFile->location = string("file://") + BFS_COMPLETE(sourcePath.branch_path()).string(); sourceFile->set(MS_no_nativeID_format); msd.fileDescription.sourceFilePtrs.push_back(sourceFile); } SoftwarePtr softwareMassLynx(new Software); softwareMassLynx->id = "MassLynx"; softwareMassLynx->set(MS_MassLynx); softwareMassLynx->version = "4.1"; msd.softwarePtrs.push_back(softwareMassLynx); SoftwarePtr softwarePwiz(new Software); softwarePwiz->id = "pwiz_Reader_Waters"; softwarePwiz->set(MS_pwiz); softwarePwiz->version = pwiz::msdata::Version::str(); msd.softwarePtrs.push_back(softwarePwiz); DataProcessingPtr dpPwiz(new DataProcessing); dpPwiz->id = "pwiz_Reader_Waters_conversion"; dpPwiz->processingMethods.push_back(ProcessingMethod()); dpPwiz->processingMethods.back().softwarePtr = softwarePwiz; dpPwiz->processingMethods.back().set(MS_Conversion_to_mzML); // give ownership of dpPwiz to the SpectrumList (and ChromatogramList) SpectrumList_Waters* sl = dynamic_cast(msd.run.spectrumListPtr.get()); ChromatogramList_Waters* cl = dynamic_cast(msd.run.chromatogramListPtr.get()); if (sl) sl->setDataProcessingPtr(dpPwiz); if (cl) cl->setDataProcessingPtr(dpPwiz); //initializeInstrumentConfigurationPtrs(msd, rawfile, softwareXcalibur); msd.instrumentConfigurationPtrs.push_back(InstrumentConfigurationPtr(new InstrumentConfiguration("IC"))); msd.instrumentConfigurationPtrs.back()->set(MS_Waters_instrument_model); if (!msd.instrumentConfigurationPtrs.empty()) msd.run.defaultInstrumentConfigurationPtr = msd.instrumentConfigurationPtrs[0]; msd.id = bfs::basename(p); msd.run.id = msd.id; string dateStamp = rawdata->GetHeaderProp("Acquired Date"); if (!dateStamp.empty()) { string timeStamp = rawdata->GetHeaderProp("Acquired Time"); if (!timeStamp.empty()) dateStamp += " " + timeStamp; blt::local_date_time dateTime = parse_date_time("%d-%b-%Y %H:%M:%S", dateStamp); if (!dateTime.is_not_a_date_time()) msd.run.startTimeStamp = encode_xml_datetime(dateTime); } } } // namespace PWIZ_API_DECL void Reader_Waters::read(const string& filename, const string& head, MSData& result, int runIndex, const Config& config) const { if (runIndex != 0) throw ReaderFail("[Reader_Waters::read] multiple runs not supported"); RawDataPtr rawdata = RawDataPtr(new RawData(filename)); result.run.spectrumListPtr = SpectrumListPtr(new SpectrumList_Waters(result, rawdata, config)); result.run.chromatogramListPtr = ChromatogramListPtr(new ChromatogramList_Waters(rawdata)); fillInMetadata(filename, rawdata, result); } } // namespace msdata } // namespace pwiz #else // PWIZ_READER_WATERS // // non-MSVC implementation // #include "Reader_Waters.hpp" #include namespace pwiz { namespace msdata { PWIZ_API_DECL void Reader_Waters::read(const string& filename, const string& head, MSData& result, int runIndex, const Config& config) const { throw ReaderFail("[Reader_Waters::read()] Waters RAW reader not implemented: " #ifdef _MSC_VER // should be possible, apparently somebody decided to skip it "support was explicitly disabled when program was built" #elif defined(WIN32) // wrong compiler "program was built without COM support and cannot access MassLynx DLLs - try building with MSVC instead of GCC" #else // wrong platform "requires MassLynx which only work on Windows" #endif ); } } // namespace msdata } // namespace pwiz #endif // PWIZ_READER_WATERS pwiz/pwiz/data/vendor_readers/Waters/SpectrumList_Waters.hpp0000664000175100017510000000624512664775617026434 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_Waters.hpp 9095 2015-11-01 01:14:24Z pcbrefugee $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/SpectrumListBase.hpp" #include "Reader_Waters_Detail.hpp" #include "pwiz/utility/misc/Container.hpp" #include "pwiz/utility/misc/String.hpp" #include "pwiz/utility/misc/Stream.hpp" #include "pwiz/data/msdata/Reader.hpp" #include "pwiz/analysis/spectrum_processing/SpectrumList_3D.hpp" #include using boost::shared_ptr; namespace pwiz { namespace msdata { namespace detail { // // SpectrumList_Waters // class PWIZ_API_DECL SpectrumList_Waters : public SpectrumListBase { public: virtual size_t size() const; virtual const SpectrumIdentity& spectrumIdentity(size_t index) const; virtual size_t find(const string& id) const; virtual SpectrumPtr spectrum(size_t index, bool getBinaryData) const; virtual SpectrumPtr spectrum(size_t index, DetailLevel detailLevel) const; virtual SpectrumPtr spectrum(size_t index, bool getBinaryData, double lockmassMzPosScans, double lockmassMzNegScans, double lockmassTolerance) const; virtual SpectrumPtr spectrum(size_t index, DetailLevel detailLevel, double lockmassMzPosScans, double lockmassMzNegScans, double lockmassTolerance) const; virtual pwiz::analysis::Spectrum3DPtr spectrum3d(double scanStartTime, const boost::icl::interval_set& driftTimeRanges) const; #ifdef PWIZ_READER_WATERS SpectrumList_Waters(MSData& msd, RawDataPtr rawdata, const Reader::Config& config); private: MSData& msd_; RawDataPtr rawdata_; size_t size_; Reader::Config config_; struct IndexEntry : public SpectrumIdentity { int function; int process; int scan; int block; // block < 0 is not ion mobility }; mutable vector index_; mutable map idToIndexMap_; mutable boost::container::flat_map > > scanTimeToFunctionAndBlockMap_; void initializeCoefficients() const; double calibrate(const double &mz) const; mutable vector calibrationCoefficients_; mutable vector imsCalibratedMasses_; mutable vector imsMasses_; mutable vector massIndices_; mutable vector imsIntensities_; mutable boost::mutex readMutex; void createIndex(); #endif // PWIZ_READER_WATERS }; } // detail } // msdata } // pwiz pwiz/pwiz/data/vendor_readers/Waters/Reader_Waters_Test.cpp0000664000175100017510000000337112664775617026167 0ustar teamcityteamcity00000000000000// // $Id: Reader_Waters_Test.cpp 7155 2015-02-03 22:38:32Z chambm $ // // // Original author: Matt Chambers // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/unit.hpp" #include "Reader_Waters.hpp" #include "pwiz/utility/misc/VendorReaderTestHarness.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" struct IsRawData : public pwiz::util::TestPathPredicate { bool operator() (const string& rawpath) const { return bfs::is_directory(rawpath) && bal::to_lower_copy(BFS_STRING(bfs::path(rawpath).extension())) == ".raw"; } }; int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) #ifdef PWIZ_READER_WATERS const bool testAcceptOnly = false; #else const bool testAcceptOnly = true; #endif try { bool requireUnicodeSupport = false; pwiz::util::testReader(pwiz::msdata::Reader_Waters(), testArgs, testAcceptOnly, requireUnicodeSupport, IsRawData()); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/vendor_readers/Waters/Reader_Waters_Detail.cpp0000664000175100017510000001171212664775617026450 0ustar teamcityteamcity00000000000000// // $Id: Reader_Waters_Detail.cpp 7398 2015-04-17 15:39:31Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Reader_Waters_Detail.hpp" #include "pwiz/utility/misc/Container.hpp" #include "pwiz/utility/misc/String.hpp" namespace pwiz { namespace msdata { namespace detail { namespace Waters { PWIZ_API_DECL vector createInstrumentConfigurations(RawDataPtr rawdata) { return vector(); } PWIZ_API_DECL CVID translateAsInstrumentModel(RawDataPtr rawdata) { return CVID_Unknown; } PWIZ_API_DECL void translateFunctionType(PwizFunctionType functionType, int& msLevel, CVID& spectrumType) { switch (functionType) { /*case FunctionType_MSMSMS: msLevel = 3; spectrumType = MS_MSn_spectrum; break;*/ case FunctionType_Daughters: //case FunctionType_MSMS: case FunctionType_MS2: case FunctionType_TOF_Daughter: case FunctionType_Auto_Daughters: msLevel = 2; spectrumType = MS_MSn_spectrum; break; case FunctionType_SIR: msLevel = 1; spectrumType = MS_SIM_spectrum; break; case FunctionType_MRM: case FunctionType_AutoSpec_MRM: case FunctionType_AutoSpec_Q_MRM_Quad: case FunctionType_AutoSpec_MIKES_Scan: msLevel = 2; spectrumType = MS_SRM_spectrum; break; case FunctionType_Neutral_Loss: msLevel = 2; spectrumType = MS_constant_neutral_loss_spectrum; break; case FunctionType_Neutral_Gain: msLevel = 2; spectrumType = MS_constant_neutral_gain_spectrum; break; case FunctionType_Parents: case FunctionType_Scan: case FunctionType_Q1F: case FunctionType_TOF: case FunctionType_TOF_MS: case FunctionType_TOF_Survey: case FunctionType_TOF_Parent: case FunctionType_MALDI_TOF: msLevel = 1; spectrumType = MS_MS1_spectrum; break; // these functions are not mass spectra case FunctionType_Diode_Array: msLevel = 0; spectrumType = MS_EMR_spectrum; break; case FunctionType_Off: case FunctionType_Voltage_Scan: case FunctionType_Magnetic_Scan: case FunctionType_Voltage_SIR: case FunctionType_Magnetic_SIR: msLevel = 0; spectrumType = CVID_Unknown; break; /* TODO: figure out what these function types translate to FunctionType_Delay FunctionType_Concatenated FunctionType_TOF_PSD FunctionType_AutoSpec_B_E_Scan FunctionType_AutoSpec_B2_E_Scan FunctionType_AutoSpec_CNL_Scan FunctionType_AutoSpec_MIKES_Scan FunctionType_AutoSpec_NRMS_Scan */ default: throw std::runtime_error("[translateFunctionType] Unable to translate function type."); } } PWIZ_API_DECL CVID translateAsIonizationType(PwizIonizationType ionizationType) { /*switch (ionizationType) { case IonizationType_EI = 0, // Electron Ionization case IonizationType_CI, // Chemical Ionization case IonizationType_FB, // Fast Atom Bombardment case IonizationType_TS, // Thermospray case IonizationType_ES, // Electrospray Ionization case IonizationType_AI, // Atmospheric Ionization case IonizationType_LD, // Laser Desorption Ionization case IonizationType_FI, // ? case IonizationType_Generic, case IonizationType_Count*/ return CVID_Unknown; } PWIZ_API_DECL CVID translate(PwizPolarityType polarityType) { switch (polarityType) { case PolarityType_Positive: return MS_positive_scan; case PolarityType_Negative: return MS_negative_scan; default: return CVID_Unknown; } } } // Waters } // detail } // msdata } // pwiz pwiz/pwiz/data/vendor_readers/Waters/Reader_Waters.hpp0000664000175100017510000000402712664775617025174 0ustar teamcityteamcity00000000000000// // $Id: Reader_Waters.hpp 3808 2012-07-24 20:31:10Z donmarsh $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _READER_WATERS_HPP_ #define _READER_WATERS_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/Reader.hpp" // DAC usage is msvc only - mingw doesn't provide com support #if (!defined(_MSC_VER) && defined(PWIZ_READER_WATERS)) #undef PWIZ_READER_WATERS #endif namespace pwiz { namespace msdata { class PWIZ_API_DECL Reader_Waters : public Reader { public: virtual std::string identify(const std::string& filename, const std::string& head) const; virtual void read(const std::string& filename, const std::string& head, MSData& result, int runIndex = 0, const Config& config = Config()) const; virtual void read(const std::string& filename, const std::string& head, std::vector& results, const Config& config = Config()) const { results.push_back(MSDataPtr(new MSData)); read(filename, head, *results.back(), 0, config); } virtual const char * getType() const {return "Waters RAW";} }; } // namespace msdata } // namespace pwiz #endif // _READER_WATERS_HPP_ pwiz/pwiz/data/vendor_readers/Waters/ChromatogramList_Waters.cpp0000664000175100017510000002433012664775617027243 0ustar teamcityteamcity00000000000000// // $Id: ChromatogramList_Waters.cpp 7680 2015-06-22 15:15:42Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "ChromatogramList_Waters.hpp" #ifdef PWIZ_READER_WATERS #include "Reader_Waters_Detail.hpp" #include "pwiz/utility/misc/SHA1Calculator.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include namespace pwiz { namespace msdata { namespace detail { using namespace Waters; PWIZ_API_DECL ChromatogramList_Waters::ChromatogramList_Waters(RawDataPtr rawdata) : rawdata_(rawdata), size_(0), indexInitialized_(util::init_once_flag_proxy) { } PWIZ_API_DECL size_t ChromatogramList_Waters::size() const { boost::call_once(indexInitialized_.flag, boost::bind(&ChromatogramList_Waters::createIndex, this)); return size_; } PWIZ_API_DECL const ChromatogramIdentity& ChromatogramList_Waters::chromatogramIdentity(size_t index) const { boost::call_once(indexInitialized_.flag, boost::bind(&ChromatogramList_Waters::createIndex, this)); if (index>size_) throw runtime_error(("[ChromatogramList_Waters::chromatogramIdentity()] Bad index: " + lexical_cast(index)).c_str()); return index_[index]; } PWIZ_API_DECL size_t ChromatogramList_Waters::find(const string& id) const { boost::call_once(indexInitialized_.flag, boost::bind(&ChromatogramList_Waters::createIndex, this)); map::const_iterator scanItr = idToIndexMap_.find(id); if (scanItr == idToIndexMap_.end()) return size_; return scanItr->second; } PWIZ_API_DECL ChromatogramPtr ChromatogramList_Waters::chromatogram(size_t index, bool getBinaryData) const { boost::call_once(indexInitialized_.flag, boost::bind(&ChromatogramList_Waters::createIndex, this)); if (index>size_) throw runtime_error(("[ChromatogramList_Waters::chromatogram()] Bad index: " + lexical_cast(index)).c_str()); // allocate a new Chromatogram IndexEntry& ie = index_[index]; ChromatogramPtr result = ChromatogramPtr(new Chromatogram); if (!result.get()) throw std::runtime_error("[ChromatogramList_Waters::chromatogram()] Allocation error."); result->index = index; result->id = ie.id; result->set(ie.chromatogramType); switch (ie.chromatogramType) { case MS_TIC_chromatogram: { map fullFileTIC; BOOST_FOREACH(int function, rawdata_->FunctionIndexList()) { // add current function TIC to full file TIC vector times, intensities; rawdata_->ChromatogramReader.ReadTICChromatogram(function, times, intensities); for (int i = 0, end = intensities.size(); i < end; ++i) fullFileTIC[times[i]] += intensities[i]; } result->setTimeIntensityArrays(std::vector(), std::vector(), UO_minute, MS_number_of_detector_counts); if (getBinaryData) { BinaryDataArrayPtr timeArray = result->getTimeArray(); BinaryDataArrayPtr intensityArray = result->getIntensityArray(); timeArray->data.reserve(fullFileTIC.size()); intensityArray->data.reserve(fullFileTIC.size()); for (map::iterator itr = fullFileTIC.begin(); itr != fullFileTIC.end(); ++itr) { timeArray->data.push_back(itr->first); intensityArray->data.push_back(itr->second); } } result->defaultArrayLength = fullFileTIC.size(); } break; case MS_SRM_chromatogram: { result->precursor.isolationWindow.set(MS_isolation_window_target_m_z, ie.Q1, MS_m_z); //result->precursor.isolationWindow.set(MS_isolation_window_lower_offset, ie.q1, MS_m_z); //result->precursor.isolationWindow.set(MS_isolation_window_upper_offset, ie.q1, MS_m_z); result->precursor.activation.set(MS_CID); result->product.isolationWindow.set(MS_isolation_window_target_m_z, ie.Q3, MS_m_z); //result->product.isolationWindow.set(MS_isolation_window_lower_offset, ie.q3, MS_m_z); //result->product.isolationWindow.set(MS_isolation_window_upper_offset, ie.q3, MS_m_z); result->setTimeIntensityArrays(std::vector(), std::vector(), UO_minute, MS_number_of_detector_counts); vector times; vector intensities; rawdata_->ChromatogramReader.ReadMRMChromatogram(ie.function, ie.offset, times, intensities); result->defaultArrayLength = times.size(); if (getBinaryData) { result->getTimeArray()->data.assign(times.begin(), times.end()); result->getIntensityArray()->data.assign(intensities.begin(), intensities.end()); } } break; case MS_SIM_chromatogram: { result->precursor.isolationWindow.set(MS_isolation_window_target_m_z, ie.Q1, MS_m_z); //result->precursor.isolationWindow.set(MS_isolation_window_lower_offset, ie.q1, MS_m_z); //result->precursor.isolationWindow.set(MS_isolation_window_upper_offset, ie.q1, MS_m_z); result->precursor.activation.set(MS_CID); result->setTimeIntensityArrays(std::vector(), std::vector(), UO_minute, MS_number_of_detector_counts); vector times; vector intensities; rawdata_->ChromatogramReader.ReadMRMChromatogram(ie.function, ie.offset, times, intensities); result->defaultArrayLength = times.size(); if (getBinaryData) { result->getTimeArray()->data.assign(times.begin(), times.end()); result->getIntensityArray()->data.assign(intensities.begin(), intensities.end()); } } break; } return result; } PWIZ_API_DECL void ChromatogramList_Waters::createIndex() const { index_.push_back(IndexEntry()); IndexEntry& ie = index_.back(); ie.index = index_.size()-1; ie.id = "TIC"; ie.chromatogramType = MS_TIC_chromatogram; idToIndexMap_[ie.id] = ie.index; BOOST_FOREACH(int function, rawdata_->FunctionIndexList()) { int msLevel; CVID spectrumType; try { translateFunctionType(WatersToPwizFunctionType(rawdata_->Info.GetFunctionType(function)), msLevel, spectrumType); } catch(...) // unable to translate function type { cerr << "[ChromatogramList_Waters::createIndex] Unable to translate function type \"" + rawdata_->Info.GetFunctionTypeString(function) + "\"" << endl; continue; } if (spectrumType != MS_SRM_spectrum && spectrumType != MS_SIM_spectrum) continue; //rawdata_->Info.GetAcquisitionTimeRange(function, f1, f2); //cout << "Time range: " << f1 << " - " << f2 << endl; vector precursorMZs, productMZs, intensities; rawdata_->ScanReader.readSpectrum(function, 1, precursorMZs, intensities, productMZs); if (spectrumType == MS_SRM_spectrum && productMZs.size() != precursorMZs.size()) throw runtime_error("[ChromatogramList_Waters::createIndex] MRM function " + lexical_cast(function+1) + " has mismatch between product m/z count (" + lexical_cast(productMZs.size()) + ") and precursor m/z count (" + lexical_cast(precursorMZs.size()) + ")"); for (size_t i=0; i < precursorMZs.size(); ++i) { index_.push_back(IndexEntry()); IndexEntry& ie = index_.back(); ie.index = index_.size()-1; ie.function = function; ie.offset = i; ie.Q1 = precursorMZs[i]; std::ostringstream oss; if (spectrumType == MS_SRM_spectrum) { ie.Q3 = productMZs[i]; ie.chromatogramType = MS_SRM_chromatogram; oss << "SRM SIC Q1=" << ie.Q1 << " Q3=" << ie.Q3 << " function=" << (function + 1) << " offset=" << ie.offset; } else { ie.Q3 = 0; ie.chromatogramType = MS_SIM_chromatogram; oss << "SIM SIC Q1=" << ie.Q1 << " function=" << (function + 1) << " offset=" << ie.offset; } ie.id = oss.str(); idToIndexMap_[ie.id] = ie.index; } } size_ = index_.size(); } } // detail } // msdata } // pwiz #else // PWIZ_READER_WATERS // // non-MSVC implementation // namespace pwiz { namespace msdata { namespace detail { namespace {const ChromatogramIdentity emptyIdentity;} size_t ChromatogramList_Waters::size() const {return 0;} const ChromatogramIdentity& ChromatogramList_Waters::chromatogramIdentity(size_t index) const {return emptyIdentity;} size_t ChromatogramList_Waters::find(const std::string& id) const {return 0;} ChromatogramPtr ChromatogramList_Waters::chromatogram(size_t index, bool getBinaryData) const {return ChromatogramPtr();} } // detail } // msdata } // pwiz #endif // PWIZ_READER_WATERS pwiz/pwiz/data/vendor_readers/Waters/Reader_Waters_Detail.hpp0000664000175100017510000000357712664775617026467 0ustar teamcityteamcity00000000000000// // $Id: Reader_Waters_Detail.hpp 6478 2014-07-08 20:01:38Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _READER_WATERS_DETAIL_HPP_ #define _READER_WATERS_DETAIL_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/MSData.hpp" #include #ifdef PWIZ_READER_WATERS #include "pwiz_aux/msrc/utility/vendor_api/Waters/MassLynxRaw.hpp" using namespace pwiz::vendor_api::Waters; namespace pwiz { namespace msdata { namespace detail { namespace Waters { PWIZ_API_DECL std::vector createInstrumentConfigurations(RawDataPtr rawdata); PWIZ_API_DECL CVID translateAsInstrumentModel(RawDataPtr rawdata); PWIZ_API_DECL void translateFunctionType(PwizFunctionType functionType, int& msLevel, CVID& spectrumType); PWIZ_API_DECL CVID translateAsIonizationType(PwizIonizationType ionizationType); PWIZ_API_DECL CVID translate(PwizPolarityType polarityType); /*PWIZ_API_DECL CVID translate(MassAnalyzerType type); PWIZ_API_DECL CVID translateAsInletType(IonizationType ionizationType); PWIZ_API_DECL CVID translate(ActivationType activationType);*/ } // Waters } // detail } // msdata } // pwiz #endif #endif // _READER_WATERS_DETAIL_HPP_ pwiz/libraries/boost_aux/boost/nowide/cstdio.hpp0000664000175100017510000000466212664775723024156 0ustar teamcityteamcity00000000000000// // Copyright (c) 2012 Artyom Beilis (Tonkikh) // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_NOWIDE_CSTDIO_H_INCLUDED #define BOOST_NOWIDE_CSTDIO_H_INCLUDED #include #include #include #include #include #include #ifdef BOOST_MSVC # pragma warning(push) # pragma warning(disable : 4996) #endif namespace boost { namespace nowide { #if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_DOXYGEN) using std::fopen; using std::freopen; using std::remove; using std::rename; #else /// /// \brief Same as freopen but file_name and mode are UTF-8 strings /// /// In invalid UTF-8 given, NULL is returned and errno is set to EINVAL /// inline FILE *freopen(char const *file_name,char const *mode,FILE *stream) { wstackstring wname; wshort_stackstring wmode; if(!wname.convert(file_name) || !wmode.convert(mode)) { errno = EINVAL; return 0; } return _wfreopen(wname.c_str(),wmode.c_str(),stream); } /// /// \brief Same as fopen but file_name and mode are UTF-8 strings /// /// In invalid UTF-8 given, NULL is returned and errno is set to EINVAL /// inline FILE *fopen(char const *file_name,char const *mode) { wstackstring wname; wshort_stackstring wmode; if(!wname.convert(file_name) || !wmode.convert(mode)) { errno = EINVAL; return 0; } return _wfopen(wname.c_str(),wmode.c_str()); } /// /// \brief Same as rename but old_name and new_name are UTF-8 strings /// /// In invalid UTF-8 given, -1 is returned and errno is set to EINVAL /// inline int rename(char const *old_name,char const *new_name) { wstackstring wold,wnew; if(!wold.convert(old_name) || !wnew.convert(new_name)) { errno = EINVAL; return -1; } return _wrename(wold.c_str(),wnew.c_str()); } /// /// \brief Same as rename but name is UTF-8 string /// /// In invalid UTF-8 given, -1 is returned and errno is set to EINVAL /// inline int remove(char const *name) { wstackstring wname; if(!wname.convert(name)) { errno = EINVAL; return -1; } return _wremove(wname.c_str()); } #endif } // nowide } // namespace boost #ifdef BOOST_MSVC #pragma warning(pop) #endif #endif /// // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 pwiz/libraries/boost_aux/boost/nowide/cstdlib.hpp0000664000175100017510000000066312664775723024312 0ustar teamcityteamcity00000000000000// // Copyright (c) 2012 Artyom Beilis (Tonkikh) // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_NOWIDE_CSTDLIB_HPP_INCLUDED #define BOOST_NOWIDE_CSTDLIB_HPP_INCLUDED #include #include #endif /// // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 pwiz/libraries/boost_aux/boost/nowide/cenv.hpp0000664000175100017510000000702512664775723023620 0ustar teamcityteamcity00000000000000// // Copyright (c) 2012 Artyom Beilis (Tonkikh) // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_NOWIDE_CENV_H_INCLUDED #define BOOST_NOWIDE_CENV_H_INCLUDED #include #include #include #include #include #include #ifdef BOOST_WINDOWS #include #endif namespace boost { namespace nowide { #if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_DOXYGEN) using ::getenv; using ::setenv; using ::unsetenv; using ::putenv; #else /// /// \brief UTF-8 aware getenv. Returns 0 if the variable is not set. /// /// This function is not thread safe or reenterable as defined by the standard library /// inline char *getenv(char const *key) { static stackstring value; wshort_stackstring name; if(!name.convert(key)) return 0; static const size_t buf_size = 64; wchar_t buf[buf_size]; std::vector tmp; wchar_t *ptr = buf; size_t n = GetEnvironmentVariableW(name.c_str(),buf,buf_size); if(n == 0 && GetLastError() == 203) // ERROR_ENVVAR_NOT_FOUND return 0; if(n >= buf_size) { tmp.resize(n+1,L'\0'); n = GetEnvironmentVariableW(name.c_str(),&tmp[0],tmp.size() - 1); // The size may have changed if(n >= tmp.size() - 1) return 0; ptr = &tmp[0]; } if(!value.convert(ptr)) return 0; return value.c_str(); } /// /// \brief UTF-8 aware setenv, \a key - the variable name, \a value is a new UTF-8 value, /// /// if override is not 0, that the old value is always overridded, otherwise, /// if the variable exists it remains unchanged /// inline int setenv(char const *key,char const *value,int override) { wshort_stackstring name; if(!name.convert(key)) return -1; if(!override) { wchar_t unused[2]; if(!(GetEnvironmentVariableW(name.c_str(),unused,2)==0 && GetLastError() == 203)) // ERROR_ENVVAR_NOT_FOUND return 0; } wstackstring wval; if(!wval.convert(value)) return -1; if(SetEnvironmentVariableW(name.c_str(),wval.c_str())) return 0; return -1; } /// /// \brief Remove enviroment variable \a key /// inline int unsetenv(char const *key) { wshort_stackstring name; if(!name.convert(key)) return -1; if(SetEnvironmentVariableW(name.c_str(),0)) return 0; return -1; } /// /// \brief UTF-8 aware putenv implementation, expects string in format KEY=VALUE /// inline int putenv(char *string) { char const *key = string; char const *key_end = string; while(*key_end!='=' && key_end!='\0') key_end++; if(*key_end == '\0') return -1; wshort_stackstring wkey; if(!wkey.convert(key,key_end)) return -1; wstackstring wvalue; if(!wvalue.convert(key_end+1)) return -1; if(SetEnvironmentVariableW(wkey.c_str(),wvalue.c_str())) return 0; return -1; } #endif } // nowide } // namespace boost #endif /// // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 pwiz/libraries/boost_aux/boost/nowide/fstream.hpp0000664000175100017510000001562412664775723024332 0ustar teamcityteamcity00000000000000// // Copyright (c) 2012 Artyom Beilis (Tonkikh) // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_NOWIDE_FSTREAM_INCLUDED_HPP #define BOOST_NOWIDE_FSTREAM_INCLUDED_HPP #include #include #include #include #include #include #include namespace boost { /// /// \brief This namespace includes implementation of the standard library functios /// such that they accept UTF-8 strings on Windows. On other platforms it is just an alias /// of std namespace (i.e. not on Windows) /// namespace nowide { #if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_FSTREAM_TESTS) && !defined(BOOST_NOWIDE_DOXYGEN) using std::basic_ifstream; using std::basic_ofstream; using std::basic_fstream; using std::ifstream; using std::ofstream; using std::fstream; #else /// /// \brief Same as std::basic_ifstream but accepts UTF-8 strings under Windows /// template > class basic_ifstream : public std::basic_istream { public: typedef basic_filebuf internal_buffer_type; typedef std::basic_istream internal_stream_type; basic_ifstream() : internal_stream_type(0) { buf_.reset(new internal_buffer_type()); std::ios::rdbuf(buf_.get()); } explicit basic_ifstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::in) : internal_stream_type(0) { buf_.reset(new internal_buffer_type()); std::ios::rdbuf(buf_.get()); open(file_name,mode); } void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::in) { if(!buf_->open(file_name,mode | std::ios_base::in)) { this->setstate(std::ios_base::failbit); } else { this->clear(); } } bool is_open() { return buf_->is_open(); } bool is_open() const { return buf_->is_open(); } void close() { if(!buf_->close()) this->setstate(std::ios_base::failbit); else this->clear(); } internal_buffer_type *rdbuf() const { return buf_.get(); } ~basic_ifstream() { buf_->close(); } private: boost::scoped_ptr buf_; }; /// /// \brief Same as std::basic_ofstream but accepts UTF-8 strings under Windows /// template > class basic_ofstream : public std::basic_ostream { public: typedef basic_filebuf internal_buffer_type; typedef std::basic_ostream internal_stream_type; basic_ofstream() : internal_stream_type(0) { buf_.reset(new internal_buffer_type()); std::ios::rdbuf(buf_.get()); } explicit basic_ofstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::out) : internal_stream_type(0) { buf_.reset(new internal_buffer_type()); std::ios::rdbuf(buf_.get()); open(file_name,mode); } void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out) { if(!buf_->open(file_name,mode | std::ios_base::out)) { this->setstate(std::ios_base::failbit); } else { this->clear(); } } bool is_open() { return buf_->is_open(); } bool is_open() const { return buf_->is_open(); } void close() { if(!buf_->close()) this->setstate(std::ios_base::failbit); else this->clear(); } internal_buffer_type *rdbuf() const { return buf_.get(); } ~basic_ofstream() { buf_->close(); } private: boost::scoped_ptr buf_; }; /// /// \brief Same as std::basic_fstream but accepts UTF-8 strings under Windows /// template > class basic_fstream : public std::basic_iostream { public: typedef basic_filebuf internal_buffer_type; typedef std::basic_iostream internal_stream_type; basic_fstream() : internal_stream_type(0) { buf_.reset(new internal_buffer_type()); std::ios::rdbuf(buf_.get()); } explicit basic_fstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::in) : internal_stream_type(0) { buf_.reset(new internal_buffer_type()); std::ios::rdbuf(buf_.get()); open(file_name,mode); } void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::out) { if(!buf_->open(file_name,mode)) { this->setstate(std::ios_base::failbit); } else { this->clear(); } } bool is_open() { return buf_->is_open(); } bool is_open() const { return buf_->is_open(); } void close() { if(!buf_->close()) this->setstate(std::ios_base::failbit); else this->clear(); } internal_buffer_type *rdbuf() const { return buf_.get(); } ~basic_fstream() { buf_->close(); } private: boost::scoped_ptr buf_; }; /// /// \brief Same as std::filebuf but accepts UTF-8 strings under Windows /// typedef basic_filebuf filebuf; /// /// Same as std::ifstream but accepts UTF-8 strings under Windows /// typedef basic_ifstream ifstream; /// /// Same as std::ofstream but accepts UTF-8 strings under Windows /// typedef basic_ofstream ofstream; /// /// Same as std::fstream but accepts UTF-8 strings under Windows /// typedef basic_fstream fstream; #endif } // nowide } // namespace boost #endif // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 pwiz/libraries/boost_aux/boost/nowide/args.hpp0000664000175100017510000001115712664775723023622 0ustar teamcityteamcity00000000000000// // Copyright (c) 2012 Artyom Beilis (Tonkikh) // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_NOWIDE_ARGS_HPP_INCLUDED #define BOOST_NOWIDE_ARGS_HPP_INCLUDED #include #include #include #ifdef BOOST_WINDOWS #include #endif namespace boost { namespace nowide { #if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_DOXYGEN) class args { public: args(int &,char **&) {} args(int &,char **&,char **&){} ~args() {} }; #else /// /// \brief args is a class that fixes standard main() function arguments and changes them to UTF-8 under /// Microsoft Windows. /// /// The class uses \c GetCommandLineW(), \c CommandLineToArgvW() and \c GetEnvironmentStringsW() /// in order to obtain the information. It does not relates to actual values of argc,argv and env /// under Windows. /// /// It restores the original values in its destructor /// /// \note the class owns the memory of the newly allocated strings /// class args { public: /// /// Fix command line agruments /// args(int &argc,char **&argv) : old_argc_(argc), old_argv_(argv), old_env_(0), old_argc_ptr_(&argc), old_argv_ptr_(&argv), old_env_ptr_(0) { fix_args(argc,argv); } /// /// Fix command line agruments and environment /// args(int &argc,char **&argv,char **&en) : old_argc_(argc), old_argv_(argv), old_env_(en), old_argc_ptr_(&argc), old_argv_ptr_(&argv), old_env_ptr_(&en) { fix_args(argc,argv); fix_env(en); } /// /// Restore original argc,argv,env values, if changed /// ~args() { if(old_argc_ptr_) *old_argc_ptr_ = old_argc_; if(old_argv_ptr_) *old_argv_ptr_ = old_argv_; if(old_env_ptr_) *old_env_ptr_ = old_env_; } private: void fix_args(int &argc,char **&argv) { int wargc; wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(),&wargc); if(!wargv) { argc = 0; static char *dummy = 0; argv = &dummy; return; } try{ args_.resize(wargc+1,0); arg_values_.resize(wargc); for(int i=0;i args_; std::vector arg_values_; stackstring env_; std::vector envp_; int old_argc_; char **old_argv_; char **old_env_; int *old_argc_ptr_; char ***old_argv_ptr_; char ***old_env_ptr_; }; #endif } // nowide } // namespace boost #endif /// // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 pwiz/libraries/boost_aux/boost/nowide/system.hpp0000664000175100017510000000166412664775723024214 0ustar teamcityteamcity00000000000000// // Copyright (c) 2012 Artyom Beilis (Tonkikh) // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_NOWIDE_CSTDLIB_HPP #define BOOST_NOWIDE_CSTDLIB_HPP #include #include #include namespace boost { namespace nowide { #if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_DOXYGEN) using ::system; #else // Windows /// /// Same as std::system but cmd is UTF-8. /// /// If the input is not valid UTF-8, -1 returned and errno set to EINVAL /// inline int system(char const *cmd) { if(!cmd) return _wsystem(0); wstackstring wcmd; if(!wcmd.convert(cmd)) { errno = EINVAL; return -1; } return _wsystem(wcmd.c_str()); } #endif } // nowide } // namespace boost #endif /// // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 pwiz/libraries/boost_aux/boost/nowide/convert.hpp0000664000175100017510000001216112664775723024342 0ustar teamcityteamcity00000000000000// // Copyright (c) 2012 Artyom Beilis (Tonkikh) // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_NOWIDE_CONVERT_H_INCLUDED #define BOOST_NOWIDE_CONVERT_H_INCLUDED #include #include namespace boost { namespace nowide { /// /// \brief Template function that converts a buffer of UTF sequence in range [source_begin,source_end) /// to the output \a buffer of size \a buffer_size. /// /// In case of success a NUL terminated string returned (buffer), otherwise 0 is returned. /// /// If there is not enough room in the buffer or the source sequence contains invalid UTF /// 0 is returned, and the contend of the buffer is undefined. /// template CharOut *basic_convert(CharOut *buffer,size_t buffer_size,CharIn const *source_begin,CharIn const *source_end) { CharOut *rv = buffer; if(buffer_size == 0) return 0; buffer_size --; while(source_begin!=source_end) { using namespace boost::locale::utf; code_point c = utf_traits::template decode(source_begin,source_end); if(c==illegal || c==incomplete) { rv = 0; break; } size_t width = utf_traits::width(c); if(buffer_size < width) { rv=0; break; } buffer = utf_traits::template encode(c,buffer); buffer_size -= width; } *buffer++ = 0; return rv; } /// \cond INTERNAL namespace details { // // wcslen defined only in C99... So we will not use it // template Char const *basic_strend(Char const *s) { while(*s) s++; return s; } } /// \endcond /// /// Convert NUL terminated UTF source string to NUL terminated \a output string of size at /// most output_size (including NUL) /// /// In case of surcess output is returned, if the input sequence is illegal, /// or there is not enough room NULL is returned /// inline char *narrow(char *output,size_t output_size,wchar_t const *source) { return basic_convert(output,output_size,source,details::basic_strend(source)); } /// /// Convert UTF text in range [begin,end) to NUL terminated \a output string of size at /// most output_size (including NUL) /// /// In case of surcess output is returned, if the input sequence is illegal, /// or there is not enough room NULL is returned /// inline char *narrow(char *output,size_t output_size,wchar_t const *begin,wchar_t const *end) { return basic_convert(output,output_size,begin,end); } /// /// Convert NUL terminated UTF source string to NUL terminated \a output string of size at /// most output_size (including NUL) /// /// In case of surcess output is returned, if the input sequence is illegal, /// or there is not enough room NULL is returned /// inline wchar_t *widen(wchar_t *output,size_t output_size,char const *source) { return basic_convert(output,output_size,source,details::basic_strend(source)); } /// /// Convert UTF text in range [begin,end) to NUL terminated \a output string of size at /// most output_size (including NUL) /// /// In case of surcess output is returned, if the input sequence is illegal, /// or there is not enough room NULL is returned /// inline wchar_t *widen(wchar_t *output,size_t output_size,char const *begin,char const *end) { return basic_convert(output,output_size,begin,end); } /// /// Convert between Wide - UTF-16/32 string and UTF-8 string. /// /// boost::locale::conv::conversion_error is thrown in a case of a error /// inline std::string narrow(wchar_t const *s) { return boost::locale::conv::utf_to_utf(s); } /// /// Convert between UTF-8 and UTF-16 string, implemented only on Windows platform /// /// boost::locale::conv::conversion_error is thrown in a case of a error /// inline std::wstring widen(char const *s) { return boost::locale::conv::utf_to_utf(s); } /// /// Convert between Wide - UTF-16/32 string and UTF-8 string /// /// boost::locale::conv::conversion_error is thrown in a case of a error /// inline std::string narrow(std::wstring const &s) { return boost::locale::conv::utf_to_utf(s); } /// /// Convert between UTF-8 and UTF-16 string, implemented only on Windows platform /// /// boost::locale::conv::conversion_error is thrown in a case of a error /// inline std::wstring widen(std::string const &s) { return boost::locale::conv::utf_to_utf(s); } } // nowide } // namespace boost #endif /// // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 pwiz/libraries/boost_aux/boost/nowide/windows.hpp0000664000175100017510000000231112664775723024350 0ustar teamcityteamcity00000000000000// // Copyright (c) 2012 Artyom Beilis (Tonkikh) // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_NOWIDE_WINDOWS_HPP_INCLUDED #define BOOST_NOWIDE_WINDOWS_HPP_INCLUDED #include #ifdef BOOST_NOWIDE_USE_WINDOWS_H #include #else // // These are function prototypes... Allow to to include windows.h // extern "C" { __declspec(dllimport) wchar_t* __stdcall GetEnvironmentStringsW(void); __declspec(dllimport) int __stdcall FreeEnvironmentStringsW(wchar_t *); __declspec(dllimport) wchar_t* __stdcall GetCommandLineW(void); __declspec(dllimport) wchar_t** __stdcall CommandLineToArgvW(wchar_t const *,int *); __declspec(dllimport) unsigned long __stdcall GetLastError(); __declspec(dllimport) void* __stdcall LocalFree(void *); __declspec(dllimport) int __stdcall SetEnvironmentVariableW(wchar_t const *,wchar_t const *); __declspec(dllimport) unsigned long __stdcall GetEnvironmentVariableW(wchar_t const *,wchar_t *,unsigned long); } #endif #endif /// // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 pwiz/libraries/boost_aux/boost/nowide/filebuf.hpp0000664000175100017510000002713012664775723024300 0ustar teamcityteamcity00000000000000// // Copyright (c) 2012 Artyom Beilis (Tonkikh) // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_NOWIDE_FILEBUF_HPP #define BOOST_NOWIDE_FILEBUF_HPP #include #include #include #include #include #include #ifdef BOOST_MSVC # pragma warning(push) # pragma warning(disable : 4996 4244) #endif namespace boost { namespace nowide { #if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_FSTREAM_TESTS) && !defined(BOOST_NOWIDE_DOXYGEN) using std::basic_filebuf; using std::filebuf; #else // Windows /// /// \brief This forward declaration defined the basic_filebuf type. /// /// it is implemented and specialized for CharType = char, it behaves /// implements std::filebuf over standard C I/O /// template > class basic_filebuf; /// /// \brief This is implementation of std::filebuf /// /// it is implemented and specialized for CharType = char, it behaves /// implements std::filebuf over standard C I/O /// template<> class basic_filebuf : public std::basic_streambuf { public: /// /// Creates new filebuf /// basic_filebuf() : buffer_size_(4), buffer_(0), file_(0), own_(true), mode_(std::ios::in | std::ios::out) { setg(0,0,0); setp(0,0); } virtual ~basic_filebuf() { if(file_) { ::fclose(file_); file_ = 0; } if(own_ && buffer_) delete [] buffer_; } /// /// Same as std::filebuf::open but s is UTF-8 string /// basic_filebuf *open(std::string const &s,std::ios_base::openmode mode) { return open(s.c_str(),mode); } /// /// Same as std::filebuf::open but s is UTF-8 string /// basic_filebuf *open(char const *s,std::ios_base::openmode mode) { if(file_) { sync(); ::fclose(file_); file_ = 0; } wchar_t const *smode = get_mode(mode); if(!smode) return 0; wstackstring name; if(!name.convert(s)) return 0; #ifdef BOOST_NOWIDE_FSTREAM_TESTS FILE *f = ::fopen(s,boost::nowide::convert(smode).c_str()); #else FILE *f = ::_wfopen(name.c_str(),smode); #endif if(!f) return 0; file_ = f; return this; } /// /// Same as std::filebuf::close() /// basic_filebuf *close() { bool res = sync() == 0; if(file_) { if(::fclose(file_)!=0) res = false; file_ = 0; } return res ? this : 0; } /// /// Same as std::filebuf::is_open() /// bool is_open() const { return file_ != 0; } private: void make_buffer() { if(buffer_) return; if(buffer_size_ > 0) { buffer_ = new char [buffer_size_]; own_ = true; } } protected: virtual std::streambuf *setbuf(char *s,std::streamsize n) { if(!buffer_ && n>=0) { buffer_ = s; buffer_size_ = n; own_ = false; } return this; } #ifdef BOOST_NOWIDE_DEBUG_FILEBUF void print_buf(char *b,char *p,char *e) { std::cerr << "-- Is Null: " << (b==0) << std::endl;; if(b==0) return; if(e != 0) std::cerr << "-- Total: " << e - b <<" offset from start " << p - b << std::endl; else std::cerr << "-- Total: " << p - b << std::endl; std::cerr << "-- ["; for(char *ptr = b;ptrprint_state(); } ~print_guard() { std::cerr << "Out: " << f << std::endl; self->print_state(); } basic_filebuf *self; char const *f; }; #else #endif int overflow(int c) { #ifdef BOOST_NOWIDE_DEBUG_FILEBUF print_guard g(this,__FUNCTION__); #endif if(!file_) return EOF; if(fixg() < 0) return EOF; size_t n = pptr() - pbase(); if(n > 0) { if(::fwrite(pbase(),1,n,file_) < n) return -1; } if(buffer_size_ > 0) { make_buffer(); setp(buffer_,buffer_+buffer_size_); if(c!=EOF) sputc(c); } else if(c!=EOF) { if(::fputc(c,file_)==EOF) return EOF; } return 0; } int sync() { return (file_ == 0 || overflow(EOF)==EOF || 0 <= fflush(file_)) ? 0 : -1; } int underflow() { #ifdef BOOST_NOWIDE_DEBUG_FILEBUF print_guard g(this,__FUNCTION__); #endif if(!file_) return EOF; if(fixp() < 0) return EOF; if(buffer_size_ == 0) { int c = ::fgetc(file_); if(c==EOF) { return EOF; } last_char_ = c; setg(&last_char_,&last_char_,&last_char_ + 1); return c; } make_buffer(); size_t n = ::fread(buffer_,1,buffer_size_,file_); setg(buffer_,buffer_,buffer_+n); if(n == 0) return EOF; return std::char_traits::to_int_type(*gptr()); } int pbackfail(int) { return pubseekoff(-1,std::ios::cur); } std::streampos seekoff(std::streamoff off, std::ios_base::seekdir seekdir, std::ios_base::openmode /*m*/) { #ifdef BOOST_NOWIDE_DEBUG_FILEBUF print_guard g(this,__FUNCTION__); #endif if(!file_) return EOF; if(fixp() < 0 || fixg() < 0) return EOF; if(seekdir == std::ios_base::cur) { if (::_fseeki64(file_, off, SEEK_CUR) < 0) return EOF; } else if(seekdir == std::ios_base::beg) { if (::_fseeki64(file_, off, SEEK_SET) < 0) return EOF; } else if(seekdir == std::ios_base::end) { if (::_fseeki64(file_, off, SEEK_END) < 0) return EOF; } else return -1; return _ftelli64(file_); } std::streampos seekpos(std::streampos off,std::ios_base::openmode m) { return seekoff(std::streamoff(off),std::ios_base::beg,m); } private: int fixg() { if(gptr()!=egptr()) { std::streamsize off = gptr() - egptr(); setg(0,0,0); if (_fseeki64(file_, off, SEEK_CUR) != 0) return -1; } setg(0,0,0); return 0; } int fixp() { if(pptr()!=0) { int r = sync(); setp(0,0); return r; } return 0; } void reset(FILE *f = 0) { sync(); if(file_) { fclose(file_); file_ = 0; } file_ = f; } static wchar_t const *get_mode(std::ios_base::openmode mode) { // // done according to n2914 table 106 27.9.1.4 // // note can't use switch case as overload operator can't be used // in constant expression if(mode == (std::ios_base::out)) return L"w"; if(mode == (std::ios_base::out | std::ios_base::app)) return L"a"; if(mode == (std::ios_base::app)) return L"a"; if(mode == (std::ios_base::out | std::ios_base::trunc)) return L"w"; if(mode == (std::ios_base::in)) return L"r"; if(mode == (std::ios_base::in | std::ios_base::out)) return L"r+"; if(mode == (std::ios_base::in | std::ios_base::out | std::ios_base::trunc)) return L"w+"; if(mode == (std::ios_base::in | std::ios_base::out | std::ios_base::app)) return L"a+"; if(mode == (std::ios_base::in | std::ios_base::app)) return L"a+"; if(mode == (std::ios_base::binary | std::ios_base::out)) return L"wb"; if(mode == (std::ios_base::binary | std::ios_base::out | std::ios_base::app)) return L"ab"; if(mode == (std::ios_base::binary | std::ios_base::app)) return L"ab"; if(mode == (std::ios_base::binary | std::ios_base::out | std::ios_base::trunc)) return L"wb"; if(mode == (std::ios_base::binary | std::ios_base::in)) return L"rb"; if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out)) return L"r+b"; if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::trunc)) return L"w+b"; if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::app)) return L"a+b"; if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::app)) return L"a+b"; return 0; } size_t buffer_size_; char *buffer_; FILE *file_; bool own_; char last_char_; std::ios::openmode mode_; }; /// /// \brief Convinience typedef /// typedef basic_filebuf filebuf; #endif // windows } // nowide } // namespace boost #ifdef BOOST_MSVC # pragma warning(pop) #endif #endif // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 pwiz/libraries/boost_aux/boost/nowide/stackstring.hpp0000664000175100017510000000760012664775723025220 0ustar teamcityteamcity00000000000000// // Copyright (c) 2012 Artyom Beilis (Tonkikh) // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_NOWIDE_DETAILS_WIDESTR_H_INCLUDED #define BOOST_NOWIDE_DETAILS_WIDESTR_H_INCLUDED #include #include #include namespace boost { namespace nowide { /// /// \brief A class that allows to create a temporary wide or narrow UTF strings from /// wide or narrow UTF source. /// /// It uses on stack buffer of the string is short enough /// and allocated a buffer on the heap if the size of the buffer is too small /// template class basic_stackstring { public: static const size_t buffer_size = BufferSize; typedef CharOut output_char; typedef CharIn input_char; basic_stackstring(basic_stackstring const &other) : mem_buffer_(0) { clear(); if(other.mem_buffer_) { size_t len = 0; while(other.mem_buffer_[len]) len ++; mem_buffer_ = new output_char[len + 1]; memcpy(mem_buffer_,other.mem_buffer_,sizeof(output_char) * (len+1)); } else { memcpy(buffer_,other.buffer_,buffer_size * sizeof(output_char)); } } void swap(basic_stackstring &other) { std::swap(mem_buffer_,other.mem_buffer_); for(size_t i=0;i wstackstring; /// /// Convinience typedef /// typedef basic_stackstring stackstring; /// /// Convinience typedef /// typedef basic_stackstring wshort_stackstring; /// /// Convinience typedef /// typedef basic_stackstring short_stackstring; } // nowide } // namespace boost #endif /// // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 pwiz/libraries/boost_aux/boost/nowide/iostream.hpp0000664000175100017510000000531612664775723024511 0ustar teamcityteamcity00000000000000// // Copyright (c) 2012 Artyom Beilis (Tonkikh) // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_NOWIDE_IOSTREAM_HPP_INCLUDED #define BOOST_NOWIDE_IOSTREAM_HPP_INCLUDED #include #include #include #include #include #ifdef BOOST_MSVC # pragma warning(push) # pragma warning(disable : 4251) #endif namespace boost { namespace nowide { #if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_DOXYGEN) using std::cout; using std::cerr; using std::cin; using std::clog; #else /// \cond INTERNAL namespace details { class console_output_buffer; class console_input_buffer; class BOOST_NOWIDE_DECL winconsole_ostream : public std::ostream { winconsole_ostream(winconsole_ostream const &); void operator=(winconsole_ostream const &); public: winconsole_ostream(int fd); ~winconsole_ostream(); private: boost::scoped_ptr d; }; class BOOST_NOWIDE_DECL winconsole_istream : public std::istream { winconsole_istream(winconsole_istream const &); void operator=(winconsole_istream const &); public: winconsole_istream(); ~winconsole_istream(); private: struct data; boost::scoped_ptr d; }; } // details /// \endcond /// /// \brief Same as std::cin, but uses UTF-8 /// /// Note, the stream is not synchronized with stdio and not affected by std::ios::sync_with_stdio /// extern BOOST_NOWIDE_DECL details::winconsole_istream cin; /// /// \brief Same as std::cout, but uses UTF-8 /// /// Note, the stream is not synchronized with stdio and not affected by std::ios::sync_with_stdio /// extern BOOST_NOWIDE_DECL details::winconsole_ostream cout; /// /// \brief Same as std::cerr, but uses UTF-8 /// /// Note, the stream is not synchronized with stdio and not affected by std::ios::sync_with_stdio /// extern BOOST_NOWIDE_DECL details::winconsole_ostream cerr; /// /// \brief Same as std::clog, but uses UTF-8 /// /// Note, the stream is not synchronized with stdio and not affected by std::ios::sync_with_stdio /// extern BOOST_NOWIDE_DECL details::winconsole_ostream clog; #endif } // nowide } // namespace boost #ifdef BOOST_MSVC # pragma warning(pop) #endif #endif /// // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 pwiz/libraries/boost_aux/boost/nowide/config.hpp0000664000175100017510000000274512664775723024136 0ustar teamcityteamcity00000000000000// // Copyright (c) 2012 Artyom Beilis (Tonkikh) // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_NOWIDE_CONFIG_HPP_INCLUDED #define BOOST_NOWIDE_CONFIG_HPP_INCLUDED #include #ifndef BOOST_SYMBOL_VISIBLE # define BOOST_SYMBOL_VISIBLE #endif #ifdef BOOST_HAS_DECLSPEC # if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_NOWIDE_DYN_LINK) # ifdef BOOST_NOWIDE_SOURCE # define BOOST_NOWIDE_DECL BOOST_SYMBOL_EXPORT # else # define BOOST_NOWIDE_DECL BOOST_SYMBOL_IMPORT # endif // BOOST_NOWIDE_SOURCE # endif // DYN_LINK #endif // BOOST_HAS_DECLSPEC #ifndef BOOST_NOWIDE_DECL # define BOOST_NOWIDE_DECL #endif // // Automatically link to the correct build variant where possible. // #if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_NOWIDE_NO_LIB) && !defined(BOOST_NOWIDE_SOURCE) // // Set the name of our library, this will get undef'ed by auto_link.hpp // once it's done with it: // #define BOOST_LIB_NAME boost_nowide // // If we're importing code from a dll, then tell auto_link.hpp about it: // #if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_NOWIDE_DYN_LINK) # define BOOST_DYN_LINK #endif // // And include the header that does the work: // #include #endif // auto-linking disabled #endif // boost/nowide/config.hpp // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4pwiz/pwiz/data/tradata/DefaultReaderList.cpp0000664000175100017510000001121712664775617023153 0ustar teamcityteamcity00000000000000// // $Id: DefaultReaderList.cpp 6909 2014-11-19 17:18:29Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include "DefaultReaderList.hpp" #include "Serializer_traML.hpp" #include "References.hpp" #include "pwiz/data/tradata/Version.hpp" #include "boost/xpressive/xpressive_dynamic.hpp" namespace bxp = boost::xpressive; namespace pwiz { namespace tradata { namespace { string GetXMLRootElement(const string& fileheader) { const static bxp::sregex e = bxp::sregex::compile("<\\?xml.*?>.*?<([^?!]\\S+?)[\\s>]"); // convert Unicode to ASCII string asciiheader; asciiheader.reserve(fileheader.size()); BOOST_FOREACH(char c, fileheader) { if(c > 0) asciiheader.push_back(c); } bxp::smatch m; if (bxp::regex_search(asciiheader, m, e)) return m[1]; throw runtime_error("[GetXMLRootElement] Root element not found (header is not well-formed XML)"); } string GetXMLRootElement(istream& is) { char buf[513]; is.read(buf, 512); return GetXMLRootElement(buf); } string GetXMLRootElementFromFile(const string& filepath) { pwiz::util::random_access_compressed_ifstream file(filepath.c_str()); if (!file) throw runtime_error("[GetXMLRootElementFromFile] Error opening file"); return GetXMLRootElement(file); } SoftwarePtr getSoftwarePwiz(vector& softwarePtrs) { string version = pwiz::tradata::Version::str(); for (vector::const_iterator it=softwarePtrs.begin(); it!=softwarePtrs.end(); ++it) if ((*it)->hasCVParam(MS_pwiz) && (*it)->version==version) return *it; SoftwarePtr sp(new Software); sp->id = "pwiz_" + version; sp->set(MS_pwiz); sp->version = version; softwarePtrs.push_back(sp); return sp; } void fillInCommonMetadata(const string& filename, TraData& td) { td.cvs = defaultCVList(); SoftwarePtr softwarePwiz = getSoftwarePwiz(td.softwarePtrs); } class Reader_traML : public Reader { public: virtual std::string identify(const std::string& filename, const std::string& head) const { istringstream iss(head); return std::string((type(iss) != Type_Unknown)?getType():""); } virtual void read(const std::string& filename, const std::string& head, TraData& result, int documentIndex = 0) const { if (documentIndex != 0) throw ReaderFail("[Reader_traML::read] multiple documents not supported"); shared_ptr is(new pwiz::util::random_access_compressed_ifstream(filename.c_str())); if (!is.get() || !*is) throw runtime_error(("[Reader_traML::read] Unable to open file " + filename).c_str()); switch (type(*is)) { case Type_traML: { Serializer_traML serializer; serializer.read(is, result); break; } case Type_Unknown: default: { throw runtime_error("[Reader_traML::read] This isn't happening."); } } fillInCommonMetadata(filename, result); } virtual void read(const std::string& filename, const std::string& head, std::vector& results) const { results.push_back(TraDataPtr(new TraData)); read(filename, head, *results.back()); } virtual const char *getType() const {return "TraML";} private: enum Type { Type_traML, Type_Unknown }; Type type(istream& is) const { try { string rootElement = GetXMLRootElement(is); if (rootElement == "TraML") return Type_traML; } catch (runtime_error&) { } return Type_Unknown; } }; } // namespace /// default Reader list PWIZ_API_DECL DefaultReaderList::DefaultReaderList() { push_back(ReaderPtr(new Reader_traML)); } } // namespace tradata } // namespace pwiz pwiz/pwiz/data/tradata/Version.hpp0000664000175100017510000000216412664775617021243 0ustar teamcityteamcity00000000000000// // $Id: Version.hpp 1192 2009-08-14 21:03:26Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PWIZ_TRADATA_VERSION_HPP_ #define _PWIZ_TRADATA_VERSION_HPP_ #include namespace pwiz { namespace tradata { struct Version { static int Major(); static int Minor(); static int Revision(); static std::string str(); static std::string LastModified(); }; } // namespace tradata } // namespace pwiz #endif // _PWIZ_TRADATA_VERSION_HPP_ pwiz/pwiz/data/tradata/Diff.cpp0000664000175100017510000002664412664775617020472 0ustar teamcityteamcity00000000000000// // $Id: Diff.cpp 3706 2012-06-16 15:31:33Z pcbrefugee $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Diff.hpp" #include "TextWriter.hpp" #include "pwiz/utility/misc/Std.hpp" #include namespace pwiz { namespace data { namespace diff_impl { PWIZ_API_DECL void diff(const Contact& a, const Contact& b, Contact& a_b, Contact& b_a, const DiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); diff(a.id, b.id, a_b.id, b_a.id, config); // provide id for context if (!a_b.empty() || !b_a.empty()) { a_b.id = a.id; b_a.id = b.id; } } PWIZ_API_DECL void diff(const Publication& a, const Publication& b, Publication& a_b, Publication& b_a, const DiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); diff(a.id, b.id, a_b.id, b_a.id, config); // provide id for context if (!a_b.empty() || !b_a.empty()) { a_b.id = a.id; b_a.id = b.id; } } PWIZ_API_DECL void diff(const Instrument& a, const Instrument& b, Instrument& a_b, Instrument& b_a, const DiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); diff(a.id, b.id, a_b.id, b_a.id, config); // provide id for context if (!a_b.empty() || !b_a.empty()) { a_b.id = a.id; b_a.id = b.id; } } PWIZ_API_DECL void diff(const Software& a, const Software& b, Software& a_b, Software& b_a, const DiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); diff(a.id, b.id, a_b.id, b_a.id, config); if (!config.ignoreVersions) diff(a.version, b.version, a_b.version, b_a.version, config); // provide id for context if (!a_b.empty() || !b_a.empty()) { a_b.id = a.id; b_a.id = b.id; } } PWIZ_API_DECL void diff(const Protein& a, const Protein& b, Protein& a_b, Protein& b_a, const DiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); diff(a.id, b.id, a_b.id, b_a.id, config); diff(a.sequence, b.sequence, a_b.sequence, b_a.sequence, config); // provide id for context if (!a_b.empty() || !b_a.empty()) { a_b.id = a.id; b_a.id = b.id; } } PWIZ_API_DECL void diff(const RetentionTime& a, const RetentionTime& b, RetentionTime& a_b, RetentionTime& b_a, const DiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); ptr_diff(a.softwarePtr, b.softwarePtr, a_b.softwarePtr, b_a.softwarePtr, config); } PWIZ_API_DECL void diff(const Evidence& a, const Evidence& b, Evidence& a_b, Evidence& b_a, const DiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); } PWIZ_API_DECL void diff(const Modification& a, const Modification& b, Modification& a_b, Modification& b_a, const DiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); diff_integral(a.location, b.location, a_b.location, b_a.location, config); diff_floating(a.monoisotopicMassDelta, b.monoisotopicMassDelta, a_b.monoisotopicMassDelta, b_a.monoisotopicMassDelta, config); diff_floating(a.averageMassDelta, b.averageMassDelta, a_b.averageMassDelta, b_a.averageMassDelta, config); } PWIZ_API_DECL void diff(const Peptide& a, const Peptide& b, Peptide& a_b, Peptide& b_a, const DiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); diff(a.id, b.id, a_b.id, b_a.id, config); diff(a.sequence, b.sequence, a_b.sequence, b_a.sequence, config); vector_diff_deep(a.proteinPtrs, b.proteinPtrs, a_b.proteinPtrs, b_a.proteinPtrs, config); vector_diff_diff(a.modifications, b.modifications, a_b.modifications, b_a.modifications, config); vector_diff_diff(a.retentionTimes, b.retentionTimes, a_b.retentionTimes, b_a.retentionTimes, config); diff(a.evidence, b.evidence, a_b.evidence, b_a.evidence, config); // provide id for context if (!a_b.empty() || !b_a.empty()) { a_b.id = a.id; b_a.id = b.id; } } PWIZ_API_DECL void diff(const Compound& a, const Compound& b, Compound& a_b, Compound& b_a, const DiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); diff(a.id, b.id, a_b.id, b_a.id, config); vector_diff_diff(a.retentionTimes, b.retentionTimes, a_b.retentionTimes, b_a.retentionTimes, config); // provide id for context if (!a_b.empty() || !b_a.empty()) { a_b.id = a.id; b_a.id = b.id; } } PWIZ_API_DECL void diff(const Prediction& a, const Prediction& b, Prediction& a_b, Prediction& b_a, const DiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); ptr_diff(a.contactPtr, b.contactPtr, a_b.contactPtr, b_a.contactPtr, config); ptr_diff(a.softwarePtr, b.softwarePtr, a_b.softwarePtr, b_a.softwarePtr, config); } PWIZ_API_DECL void diff(const Validation& a, const Validation& b, Validation& a_b, Validation& b_a, const DiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); } PWIZ_API_DECL void diff(const Interpretation& a, const Interpretation& b, Interpretation& a_b, Interpretation& b_a, const DiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); } PWIZ_API_DECL void diff(const Configuration& a, const Configuration& b, Configuration& a_b, Configuration& b_a, const DiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); ptr_diff(a.contactPtr, b.contactPtr, a_b.contactPtr, b_a.contactPtr, config); ptr_diff(a.instrumentPtr, b.instrumentPtr, a_b.instrumentPtr, b_a.instrumentPtr, config); vector_diff_diff(a.validations, b.validations, a_b.validations, b_a.validations, config); } PWIZ_API_DECL void diff(const Transition& a, const Transition& b, Transition& a_b, Transition& b_a, const DiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); diff(a.id, b.id, a_b.id, b_a.id, config); diff(a.precursor, b.precursor, a_b.precursor, b_a.precursor, config); diff(a.product, b.product, a_b.product, b_a.product, config); diff(a.prediction, b.prediction, a_b.prediction, b_a.prediction, config); diff(a.retentionTime, b.retentionTime, a_b.retentionTime, b_a.retentionTime, config); ptr_diff(a.peptidePtr, b.peptidePtr, a_b.peptidePtr, b_a.peptidePtr, config); ptr_diff(a.compoundPtr, b.compoundPtr, a_b.compoundPtr, b_a.compoundPtr, config); vector_diff_diff(a.interpretationList, b.interpretationList, a_b.interpretationList, b_a.interpretationList, config); vector_diff_diff(a.configurationList, b.configurationList, a_b.configurationList, b_a.configurationList, config); // provide name for context if (!a_b.empty() || !b_a.empty()) { a_b.id = a.id; b_a.id = b.id; } } PWIZ_API_DECL void diff(const Target& a, const Target& b, Target& a_b, Target& b_a, const DiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); diff(a.id, b.id, a_b.id, b_a.id, config); diff(a.precursor, b.precursor, a_b.precursor, b_a.precursor, config); diff(a.retentionTime, b.retentionTime, a_b.retentionTime, b_a.retentionTime, config); ptr_diff(a.peptidePtr, b.peptidePtr, a_b.peptidePtr, b_a.peptidePtr, config); ptr_diff(a.compoundPtr, b.compoundPtr, a_b.compoundPtr, b_a.compoundPtr, config); vector_diff_diff(a.configurationList, b.configurationList, a_b.configurationList, b_a.configurationList, config); // provide name for context if (!a_b.empty() || !b_a.empty()) { a_b.id = a.id; b_a.id = b.id; } } PWIZ_API_DECL void diff(const TraData& a, const TraData& b, TraData& a_b, TraData& b_a, const DiffConfig& config) { string a_b_version, b_a_version; diff(a.id, b.id, a_b.id, b_a.id, config); if (!config.ignoreVersions) diff(a.version(), b.version(), a_b_version, b_a_version, config); vector_diff_diff(a.cvs, b.cvs, a_b.cvs, b_a.cvs, config); vector_diff_deep(a.contactPtrs, b.contactPtrs, a_b.contactPtrs, b_a.contactPtrs, config); vector_diff_diff(a.publications, b.publications, a_b.publications, b_a.publications, config); vector_diff_deep(a.instrumentPtrs, b.instrumentPtrs, a_b.instrumentPtrs, b_a.instrumentPtrs, config); vector_diff_deep(a.softwarePtrs, b.softwarePtrs, a_b.softwarePtrs, b_a.softwarePtrs, config); vector_diff_deep(a.proteinPtrs, b.proteinPtrs, a_b.proteinPtrs, b_a.proteinPtrs, config); vector_diff_deep(a.peptidePtrs, b.peptidePtrs, a_b.peptidePtrs, b_a.peptidePtrs, config); vector_diff_deep(a.compoundPtrs, b.compoundPtrs, a_b.compoundPtrs, b_a.compoundPtrs, config); vector_diff_diff(a.transitions, b.transitions, a_b.transitions, b_a.transitions, config); vector_diff_diff(a.targets.targetExcludeList, b.targets.targetExcludeList, a_b.targets.targetExcludeList, b_a.targets.targetExcludeList, config); vector_diff_diff(a.targets.targetIncludeList, b.targets.targetIncludeList, a_b.targets.targetIncludeList, b_a.targets.targetIncludeList, config); // provide context if (!a_b.empty() || !b_a.empty() || !a_b_version.empty() || !b_a_version.empty()) { a_b.id = a.id + (a_b_version.empty() ? "" : " (" + a_b_version + ")"); b_a.id = b.id + (b_a_version.empty() ? "" : " (" + b_a_version + ")"); } } } // namespace diff_impl } // namespace data namespace tradata { PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const data::Diff& diff) { using namespace diff_impl; TextWriter write(os,1); if(!diff.a_b.empty() || !diff.b_a.empty()) { os<<"+\n"; write(diff.a_b); os<<"-\n"; write(diff.b_a); } return os; } } // namespace tradata } // namespace pwiz pwiz/pwiz/data/tradata/DefaultReaderList.hpp0000664000175100017510000000230512664775617023156 0ustar teamcityteamcity00000000000000// // $Id: DefaultReaderList.hpp 1195 2009-08-14 22:12:04Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _TRADATA_DEFAULTREADERLIST_HPP_ #define _TRADATA_DEFAULTREADERLIST_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "Reader.hpp" namespace pwiz { namespace tradata { /// default Reader list class PWIZ_API_DECL DefaultReaderList : public ReaderList { public: DefaultReaderList(); }; } // namespace tradata } // namespace pwiz #endif // _TRADATA_DEFAULTREADERLIST_HPP_ pwiz/pwiz/data/tradata/Serializer_traML.hpp0000664000175100017510000000271612664775617023031 0ustar teamcityteamcity00000000000000// // $Id: Serializer_traML.hpp 1639 2009-12-18 23:30:38Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SERIALIZER_TRAML_HPP_ #define _SERIALIZER_TRAML_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "TraData.hpp" namespace pwiz { namespace tradata { /// TraData <-> traML stream serialization class PWIZ_API_DECL Serializer_traML { public: Serializer_traML() {} /// write TraData object to ostream as traML void write(std::ostream& os, const TraData& td) const; /// read in TraData object from a traML istream void read(boost::shared_ptr is, TraData& td) const; private: Serializer_traML(Serializer_traML&); Serializer_traML& operator=(Serializer_traML&); }; } // namespace tradata } // namespace pwiz #endif // _SERIALIZER_TRAML_HPP_ pwiz/pwiz/data/tradata/TraDataFile.hpp0000664000175100017510000000435612664775617021743 0ustar teamcityteamcity00000000000000// // $Id: TraDataFile.hpp 1195 2009-08-14 22:12:04Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _TRADATAFILE_HPP_ #define _TRADATAFILE_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "TraData.hpp" #include "Reader.hpp" namespace pwiz { namespace tradata { /// TraData object plus file I/O struct PWIZ_API_DECL TraDataFile : public TraData { /// constructs TraData object backed by file; /// reader==0 -> use DefaultReaderList TraDataFile(const std::string& filename, const Reader* reader = 0); /// data format for write() enum PWIZ_API_DECL Format {Format_Text, Format_traML}; /// configuration for write() struct PWIZ_API_DECL WriteConfig { Format format; bool gzipped; // if true, file is written as .gz WriteConfig(Format format = Format_traML, bool gzipped = false) : format(format), gzipped(gzipped) {} }; /// static write function for any TraData object; static void write(const TraData& msd, const std::string& filename, const WriteConfig& config = WriteConfig()); /// member write function void write(const std::string& filename, const WriteConfig& config = WriteConfig()); }; PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, TraDataFile::Format format); PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const TraDataFile::WriteConfig& config); } // namespace tradata } // namespace pwiz #endif // _TRADATAFILE_HPP_ pwiz/pwiz/data/tradata/References.cpp0000664000175100017510000001030012664775617021661 0ustar teamcityteamcity00000000000000// // $Id: References.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "References.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace tradata { namespace References { template struct HasID { const string& id_; HasID(const string& id) : id_(id) {} bool operator()(const shared_ptr& objectPtr) { return objectPtr.get() && objectPtr->id == id_; } }; template void resolve(shared_ptr& reference, const vector< shared_ptr >& referentList) { if (!reference.get() || reference->id.empty()) return; typename vector< shared_ptr >::const_iterator it = find_if(referentList.begin(), referentList.end(), HasID(reference->id)); if (it == referentList.end()) { ostringstream oss; oss << "[References::resolve()] Failed to resolve reference.\n" << " object type: " << typeid(object_type).name() << endl << " reference id: " << reference->id << endl << " referent list: " << referentList.size() << endl; for (typename vector< shared_ptr >::const_iterator it=referentList.begin(); it!=referentList.end(); ++it) oss << " " << (*it)->id << endl; throw runtime_error(oss.str().c_str()); } reference = *it; } template void resolve(vector < shared_ptr >& references, const vector< shared_ptr >& referentList) { for (typename vector< shared_ptr >::iterator it=references.begin(); it!=references.end(); ++it) resolve(*it, referentList); } template void resolve(vector& objects, const TraData& msd) { for (typename vector::iterator it=objects.begin(); it!=objects.end(); ++it) resolve(*it, msd); } template void resolve(vector< shared_ptr >& objectPtrs, const TraData& msd) { for (typename vector< shared_ptr >::iterator it=objectPtrs.begin(); it!=objectPtrs.end(); ++it) resolve(**it, msd); } PWIZ_API_DECL void resolve(RetentionTime& retentionTime, const TraData& td) { resolve(retentionTime.softwarePtr, td.softwarePtrs); } PWIZ_API_DECL void resolve(Prediction& prediction, const TraData& td) { resolve(prediction.softwarePtr, td.softwarePtrs); resolve(prediction.contactPtr, td.contactPtrs); } PWIZ_API_DECL void resolve(Configuration& configuration, const TraData& td) { resolve(configuration.contactPtr, td.contactPtrs); resolve(configuration.instrumentPtr, td.instrumentPtrs); } PWIZ_API_DECL void resolve(Peptide& peptide, const TraData& td) { BOOST_FOREACH(ProteinPtr& proteinPtr, peptide.proteinPtrs) resolve(proteinPtr, td.proteinPtrs); } PWIZ_API_DECL void resolve(Transition& transition, const TraData& td) { resolve(transition.peptidePtr, td.peptidePtrs); resolve(transition.compoundPtr, td.compoundPtrs); } PWIZ_API_DECL void resolve(Target& target, const TraData& td) { resolve(target.peptidePtr, td.peptidePtrs); resolve(target.compoundPtr, td.compoundPtrs); } PWIZ_API_DECL void resolve(TraData& td) { resolve(td.peptidePtrs, td); resolve(td.transitions, td); resolve(td.targets.targetExcludeList, td); resolve(td.targets.targetIncludeList, td); } } // namespace References } // namespace tradata } // namespace pwiz pwiz/pwiz/data/tradata/TraDataFile.cpp0000664000175100017510000001111212664775617021722 0ustar teamcityteamcity00000000000000// // $Id: TraDataFile.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "TraDataFile.hpp" #include "TextWriter.hpp" #include "Serializer_traML.hpp" #include "DefaultReaderList.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/minimxml/XMLWriter.hpp" // for charcounter defn #include "boost/iostreams/device/file.hpp" #include "boost/iostreams/filtering_stream.hpp" #include "boost/iostreams/filter/gzip.hpp" namespace pwiz { namespace tradata { using namespace pwiz::util; using boost::shared_ptr; namespace { void readFile(const string& filename, TraData& td, const Reader& reader, const string& head) { if (!reader.accept(filename, head)) throw runtime_error("[TraDataFile::readFile()] Unsupported file format."); reader.read(filename, head, td); } shared_ptr defaultReaderList_; } // namespace PWIZ_API_DECL TraDataFile::TraDataFile(const string& filename, const Reader* reader) { // peek at head of file string head = read_file_header(filename, 512); if (reader) { readFile(filename, *this, *reader, head); } else { if (!defaultReaderList_.get()) defaultReaderList_ = shared_ptr(new DefaultReaderList); readFile(filename, *this, *defaultReaderList_, head); } } PWIZ_API_DECL void TraDataFile::write(const string& filename, const WriteConfig& config) { write(*this, filename, config); } namespace { shared_ptr openFile(const string& filename, bool gzipped) { if (gzipped) { // use boost's filter stack to count outgoing bytes, and gzip them boost::iostreams::filtering_ostream *filt = new boost::iostreams::filtering_ostream(); shared_ptr result(filt); if (filt) { filt->push(pwiz::minimxml::charcounter()); // for counting bytes before compression filt->push(boost::iostreams::gzip_compressor(9)); // max compression filt->push(boost::iostreams::file_sink(filename.c_str(), ios::binary)); } if (!result.get() || !*result || !filt->good()) throw runtime_error(("[TraDataFile::openFile()] Unable to open file " + filename).c_str()); return result; } else { shared_ptr result(new ofstream(filename.c_str(), ios::binary)); if (!result.get() || !*result) throw runtime_error(("[TraDataFile::openFile()] Unable to open file " + filename).c_str()); return result; } } void writeStream(ostream& os, const TraData& td, const TraDataFile::WriteConfig& config) { switch (config.format) { case TraDataFile::Format_Text: { TextWriter(os,0)(td); break; } case TraDataFile::Format_traML: { Serializer_traML serializer; serializer.write(os, td); break; } default: throw runtime_error("[TraDataFile::write()] Format not implemented."); } } } // namespace PWIZ_API_DECL void TraDataFile::write(const TraData& td, const string& filename, const WriteConfig& config) { shared_ptr os = openFile(filename,config.gzipped); writeStream(*os, td, config); } PWIZ_API_DECL ostream& operator<<(ostream& os, TraDataFile::Format format) { switch (format) { case TraDataFile::Format_Text: os << "Text"; return os; case TraDataFile::Format_traML: os << "traML"; return os; default: os << "Unknown"; return os; } } PWIZ_API_DECL ostream& operator<<(ostream& os, const TraDataFile::WriteConfig& config) { os << config.format; return os; } } // namespace tradata } // namespace pwiz pwiz/pwiz/data/tradata/Version.cpp0000664000175100017510000000266612664776103021234 0ustar teamcityteamcity00000000000000// This file was generated by the "svnrev" utility // You should not modify it manually, as it may be re-generated. // // $Revision: 9248 $ // $Date: 2015-12-30 $ // // Licensed under the Apache License, Version 2.0 (the License); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an AS IS BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "Version.hpp" #include #ifdef PWIZ_USER_VERSION_INFO_H // in case you need to add any info version of your own #include PWIZ_USER_VERSION_INFO_H // must define PWIZ_USER_VERSION_INFO_H_STR for use below #endif namespace pwiz { namespace tradata { int Version::Major() {return 3;} int Version::Minor() {return 0;} int Version::Revision() {return 9248;} std::string Version::LastModified() {return "2015-12-30";} std::string Version::str() { std::ostringstream v; v << Major() << '.' << Minor() << '.' << Revision(); #ifdef PWIZ_USER_VERSION_INFO_H v << " (" << PWIZ_USER_VERSION_INFO_H_STR << ")"; #endif return v.str(); } } // namespace tradata } // namespace pwiz pwiz/pwiz/data/tradata/ReferencesTest.cpp0000664000175100017510000000763712664775617022544 0ustar teamcityteamcity00000000000000// // $Id: ReferencesTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "References.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/minimxml/XMLWriter.hpp" using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::tradata; ostream* os_ = 0; void testTransition() { if (os_) *os_ << "testTransition()\n"; Transition transition; transition.peptidePtr = PeptidePtr(new Peptide("pep1")); transition.peptidePtr->proteinPtrs.push_back(ProteinPtr(new Protein("prot1"))); transition.compoundPtr = CompoundPtr(new Compound("cmp1")); TraData td; td.peptidePtrs.push_back(PeptidePtr(new Peptide("pep1"))); td.peptidePtrs.back()->set(MS_theoretical_mass, 123); td.peptidePtrs.back()->proteinPtrs.push_back(ProteinPtr(new Protein("prot1"))); td.peptidePtrs.back()->proteinPtrs.back()->sequence = "ABCD"; td.compoundPtrs.push_back(CompoundPtr(new Compound("cmp1"))); td.compoundPtrs.back()->retentionTimes.push_back(RetentionTime()); td.compoundPtrs.back()->retentionTimes.back().set(MS_peak_intensity, 123); References::resolve(transition, td); unit_assert(transition.peptidePtr->cvParam(MS_theoretical_mass).value == "123"); unit_assert(transition.peptidePtr->proteinPtrs.back().get()); unit_assert(transition.peptidePtr->proteinPtrs.back()->sequence == "ABCD"); unit_assert(!transition.compoundPtr->retentionTimes.empty()); unit_assert(transition.compoundPtr->retentionTimes.back().cvParam(MS_peak_intensity).value == "123"); } void testTraData() { TraData td; td.proteinPtrs.push_back(ProteinPtr(new Protein("prot1"))); td.proteinPtrs.back()->sequence = "ABCD"; td.peptidePtrs.push_back(PeptidePtr(new Peptide("pep1"))); td.peptidePtrs.back()->set(MS_theoretical_mass, 123); td.peptidePtrs.back()->proteinPtrs.push_back(ProteinPtr(new Protein("prot1"))); td.compoundPtrs.push_back(CompoundPtr(new Compound("cmp1"))); td.compoundPtrs.back()->retentionTimes.push_back(RetentionTime()); td.compoundPtrs.back()->retentionTimes.back().set(MS_peak_intensity, 123); td.transitions.push_back(Transition()); Transition& transition = td.transitions.back(); transition.peptidePtr = PeptidePtr(new Peptide("pep1")); transition.peptidePtr->proteinPtrs.push_back(ProteinPtr(new Protein("prot1"))); transition.compoundPtr = CompoundPtr(new Compound("cmp1")); References::resolve(td); unit_assert(transition.peptidePtr->cvParam(MS_theoretical_mass).value == "123"); unit_assert(transition.peptidePtr->proteinPtrs.back().get()); unit_assert(transition.peptidePtr->proteinPtrs.back()->sequence == "ABCD"); unit_assert(!transition.compoundPtr->retentionTimes.empty()); unit_assert(transition.compoundPtr->retentionTimes.back().cvParam(MS_peak_intensity).value == "123"); } void test() { testTransition(); testTraData(); } int main(int argc, char* argv[]) { TEST_PROLOG_EX(argc, argv, "_TraData") try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/tradata/DiffTest.cpp0000664000175100017510000002456212664775617021327 0ustar teamcityteamcity00000000000000// // $Id: DiffTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "Diff.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::data; using namespace pwiz::tradata; ostream* os_ = 0; void testContact() { if (os_) *os_ << "testContact()\n"; Contact a, b; a.userParams.push_back(UserParam("common")); b.userParams.push_back(UserParam("common")); a.cvParams.push_back(MS_m_z); b.cvParams.push_back(MS_m_z); a.id = b.id = "foo"; Diff diff(a, b); unit_assert(!diff); a.id = "bar"; diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testInstrument() { if (os_) *os_ << "testInstrument()\n"; Instrument a, b; a.userParams.push_back(UserParam("common")); b.userParams.push_back(UserParam("common")); a.cvParams.push_back(MS_m_z); b.cvParams.push_back(MS_m_z); a.id = b.id = "foo"; Diff diff(a, b); unit_assert(!diff); a.id = "bar"; diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testConfiguration() { if (os_) *os_ << "testConfiguration()\n"; Configuration a, b; a.userParams.push_back(UserParam("common")); b.userParams.push_back(UserParam("common")); a.cvParams.push_back(MS_m_z); b.cvParams.push_back(MS_m_z); a.instrumentPtr = InstrumentPtr(new Instrument("common")); b.instrumentPtr = InstrumentPtr(new Instrument("common")); a.contactPtr = ContactPtr(new Contact("common")); b.contactPtr = ContactPtr(new Contact("common")); Diff diff(a, b); unit_assert(!diff); a.instrumentPtr->id = "different"; diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testPrediction() { if (os_) *os_ << "testPrediction()\n"; Prediction a, b; a.userParams.push_back(UserParam("common")); b.userParams.push_back(UserParam("common")); a.cvParams.push_back(MS_m_z); b.cvParams.push_back(MS_m_z); a.contactPtr = ContactPtr(new Contact("common")); b.contactPtr = ContactPtr(new Contact("common")); Diff diff(a, b); unit_assert(!diff); a.softwarePtr = SoftwarePtr(new Software("different")); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testValidation() { if (os_) *os_ << "testValidation()\n"; Validation a, b; a.userParams.push_back(UserParam("common")); b.userParams.push_back(UserParam("common")); a.cvParams.push_back(MS_m_z); b.cvParams.push_back(MS_m_z); Diff diff(a, b); unit_assert(!diff); b.set(MS_peak_intensity, 42); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testEvidence() { if (os_) *os_ << "testEvidence()\n"; Evidence a, b; a.userParams.push_back(UserParam("common")); b.userParams.push_back(UserParam("common")); a.cvParams.push_back(MS_m_z); b.cvParams.push_back(MS_m_z); Diff diff(a, b); unit_assert(!diff); a.set(MS_peak_intensity, 42); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testRetentionTime() { if (os_) *os_ << "testRetentionTime()\n"; RetentionTime a, b; a.userParams.push_back(UserParam("common")); b.userParams.push_back(UserParam("common")); a.cvParams.push_back(MS_m_z); b.cvParams.push_back(MS_m_z); Diff diff(a, b); unit_assert(!diff); a.set(MS_peak_intensity, 42); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testProtein() { if (os_) *os_ << "testProtein()\n"; Protein a, b; a.userParams.push_back(UserParam("common")); b.userParams.push_back(UserParam("common")); a.cvParams.push_back(MS_m_z); b.cvParams.push_back(MS_m_z); a.sequence = b.sequence = "ABCD"; a.id = b.id = "foo"; Diff diff(a, b); unit_assert(!diff); a.sequence = "DCBA"; diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testModification() { if (os_) *os_ << "testModification()\n"; Modification a, b; a.location = b.location = 7; a.monoisotopicMassDelta = b.monoisotopicMassDelta = 42; a.averageMassDelta = b.averageMassDelta = 42; Diff diff(a, b); unit_assert(!diff); a.monoisotopicMassDelta = 84; diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testPeptide() { if (os_) *os_ << "testPeptide()\n"; Peptide a, b; a.userParams.push_back(UserParam("common")); b.userParams.push_back(UserParam("common")); a.cvParams.push_back(MS_m_z); b.cvParams.push_back(MS_m_z); a.evidence.set(MS_peak_intensity, 42); b.evidence.set(MS_peak_intensity, 42); a.sequence = b.sequence = "ABCD"; a.id = b.id = "foo"; Diff diff(a, b); unit_assert(!diff); a.sequence = "DCBA"; diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testCompound() { if (os_) *os_ << "testCompound()\n"; Compound a, b; a.userParams.push_back(UserParam("common")); b.userParams.push_back(UserParam("common")); a.cvParams.push_back(MS_m_z); b.cvParams.push_back(MS_m_z); a.id = b.id = "foo"; Diff diff(a, b); unit_assert(!diff); b.retentionTimes.push_back(RetentionTime()); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testTransition() { if (os_) *os_ << "testTransition()\n"; Transition a, b; a.id = b.id = "T1"; a.precursor.set(MS_selected_ion_m_z, 123.45); b.precursor.set(MS_selected_ion_m_z, 123.45); a.product.set(MS_selected_ion_m_z, 456.78); b.product.set(MS_selected_ion_m_z, 456.78); Validation v; v.set(MS_peak_intensity, 42); Configuration c; c.validations.push_back(v); a.configurationList.push_back(c); b.configurationList.push_back(c); a.peptidePtr = PeptidePtr(new Peptide("common")); b.peptidePtr = PeptidePtr(new Peptide("common")); Diff diff(a, b); unit_assert(!diff); b.peptidePtr->sequence = "different"; diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testTarget() { if (os_) *os_ << "testTarget()\n"; Target a, b; a.id = b.id = "T1"; a.precursor.set(MS_selected_ion_m_z, 123.45); b.precursor.set(MS_selected_ion_m_z, 123.45); Validation v; v.set(MS_peak_intensity, 42); Configuration c; c.validations.push_back(v); a.configurationList.push_back(c); b.configurationList.push_back(c); a.peptidePtr = PeptidePtr(new Peptide("common")); b.peptidePtr = PeptidePtr(new Peptide("common")); Diff diff(a, b); unit_assert(!diff); b.peptidePtr->sequence = "different"; diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testSoftware() { if (os_) *os_ << "testSoftware()\n"; Software a, b; a.id = "msdata"; a.version = "4.20"; a.set(MS_ionization_type); b = a; Diff diff(a, b); unit_assert(!diff); b.version = "4.21"; diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } /*void testPrecursor() { if (os_) *os_ << "testPrecursor()\n"; Precursor a, b; a.mz = 420; a.charge = 2; b = a; Diff diff(a, b); unit_assert(!diff); b.charge = 3; diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.mz == 0); unit_assert(diff.a_b.charge == -1); unit_assert(diff.b_a.mz == 0); unit_assert(diff.b_a.charge == 1); } void testProduct() { if (os_) *os_ << "testProduct()\n"; Product a, b; a.mz = 420; a.charge = 2; b = a; Diff diff(a, b); unit_assert(!diff); b.charge = 3; diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.mz == 0); unit_assert(diff.a_b.charge == -1); unit_assert(diff.b_a.mz == 0); unit_assert(diff.b_a.charge == 1); }*/ void testTraData() { if (os_) *os_ << "testTraData()\n"; TraData a, b; Diff diff(a, b); unit_assert(!diff); a.cvs.push_back(CV()); b.softwarePtrs.push_back(SoftwarePtr(new Software("software"))); Publication pub; pub.id = "PUBMED1"; pub.set(UO_dalton, 123); a.publications.push_back(pub); b.publications.push_back(pub); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.cvs.size() == 1); unit_assert(diff.b_a.cvs.empty()); unit_assert(diff.a_b.softwarePtrs.empty()); unit_assert(!diff.b_a.softwarePtrs.empty()); unit_assert(diff.a_b.publications.empty()); unit_assert(diff.b_a.publications.empty()); } void test() { testContact(); testInstrument(); testSoftware(); testConfiguration(); testPrediction(); testValidation(); testEvidence(); testRetentionTime(); testProtein(); testModification(); testPeptide(); testCompound(); testTransition(); testTarget(); //testPrecursor(); //testProduct(); testTraData(); } int main(int argc, char* argv[]) { TEST_PROLOG_EX(argc, argv, "_TraData") try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/tradata/TextWriter.hpp0000664000175100017510000002422712664775617021743 0ustar teamcityteamcity00000000000000// // $Id: TextWriter.hpp 1605 2009-12-09 23:50:27Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _TRADATA_TEXTWRITER_HPP_ #define _TRADATA_TEXTWRITER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "TraData.hpp" #include "boost/lexical_cast.hpp" #include #include #include namespace pwiz { namespace tradata { using boost::lexical_cast; using std::string; class PWIZ_API_DECL TextWriter { public: TextWriter(std::ostream& os, int depth = 0) : os_(os), depth_(depth), indent_(depth*2, ' ') {} TextWriter child() {return TextWriter(os_, depth_+1);} TextWriter& operator()(const std::string& text) { os_ << indent_ << text << std::endl; return *this; } TextWriter& operator()(const CVParam& cvParam) { os_ << indent_ << "cvParam: " << cvTermInfo(cvParam.cvid).name; if (!cvParam.value.empty()) os_ << ", " << cvParam.value; if (cvParam.units != CVID_Unknown) os_ << ", " << cvParam.unitsName(); os_ << std::endl; return *this; } TextWriter& operator()(const UserParam& userParam) { os_ << indent_ << "userParam: " << userParam.name; if (!userParam.value.empty()) os_ << ", " << userParam.value; if (!userParam.type.empty()) os_ << ", " << userParam.type; if (userParam.units != CVID_Unknown) os_ << ", " << cvTermInfo(userParam.units).name; os_ << std::endl; return *this; } template TextWriter& operator()(const std::string& label, const std::vector& v) { (*this)(label); for_each(v.begin(), v.end(), child()); return *this; } template TextWriter& operator()(const std::string& label, const object_type& v) { (*this)(label)(boost::lexical_cast(v)); return *this; } TextWriter& operator()(const TraData& msd) { (*this)("tradata:"); child()("version: " + msd.version()); if (!msd.cvs.empty()) child()("cvList: ", msd.cvs); if (!msd.contactPtrs.empty()) child()("contactList: ", msd.contactPtrs); if (!msd.publications.empty()) child()("publicationList: ", msd.publications); if (!msd.instrumentPtrs.empty()) child()("instrumentList: ", msd.instrumentPtrs); if (!msd.softwarePtrs.empty()) child()("softwareList: ", msd.softwarePtrs); if (!msd.proteinPtrs.empty()) child()("proteinList: ", msd.proteinPtrs); if (!msd.peptidePtrs.empty()) child()("peptideList: ", msd.peptidePtrs); if (!msd.compoundPtrs.empty()) child()("compoundList: ", msd.compoundPtrs); if (!msd.transitions.empty()) child()("transitionList: ", msd.transitions); if (!msd.targets.empty()) child()(msd.targets); return *this; } TextWriter& operator()(const CV& cv) { (*this)("cv:"); child() ("id: " + cv.id) ("fullName: " + cv.fullName) ("version: " + cv.version) ("URI: " + cv.URI); return *this; } TextWriter& operator()(const ParamContainer& paramContainer) { for_each(paramContainer.cvParams.begin(), paramContainer.cvParams.end(), *this); for_each(paramContainer.userParams.begin(), paramContainer.userParams.end(), *this); return *this; } TextWriter& operator()(const Publication& publication) { (*this)("publication:"); child() ("id: " + publication.id) (static_cast(publication)); return *this; } TextWriter& operator()(const Software& software) { (*this)("software:"); child() ("id: " + software.id) ("version: " + software.version) (static_cast(software)); return *this; } TextWriter& operator()(const Contact& contact) { (*this)("contact:"); child()(static_cast(contact)); return *this; } TextWriter& operator()(const RetentionTime& retentionTime) { (*this)("retentionTime:"); child()(static_cast(retentionTime)); if (retentionTime.softwarePtr.get() && !retentionTime.softwarePtr->empty()) child()("softwareRef: " + retentionTime.softwarePtr->id); return *this; } TextWriter& operator()(const Prediction& prediction) { (*this)("prediction:"); child()(static_cast(prediction)); return *this; } TextWriter& operator()(const Evidence& evidence) { (*this)("evidence:"); child()(static_cast(evidence)); return *this; } TextWriter& operator()(const Validation& validation) { (*this)("validation:"); child()(static_cast(validation)); return *this; } TextWriter& operator()(const Protein& protein) { (*this)("protein:"); child()("id: " + protein.id) ("sequence: " + protein.sequence); child()(static_cast(protein)); return *this; } TextWriter& operator()(const Modification& modification) { (*this)("modification:"); child()("location: ", lexical_cast(modification.location)) ("monoisotopicMassDelta: " + lexical_cast(modification.monoisotopicMassDelta)) ("averageMassDelta: " + lexical_cast(modification.averageMassDelta)); child()(static_cast(modification)); return *this; } TextWriter& operator()(const Peptide& peptide) { (*this)("peptide:"); child()("id: " + peptide.id) ("sequence: " + peptide.sequence) (peptide.evidence); if (!peptide.proteinPtrs.empty()) child()("proteinRefs:", peptide.proteinPtrs); if (!peptide.modifications.empty()) child()("modifications:", peptide.modifications); if (!peptide.retentionTimes.empty()) child()("retentionTimes:", peptide.retentionTimes); child()(static_cast(peptide)); return *this; } TextWriter& operator()(const Compound& compound) { (*this)("compound:"); child()("id: " + compound.id) ("retentionTimes:", compound.retentionTimes); child()(static_cast(compound)); return *this; } TextWriter& operator()(const Precursor& precursor) { (*this)("precursor:"); child()(static_cast(precursor)); return *this; } TextWriter& operator()(const Product& product) { (*this)("product:"); child()(static_cast(product)); return *this; } TextWriter& operator()(const Transition& transition) { (*this)("transition:"); child()("id: ", transition.id); if (!transition.precursor.empty()) child()(transition.precursor); if (!transition.product.empty()) child()(transition.product); if (!transition.prediction.empty()) child()(transition.prediction); if (!transition.interpretationList.empty()) child()("interpretationList: ", transition.interpretationList); if (!transition.configurationList.empty()) child()("configurationList: ", transition.configurationList); if (transition.peptidePtr.get() && !transition.peptidePtr->empty()) child()("peptideRef: " + transition.peptidePtr->id); if (transition.compoundPtr.get() && !transition.compoundPtr->empty()) child()("compoundRef: " + transition.compoundPtr->id); return *this; } TextWriter& operator()(const Target& target) { (*this)("target:"); child()("id: ", target.id); if (!target.precursor.empty()) child()(target.precursor); if (!target.configurationList.empty()) child()("configurationList: ", target.configurationList); if (target.peptidePtr.get() && !target.peptidePtr->empty()) child()("peptideRef: " + target.peptidePtr->id); if (target.compoundPtr.get() && !target.compoundPtr->empty()) child()("compoundRef: " + target.compoundPtr->id); return *this; } TextWriter& operator()(const TargetList& targetList) { (*this)("targetList:"); child()(static_cast(targetList)); if (!targetList.targetExcludeList.empty()) child()("targetExcludeList: ", targetList.targetExcludeList); if (!targetList.targetIncludeList.empty()) child()("targetIncludeList: ", targetList.targetIncludeList); return *this; } // if no other overload matches, assume the object is a shared_ptr of a valid overloaded type template TextWriter& operator()(const boost::shared_ptr& p) { return p.get() ? (*this)(*p) : *this; } private: std::ostream& os_; int depth_; std::string indent_; }; } // namespace tradata } // namespace pwiz #endif // _TRADATA_TEXTWRITER_HPP_ pwiz/pwiz/data/tradata/Serializer_traML.cpp0000664000175100017510000000325212664775617023020 0ustar teamcityteamcity00000000000000// // $Id: Serializer_traML.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Serializer_traML.hpp" #include "IO.hpp" #include "pwiz/utility/minimxml/XMLWriter.hpp" #include "pwiz/utility/minimxml/SAXParser.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace tradata { using minimxml::XMLWriter; using boost::iostreams::stream_offset; using namespace pwiz::minimxml; void Serializer_traML::write(ostream& os, const TraData& td) const { // instantiate XMLWriter XMLWriter::Config xmlConfig; XMLWriter xmlWriter(os, xmlConfig); string xmlData = "version=\"1.0\" encoding=\"ISO-8859-1\""; xmlWriter.processingInstruction("xml", xmlData); IO::write(xmlWriter, td); } void Serializer_traML::read(shared_ptr is, TraData& td) const { if (!is.get() || !*is) throw runtime_error("[Serializer_traML::read()] Bad istream."); is->seekg(0); IO::read(*is, td); } } // namespace tradata } // namespace pwiz pwiz/pwiz/data/tradata/Reader.hpp0000664000175100017510000001506212664775617021021 0ustar teamcityteamcity00000000000000// // $Id: Reader.hpp 1195 2009-08-14 22:12:04Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _TRADATA_READER_HPP_ #define _TRADATA_READER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "TraData.hpp" #include #include namespace pwiz { namespace tradata { /// interface for file readers class PWIZ_API_DECL Reader { public: /// return true iff Reader recognizes the file as one it should handle /// that's not to say one it CAN handle, necessarily, as in Thermo on linux, /// see comment for identify() below bool accept(const std::string& filename, const std::string& head) const { return (identify(filename,head).length() != 0); } /// return file type iff Reader recognizes the file, else empty; /// note: for formats requiring a 3rd party DLL identify() should /// return true if it recognized the format, even though reading /// may fail if the 3rd party DLL isn't actually present /// Reader may filter based on filename and/or head of the file virtual std::string identify(const std::string& filename, const std::string& head) const = 0; /// fill in the TraData structure from the first (or only) sample virtual void read(const std::string& filename, const std::string& head, TraData& result, int runIndex = 0) const = 0; /// fill in a vector of TraData structures; provides support for multi-run input files virtual void read(const std::string& filename, const std::string& head, std::vector& results) const = 0; /// fill in a vector of MSData.Id values; provides support for multi-run input files /*virtual void readIds(const std::string& filename, const std::string& head, std::vector& dataIds) const;*/ virtual const char *getType() const = 0; // what kind of reader are you? virtual ~Reader(){} }; class PWIZ_API_DECL ReaderFail : public std::runtime_error // reader failure exception { public: ReaderFail(const std::string& error) : std::runtime_error(("[ReaderFail] " + error).c_str()), error_(error) {} virtual const std::string& error() const {return error_;} virtual ~ReaderFail() throw() {} private: std::string error_; }; typedef boost::shared_ptr ReaderPtr; /// /// Reader container (composite pattern). /// /// The template get() gives access to child Readers by type, to facilitate /// Reader-specific configuration at runtime. /// class PWIZ_API_DECL ReaderList : public Reader, public std::vector { public: /// returns child name iff some child identifies, else empty string virtual std::string identify(const std::string& filename) const; /// returns child name iff some child identifies, else empty string virtual std::string identify(const std::string& filename, const std::string& head) const; /// delegates to first child that identifies virtual void read(const std::string& filename, TraData& result, int runIndex = 0) const; /// delegates to first child that identifies virtual void read(const std::string& filename, const std::string& head, TraData& result, int runIndex = 0) const; /// delegates to first child that identifies; /// provides support for multi-run input files virtual void read(const std::string& filename, std::vector& results) const; /// delegates to first child that identifies; /// provides support for multi-run input files virtual void read(const std::string& filename, const std::string& head, std::vector& results) const; /// delegates to first child that identifies; /// provides support for multi-run input files /*virtual void readIds(const std::string& filename, std::vector& results) const;*/ /// delegates to first child that identifies; /// provides support for multi-run input files /*virtual void readIds(const std::string& filename, const std::string& head, std::vector& results) const;*/ /// appends all of the rhs operand's Readers to the list ReaderList& operator +=(const ReaderList& rhs); /// appends the rhs Reader to the list ReaderList& operator +=(const ReaderPtr& rhs); /// returns a concatenated list of all the Readers from the lhs and rhs operands ReaderList operator +(const ReaderList& rhs) const; /// returns a concatenated list of all the Readers from the lhs and rhs operands ReaderList operator +(const ReaderPtr& rhs) const; /// returns pointer to Reader of the specified type template reader_type* get() { for (iterator it=begin(); it!=end(); ++it) { reader_type* p = dynamic_cast(it->get()); if (p) return p; } return 0; } /// returns const pointer to Reader of the specified type template const reader_type* get() const { return const_cast(this)->get(); } virtual const char *getType() const {return "ReaderList";} // satisfy inheritance }; /// returns a list containing the lhs and rhs as readers PWIZ_API_DECL ReaderList operator +(const ReaderPtr& lhs, const ReaderPtr& rhs); } // namespace tradata } // namespace pwiz #endif // _TRADATA_READER_HPP_ pwiz/pwiz/data/tradata/Diff.hpp0000664000175100017510000001050212664775617020461 0ustar teamcityteamcity00000000000000// // $Id: Diff.hpp 1656 2009-12-30 20:54:17Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _TRADATA_DIFF_HPP_ #define _TRADATA_DIFF_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "TraData.hpp" namespace pwiz { namespace tradata { struct DiffConfig; } } namespace pwiz { namespace data { namespace diff_impl { using namespace tradata; PWIZ_API_DECL void diff(const Contact& a, const Contact& b, Contact& a_b, Contact& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Publication& a, const Publication& b, Publication& a_b, Publication& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const RetentionTime& a, const RetentionTime& b, RetentionTime& a_b, RetentionTime& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Prediction& a, const Prediction& b, Prediction& a_b, Prediction& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Evidence& a, const Evidence& b, Evidence& a_b, Evidence& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Validation& a, const Validation& b, Validation& a_b, Validation& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Instrument& a, const Instrument& b, Instrument& a_b, Instrument& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Configuration& a, const Configuration& b, Configuration& a_b, Configuration& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Software& a, const Software& b, Software& a_b, Software& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Interpretation& a, const Interpretation& b, Interpretation& a_b, Interpretation& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Protein& a, const Protein& b, Protein& a_b, Protein& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Modification& a, const Modification& b, Modification& a_b, Modification& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Peptide& a, const Peptide& b, Peptide& a_b, Peptide& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Compound& a, const Compound& b, Compound& a_b, Compound& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Transition& a, const Transition& b, Transition& a_b, Transition& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Target& a, const Target& b, Target& a_b, Target& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const TraData& a, const TraData& b, TraData& a_b, TraData& b_a, const DiffConfig& config); } // namespace diff_impl } // namespace data } // namespace pwiz // this include must come after the above declarations or GCC won't see them #include "pwiz/data/common/diff_std.hpp" namespace pwiz { namespace tradata { /// configuration struct for diffs struct PWIZ_API_DECL DiffConfig : public pwiz::data::BaseDiffConfig { DiffConfig() : BaseDiffConfig(1e-6) {} }; PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const data::Diff& diff); } // namespace tradata } // namespace pwiz #endif // _TRADATA_DIFF_HPP_ pwiz/pwiz/data/tradata/Reader.cpp0000664000175100017510000001051212664775617021007 0ustar teamcityteamcity00000000000000// // $Id: Reader.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Reader.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace tradata { using namespace pwiz::util; // default implementation; most Readers don't need to worry about multi-run input files /*PWIZ_API_DECL void Reader::readIds(const string& filename, const string& head, vector& results) const { TraData data; read(filename, head, data); results.push_back(data.id); }*/ PWIZ_API_DECL std::string ReaderList::identify(const string& filename) const { return identify(filename, read_file_header(filename, 512)); } PWIZ_API_DECL std::string ReaderList::identify(const string& filename, const string& head) const { std::string result; for (const_iterator it=begin(); it!=end(); ++it) { result = (*it)->identify(filename, head); if (result.length()) { break; } } return result; } PWIZ_API_DECL void ReaderList::read(const string& filename, TraData& result, int sampleIndex /* = 0 */) const { read(filename, read_file_header(filename, 512), result, sampleIndex); } PWIZ_API_DECL void ReaderList::read(const string& filename, const string& head, TraData& result, int sampleIndex /* = 0 */) const { for (const_iterator it=begin(); it!=end(); ++it) if ((*it)->accept(filename, head)) { (*it)->read(filename, head, result, sampleIndex); return; } throw ReaderFail((" don't know how to read " + filename).c_str()); } PWIZ_API_DECL void ReaderList::read(const string& filename, vector& results) const { read(filename, read_file_header(filename, 512), results); } PWIZ_API_DECL void ReaderList::read(const string& filename, const string& head, vector& results) const { for (const_iterator it=begin(); it!=end(); ++it) if ((*it)->accept(filename, head)) { (*it)->read(filename, head, results); return; } throw ReaderFail((" don't know how to read " + filename).c_str()); } /*PWIZ_API_DECL void ReaderList::readIds(const string& filename, vector& results) const { readIds(filename, read_file_header(filename, 512), results); } PWIZ_API_DECL void ReaderList::readIds(const string& filename, const string& head, vector& results) const { for (const_iterator it=begin(); it!=end(); ++it) if ((*it)->accept(filename, head)) { (*it)->readIds(filename, head, results); return; } throw ReaderFail((" don't know how to read " + filename).c_str()); }*/ PWIZ_API_DECL ReaderList& ReaderList::operator +=(const ReaderList& rhs) { insert(end(), rhs.begin(), rhs.end()); return *this; } PWIZ_API_DECL ReaderList& ReaderList::operator +=(const ReaderPtr& rhs) { push_back(rhs); return *this; } PWIZ_API_DECL ReaderList ReaderList::operator +(const ReaderList& rhs) const { ReaderList readerList(*this); readerList += rhs; return readerList; } PWIZ_API_DECL ReaderList ReaderList::operator +(const ReaderPtr& rhs) const { ReaderList readerList(*this); readerList += rhs; return readerList; } PWIZ_API_DECL ReaderList operator +(const ReaderPtr& lhs, const ReaderPtr& rhs) { ReaderList readerList; readerList.push_back(lhs); readerList.push_back(rhs); return readerList; } } // namespace tradata } // namespace pwiz pwiz/pwiz/data/tradata/IO.cpp0000664000175100017510000012704112664775617020122 0ustar teamcityteamcity00000000000000// // $Id: IO.cpp 3397 2012-03-19 19:20:57Z pcbrefugee $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "IO.hpp" #include "References.hpp" #include "pwiz/utility/minimxml/SAXParser.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace tradata { namespace IO { using namespace minimxml; using namespace minimxml::SAXParser; //using namespace util; static const int TRAML_VERSION_PRERELEASE = 0; static const int TRAML_VERSION_1_0 = 1; template void writeList(minimxml::XMLWriter& writer, const vector& objects, const string& label, bool writeCountAttribute = false) { if (!objects.empty()) { XMLWriter::Attributes attributes; if (writeCountAttribute) attributes.push_back(make_pair("count", lexical_cast(objects.size()))); writer.startElement(label, attributes); for (typename vector::const_iterator it=objects.begin(); it!=objects.end(); ++it) write(writer, *it); writer.endElement(); } } template void writePtrList(minimxml::XMLWriter& writer, const vector& objectPtrs, const string& label, bool writeCountAttribute = false) { if (!objectPtrs.empty()) { XMLWriter::Attributes attributes; if (writeCountAttribute) attributes.push_back(make_pair("count", lexical_cast(objectPtrs.size()))); writer.startElement(label, attributes); for (typename vector::const_iterator it=objectPtrs.begin(); it!=objectPtrs.end(); ++it) write(writer, **it); writer.endElement(); } } // // CV // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const CV& cv) { XMLWriter::Attributes attributes; attributes.push_back(make_pair("id", cv.id)); attributes.push_back(make_pair("fullName", cv.fullName)); attributes.push_back(make_pair("version", cv.version)); attributes.push_back(make_pair("URI", cv.URI)); writer.startElement("cv", attributes, XMLWriter::EmptyElement); } struct HandlerCV : public SAXParser::Handler { CV* cv; HandlerCV(CV* _cv = 0) : cv(_cv) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name != "cv") throw runtime_error(("[IO::HandlerCV] Unexpected element name: " + name).c_str()); getAttribute(attributes, "id", cv->id); getAttribute(attributes, "fullName", cv->fullName); getAttribute(attributes, "version", cv->version); getAttribute(attributes, "URI", cv->URI); return Status::Ok; } }; PWIZ_API_DECL void read(std::istream& is, CV& cv) { HandlerCV handler(&cv); SAXParser::parse(is, handler); } // // UserParam // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const UserParam& userParam) { XMLWriter::Attributes attributes; attributes.push_back(make_pair("name", userParam.name)); if (!userParam.value.empty()) attributes.push_back(make_pair("value", userParam.value)); if (!userParam.type.empty()) attributes.push_back(make_pair("type", userParam.type)); if (userParam.units != CVID_Unknown) { attributes.push_back(make_pair("unitAccession", cvTermInfo(userParam.units).id)); attributes.push_back(make_pair("unitName", cvTermInfo(userParam.units).name)); } writer.startElement("UserParam", attributes, XMLWriter::EmptyElement); } struct HandlerUserParam : public SAXParser::Handler { UserParam* userParam; HandlerUserParam(UserParam* _userParam = 0) : userParam(_userParam) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name != "UserParam") throw runtime_error(("[IO::HandlerUserParam] Unexpected element name: " + name).c_str()); if (!userParam) throw runtime_error("[IO::HandlerUserParam] Null UserParam."); getAttribute(attributes, "name", userParam->name); getAttribute(attributes, "value", userParam->value); getAttribute(attributes, "type", userParam->type); string unitAccession; getAttribute(attributes, "unitAccession", unitAccession); if (!unitAccession.empty()) userParam->units = cvTermInfo(unitAccession).cvid; return Status::Ok; } }; PWIZ_API_DECL void read(std::istream& is, UserParam& userParam) { HandlerUserParam handler(&userParam); SAXParser::parse(is, handler); } // // CVParam // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const CVParam& cvParam) { XMLWriter::Attributes attributes; attributes.push_back(make_pair("cvRef", cvTermInfo(cvParam.cvid).prefix())); attributes.push_back(make_pair("accession", cvTermInfo(cvParam.cvid).id)); attributes.push_back(make_pair("name", cvTermInfo(cvParam.cvid).name)); attributes.push_back(make_pair("value", cvParam.value)); if (cvParam.units != CVID_Unknown) { attributes.push_back(make_pair("unitCvRef", cvTermInfo(cvParam.units).prefix())); attributes.push_back(make_pair("unitAccession", cvTermInfo(cvParam.units).id)); attributes.push_back(make_pair("unitName", cvTermInfo(cvParam.units).name)); } writer.startElement("cvParam", attributes, XMLWriter::EmptyElement); } struct HandlerCVParam : public SAXParser::Handler { CVParam* cvParam; HandlerCVParam(CVParam* _cvParam = 0) : cvParam(_cvParam) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name != "cvParam") throw runtime_error(("[IO::HandlerCVParam] Unexpected element name: " + name).c_str()); if (!cvParam) throw runtime_error("[IO::HandlerCVParam] Null cvParam."); string accession; getAttribute(attributes, "accession", accession); if (!accession.empty()) cvParam->cvid = cvTermInfo(accession).cvid; getAttribute(attributes, "value", cvParam->value); string unitAccession; getAttribute(attributes, "unitAccession", unitAccession); if (!unitAccession.empty()) cvParam->units = cvTermInfo(unitAccession).cvid; return Status::Ok; } }; PWIZ_API_DECL void read(std::istream& is, CVParam& cvParam) { HandlerCVParam handler(&cvParam); SAXParser::parse(is, handler); } // // ParamContainer // // // note: These are auxilliary functions to be called by ParamContainer subclasses // PWIZ_API_DECL void writeParamContainer(minimxml::XMLWriter& writer, const ParamContainer& pc) { for (vector::const_iterator it=pc.cvParams.begin(); it!=pc.cvParams.end(); ++it) write(writer, *it); for (vector::const_iterator it=pc.userParams.begin(); it!=pc.userParams.end(); ++it) write(writer, *it); } struct HandlerParamContainer : public SAXParser::Handler { ParamContainer* paramContainer; HandlerParamContainer(ParamContainer* _paramContainer = 0) : paramContainer(_paramContainer) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!paramContainer) throw runtime_error("[IO::HandlerParamContainer] Null paramContainer."); if (name == "cvParam") { paramContainer->cvParams.push_back(CVParam()); handlerCVParam_.cvParam = ¶mContainer->cvParams.back(); return Status(Status::Delegate, &handlerCVParam_); } else if (name == "UserParam") { paramContainer->userParams.push_back(UserParam()); handlerUserParam_.userParam = ¶mContainer->userParams.back(); return Status(Status::Delegate, &handlerUserParam_); } throw runtime_error(("[IO::HandlerParamContainer] Unknown element " + name).c_str()); } private: HandlerCVParam handlerCVParam_; HandlerUserParam handlerUserParam_; }; struct HandlerNamedParamContainer : public HandlerParamContainer { const string name_; HandlerNamedParamContainer(const string& name, ParamContainer* paramContainer = 0) : HandlerParamContainer(paramContainer), name_(name) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == name_) return Status::Ok; return HandlerParamContainer::startElement(name, attributes, position); } }; // // Contact // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Contact& c) { XMLWriter::Attributes attributes; attributes.push_back(make_pair("id", c.id)); writer.startElement("Contact", attributes); writeParamContainer(writer, c); writer.endElement(); } // // Publication // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Publication& p) { XMLWriter::Attributes attributes; attributes.push_back(make_pair("id", p.id)); writer.startElement("Publication", attributes); writeParamContainer(writer, p); writer.endElement(); } // // Interpretation // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Interpretation& x) { writer.startElement("Interpretation"); writeParamContainer(writer, x); writer.endElement(); } // // RetentionTime // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const RetentionTime& x) { XMLWriter::Attributes attributes; if (x.softwarePtr.get()) { attributes.push_back(make_pair("softwareRef", x.softwarePtr->id)); } writer.startElement("RetentionTime", attributes); writeParamContainer(writer, x); writer.endElement(); } // // Configuration // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Configuration& x) { XMLWriter::Attributes attributes; if (x.contactPtr.get() && !x.contactPtr->empty()) attributes.push_back(make_pair("contactRef", x.contactPtr->id)); if (x.instrumentPtr.get() && !x.instrumentPtr->empty()) attributes.push_back(make_pair("instrumentRef", x.instrumentPtr->id)); writer.startElement("Configuration", attributes); writeParamContainer(writer, x); for (size_t i=0; i < x.validations.size(); ++i) { const Validation& v = x.validations[i]; writer.startElement("Validation"); writeParamContainer(writer, v); writer.endElement(); } writer.endElement(); } struct HandlerConfiguration : public HandlerParamContainer { Configuration* configuration; HandlerConfiguration(Configuration* configuration = 0) : configuration(configuration), handlerValidation_("Validation") {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!configuration) throw runtime_error("[IO::HandlerConfiguration] Null configuration."); if (name == "Configuration") { // note: placeholder string contactRef; getAttribute(attributes, "contactRef", contactRef); if (!contactRef.empty()) configuration->contactPtr = ContactPtr(new Contact(contactRef)); // note: placeholder string instrumentRef; getAttribute(attributes, "instrumentRef", instrumentRef); if (!instrumentRef.empty()) configuration->instrumentPtr = InstrumentPtr(new Instrument(instrumentRef)); return Status::Ok; } else if (name == "Validation") { configuration->validations.push_back(Validation()); handlerValidation_.paramContainer = &configuration->validations.back(); return Status(Status::Delegate, &handlerValidation_); } HandlerParamContainer::paramContainer = configuration; return HandlerParamContainer::startElement(name, attributes, position); } private: HandlerNamedParamContainer handlerValidation_; }; PWIZ_API_DECL void read(std::istream& is, Configuration& x) { HandlerConfiguration handler(&x); SAXParser::parse(is, handler); } // // Prediction // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Prediction& x) { XMLWriter::Attributes attributes; if (x.contactPtr.get() && !x.contactPtr->empty()) attributes.push_back(make_pair("contactRef", x.contactPtr->id)); if (x.softwarePtr.get() && !x.softwarePtr->empty()) attributes.push_back(make_pair("softwareRef", x.softwarePtr->id)); writer.startElement("Prediction", attributes); writeParamContainer(writer, x); writer.endElement(); } struct HandlerPrediction : public HandlerParamContainer { Prediction* prediction; HandlerPrediction(Prediction* prediction = 0) : prediction(prediction) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!prediction) throw runtime_error("[IO::HandlerPrediction] Null prediction."); if (name == "Prediction") { // note: placeholder string contactRef; getAttribute(attributes, "contactRef", contactRef); if (!contactRef.empty()) prediction->contactPtr = ContactPtr(new Contact(contactRef)); // note: placeholder string softwareRef; getAttribute(attributes, "softwareRef", softwareRef); if (!softwareRef.empty()) prediction->softwarePtr = SoftwarePtr(new Software(softwareRef)); return Status::Ok; } HandlerParamContainer::paramContainer = prediction; return HandlerParamContainer::startElement(name, attributes, position); } }; PWIZ_API_DECL void read(std::istream& is, Prediction& x) { HandlerPrediction handler(&x); SAXParser::parse(is, handler); } // // Instrument // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Instrument& instrument) { XMLWriter::Attributes attributes; attributes.push_back(make_pair("id", instrument.id)); writer.startElement("Instrument", attributes); writeParamContainer(writer, instrument); writer.endElement(); } struct HandlerInstrument : public HandlerParamContainer { Instrument* instrument; HandlerInstrument(Instrument* instrument = 0) : instrument(instrument) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!instrument) throw runtime_error("[IO::HandlerInstrument] Null instrument."); if (name == "Instrument") { getAttribute(attributes, "id", instrument->id); return Status::Ok; } HandlerParamContainer::paramContainer = instrument; return HandlerParamContainer::startElement(name, attributes, position); } }; PWIZ_API_DECL void read(std::istream& is, Instrument& instrument) { HandlerInstrument handler(&instrument); SAXParser::parse(is, handler); } // // Software // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Software& software) { XMLWriter::Attributes attributes; attributes.push_back(make_pair("id", software.id)); attributes.push_back(make_pair("version", software.version)); writer.startElement("Software", attributes); writeParamContainer(writer, software); writer.endElement(); } struct HandlerSoftware : public HandlerParamContainer { Software* software; HandlerSoftware(Software* _software = 0) : software(_software) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!software) throw runtime_error("[IO::HandlerSoftware] Null Software."); if (name == "Software") { getAttribute(attributes, "id", software->id); getAttribute(attributes, "version", software->version); return Status::Ok; } HandlerParamContainer::paramContainer = software; return HandlerParamContainer::startElement(name, attributes, position); } }; PWIZ_API_DECL void read(std::istream& is, Software& software) { HandlerSoftware handler(&software); SAXParser::parse(is, handler); } // // Protein // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const ProteinPtr& proteinPtr) { XMLWriter::Attributes attributes; attributes.push_back(make_pair("id", proteinPtr->id)); writer.startElement("Protein", attributes); writeParamContainer(writer, *proteinPtr); if (!proteinPtr->sequence.empty()) { writer.startElement("Sequence"); writer.characters(proteinPtr->sequence); writer.endElement(); } writer.endElement(); } struct HandlerProtein : public HandlerParamContainer { Protein* protein; HandlerProtein(Protein* protein = 0) : protein(protein) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!protein) throw runtime_error("[IO::HandlerProtein] Null Protein."); if (name == "Protein") { getAttribute(attributes, "id", protein->id); return Status::Ok; } else if (name == "Sequence") { return Status::Ok; } HandlerParamContainer::paramContainer = protein; return HandlerParamContainer::startElement(name, attributes, position); } virtual Status characters(const SAXParser::saxstring& text, stream_offset position) { protein->sequence = text.c_str(); return Status::Ok; } }; PWIZ_API_DECL void read(std::istream& is, Protein& protein) { HandlerProtein handler(&protein); SAXParser::parse(is, handler); } // // Protein // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Modification& modification) { XMLWriter::Attributes attributes; attributes.push_back(make_pair("location", lexical_cast(modification.location))); attributes.push_back(make_pair("monoisotopicMassDelta", lexical_cast(modification.monoisotopicMassDelta))); attributes.push_back(make_pair("averageMassDelta", lexical_cast(modification.averageMassDelta))); writer.startElement("Modification", attributes); writeParamContainer(writer, modification); writer.endElement(); } struct HandlerModification : public HandlerParamContainer { Modification* modification; HandlerModification(Modification* modification = 0) : modification(modification) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!modification) throw runtime_error("[IO::HandlerModification] Null modification."); if (name == "Modification") { getAttribute(attributes, "location", modification->location); getAttribute(attributes, "monoisotopicMassDelta", modification->monoisotopicMassDelta); getAttribute(attributes, "averageMassDelta", modification->averageMassDelta); return Status::Ok; } HandlerParamContainer::paramContainer = modification; return HandlerParamContainer::startElement(name, attributes, position); } }; PWIZ_API_DECL void read(std::istream& is, Modification& modification) { HandlerModification handler(&modification); SAXParser::parse(is, handler); } // // Peptide // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const PeptidePtr& peptidePtr) { XMLWriter::Attributes attributes; attributes.push_back(make_pair("id", peptidePtr->id)); attributes.push_back(make_pair("sequence", peptidePtr->sequence)); writer.startElement("Peptide", attributes); writeParamContainer(writer, *peptidePtr); BOOST_FOREACH(const ProteinPtr& p, peptidePtr->proteinPtrs) { attributes.clear(); attributes.push_back(make_pair("ref", p->id)); writer.startElement("ProteinRef", attributes, XMLWriter::EmptyElement); } BOOST_FOREACH(const Modification& m, peptidePtr->modifications) { write(writer, m); } writeList(writer, peptidePtr->retentionTimes, "RetentionTimeList"); if (!peptidePtr->evidence.empty()) { writer.startElement("Evidence"); writeParamContainer(writer, peptidePtr->evidence); writer.endElement(); } writer.endElement(); } struct HandlerPeptide : public HandlerParamContainer { Peptide* peptide; HandlerPeptide(Peptide* peptide = 0) : peptide(peptide), handlerModification_("Modification"), handlerRetentionTime_("RetentionTime") {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!peptide) throw runtime_error("[IO::HandlerPeptide] Null peptide."); if (name == "Peptide") { getAttribute(attributes, "id", peptide->id); getAttribute(attributes, "sequence", peptide->sequence); return Status::Ok; } else if (name == "ProteinRef") { // note: placeholder string proteinRef; getAttribute(attributes, "ref", proteinRef); if (!proteinRef.empty()) peptide->proteinPtrs.push_back(ProteinPtr(new Protein(proteinRef))); return Status::Ok; } else if (name == "Modification") { peptide->modifications.push_back(Modification()); getAttribute(attributes, "location", peptide->modifications.back().location); getAttribute(attributes, "monoisotopicMassDelta", peptide->modifications.back().monoisotopicMassDelta); getAttribute(attributes, "averageMassDelta", peptide->modifications.back().averageMassDelta); handlerModification_.paramContainer = &peptide->modifications.back(); return Status(Status::Delegate, &handlerModification_); } else if (name == "RetentionTime") { peptide->retentionTimes.push_back(RetentionTime()); // note: placeholder string softwareRef; getAttribute(attributes, "softwareRef", softwareRef); if (!softwareRef.empty()) peptide->retentionTimes.back().softwarePtr = SoftwarePtr(new Software(softwareRef)); handlerRetentionTime_.paramContainer = &peptide->retentionTimes.back(); return Status(Status::Delegate, &handlerRetentionTime_); } else if (name == "Evidence") { HandlerParamContainer::paramContainer = &peptide->evidence; return Status::Ok; } HandlerParamContainer::paramContainer = peptide; return HandlerParamContainer::startElement(name, attributes, position); } HandlerNamedParamContainer handlerModification_; HandlerNamedParamContainer handlerRetentionTime_; }; PWIZ_API_DECL void read(std::istream& is, Peptide& peptide) { HandlerPeptide handler(&peptide); SAXParser::parse(is, handler); } // // Compound // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const CompoundPtr& compoundPtr) { XMLWriter::Attributes attributes; attributes.push_back(make_pair("id", compoundPtr->id)); writer.startElement("Compound", attributes); writeParamContainer(writer, *compoundPtr); writeList(writer, compoundPtr->retentionTimes, "RetentionTimeList"); writer.endElement(); } struct HandlerCompound : public HandlerParamContainer { Compound* compound; HandlerCompound(Compound* compound = 0) : compound(compound), handlerRetentionTime_("RetentionTime") {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!compound) throw runtime_error("[IO::HandlerCompound] Null compound."); if (name == "Compound") { getAttribute(attributes, "id", compound->id); return Status::Ok; } else if (name == "RetentionTime") { compound->retentionTimes.push_back(RetentionTime()); // note: placeholder string softwareRef; getAttribute(attributes, "softwareRef", softwareRef); if (!softwareRef.empty()) compound->retentionTimes.back().softwarePtr = SoftwarePtr(new Software(softwareRef)); handlerRetentionTime_.paramContainer = &compound->retentionTimes.back(); return Status(Status::Delegate, &handlerRetentionTime_); } HandlerParamContainer::paramContainer = compound; return HandlerParamContainer::startElement(name, attributes, position); } private: HandlerNamedParamContainer handlerRetentionTime_; }; PWIZ_API_DECL void read(std::istream& is, Compound& compound) { HandlerCompound handler(&compound); SAXParser::parse(is, handler); } // // Transition // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Transition& transition) { XMLWriter::Attributes attributes; attributes.push_back(make_pair("id", transition.id)); if (transition.peptidePtr.get()) attributes.push_back(make_pair("peptideRef", transition.peptidePtr->id)); if (transition.compoundPtr.get()) attributes.push_back(make_pair("compoundRef", transition.compoundPtr->id)); writer.startElement("Transition", attributes); writeParamContainer(writer, transition); writer.startElement("Precursor"); writeParamContainer(writer, transition.precursor); writer.endElement(); writer.startElement("Product"); writeParamContainer(writer, transition.product); writer.endElement(); if (!transition.retentionTime.empty()) { writer.startElement("RetentionTime"); writeParamContainer(writer, transition.retentionTime); writer.endElement(); } if (!transition.prediction.empty()) write(writer, transition.prediction); writeList(writer, transition.interpretationList, "InterpretationList"); writeList(writer, transition.configurationList, "ConfigurationList"); writer.endElement(); } struct HandlerTransition : public HandlerParamContainer { Transition* transition; HandlerTransition(Transition* _transition = 0) : transition(_transition), handlerInterpretation_("Interpretation"), handlerPrecursor_("Precursor"), handlerProduct_("Product"), handlerRetentionTime_("RetentionTime") {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!transition) throw runtime_error("[IO::HandlerTransition] Null transition."); if (name == "Transition") { getAttribute(attributes, "id", transition->id); // note: placeholder string peptideRef; getAttribute(attributes, "peptideRef", peptideRef); if (!peptideRef.empty()) transition->peptidePtr = PeptidePtr(new Peptide(peptideRef)); // note: placeholder string compoundRef; getAttribute(attributes, "compoundRef", compoundRef); if (!compoundRef.empty()) transition->compoundPtr = CompoundPtr(new Compound(compoundRef)); return Status::Ok; } else if (name == "InterpretationList" || name == "ConfigurationList") { return Status::Ok; } else if (name == "Interpretation") { transition->interpretationList.push_back(Interpretation()); handlerInterpretation_.paramContainer = &transition->interpretationList.back(); return Status(Status::Delegate, &handlerInterpretation_); } else if (name == "Configuration") { transition->configurationList.push_back(Configuration()); handlerConfiguration_.configuration = &transition->configurationList.back(); return Status(Status::Delegate, &handlerConfiguration_); } else if (name == "Precursor") { handlerPrecursor_.paramContainer = &transition->precursor; return Status(Status::Delegate, &handlerPrecursor_); } else if (name == "Product") { handlerProduct_.paramContainer = &transition->product; return Status(Status::Delegate, &handlerProduct_); } else if (name == "Prediction") { handlerPrediction_.prediction = &transition->prediction; return Status(Status::Delegate, &handlerPrediction_); } else if (name == "RetentionTime") { handlerRetentionTime_.paramContainer = &transition->retentionTime; return Status(Status::Delegate, &handlerRetentionTime_); } HandlerParamContainer::paramContainer = transition; return HandlerParamContainer::startElement(name, attributes, position); } private: HandlerNamedParamContainer handlerInterpretation_; HandlerConfiguration handlerConfiguration_; HandlerNamedParamContainer handlerPrecursor_; HandlerNamedParamContainer handlerProduct_; HandlerPrediction handlerPrediction_; HandlerNamedParamContainer handlerRetentionTime_; }; PWIZ_API_DECL void read(std::istream& is, Transition& transition) { HandlerTransition handler(&transition); SAXParser::parse(is, handler); } // // Target // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Target& target) { XMLWriter::Attributes attributes; attributes.push_back(make_pair("id", target.id)); if (target.peptidePtr.get()) attributes.push_back(make_pair("peptideRef", target.peptidePtr->id)); if (target.compoundPtr.get()) attributes.push_back(make_pair("compoundRef", target.compoundPtr->id)); writer.startElement("Target", attributes); writeParamContainer(writer, target); writer.startElement("Precursor"); writeParamContainer(writer, target.precursor); writer.endElement(); if (!target.retentionTime.empty()) { writer.startElement("RetentionTime"); writeParamContainer(writer, target.retentionTime); writer.endElement(); } writeList(writer, target.configurationList, "ConfigurationList"); writer.endElement(); } struct HandlerTarget : public HandlerParamContainer { Target* target; HandlerTarget(Target* _target = 0) : target(_target), handlerPrecursor_("Precursor"), handlerRetentionTime_("RetentionTime") {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!target) throw runtime_error("[IO::HandlerTarget] Null target."); if (name == "Target") { getAttribute(attributes, "id", target->id); // note: placeholder string peptideRef; getAttribute(attributes, "peptideRef", peptideRef); if (!peptideRef.empty()) target->peptidePtr = PeptidePtr(new Peptide(peptideRef)); // note: placeholder string compoundRef; getAttribute(attributes, "compoundRef", compoundRef); if (!compoundRef.empty()) target->compoundPtr = CompoundPtr(new Compound(compoundRef)); return Status::Ok; } else if (name == "ConfigurationList") { return Status::Ok; } else if (name == "Configuration") { target->configurationList.push_back(Configuration()); handlerConfiguration_.configuration = &target->configurationList.back(); return Status(Status::Delegate, &handlerConfiguration_); } else if (name == "Precursor") { handlerPrecursor_.paramContainer = &target->precursor; return Status(Status::Delegate, &handlerPrecursor_); } else if (name == "RetentionTime") { handlerRetentionTime_.paramContainer = &target->retentionTime; return Status(Status::Delegate, &handlerRetentionTime_); } HandlerParamContainer::paramContainer = target; return HandlerParamContainer::startElement(name, attributes, position); } private: HandlerConfiguration handlerConfiguration_; HandlerNamedParamContainer handlerPrecursor_; HandlerNamedParamContainer handlerRetentionTime_; }; PWIZ_API_DECL void read(std::istream& is, Target& target) { HandlerTarget handler(&target); SAXParser::parse(is, handler); } // // TargetList // struct HandlerTargetList : public HandlerParamContainer { TargetList* targets; HandlerTargetList(TargetList* _targets = 0) : targets(_targets) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!targets) throw runtime_error("[IO::HandlerTargetList] Null target."); if (name == "TargetList") { return Status::Ok; } else if (name == "TargetExcludeList") { excludeTargets_ = true; return Status::Ok; } else if (name == "TargetIncludeList") { excludeTargets_ = false; return Status::Ok; } else if (name == "Target") { if (excludeTargets_) { targets->targetExcludeList.push_back(Target()); handlerTarget_.target = &targets->targetExcludeList.back(); } else { targets->targetIncludeList.push_back(Target()); handlerTarget_.target = &targets->targetIncludeList.back(); } return Status(Status::Delegate, &handlerTarget_); } HandlerParamContainer::paramContainer = targets; return HandlerParamContainer::startElement(name, attributes, position); } private: bool excludeTargets_; HandlerTarget handlerTarget_; }; // // TraData // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const TraData& td) { XMLWriter::Attributes attributes; attributes.push_back(make_pair("xmlns", "http://psi.hupo.org/ms/traml")); attributes.push_back(make_pair("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")); attributes.push_back(make_pair("xsi:schemaLocation", "http://psi.hupo.org/ms/traml http://www.peptideatlas.org/tmp/TraML/" + td.version() + "/TraML" + td.version() + ".xsd")); attributes.push_back(make_pair("version", td.version())); writer.startElement("TraML", attributes); writeList(writer, td.cvs, "cvList"); writePtrList(writer, td.contactPtrs, "ContactList"); writeList(writer, td.publications, "PublicationList"); writePtrList(writer, td.instrumentPtrs, "InstrumentList"); writePtrList(writer, td.softwarePtrs, "SoftwareList"); writeList(writer, td.proteinPtrs, "ProteinList"); if (!td.peptidePtrs.empty() || !td.compoundPtrs.empty()) { writer.startElement("CompoundList"); for (vector::const_iterator it=td.peptidePtrs.begin(); it!=td.peptidePtrs.end(); ++it) write(writer, *it); for (vector::const_iterator it=td.compoundPtrs.begin(); it!=td.compoundPtrs.end(); ++it) write(writer, *it); writer.endElement(); } writeList(writer, td.transitions, "TransitionList"); writer.startElement("TargetList"); writeParamContainer(writer, td.targets); writeList(writer, td.targets.targetIncludeList, "TargetIncludeList"); writeList(writer, td.targets.targetExcludeList, "TargetExcludeList"); writer.endElement(); writer.endElement(); } struct HandlerTraData : public SAXParser::Handler { TraData* td; HandlerTraData(TraData* td = 0) : td(td), handlerContact_("Contact"), handlerPublication_("Publication") {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!td) throw runtime_error("[IO::HandlerTraData] Null td."); if (name == "TraML") { // "http://psi.hupo.org/ms/traml http://psidev.info/files/ms/traML/xsd/traML.xsd" string schemaLocation; getAttribute(attributes, "xsi:schemaLocation", schemaLocation); if (schemaLocation.empty()) getAttribute(attributes, "version", td->version_); // fallback else { schemaLocation = schemaLocation.substr(schemaLocation.find(' ')+1); string xsdName = BFS_STRING(bfs::path(schemaLocation).filename()); td->version_ = xsdName.substr(5, xsdName.length()-9); // read between "traML" and ".xsd" } version = TRAML_VERSION_PRERELEASE; //if (td->version_.find("1.0") == 0) // version = TRAML_VERSION_1_0; return Status::Ok; } else if (name == "cvList" || name == "ContactList" || name == "PublicationList" || name == "InstrumentList" || name == "SoftwareList" || name == "ProteinList" || name == "CompoundList" || name == "TransitionList") { // ignore these, unless we want to validate the count attribute return Status::Ok; } else if (name == "cv") { td->cvs.push_back(CV()); handlerCV_.cv = &td->cvs.back(); return Status(Status::Delegate, &handlerCV_); } else if (name == "Contact") { td->contactPtrs.push_back(ContactPtr(new Contact)); getAttribute(attributes, "id", td->contactPtrs.back()->id); handlerContact_.paramContainer = td->contactPtrs.back().get(); return Status(Status::Delegate, &handlerContact_); } else if (name == "Publication") { td->publications.push_back(Publication()); getAttribute(attributes, "id", td->publications.back().id); handlerPublication_.paramContainer = &td->publications.back(); return Status(Status::Delegate, &handlerPublication_); } else if (name == "Instrument") { td->instrumentPtrs.push_back(InstrumentPtr(new Instrument)); handlerInstrument_.instrument = td->instrumentPtrs.back().get(); return Status(Status::Delegate, &handlerInstrument_); } else if (name == "Software") { td->softwarePtrs.push_back(SoftwarePtr(new Software)); handlerSoftware_.software = td->softwarePtrs.back().get(); return Status(Status::Delegate, &handlerSoftware_); } else if (name == "Protein") { td->proteinPtrs.push_back(ProteinPtr(new Protein)); handlerProtein_.protein = td->proteinPtrs.back().get(); return Status(Status::Delegate, &handlerProtein_); } else if (name == "Peptide") { td->peptidePtrs.push_back(PeptidePtr(new Peptide)); handlerPeptide_.peptide = td->peptidePtrs.back().get(); return Status(Status::Delegate, &handlerPeptide_); } else if (name == "Compound") { td->compoundPtrs.push_back(CompoundPtr(new Compound)); handlerCompound_.compound = td->compoundPtrs.back().get(); return Status(Status::Delegate, &handlerCompound_); } else if (name == "Transition") { td->transitions.push_back(Transition()); handlerTransition_.transition = &td->transitions.back(); return Status(Status::Delegate, &handlerTransition_); } else if (name == "TargetList") { handlerTargetList_.targets = &td->targets; return Status(Status::Delegate, &handlerTargetList_); } throw runtime_error(("[IO::HandlerTraData] Unexpected element name: " + name).c_str()); } private: HandlerCV handlerCV_; HandlerNamedParamContainer handlerContact_; HandlerNamedParamContainer handlerPublication_; HandlerInstrument handlerInstrument_; HandlerSoftware handlerSoftware_; HandlerProtein handlerProtein_; HandlerPeptide handlerPeptide_; HandlerCompound handlerCompound_; HandlerTransition handlerTransition_; HandlerTargetList handlerTargetList_; }; PWIZ_API_DECL void read(std::istream& is, TraData& td) { HandlerTraData handler(&td); SAXParser::parse(is, handler); References::resolve(td); } } // namespace IO } // namespace tradata } // namespace pwiz pwiz/pwiz/data/tradata/TraDataFileTest.cpp0000664000175100017510000000675712664775617022605 0ustar teamcityteamcity00000000000000// // $Id: TraDataFileTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "TraDataFile.hpp" #include "Diff.hpp" #include "IO.hpp" #include "examples.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include #include #include #include using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::data; using namespace pwiz::tradata; ostream* os_ = 0; string filenameBase_ = "temp.TraDataFileTest"; void hackInMemoryTraData(TraData& td) { // remove metadata ptrs appended on read //vector& sfs = msd.fileDescription.sourceFilePtrs; //if (!sfs.empty()) sfs.erase(sfs.end()-1); vector& sws = td.softwarePtrs; if (!sws.empty()) sws.erase(sws.end()-1); } void test() { TraDataFile::WriteConfig writeConfig; if (os_) *os_ << "test()\n " << writeConfig << endl; string filename1 = filenameBase_ + ".1"; string filename2 = filenameBase_ + ".2"; { // create TraData object in memory TraData tiny; examples::initializeTiny(tiny); // write to file #1 (static) TraDataFile::write(tiny, filename1, writeConfig); // read back into an TraDataFile object TraDataFile td1(filename1); hackInMemoryTraData(td1); // compare Diff diff(tiny, td1); if (diff && os_) *os_ << diff << endl; unit_assert(!diff); // write to file #2 (member) td1.write(filename2, writeConfig); // read back into another TraDataFile object TraDataFile td2(filename2); hackInMemoryTraData(td2); // compare diff(tiny, td2); if (diff && os_) *os_ << diff << endl; unit_assert(!diff); // now give the gzip read a workout bio::filtering_istream tinyGZ(bio::gzip_compressor() | bio::file_descriptor_source(filename1)); bio::copy(tinyGZ, bio::file_descriptor_sink(filename1+".gz", ios::out|ios::binary)); TraDataFile td3(filename1); hackInMemoryTraData(td3); // compare diff(tiny, td3); if (diff && os_) *os_ << diff << endl; unit_assert(!diff); } // remove temp files boost::filesystem::remove(filename1); boost::filesystem::remove(filename2); boost::filesystem::remove(filename1 + ".gz"); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/tradata/Serializer_traML_Test.cpp0000664000175100017510000000366012664775617024022 0ustar teamcityteamcity00000000000000// // $Id: Serializer_traML_Test.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "Serializer_traML.hpp" #include "Diff.hpp" #include "TextWriter.hpp" #include "examples.hpp" #include "pwiz/utility/misc/unit.hpp" #include "boost/iostreams/positioning.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::tradata; ostream* os_ = 0; void testWriteRead() { if (os_) *os_ << "testWriteRead()" << endl; TraData td; examples::initializeTiny(td); Serializer_traML tramlSerializer; ostringstream oss; tramlSerializer.write(oss, td); if (os_) *os_ << "oss:\n" << oss.str() << endl; shared_ptr iss(new istringstream(oss.str())); TraData td2; tramlSerializer.read(iss, td2); Diff diff(td, td2); if (os_ && diff) *os_ << diff << endl; unit_assert(!diff); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; testWriteRead(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/tradata/References.hpp0000664000175100017510000000322012664775617021671 0ustar teamcityteamcity00000000000000// // $Id: References.hpp 1605 2009-12-09 23:50:27Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _TRADATA_REFERENCES_HPP_ #define _TRADATA_REFERENCES_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "TraData.hpp" namespace pwiz { namespace tradata { /// functions for resolving references from objects into the internal MSData lists namespace References { PWIZ_API_DECL void resolve(RetentionTime& retentionTime, const TraData& td); PWIZ_API_DECL void resolve(Prediction& prediction, const TraData& td); PWIZ_API_DECL void resolve(Configuration& configuration, const TraData& td); PWIZ_API_DECL void resolve(Peptide& peptide, const TraData& td); PWIZ_API_DECL void resolve(Transition& transition, const TraData& td); PWIZ_API_DECL void resolve(Target& target, const TraData& td); /// Resolve internal references in a TraData object. PWIZ_API_DECL void resolve(TraData& td); } // namespace References } // namespace tradata } // namespace pwiz #endif // _TRADATA_REFERENCES_HPP_ pwiz/pwiz/data/tradata/examples.hpp0000664000175100017510000000221512664775617021431 0ustar teamcityteamcity00000000000000// // $Id: examples.hpp 1195 2009-08-14 22:12:04Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _TRADATA_EXAMPLES_HPP_ #define _TRADATA_EXAMPLES_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "TraData.hpp" namespace pwiz { namespace tradata { namespace examples { PWIZ_API_DECL void initializeTiny(TraData& td); PWIZ_API_DECL void addMIAPEExampleMetadata(TraData& td); } // namespace examples } // namespace msdata } // namespace pwiz #endif // _TRADATA_EXAMPLES_HPP_ pwiz/pwiz/data/tradata/TraDataTest.cpp0000664000175100017510000000616412664775617021775 0ustar teamcityteamcity00000000000000// // $Id: TraDataTest.cpp 6141 2014-05-05 21:03:47Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "TraData.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::cv; using namespace pwiz::util; using namespace pwiz::tradata; void testParamContainer() { ParamContainer pc; pc.cvParams.push_back(MS_reflectron_on); pc.cvParams.push_back(MS_MSn_spectrum); pc.cvParams.push_back(MS_reflectron_off); pc.cvParams.push_back(CVParam(MS_ionization_type, 420)); pc.userParams.push_back(UserParam("name1", "1", "type1", UO_second)); pc.userParams.push_back(UserParam("name2", "2", "type2", UO_minute)); unit_assert(pc.hasCVParam(MS_reflectron_off)); unit_assert(!pc.hasCVParam(MS_spectrum_type)); unit_assert(pc.hasCVParamChild(MS_spectrum_type)); unit_assert(pc.cvParam(MS_selected_ion_m_z) == CVID_Unknown); unit_assert(pc.cvParam(MS_reflectron_off) == MS_reflectron_off); unit_assert(pc.cvParamChild(MS_spectrum_type) == MS_MSn_spectrum); string result = "goober"; result = pc.cvParam(MS_selected_ion_m_z).value; unit_assert(result == ""); result = pc.cvParam(MS_ionization_type).value; unit_assert(result == "420"); UserParam userParam = pc.userParam("name"); unit_assert(userParam.empty()); userParam = pc.userParam("name1"); unit_assert(userParam.name == "name1"); unit_assert(userParam.valueAs() == 1); unit_assert(userParam.type == "type1"); unit_assert(userParam.units == UO_second); userParam = pc.userParam("name2"); unit_assert(userParam.name == "name2"); unit_assert(userParam.valueAs() == 2); unit_assert(userParam.type == "type2"); unit_assert(userParam.units == UO_minute); unit_assert(pc.userParam("goober").valueAs() == 0); pc.set(MS_ms_level, 2); unit_assert(pc.cvParam(MS_ms_level).valueAs() == 2); pc.set(MS_ms_level, 3); unit_assert(pc.cvParam(MS_ms_level).valueAs() == 3); pc.set(MS_deisotoping, true); unit_assert(pc.cvParam(MS_deisotoping).valueAs() == true); pc.set(MS_deisotoping, false); unit_assert(pc.cvParam(MS_deisotoping).valueAs() == false); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { testParamContainer(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/tradata/IOTest.cpp0000664000175100017510000001035612664775617020762 0ustar teamcityteamcity00000000000000// // $Id: IOTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "IO.hpp" #include "Diff.hpp" #include "examples.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::cv; using namespace pwiz::util; using namespace pwiz::minimxml; using namespace pwiz::tradata; using boost::iostreams::stream_offset; ostream* os_ = 0; template void testObject(const object_type& a) { if (os_) *os_ << "testObject(): " << typeid(a).name() << endl; // write 'a' out to a stream ostringstream oss; XMLWriter writer(oss); IO::write(writer, a); if (os_) *os_ << oss.str() << endl; // read 'b' in from stream object_type b; istringstream iss(oss.str()); IO::read(iss, b); // compare 'a' and 'b' Diff diff(a,b); if (diff && os_) *os_ << "diff:\n" << diff << endl; unit_assert(!diff); } void testCV() { CV a; a.URI = "abcd"; a.id = "efgh"; a.fullName = "ijkl"; a.version = "mnop"; testObject(a); } void testUserParam() { UserParam a; a.name = "abcd"; a.value = "efgh"; a.type = "ijkl"; a.units = UO_minute; testObject(a); } void testCVParam() { CVParam a(MS_selected_ion_m_z, "810.48", MS_m_z); testObject(a); CVParam b(UO_second, "123.45"); testObject(b); } template void testNamedParamContainer() { object_type a; a.userParams.push_back(UserParam("goober", "goo", "peanuts")); a.cvParams.push_back(CVParam(MS_ionization_type, "420")); a.cvParams.push_back(CVParam(MS_selected_ion_m_z, "666", MS_m_z)); testObject(a); } void testSoftware() { Software a; a.id = "goober"; a.set(MS_ionization_type); a.version = "4.20"; testObject(a); } /*void testInstrument() { Instrument a; a.id = "LCQ Deca"; a.cvParams.push_back(MS_LCQ_Deca); a.cvParams.push_back(CVParam(MS_instrument_serial_number, 23433)); testObject(a); } void testConfiguration() { Configuration a; a.instrumentPtr = "LCA Deca"; a.contactPtr = "Bob"; a.cvParams.push_back(CVParam(MS_ionization_type, "420")); }*/ /*void testPrecursor() { Precursor a; a.mz = 123.45; a.charge = 2; testObject(a); Precursor b; b.mz = 456.78; testObject(b); } void testProduct() { Product a; a.mz = 123.45; a.charge = 2; testObject(a); Product b; b.mz = 456.78; testObject(b); }*/ void testTraData() { if (os_) *os_ << "testTraData():\n"; TraData a; examples::initializeTiny(a); // write 'a' out to a stream ostringstream oss; XMLWriter writer(oss); IO::write(writer, a); if (os_) *os_ << oss.str() << endl; // read 'b' in from stream TraData b; istringstream iss(oss.str()); IO::read(iss, b); // compare 'a' and 'b' Diff diff(a,b); if (diff && os_) *os_ << "diff:\n" << diff << endl; unit_assert(!diff); } void test() { testCV(); testUserParam(); testCVParam(); //testNamedParamContainer(); //testNamedParamContainer(); /*testInstrument(); testConfiguration(); testPrecursor(); testProduct();*/ testTraData(); } int main(int argc, char* argv[]) { TEST_PROLOG_EX(argc, argv, "_TraData") try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/tradata/examples.cpp0000664000175100017510000002003612664775617021425 0ustar teamcityteamcity00000000000000// // $Id: examples.cpp 7331 2015-03-24 16:11:12Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "examples.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace tradata { namespace examples { PWIZ_API_DECL void initializeTiny(TraData& td) { //td.id = "urn:lsid:psidev.info:mzML.instanceDocuments.tiny.pwiz"; td.cvs = defaultCVList(); Transition transition1; transition1.id = "Transition1"; transition1.precursor.set(MS_isolation_window_target_m_z, 456.78, MS_m_z); transition1.product.set(MS_isolation_window_target_m_z, 678.90, MS_m_z); Transition transition2; transition2.id = "Transition2"; transition2.precursor.set(MS_isolation_window_target_m_z, 456.78, MS_m_z); transition2.product.set(MS_isolation_window_target_m_z, 789.00, MS_m_z); td.transitions.push_back(transition1); td.transitions.push_back(transition2); Target target1; target1.id = "Target1"; target1.precursor.set(MS_isolation_window_target_m_z, 456.78, MS_m_z); Target target2; target2.id = "Target2"; target2.precursor.set(MS_isolation_window_target_m_z, 567.89, MS_m_z); td.targets.set(MS_includes_supersede_excludes); td.targets.targetExcludeList.push_back(target1); td.targets.targetIncludeList.push_back(target2); } // initializeTiny() PWIZ_API_DECL void addMIAPEExampleMetadata(TraData& td) { ContactPtr contactPtr(new Contact("JQP")); contactPtr->set(MS_contact_name, "John Q. Public"); contactPtr->set(MS_contact_affiliation, "Department of Redundancy Department"); contactPtr->set(MS_contact_address, "1600 Pennsylvania Ave."); td.contactPtrs.push_back(contactPtr); Publication publication; publication.id = "Al_et_al"; publication.set(MS_PubMed_identifier, 123456); td.publications.push_back(publication); InstrumentPtr lcqInstrumentPtr(new Instrument("LCQ")); lcqInstrumentPtr->set(MS_LCQ_Deca); lcqInstrumentPtr->set(MS_instrument_serial_number,"23433"); td.instrumentPtrs.push_back(lcqInstrumentPtr); InstrumentPtr qtrapInstrumentPtr(new Instrument("QTRAP")); qtrapInstrumentPtr->set(MS_4000_QTRAP); td.instrumentPtrs.push_back(qtrapInstrumentPtr); SoftwarePtr softwarePtr(new Software("Xcalibur")); softwarePtr->set(MS_Xcalibur); softwarePtr->version = "2.0.5"; SoftwarePtr softwareMaRiMba(new Software("MaRiMba")); softwareMaRiMba->set(MS_MaRiMba); softwareMaRiMba->version = "0.5"; SoftwarePtr softwarepwiz(new Software("pwiz")); softwarepwiz->set(MS_pwiz); softwarepwiz->version = "1.0"; td.softwarePtrs.push_back(softwareMaRiMba); td.softwarePtrs.push_back(softwarepwiz); td.softwarePtrs.push_back(softwarePtr); ProteinPtr proteinPtr(new Protein("Q123")); proteinPtr->set(MS_protein_accession, "Q123"); proteinPtr->sequence = "ABCD"; proteinPtr->set(MS_protein_name, "A short protein."); proteinPtr->set(MS_molecular_mass_OBSOLETE, 12345, UO_dalton); td.proteinPtrs.push_back(proteinPtr); PeptidePtr peptide1Ptr(new Peptide("Pep1")); peptide1Ptr->sequence = "AB"; peptide1Ptr->set(MS_theoretical_mass, 1234, UO_dalton); peptide1Ptr->proteinPtrs.push_back(proteinPtr); peptide1Ptr->modifications.push_back(Modification()); peptide1Ptr->modifications.back().set(UNIMOD_Methylmalonylation); peptide1Ptr->modifications.back().location = 1; peptide1Ptr->modifications.back().monoisotopicMassDelta = 123; peptide1Ptr->retentionTimes.push_back(RetentionTime()); peptide1Ptr->retentionTimes.back().set(MS_predicted_retention_time, 42, UO_minute); peptide1Ptr->retentionTimes.back().softwarePtr = softwareMaRiMba; peptide1Ptr->evidence.set(MS_confident_peptide_sequence_number, 6); td.peptidePtrs.push_back(peptide1Ptr); CompoundPtr compound1Ptr(new Compound("Cmp1")); compound1Ptr->set(MS_theoretical_mass, 1234, UO_dalton); compound1Ptr->retentionTimes.push_back(RetentionTime()); compound1Ptr->retentionTimes.back().set(MS_predicted_retention_time, 42, UO_minute); compound1Ptr->retentionTimes.back().softwarePtr = softwareMaRiMba; td.compoundPtrs.push_back(compound1Ptr); Interpretation interpretation1; interpretation1.set(MS_frag__y_ion); interpretation1.set(MS_product_ion_series_ordinal, 8); interpretation1.set(MS_product_ion_m_z_delta, 0.03); Interpretation interpretation2; interpretation2.set(MS_frag__b_ion___H2O); interpretation2.set(MS_product_ion_series_ordinal, 9); interpretation2.set(MS_product_ion_m_z_delta, -0.43); Validation qtrapValidation; qtrapValidation.set(MS_transition_optimized_on_specified_instrument); qtrapValidation.set(MS_4000_QTRAP); qtrapValidation.set(MS_peak_intensity, 4072, MS_percent_of_base_peak_times_100); qtrapValidation.set(MS_peak_intensity_rank, 2); qtrapValidation.set(MS_peak_targeting_suitability_rank, 1); Configuration qtrapConfiguration; qtrapConfiguration.instrumentPtr = qtrapInstrumentPtr; qtrapConfiguration.contactPtr = contactPtr; qtrapConfiguration.set(MS_dwell_time, 0.12, UO_second); qtrapConfiguration.set(MS_collision_gas, "argon"); qtrapConfiguration.set(MS_collision_gas_pressure, 12, UO_pascal); qtrapConfiguration.set(MS_collision_energy, 26, UO_electronvolt); qtrapConfiguration.set(MS_cone_voltage, 1200, UO_volt); qtrapConfiguration.set(MS_interchannel_delay, 0.1, UO_second); qtrapConfiguration.set(MS_tube_lens_voltage, 23, UO_volt); qtrapConfiguration.validations.push_back(qtrapValidation); Transition& tra0 = td.transitions[0]; tra0.peptidePtr = peptide1Ptr; tra0.precursor.set(MS_charge_state, 2); tra0.product.set(MS_charge_state, 1); tra0.prediction.softwarePtr = softwareMaRiMba; tra0.prediction.set(MS_transition_purported_from_an_MS_MS_spectrum_on_a_different__specified_instrument); tra0.prediction.set(MS_linear_ion_trap); tra0.prediction.set(MS_peak_intensity, 10000, UO_electronvolt); tra0.prediction.set(MS_peak_intensity_rank, 1); tra0.prediction.set(MS_peak_targeting_suitability_rank, 1); tra0.retentionTime.set(MS_local_retention_time, 40.02, UO_minute); tra0.retentionTime.set(MS_retention_time_window_lower_offset, 3, UO_minute); tra0.retentionTime.set(MS_retention_time_window_upper_offset, 3, UO_minute); tra0.configurationList.push_back(qtrapConfiguration); Transition& tra1 = td.transitions[1]; tra1.compoundPtr = compound1Ptr; tra1.precursor.set(MS_charge_state, 2); tra1.product.set(MS_charge_state, 1); Configuration lcqConfiguration; lcqConfiguration.instrumentPtr = lcqInstrumentPtr; lcqConfiguration.contactPtr = contactPtr; lcqConfiguration.set(MS_collision_energy, 42, UO_electronvolt); Target& tar0 = td.targets.targetIncludeList[0]; tar0.compoundPtr = compound1Ptr; tar0.precursor.set(MS_charge_state, 2); tar0.retentionTime.set(MS_local_retention_time, 12.3, UO_minute); tar0.retentionTime.set(MS_retention_time_window_lower_offset, 1, UO_minute); tar0.retentionTime.set(MS_retention_time_window_upper_offset, 2, UO_minute); tar0.configurationList.push_back(lcqConfiguration); td.targets.targetExcludeList[0].peptidePtr = peptide1Ptr; td.targets.targetExcludeList[0].precursor.set(MS_charge_state, 2); } // addMIAPEExampleMetadata() } // namespace examples } // namespace tdata } // namespace pwiz pwiz/pwiz/data/tradata/IO.hpp0000664000175100017510000000674612664775617020137 0ustar teamcityteamcity00000000000000// // $Id: IO.hpp 1605 2009-12-09 23:50:27Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _TRADATA_IO_HPP_ #define _TRADATA_IO_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "TraData.hpp" #include "pwiz/utility/minimxml/XMLWriter.hpp" namespace pwiz { namespace tradata { namespace IO { PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const CV& cv); PWIZ_API_DECL void read(std::istream& is, CV& cv); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const UserParam& userParam); PWIZ_API_DECL void read(std::istream& is, UserParam& userParam); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const CVParam& cv); PWIZ_API_DECL void read(std::istream& is, CVParam& cv); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Software& software); PWIZ_API_DECL void read(std::istream& is, Software& software); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const RetentionTime& x); PWIZ_API_DECL void read(std::istream& is, RetentionTime& x); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Instrument& instrument); PWIZ_API_DECL void read(std::istream& is, Instrument& instrument); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const ProteinPtr& proteinPtr); PWIZ_API_DECL void read(std::istream& is, Protein& protein); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Modification& modification); PWIZ_API_DECL void read(std::istream& is, Modification& modification); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const PeptidePtr& peptidePtr); PWIZ_API_DECL void read(std::istream& is, Peptide& peptide); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const CompoundPtr& compoundPtr); PWIZ_API_DECL void read(std::istream& is, Compound& compound); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Precursor& precursor); PWIZ_API_DECL void read(std::istream& is, Precursor& precursor); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Product& product); PWIZ_API_DECL void read(std::istream& is, Product& product); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Transition& transition); PWIZ_API_DECL void read(std::istream& is, Transition& transition); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Target& target); PWIZ_API_DECL void read(std::istream& is, Target& target); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const TraData& td); PWIZ_API_DECL void read(std::istream& is, TraData& td); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Contact& c); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Publication& p); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Interpretation& x); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Configuration& x); } // namespace IO } // namespace tradata } // namespace pwiz #endif // _TRADATA_IO_HPP_ pwiz/pwiz/data/tradata/TraData.hpp0000664000175100017510000003014512664775617021136 0ustar teamcityteamcity00000000000000// // $Id: TraData.hpp 1987 2010-05-17 19:40:16Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _TRADATA_HPP_ #define _TRADATA_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/common/cv.hpp" #include "pwiz/data/common/ParamTypes.hpp" #include #include namespace pwiz { namespace tradata { using namespace pwiz::data; /// returns a default list of CVs used in an TraML document; /// currently includes PSI-MS, Unit Ontology, and UNIMOD PWIZ_API_DECL std::vector defaultCVList(); struct PWIZ_API_DECL Contact : public ParamContainer { /// Identifier for the contact to be used for referencing within a document std::string id; Contact(const std::string& id = ""); /// returns true iff all members are empty and contain no params bool empty() const; }; typedef boost::shared_ptr ContactPtr; struct PWIZ_API_DECL Publication : public ParamContainer { /// Identifier for the publication to be used for referencing within a document std::string id; /// returns true iff all members are empty and contain no params bool empty() const; }; struct PWIZ_API_DECL Software : public ParamContainer { /// Identifier for the software to be used for referencing within a document std::string id; /// Version of the software program described std::string version; Software(const std::string& _id = ""); Software(const std::string& _id, const CVParam& _param, const std::string& _version); /// returns true iff all members are empty and contain no params bool empty() const; }; typedef boost::shared_ptr SoftwarePtr; struct PWIZ_API_DECL RetentionTime : public ParamContainer { /// Software used to determine the retention time SoftwarePtr softwarePtr; /// returns true iff all members are empty and contain no params bool empty() const; }; /// Information about a prediction for a suitable transition using some software struct PWIZ_API_DECL Prediction : public ParamContainer { /// Reference to a software package from which this prediction is derived SoftwarePtr softwarePtr; /// Reference to a contact person that generated this prediction ContactPtr contactPtr; /// returns true iff all members are empty and contain no params bool empty() const; }; /// Information about empirical mass spectrometer observations of the peptide struct PWIZ_API_DECL Evidence : public ParamContainer { /// returns true iff contain no params bool empty() const; }; /// Information about the state of validation of a transition on a given instrument model struct PWIZ_API_DECL Validation : public ParamContainer { /// returns true iff contain no params bool empty() const; }; /// Instrument on which transitions are validated struct PWIZ_API_DECL Instrument : public ParamContainer { /// Identifier for the instrument to be used for referencing within a document std::string id; Instrument(const std::string& id = ""); /// returns true iff all members are empty and contain no params bool empty() const; }; typedef boost::shared_ptr InstrumentPtr; /// Instrument configuration used in the validation or optimization of the transitions struct PWIZ_API_DECL Configuration : public ParamContainer { std::vector validations; /// Reference to a contact person originating this information ContactPtr contactPtr; /// Reference to an instrument for which this configuration information is appropriate InstrumentPtr instrumentPtr; /// returns true iff all members are empty and contain no params bool empty() const; }; /// A possible interpration of the product ion for a transition struct PWIZ_API_DECL Interpretation : public ParamContainer { /// returns true iff contains no params bool empty() const; }; struct PWIZ_API_DECL Protein : public ParamContainer { /// Identifier for the protein to be used for referencing within a document std::string id; /// Amino acid sequence of the protein std::string sequence; Protein(const std::string& id = ""); /// returns true iff all members are empty and contain no params bool empty() const; }; typedef boost::shared_ptr ProteinPtr; /// A molecule modification specification. /// If n modifications are present on the peptide, there should be n instances of the modification element. /// If multiple modifications are provided as cvParams, it is assumed the modification is ambiguous, /// i.e. one modification or the other. If no cvParams are provided it is assumed that the delta has not been /// matched to a known modification. struct PWIZ_API_DECL Modification : public ParamContainer { Modification(); /// Location of the modification within the peptide sequence, counted from the N-terminus, starting at position 1. Specific modifications to the N-terminus should be given the location 0. Modification to the C-terminus should be given as peptide length + 1. int location; /// Atomic mass delta when assuming only the most common isotope of elements in Daltons. double monoisotopicMassDelta; /// Atomic mass delta when considering the natural distribution of isotopes in Daltons. double averageMassDelta; /// returns true iff all members are zero and contain no params bool empty() const; }; /// Peptide for which one or more transitions are intended to identify struct PWIZ_API_DECL Peptide : public ParamContainer { /// Identifier for the peptide to be used for referencing within a document std::string id; /// Amino acid sequence of the peptide being described std::string sequence; /// List of modifications on this peptide std::vector modifications; /// Reference to zero or more proteins which this peptide is intended to identify std::vector proteinPtrs; /// List of retention time information entries std::vector retentionTimes; Evidence evidence; Peptide(const std::string& id = ""); /// returns true iff all members are empty and contain no params bool empty() const; }; typedef boost::shared_ptr PeptidePtr; /// Chemical compound other than a peptide for which one or more transitions struct PWIZ_API_DECL Compound : public ParamContainer { /// Identifier for the compound to be used for referencing within a document std::string id; /// List of retention time information entries std::vector retentionTimes; Compound(const std::string& id = ""); /// returns true iff all members are empty and contain no params bool empty() const; }; typedef boost::shared_ptr CompoundPtr; /// Precursor (Q1) of the transition struct PWIZ_API_DECL Precursor : public ParamContainer { /// returns true iff contains no params bool empty() const; }; /// Product (Q3) of the transition struct PWIZ_API_DECL Product : public ParamContainer { /// returns true iff contains no params bool empty() const; }; struct PWIZ_API_DECL Transition : public ParamContainer { /// String label for this transition std::string id; /// Reference to a peptide which this transition is intended to identify PeptidePtr peptidePtr; /// Reference to a compound for this transition CompoundPtr compoundPtr; /// Precursor (Q1) of the transition Precursor precursor; /// Product (Q3) of the transition Product product; /// Information about a prediction for a suitable transition using some software Prediction prediction; /// Information about predicted or calibrated retention time RetentionTime retentionTime; /// List of possible interprations of fragment ions for a transition std::vector interpretationList; /// List of insutrument configurations used in the validation or optimization of the transitions std::vector configurationList; /// returns true iff all members are empty and contain no params bool empty() const; }; /// A peptide or compound that is to be included or excluded from a target list of precursor m/z values. struct PWIZ_API_DECL Target : public ParamContainer { /// String label for this target std::string id; /// Reference to a peptide for which this target is the trigger PeptidePtr peptidePtr; /// Reference to a compound for which this target is the trigger CompoundPtr compoundPtr; /// Precursor (Q1) of the target Precursor precursor; /// Information about predicted or calibrated retention time RetentionTime retentionTime; /// List of instrument configurations used in the validation or optimization of the target std::vector configurationList; /// returns true iff all members are empty and contain no params bool empty() const; }; /// List of precursor m/z targets to include or exclude struct PWIZ_API_DECL TargetList : public ParamContainer { /// List of precursor m/z targets to exclude std::vector targetExcludeList; /// List of precursor m/z targets to include std::vector targetIncludeList; /// returns true iff all members are empty and contain no params bool empty() const; }; namespace IO {struct HandlerTraData;} // forward declaration for friend struct PWIZ_API_DECL TraData { /// for internal use: not currently in the schema std::string id; /// List of controlled vocabularies used in a TraML document /// note: one of the elements in this list MUST be the PSI MS controlled vocabulary. All elements in the document MUST refer to one of the elements in this list. std::vector cvs; /// List of contacts referenced in the generation or validation of transitions std::vector contactPtrs; /// List of publications from which the transitions were collected or wherein they are published std::vector publications; /// List of instruments on which transitions are validated std::vector instrumentPtrs; /// List of software packages used in the generation of one of more transitions described in the document std::vector softwarePtrs; /// List of proteins for which one or more transitions are intended to identify std::vector proteinPtrs; /// List of compounds (including peptides) for which one or more transitions are intended to identify std::vector peptidePtrs; std::vector compoundPtrs; /// List of transitions std::vector transitions; /// List of precursor m/z targets to include or exclude TargetList targets; /// returns true iff all members are empty bool empty() const; /// returns the version of this traML document; /// for a document created programmatically, the version is the current release version of traML; /// for a document created from a file/stream, the version is the schema version read from the file/stream const std::string& version() const; TraData(); virtual ~TraData(); private: // no copying TraData(const TraData&); TraData& operator=(const TraData&); protected: std::string version_; // schema version read from the file/stream friend struct IO::HandlerTraData; }; typedef boost::shared_ptr TraDataPtr; } // tradata } // pwiz #endif // _TRADATA_HPP_ pwiz/pwiz/data/tradata/TraData.cpp0000664000175100017510000001260612664775617021133 0ustar teamcityteamcity00000000000000// // $Id: TraData.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "TraData.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace tradata { using namespace pwiz::cv; PWIZ_API_DECL vector defaultCVList() { vector result; result.resize(3); result[0] = cv::cv("MS"); result[1] = cv::cv("UNIMOD"); result[2] = cv::cv("UO"); return result; } PWIZ_API_DECL Contact::Contact(const string& id) : id(id) {} PWIZ_API_DECL bool Contact::empty() const { return id.empty() && ParamContainer::empty(); } PWIZ_API_DECL bool Publication::empty() const { return id.empty() && ParamContainer::empty(); } PWIZ_API_DECL Software::Software(const string& _id) : id(_id) {} PWIZ_API_DECL Software::Software(const string& _id, const CVParam& _param, const string& _version) : id(_id), version(_version) { cvParams.push_back(_param); } PWIZ_API_DECL bool Software::empty() const { return id.empty() && version.empty() && ParamContainer::empty(); } PWIZ_API_DECL bool Evidence::empty() const { return ParamContainer::empty(); } PWIZ_API_DECL bool Prediction::empty() const { return ParamContainer::empty() && (!contactPtr.get() || contactPtr->empty()) && (!softwarePtr.get() || softwarePtr->empty()); } PWIZ_API_DECL bool Validation::empty() const { return ParamContainer::empty(); } PWIZ_API_DECL bool RetentionTime::empty() const { return ParamContainer::empty(); } PWIZ_API_DECL bool Interpretation::empty() const { return ParamContainer::empty(); } PWIZ_API_DECL Instrument::Instrument(const string& id) : id(id) {} PWIZ_API_DECL bool Instrument::empty() const { return id.empty() && ParamContainer::empty(); } PWIZ_API_DECL bool Configuration::empty() const { return validations.empty() && (!contactPtr.get() || contactPtr->empty()) && (!instrumentPtr.get() || instrumentPtr->empty()) && ParamContainer::empty(); } PWIZ_API_DECL Protein::Protein(const string& id) : id(id) {} PWIZ_API_DECL bool Protein::empty() const { return sequence.empty() && ParamContainer::empty(); } PWIZ_API_DECL Modification::Modification() : location(), monoisotopicMassDelta(), averageMassDelta() {} PWIZ_API_DECL bool Modification::empty() const { return ParamContainer::empty() && location == int() && monoisotopicMassDelta == double() && averageMassDelta == double(); } PWIZ_API_DECL bool Precursor::empty() const { return ParamContainer::empty(); } PWIZ_API_DECL bool Product::empty() const { return ParamContainer::empty(); } PWIZ_API_DECL Peptide::Peptide(const string& id) : id(id) {} PWIZ_API_DECL bool Peptide::empty() const { return evidence.empty() && id.empty() && sequence.empty() && modifications.empty() && retentionTimes.empty() && proteinPtrs.empty() && ParamContainer::empty(); } PWIZ_API_DECL Compound::Compound(const string& id) : id(id) {} PWIZ_API_DECL bool Compound::empty() const { return id.empty() && retentionTimes.empty() && ParamContainer::empty(); } PWIZ_API_DECL bool Transition::empty() const { return ParamContainer::empty() && precursor.empty() && product.empty() && retentionTime.empty() && interpretationList.empty() && configurationList.empty() && (!peptidePtr.get() || peptidePtr->empty()) && (!compoundPtr.get() || compoundPtr->empty()) && id.empty(); } PWIZ_API_DECL bool Target::empty() const { return ParamContainer::empty() && precursor.empty() && retentionTime.empty() && configurationList.empty() && (!peptidePtr.get() || peptidePtr->empty()) && (!compoundPtr.get() || compoundPtr->empty()) && id.empty(); } PWIZ_API_DECL bool TargetList::empty() const { return targetExcludeList.empty() && targetIncludeList.empty() && ParamContainer::empty(); } PWIZ_API_DECL TraData::TraData() : version_("0.9.4") {} PWIZ_API_DECL TraData::~TraData() {} PWIZ_API_DECL bool TraData::empty() const { return id.empty() && cvs.empty() && contactPtrs.empty() && publications.empty() && instrumentPtrs.empty() && softwarePtrs.empty() && proteinPtrs.empty() && peptidePtrs.empty() && compoundPtrs.empty() && transitions.empty() && targets.empty(); } PWIZ_API_DECL const string& TraData::version() const { return version_; } } // namespace tradata } // namespace pwiz pwiz/pwiz/data/tradata/ReaderTest.cpp0000664000175100017510000001230612664775617021652 0ustar teamcityteamcity00000000000000// // $Id: ReaderTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "Reader.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::tradata; ostream* os_ = 0; class Reader1 : public Reader { public: struct Config { mutable bool done; Config() : done(false) {} }; Config config; virtual std::string identify(const std::string& filename, const std::string& head) const { bool result = (filename == "1"); if (os_) *os_ << "Reader1::identify(): " << boolalpha << result << endl; return result ? filename : std::string(""); } virtual void read(const std::string& filename, const std::string& head, TraData& result, int runIndex = 0) const { if (os_) *os_ << "Reader1::read()\n"; config.done = true; } virtual void read(const std::string& filename, const std::string& head, std::vector& results) const { results.push_back(TraDataPtr(new TraData)); read(filename, head, *results.back()); } virtual const char *getType() const {return "Reader1";} // satisfy inheritance }; class Reader2 : public Reader { public: struct Config { mutable bool done; Config() : done(false) {} }; Config config; virtual std::string identify(const std::string& filename, const std::string& head) const { bool result = (filename == "2"); if (os_) *os_ << "Reader2::identify(): " << boolalpha << result << endl; return result ? filename : std::string(""); } virtual void read(const std::string& filename, const std::string& head, TraData& result, int runIndex = 0) const { if (os_) *os_ << "Reader2::read()\n"; config.done = true; } virtual void read(const std::string& filename, const std::string& head, std::vector& results) const { results.push_back(TraDataPtr(new TraData)); read(filename, head, *results.back()); } const char *getType() const {return "Reader2";} // satisfy inheritance }; void testGet() { if (os_) *os_ << "testGet()\n"; ReaderList readers; readers.push_back(ReaderPtr(new Reader1)); readers.push_back(ReaderPtr(new Reader2)); unit_assert(readers.size() == 2); Reader1* reader1 = readers.get(); unit_assert(reader1); Reader2* reader2 = readers.get(); unit_assert(reader2); if (os_) *os_ << endl; } void testAccept() { if (os_) *os_ << "testAccept()\n"; ReaderList readers; readers.push_back(ReaderPtr(new Reader1)); readers.push_back(ReaderPtr(new Reader2)); if (os_) *os_ << "accept 1:\n"; unit_assert(readers.accept("1", "head")); if (os_) *os_ << "accept 2:\n"; unit_assert(readers.accept("2", "head")); if (os_) *os_ << "accept 3:\n"; unit_assert(!readers.accept("3", "head")); if (os_) *os_ << endl; } void testRead() { if (os_) *os_ << "testRead()\n"; ReaderList readers; readers.push_back(ReaderPtr(new Reader1)); readers.push_back(ReaderPtr(new Reader2)); TraData td; // note: composite pattern with accept/read will cause two calls // to accept(); the alternative is to maintain state between accept() // and read(), which opens possibility for misuse. unit_assert(readers.get()->config.done == false); if (readers.accept("1", "head")) readers.read("1", "head", td); unit_assert(readers.get()->config.done == true); readers.get()->config.done = false; unit_assert(readers.get()->config.done == false); if (readers.accept("2", "head")) readers.read("2", "head", td); unit_assert(readers.get()->config.done == false); unit_assert(readers.get()->config.done == true); if (os_) *os_ << endl; } void test() { testGet(); testAccept(); testRead(); } int main(int argc, char* argv[]) { TEST_PROLOG_EX(argc, argv, "_TraData") try { if (argc==2 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/misc/SampleDatumTest.cpp0000664000175100017510000000422412664775621022172 0ustar teamcityteamcity00000000000000// // $Id: SampleDatumTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "SampleDatum.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include #include using namespace pwiz::util; using namespace pwiz::data; ostream* os_ = 0; template void test() { typedef SampleDatum sd_type; vector v; v.push_back(sd_type(1,2)); v.push_back(sd_type(3,4)); v.push_back(sd_type(5,6)); // write the pairs out to a stream ostringstream oss; copy(v.begin(), v.end(), ostream_iterator(oss, "\n")); if (os_) *os_ << oss.str(); // read them back in vector w; istringstream iss(oss.str()); copy(istream_iterator(iss), istream_iterator(), back_inserter(w)); // compare the two vectors unit_assert(v == w); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; if (os_) *os_ << "SampleDatumTest\n"; test(); test(); test< double,complex >(); test< complex,complex >(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/misc/FrequencyData.cpp0000664000175100017510000003576612664775621021670 0ustar teamcityteamcity00000000000000// // $Id: FrequencyData.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "FrequencyData.hpp" #include "pwiz/utility/misc/Std.hpp" #include namespace pwiz { namespace data { namespace { #pragma pack(1) struct BinaryRecord { double frequency; double real; double imaginary; BinaryRecord(double f=0, double r=0, double i=0) : frequency(f), real(r), imaginary(i) {} }; struct BinaryHeader { char magic[4]; // "PCC\0" char type[4]; // "CFD\0" (Complex Frequency Data) int version; int headerSize; int scanNumber; double retentionTime; double calibrationA; double calibrationB; double observationDuration; double noiseFloor; int recordSize; int recordCount; BinaryHeader() : version(6), // increment version number here if binary format changes headerSize(sizeof(BinaryHeader)), scanNumber(0), retentionTime(0), calibrationA(0), calibrationB(0), observationDuration(0), noiseFloor(0), recordSize(sizeof(BinaryRecord)), recordCount(0) { strcpy(magic, "PCC"); strcpy(type, "CFD"); } }; #pragma pack() FrequencyDatum recordToDatum(const BinaryRecord& record) { return FrequencyDatum(record.frequency, complex(record.real, record.imaginary)); } BinaryRecord datumToRecord(const FrequencyDatum& datum) { return BinaryRecord(datum.x, datum.y.real(), datum.y.imag()); } } // namespace struct FrequencyData::Impl { container data_; int scanNumber_; double retentionTime_; CalibrationParameters calibrationParameters_; double observationDuration_; double noiseFloor_; double shift_; complex scale_; const_iterator max_; double mean_; double meanSquare_; double sumSquares_; double variance_; Impl() : scanNumber_(0), retentionTime_(0), observationDuration_(0), noiseFloor_(0), shift_(0), scale_(1), mean_(0), meanSquare_(0), sumSquares_(0), variance_(0) {} void analyze(); void transform(double shift, complex scale); void operator+=(const FrequencyData::Impl& that); void calculateNoiseFloor(); double cutoffNoiseFloor(); double observationDurationEstimatedFromData(); }; void FrequencyData::Impl::analyze() { max_ = data_.end(); double sum = 0; sumSquares_ = 0; for (const_iterator it=data_.begin(); it!=data_.end(); ++it) { if (max_==data_.end() || norm(it->y)>norm(max_->y)) max_ = it; double value = abs(it->y); sum += value; sumSquares_ += value*value; } mean_ = sum/data_.size(); meanSquare_ = sumSquares_/data_.size(); variance_ = meanSquare_ - mean_*mean_; if (noiseFloor_ == 0) calculateNoiseFloor(); } void FrequencyData::Impl::transform(double shift, complex scale) { shift_ += shift; scale_ *= scale; for (iterator it=data_.begin(); it!=data_.end(); ++it) { it->x += shift; it->y *= scale; } } void FrequencyData::Impl::operator+=(const FrequencyData::Impl& that) { if (data_.size() != that.data_.size()) throw runtime_error("[FrequencyData::Impl::operator+=] Size mismatch"); const double epsilon = 1e-6; const_iterator jt = that.data_.begin(); for (iterator it=data_.begin(); it!=data_.end(); ++it, ++jt) { if (abs(it->x - jt->x) > epsilon) throw runtime_error("[FrequencyData::Impl::operator+=] Domain mismatch"); it->y += jt->y; } } namespace { float floatNormIntensity(const FrequencyDatum& datum) { return (float)norm(datum.y); } } // namespace void FrequencyData::Impl::calculateNoiseFloor() { if (data_.empty()) return; vector squareIntensities; std::transform(data_.begin(), data_.end(), back_inserter(squareIntensities), floatNormIntensity); sort(squareIntensities.begin(), squareIntensities.end()); size_t indexMidpoint = squareIntensities.size()/2; float medianNorm = squareIntensities[indexMidpoint]; noiseFloor_ = sqrt(medianNorm * log(2.)); } double FrequencyData::Impl::cutoffNoiseFloor() { double cutoff = mean_ + sqrt(variance_); cutoff *= cutoff; // calculate stats below cutoff int count = 0; double sum = 0; double sumSquares = 0; for (const_iterator it=data_.begin(); it!=data_.end(); ++it) { if (norm(it->y) < cutoff) { double value = abs(it->y); sum += value; sumSquares += value*value; count++; } } double mean = sum/count; double meanSquare = sumSquares/count; double variance = meanSquare - mean*mean; return mean + sqrt(variance); } double FrequencyData::Impl::observationDurationEstimatedFromData() { // frequency difference between samples is 1/T // compute average frequency difference to get a better estimate double sum = 0; double count = 0; double sumAll = 0; double countAll = 0; if (data_.empty()) return 0; for (iterator it=data_.begin()+1; it!=data_.end(); ++it) { double difference = it->x - (it-1)->x; if (norm(it->y)>0 && norm((it-1)->y)>0) // avoid zero-signal gaps { count++; sum += difference; } countAll++; sumAll += difference; } double result = 0; if (sum > 0) result = count/sum; else if (sumAll > 0) result = countAll/sumAll; return result; } PWIZ_API_DECL FrequencyData::FrequencyData() : impl_(new Impl) {} PWIZ_API_DECL FrequencyData::FrequencyData(const std::string& filename, IOMode mode) : impl_(new Impl) { read(filename, mode); } PWIZ_API_DECL FrequencyData::FrequencyData(const FrequencyData& that, const_iterator begin, const_iterator end) : impl_(new Impl) { copy(begin, end, back_inserter(impl_->data_)); impl_->scanNumber_ = that.scanNumber(); impl_->retentionTime_ = that.retentionTime(); impl_->calibrationParameters_ = that.calibrationParameters(); impl_->observationDuration_ = that.observationDuration(); impl_->noiseFloor_ = that.noiseFloor(); impl_->analyze(); } PWIZ_API_DECL FrequencyData::FrequencyData(const FrequencyData& that, const_iterator center, int radius) : impl_(new Impl) { const_iterator begin = centerdata_)); impl_->scanNumber_ = that.scanNumber(); impl_->retentionTime_ = that.retentionTime(); impl_->calibrationParameters_ = that.calibrationParameters(); impl_->observationDuration_ = that.observationDuration(); impl_->noiseFloor_ = that.noiseFloor(); impl_->analyze(); } PWIZ_API_DECL FrequencyData::~FrequencyData() {} // automatic cleanup of impl_ PWIZ_API_DECL void FrequencyData::read(const string& filename, IOMode mode) { ifstream is(filename.c_str(), ios::binary); if (!is) throw runtime_error("[Data.cpp::FrequencyData::read()] Unable to open file " + filename); if (mode == Automatic) { char magic[4]; is.read(magic, 4); if (!strncmp(magic, "PCC", 4)) mode = Binary; else mode = Text; is.seekg(0, ios::beg); } read(is, mode); if (mode == Text) { impl_->observationDuration_ = impl_->observationDurationEstimatedFromData(); } } PWIZ_API_DECL void FrequencyData::read(std::istream& is, IOMode mode) { if (mode == Text) { copy(istream_iterator(is), istream_iterator(), back_inserter(impl_->data_)); } else if (mode == Binary) { BinaryHeader header; is.read((char*)&header, sizeof(header)); if (!is) throw runtime_error("[Data.cpp::FrequencyData::read()] Error reading header."); BinaryHeader good; if (strncmp(header.magic, good.magic, sizeof(good.magic)) || strncmp(header.type, good.type, sizeof(good.type)) || header.version != good.version || header.headerSize != good.headerSize || header.recordSize != good.recordSize) throw runtime_error("[Data.cpp::FrequencyData::read()] Invalid header."); impl_->scanNumber_ = header.scanNumber; impl_->retentionTime_ = header.retentionTime; impl_->calibrationParameters_.A = header.calibrationA; impl_->calibrationParameters_.B = header.calibrationB; impl_->observationDuration_ = header.observationDuration; impl_->noiseFloor_ = header.noiseFloor; vector records(header.recordCount); is.read((char*)&records[0], header.recordCount*sizeof(BinaryRecord)); if (!is) throw runtime_error("[Data.cpp::FrequencyData::read()] Error reading records."); std::transform(records.begin(), records.end(), back_inserter(impl_->data_), recordToDatum); } else { throw logic_error("[Data.cpp::FrequencyData::read()] Cannot read from stream with mode==Automatic.\n"); } impl_->analyze(); } PWIZ_API_DECL void FrequencyData::write(const std::string& filename, IOMode mode) const { ios::openmode flags = ios::out; if (mode == Binary) flags |= ios::binary; ofstream os(filename.c_str(), flags); if (!os) throw runtime_error("[Data.cpp::FrequencyData::write()] Unable to open file " + filename); write(os, mode); } PWIZ_API_DECL void FrequencyData::write(std::ostream& os, IOMode mode) const { if (mode == Text) { os << setprecision(10); copy(impl_->data_.begin(), impl_->data_.end(), ostream_iterator(os, "\n")); } else { BinaryHeader header; header.scanNumber = impl_->scanNumber_; header.retentionTime = impl_->retentionTime_; header.calibrationA = impl_->calibrationParameters_.A; header.calibrationB = impl_->calibrationParameters_.B; header.observationDuration = impl_->observationDuration_; header.noiseFloor = impl_->noiseFloor_; header.recordCount = (int)impl_->data_.size(); os.write((const char*)&header, sizeof(header)); if (!os) throw runtime_error("[Data.cpp::FrequencyData::write()] Error writing header."); vector records(header.recordCount); std::transform(impl_->data_.begin(), impl_->data_.end(), records.begin(), datumToRecord); os.write((const char*)&records[0], header.recordCount*sizeof(BinaryRecord)); if (!os) throw runtime_error("[Data.cpp::FrequencyData::write()] Error writing records."); } } PWIZ_API_DECL FrequencyData::container& FrequencyData::data() {return impl_->data_;} PWIZ_API_DECL const FrequencyData::container& FrequencyData::data() const {return impl_->data_;} PWIZ_API_DECL int FrequencyData::scanNumber() const {return impl_->scanNumber_;} PWIZ_API_DECL void FrequencyData::scanNumber(int value) {impl_->scanNumber_ = value;} PWIZ_API_DECL double FrequencyData::retentionTime() const {return impl_->retentionTime_;} PWIZ_API_DECL void FrequencyData::retentionTime(double value) {impl_->retentionTime_ = value;} PWIZ_API_DECL const CalibrationParameters& FrequencyData::calibrationParameters() const {return impl_->calibrationParameters_;} PWIZ_API_DECL void FrequencyData::calibrationParameters(const CalibrationParameters& c) {impl_->calibrationParameters_ = c;} PWIZ_API_DECL double FrequencyData::observationDuration() const {return impl_->observationDuration_;} PWIZ_API_DECL void FrequencyData::observationDuration(double value) {impl_->observationDuration_ = value;} PWIZ_API_DECL double FrequencyData::noiseFloor() const {return impl_->noiseFloor_;} PWIZ_API_DECL void FrequencyData::noiseFloor(double value) {impl_->noiseFloor_ = value;} PWIZ_API_DECL void FrequencyData::transform(double shift, complex scale) {impl_->transform(shift, scale);} PWIZ_API_DECL double FrequencyData::shift() const {return impl_->shift_;} PWIZ_API_DECL complex FrequencyData::scale() const {return impl_->scale_;} PWIZ_API_DECL void FrequencyData::normalize() {impl_->transform(-impl_->max_->x, 1/abs(impl_->max_->y));} PWIZ_API_DECL void FrequencyData::operator+=(const FrequencyData& that) {*impl_+=*that.impl_;} PWIZ_API_DECL void FrequencyData::analyze() {impl_->analyze();} PWIZ_API_DECL FrequencyData::const_iterator FrequencyData::max() const {return impl_->max_;} PWIZ_API_DECL double FrequencyData::mean() const {return impl_->mean_;} PWIZ_API_DECL double FrequencyData::meanSquare() const {return impl_->meanSquare_;} PWIZ_API_DECL double FrequencyData::sumSquares() const {return impl_->sumSquares_;} PWIZ_API_DECL double FrequencyData::variance() const {return impl_->variance_;} PWIZ_API_DECL double FrequencyData::cutoffNoiseFloor() const {return impl_->cutoffNoiseFloor();} PWIZ_API_DECL double FrequencyData::observationDurationEstimatedFromData() const {return impl_->observationDurationEstimatedFromData();} namespace { bool hasFrequencyLessThan(const FrequencyDatum& a, const FrequencyDatum& b) { return a.x < b.x; } } // namespace PWIZ_API_DECL FrequencyData::const_iterator FrequencyData::findNearest(double frequency) const { FrequencyDatum dummy(frequency, 0); const_iterator above = lower_bound(impl_->data_.begin(), impl_->data_.end(), dummy, hasFrequencyLessThan); if (above == impl_->data_.begin()) return above; if (above == impl_->data_.end()) return above-1; const_iterator below = above - 1; return (abs(above->x-frequency) < abs(below->x-frequency)) ? above : below; } PWIZ_API_DECL pair FrequencyData::magnitudeSample(const FrequencyDatum& datum) { return make_pair(datum.x, abs(datum.y)); } } // namespace data } // namespace pwiz pwiz/pwiz/data/misc/SampleDatum.hpp0000664000175100017510000000544412664775621021344 0ustar teamcityteamcity00000000000000// // $Id: SampleDatum.hpp 1195 2009-08-14 22:12:04Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SAMPLEDATUM_HPP_ #define _SAMPLEDATUM_HPP_ #include "pwiz/utility/misc/Export.hpp" #include #include #include #include namespace pwiz { namespace data { template struct SampleDatum { abscissa_type x; ordinate_type y; SampleDatum(abscissa_type _x=0, ordinate_type _y=0) : x(_x), y(_y) {} }; template bool operator==(const SampleDatum& a, const SampleDatum& b) { return (a.x==b.x && a.y==b.y); } namespace SampleDatumConstant { const char open_ = '<'; const char separator_ = ';'; // MSVC feature: this cannot be ',' const char close_ = '>'; } // namespace SampleDatumConstant template std::ostream& operator<<(std::ostream& os, const SampleDatum& datum) { os << SampleDatumConstant::open_ << datum.x << SampleDatumConstant::separator_ << datum.y << SampleDatumConstant::close_; return os; } template std::istream& operator>>(std::istream& is, SampleDatum& datum) { std::string buffer; is >> buffer; if (!is) return is; std::istringstream iss(buffer); char open, separator, close; abscissa_type x; ordinate_type y; iss >> open >> x >> separator >> y >> close; if (open != SampleDatumConstant::open_ || separator != SampleDatumConstant::separator_ || close != SampleDatumConstant::close_) throw std::runtime_error("[SampleDatum::operator>>] Invalid format."); datum.x = x; datum.y = y; return is; } } // namespace data } // namespace pwiz #endif // _SAMPLEDATUM_HPP_ pwiz/pwiz/data/misc/CalibrationParameters.hpp0000664000175100017510000000647612664775621023411 0ustar teamcityteamcity00000000000000// // $Id: CalibrationParameters.hpp 1195 2009-08-14 22:12:04Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _CALIBRATIONPARAMETERS_HPP_ #define _CALIBRATIONPARAMETERS_HPP_ #include "pwiz/utility/misc/Export.hpp" #include #include #include namespace pwiz { namespace data { const double thermoA_FT_ = 1.075e8; const double thermoB_FT_ = -3.455e8; const double thermoA_Orbitrap_ = 4.753e10; const double thermoB_Orbitrap_ = 0; #pragma pack(1) struct CalibrationParameters { double A; double B; enum InstrumentModel {FT, Orbitrap}; InstrumentModel instrumentModel; CalibrationParameters(double a=0, double b=0, InstrumentModel im=FT); double mz(double frequency) const; double frequency(double mz) const; bool operator==(const CalibrationParameters& that) const; bool operator!=(const CalibrationParameters& that) const; static CalibrationParameters thermo_FT(); static CalibrationParameters thermo_Orbitrap(); }; #pragma pack() inline std::ostream& operator<<(std::ostream& os, const CalibrationParameters& p) { os << "(" << p.A << "," << p.B << ")"; return os; } inline CalibrationParameters::CalibrationParameters(double a, double b, InstrumentModel im) : A(a), B(b), instrumentModel(im) {} inline double CalibrationParameters::mz(double frequency) const { if (frequency == 0) throw std::runtime_error("[CalibrationParameters::mz()] Division by zero.\n"); return (instrumentModel==Orbitrap) ? A/(frequency*frequency) : A/frequency + B/(frequency*frequency); } inline double CalibrationParameters::frequency(double mz) const { if (mz == 0) throw std::runtime_error("[CalibrationParameters::frequency()] Division by zero.\n"); return (instrumentModel==Orbitrap) ? sqrt(A/mz) : (A+sqrt(A*A + 4*B*mz))/(2*mz); } inline bool CalibrationParameters::operator==(const CalibrationParameters& that) const { return A==that.A && B==that.B && instrumentModel==that.instrumentModel; } inline bool CalibrationParameters::operator!=(const CalibrationParameters& that) const { return !operator==(that); } inline CalibrationParameters CalibrationParameters::thermo_FT() { return CalibrationParameters(thermoA_FT_, thermoB_FT_, FT); } inline CalibrationParameters CalibrationParameters::thermo_Orbitrap() { return CalibrationParameters(thermoA_Orbitrap_, thermoB_Orbitrap_, Orbitrap); } } // namespace data } // namespace pwiz #endif // _CALIBRATIONPARAMETERS_HPP_ pwiz/pwiz/data/misc/FrequencyDataTestData.hpp0000664000175100017510000000224612664775621023312 0ustar teamcityteamcity00000000000000// // $Id: FrequencyDataTestData.hpp 1195 2009-08-14 22:12:04Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _FREQUENCYDATATESTDATA_HPP_ #define _FREQUENCYDATATESTDATA_HPP_ struct RawMassDatum { double mz; double intensity; }; extern RawMassDatum sampleMassData_[]; extern const unsigned int sampleMassDataSize_; extern const char* sampleFrequencyData_; #endif // _FREQUENCYDATATESTDATA_HPP_ pwiz/pwiz/data/misc/MinimumPepXML.cpp0000664000175100017510000017636612664775621021600 0ustar teamcityteamcity00000000000000// // $Id: MinimumPepXML.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Kate Hoff // // Copyright 2009 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "MinimumPepXML.hpp" #include "pwiz/utility/minimxml/SAXParser.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz; using namespace pwiz::data::pepxml; using namespace pwiz::data::peakdata; using namespace pwiz::minimxml; using namespace minimxml::SAXParser; ostream* _log = 0; void setLogStream(ostream& os) { _log = &os; return; } namespace{ string stringCastVector(const vector& v) { if ( v.size() == 0 ) return ""; const char *delimiter = ","; const pair bookends = make_pair("(",")"); string result; result += bookends.first; vector::const_iterator it = v.begin(); for(; it < v.end() - 1; ++it) { result += boost::lexical_cast(*it); result += delimiter; } result += boost::lexical_cast(*it); result += bookends.second; return result; } vector vectorCastString(const string& s) { const char* delimiter = ","; const pair bookends = make_pair("(\0",")\0"); vector result; string::const_iterator it = s.begin(); ++it; // skip first bookend while (it != s.end()) // switch to using string::find here { string vectorEntry = ""; while(strncmp(&(*it), delimiter, 1) && strncmp(&(*it), bookends.second, 1)) { vectorEntry += *it; ++it; } result.push_back(boost::lexical_cast(vectorEntry)); ++it; // skip the delimiter and eventually the second bookend } return result; } bool operator==(const vector& a, const vector& b) { if (a.size() != b.size()) return false; vector::const_iterator a_it = a.begin(); vector::const_iterator b_it = b.begin(); for( ; a_it != a.end(); ++a_it, ++b_it) { if (!(**a_it == **b_it)) return false; } return true; } } // anonymous namespace PWIZ_API_DECL void Specificity::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("cut", cut)); attributes.push_back(make_pair("no_cut", noCut)); attributes.push_back(make_pair("sense", sense)); attributes.push_back(make_pair("min_spacing", boost::lexical_cast(minSpace))); writer.startElement("specificity", attributes, XMLWriter::EmptyElement); } struct HandlerSpecificity : public SAXParser::Handler { Specificity* specificity; HandlerSpecificity( Specificity* _specificity = 0 ) : specificity( _specificity ) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "specificity") { getAttribute(attributes, "cut", specificity->cut); getAttribute(attributes, "no_cut", specificity->noCut); getAttribute(attributes, "sense", specificity->sense); string value; getAttribute(attributes, "min_spacing", value); if (!value.empty()) specificity->minSpace = lexical_cast(value); return Handler::Status::Ok; } else { throw runtime_error(("[HandlerSpecificity] : Unexpected element name : " + name).c_str()); return Handler::Status::Done; } } }; PWIZ_API_DECL void Specificity::read(istream& is) { HandlerSpecificity handler(this); parse(is, handler); } PWIZ_API_DECL bool Specificity::operator==(const Specificity& that) const { return cut == that.cut && noCut == that.noCut && sense == that.sense; } PWIZ_API_DECL bool Specificity::operator!=(const Specificity& that) const { return !(*this == that); } PWIZ_API_DECL void SampleEnzyme::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("name", name)); attributes.push_back(make_pair("description", description)); attributes.push_back(make_pair("fidelity", fidelity)); attributes.push_back(make_pair("independent", independent? "true" : "false")); writer.startElement("sample_enzyme", attributes); specificity.write(writer); writer.endElement(); } struct HandlerSampleEnzyme : public SAXParser::Handler { SampleEnzyme* sampleEnzyme; HandlerSampleEnzyme( SampleEnzyme* _sampleEnzyme = 0 ) : sampleEnzyme( _sampleEnzyme ) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if ( name == "sample_enzyme" ) { getAttribute(attributes, "name", sampleEnzyme->name); getAttribute(attributes, "description", sampleEnzyme->description); getAttribute(attributes, "fidelity", sampleEnzyme->fidelity); string value; getAttribute(attributes, "independent", value); sampleEnzyme->independent = value=="true"? true : false; return Handler::Status::Ok; } else if ( name == "specificity" ) { _handlerSpecificity.specificity= &(sampleEnzyme->specificity); return Handler::Status(Status::Delegate, &(_handlerSpecificity)); } else { throw runtime_error(("[HandlerSampleEnzyme] : Unexpected element name : "+ name).c_str()); return Handler::Status::Done; } } private: HandlerSpecificity _handlerSpecificity; }; PWIZ_API_DECL void SampleEnzyme::read(istream& is) { HandlerSampleEnzyme handler(this); parse(is, handler); } PWIZ_API_DECL bool SampleEnzyme::operator==(const SampleEnzyme& that) const { return name == that.name && specificity == that.specificity; } PWIZ_API_DECL bool SampleEnzyme::operator!=(const SampleEnzyme& that) const { return !(*this == that); } PWIZ_API_DECL void SearchDatabase::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("local_path", localPath)); attributes.push_back(make_pair("database_name", databaseName)); attributes.push_back(make_pair("database_release_identifier", databaseReleaseIdentifier)); attributes.push_back(make_pair("size_in_db_entries", boost::lexical_cast(sizeInDbEntries))); attributes.push_back(make_pair("size_of_residues", boost::lexical_cast(sizeOfResidues))); attributes.push_back(make_pair("type", type)); writer.startElement("search_database", attributes, XMLWriter::EmptyElement); } struct HandlerSearchDatabase : public SAXParser::Handler { SearchDatabase* searchDatabase; HandlerSearchDatabase(SearchDatabase* _searchDatabase = 0) : searchDatabase(_searchDatabase) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "search_database") { getAttribute(attributes, "local_path", searchDatabase->localPath); getAttribute(attributes, "database_name", searchDatabase->databaseName); getAttribute(attributes, "database_release_identifier", searchDatabase->databaseReleaseIdentifier); string value; getAttribute(attributes, "size_in_db_entries", value); if (!value.empty()) searchDatabase->sizeInDbEntries = lexical_cast(value); value.clear(); getAttribute(attributes, "size_of_residues", value); if (!value.empty()) searchDatabase->sizeOfResidues = lexical_cast(value); getAttribute(attributes, "type", searchDatabase->type); return Handler::Status::Ok; } else { throw runtime_error(("[HandlerSearchDatabase] Unexpected element name : " + name).c_str()); return Handler::Status::Done; } } }; PWIZ_API_DECL void SearchDatabase::read(istream& is) { HandlerSearchDatabase handlerSearchDatabase(this); parse(is, handlerSearchDatabase); } PWIZ_API_DECL bool SearchDatabase::operator==(const SearchDatabase& that) const { return localPath == that.localPath && type == that.type; } PWIZ_API_DECL bool SearchDatabase::operator!=(const SearchDatabase& that) const { return !(*this == that); } PWIZ_API_DECL void Q3RatioResult::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("light_firstscan", boost::lexical_cast(lightFirstScan))); attributes.push_back(make_pair("light_lastscan", boost::lexical_cast(lightLastScan))); attributes.push_back(make_pair("light_mass", boost::lexical_cast(lightMass))); attributes.push_back(make_pair("heavy_firstscan", boost::lexical_cast(heavyFirstScan))); attributes.push_back(make_pair("heavy_lastscan", boost::lexical_cast(heavyLastScan))); attributes.push_back(make_pair("heavy_mass", boost::lexical_cast(heavyMass))); attributes.push_back(make_pair("light_area", boost::lexical_cast(lightArea))); attributes.push_back(make_pair("heavy_area", boost::lexical_cast(heavyArea))); attributes.push_back(make_pair("q2_light_area", boost::lexical_cast(q2LightArea))); attributes.push_back(make_pair("q2_heavy_area", boost::lexical_cast(q2HeavyArea))); attributes.push_back(make_pair("decimal_ratio", boost::lexical_cast(decimalRatio))); writer.startElement("q3ratio_result", attributes, XMLWriter::EmptyElement); } struct HandlerQ3RatioResult : public SAXParser::Handler { Q3RatioResult* q3RatioResult; HandlerQ3RatioResult(Q3RatioResult* _q3RatioResult = 0) : q3RatioResult(_q3RatioResult) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "q3ratio_result") { getAttribute(attributes, "light_firstscan", q3RatioResult->lightFirstScan); getAttribute(attributes, "light_lastscan", q3RatioResult->lightLastScan); getAttribute(attributes, "light_mass", q3RatioResult->lightMass); getAttribute(attributes, "heavy_firstscan", q3RatioResult->heavyFirstScan); getAttribute(attributes, "heavy_lastscan", q3RatioResult->heavyLastScan); getAttribute(attributes, "heavy_mass", q3RatioResult->heavyMass); getAttribute(attributes, "light_area", q3RatioResult->lightArea); getAttribute(attributes, "heavy_area", q3RatioResult->heavyArea); getAttribute(attributes, "q2_light_area", q3RatioResult->q2LightArea); getAttribute(attributes, "q2_heavy_area", q3RatioResult->q2HeavyArea); getAttribute(attributes, "decimal_ratio", q3RatioResult->decimalRatio); return Handler::Status::Ok; } else { throw runtime_error(("[HandlerQ3RatioResult] Unexpected element name: " + name).c_str()); return Handler::Status::Done; } } }; PWIZ_API_DECL void Q3RatioResult::read(istream& is) { HandlerQ3RatioResult _handlerQ3RatioResult(this); parse(is, _handlerQ3RatioResult); } PWIZ_API_DECL bool Q3RatioResult::operator==(const Q3RatioResult& that) const { return lightFirstScan == that.lightFirstScan && lightLastScan == that.lightLastScan && lightMass == that.lightMass && heavyFirstScan == that.heavyFirstScan && heavyLastScan == that.heavyLastScan && heavyMass == that.heavyMass && lightArea == that.lightArea && heavyArea == that.heavyArea && q2LightArea == that.q2LightArea && q2HeavyArea == that.q2HeavyArea && decimalRatio == that.decimalRatio; } PWIZ_API_DECL bool Q3RatioResult::operator!=(const Q3RatioResult& that) const { return !(*this == that); } struct HandlerMixtureModel : public SAXParser::Handler { MixtureModel* mixtureModel; HandlerMixtureModel(MixtureModel* _mixtureModel = 0) : mixtureModel(_mixtureModel) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!mixtureModel) throw runtime_error("[HandlerMixtureModel::startElement] " "NULL mixtureModel"); if (name != "roc_data_point") throw runtime_error(("[HandlerMixtureModel::startElement] " "Unknown tag: "+name).c_str()); getAttribute(attributes, "precursor_ion_charge", mixtureModel->precursor_ion_charge); getAttribute(attributes, "comments", mixtureModel->comments); getAttribute(attributes, "prior_probability", mixtureModel->prior_probability); getAttribute(attributes, "est_tot_correct", mixtureModel->est_tot_correct); getAttribute(attributes, "tot_num_spectra", mixtureModel->tot_num_spectra); getAttribute(attributes, "num_iterations", mixtureModel->num_iterations); return Status::Ok; } }; struct HandlerDistributionPoint : public SAXParser::Handler { DistributionPoint* distributionPoint; HandlerDistributionPoint(DistributionPoint* _distributionPoint = 0) : distributionPoint(_distributionPoint) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!distributionPoint) throw runtime_error("[HandlerDistributionPoint::startElement] " "NULL distributionPoint"); if (name != "roc_data_point") throw runtime_error(("[HandlerDistributionPoint::startElement] " "Unknown tag: "+name).c_str()); getAttribute(attributes, "fvalue", distributionPoint->fvalue); getAttribute(attributes, "obs_1_distr", distributionPoint->obs_1_distr); getAttribute(attributes, "model_1_pos_distr", distributionPoint->model_1_pos_distr); getAttribute(attributes, "model_1_neg_distr", distributionPoint->model_1_neg_distr); getAttribute(attributes, "obs_2_distr", distributionPoint->obs_2_distr); getAttribute(attributes, "model_2_pos_distr", distributionPoint->model_2_pos_distr); getAttribute(attributes, "model_2_neg_distr", distributionPoint->model_2_neg_distr); getAttribute(attributes, "obs_3_distr", distributionPoint->obs_3_distr); getAttribute(attributes, "model_3_pos_distr", distributionPoint->model_3_pos_distr); getAttribute(attributes, "model_3_neg_distr", distributionPoint->model_3_neg_distr); return Status::Ok; } }; struct HandlerErrorPoint : public SAXParser::Handler { ErrorPoint* errorPoint; HandlerErrorPoint(ErrorPoint* _errorPoint = 0) : errorPoint(_errorPoint) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!errorPoint) throw runtime_error("[HandlerErrorPoint::startElement] " "NULL errorPoint"); if (name != "roc_data_point") throw runtime_error(("[HandlerErrorPoint::startElement] " "Unknown tag: "+name).c_str()); getAttribute(attributes, "error", errorPoint->error); getAttribute(attributes, "min_prob", errorPoint->min_prob); getAttribute(attributes, "num_corr", errorPoint->num_corr); getAttribute(attributes, "num_incorr", errorPoint->num_incorr); return Status::Ok; } }; struct HandlerRocDataPoint : public SAXParser::Handler { RocDataPoint* rocDataPoint; HandlerRocDataPoint(RocDataPoint* _rocDataPoint = 0) : rocDataPoint(_rocDataPoint) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!rocDataPoint) throw runtime_error("[HandlerRocDataPoint::startElement] " "NULL rocDataPoint"); if (name != "roc_data_point") throw runtime_error(("[HandlerRocDataPoint::startElement] " "Unknown tag: "+name).c_str()); getAttribute(attributes, "min_prob", rocDataPoint->min_prob); getAttribute(attributes, "sensitivity", rocDataPoint->sensitivity); getAttribute(attributes, "error", rocDataPoint->error); getAttribute(attributes, "num_corr", rocDataPoint->num_corr); getAttribute(attributes, "num_incorr", rocDataPoint->num_incorr); return Handler::Status::Ok; } }; struct HandlerPeptideProphetSummary : public SAXParser::Handler { PeptideProphetSummary* peptideProphetSummary; HandlerPeptideProphetSummary(PeptideProphetSummary* _peptideProphetSummary = 0) : peptideProphetSummary(_peptideProphetSummary) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!peptideProphetSummary) throw runtime_error("[HandlerPeptideProphetSummary::startElement]" " NULL peptideProphetSummary."); if (name == "peptideprophet_summary") { getAttribute(attributes, "version", peptideProphetSummary->version); getAttribute(attributes, "author", peptideProphetSummary->author); getAttribute(attributes, "min_prob", peptideProphetSummary->min_prob); getAttribute(attributes, "options", peptideProphetSummary->options); getAttribute(attributes, "est_tot_num_correct", peptideProphetSummary->est_tot_num_correct); return Status::Ok; } //std::vector error_point; //std::vector distribution_point; //std::vector mixture_model; else if (name == "inputFile") { string value; getAttribute(attributes, "name", value); if (!value.empty()) peptideProphetSummary->inputFile.push_back(value); } else if (name == "roc_data_point") { peptideProphetSummary->roc_data_point.push_back(RocDataPoint()); _handlerRocDataPoint.rocDataPoint = &peptideProphetSummary->roc_data_point.back(); return Status(Status::Delegate, &_handlerRocDataPoint); } else if (name == "error_point") { peptideProphetSummary->error_point.push_back(ErrorPoint()); _handlerErrorPoint.errorPoint = &peptideProphetSummary->error_point.back(); return Handler::Status(Handler::Status::Delegate, &_handlerErrorPoint); } else if (name == "distribution_point") { peptideProphetSummary->distribution_point.push_back(DistributionPoint()); _handlerDistributionPoint.distributionPoint = &peptideProphetSummary->distribution_point.back(); return Status(Status::Delegate, &_handlerDistributionPoint); } else if (name == "mixture_mode") { peptideProphetSummary->mixture_model.push_back(MixtureModel()); _handlerMixtureModel.mixtureModel = &peptideProphetSummary->mixture_model.back(); return Status(Status::Delegate, &_handlerMixtureModel); } return Status::Ok; } private: HandlerRocDataPoint _handlerRocDataPoint; HandlerErrorPoint _handlerErrorPoint; HandlerDistributionPoint _handlerDistributionPoint; HandlerMixtureModel _handlerMixtureModel; }; PWIZ_API_DECL void PeptideProphetResult::write(XMLWriter& writer) const { const string allNttProbStr = stringCastVector(allNttProb); XMLWriter::Attributes attributes; attributes.push_back(make_pair("probability", boost::lexical_cast(probability))); attributes.push_back(make_pair("all_ntt_prob", allNttProbStr)); if (!analysis.empty()) attributes.push_back(make_pair("analysis", analysis)); writer.startElement("peptideprophet_result", attributes); writer.endElement(); } struct HandlerPeptideProphetResult : public SAXParser::Handler { PeptideProphetResult* peptideProphetResult; HandlerPeptideProphetResult(PeptideProphetResult* _peptideProphetResult = 0) : peptideProphetResult(_peptideProphetResult) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "peptideprophet_result") { getAttribute(attributes, "probability", peptideProphetResult->probability); getAttribute(attributes, "all_ntt_prob", _allNttProbStr); peptideProphetResult->allNttProb = vectorCastString(_allNttProbStr); getAttribute(attributes, "analysis", peptideProphetResult->analysis); return Handler::Status::Ok; } else { if (_log) *_log << ("[HandlerPeptideProphetResult] Ignoring non-essential element name : " + name).c_str() << endl; return Handler::Status::Ok; } } private: string _allNttProbStr; }; PWIZ_API_DECL void PeptideProphetResult::read(istream& is) { HandlerPeptideProphetResult handlerPeptideProphetResult(this); parse(is, handlerPeptideProphetResult); } PWIZ_API_DECL bool PeptideProphetResult::operator==(const PeptideProphetResult& that) const { return probability == that.probability && allNttProb == that.allNttProb; } PWIZ_API_DECL bool PeptideProphetResult::operator!=(const PeptideProphetResult& that) const { return !(*this == that); } PWIZ_API_DECL void AnalysisResult::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("analysis", analysis)); writer.startElement("analysis_result", attributes); if (analysis == "peptideprophet") peptideProphetResult.write(writer); if (analysis == "q3") q3RatioResult.write(writer); writer.endElement(); } struct HandlerAnalysisResult : public SAXParser::Handler { AnalysisResult* analysisResult; HandlerAnalysisResult(AnalysisResult* _analysisResult = 0) : analysisResult(_analysisResult){} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if ( name == "analysis_result" ) { getAttribute(attributes, "analysis", analysisResult->analysis); return Handler::Status::Ok; } else if (name == "peptideprophet_result") { _handlerPeptideProphetResult.peptideProphetResult = &(analysisResult->peptideProphetResult); return Handler::Status(Status::Delegate, &_handlerPeptideProphetResult); } else if (name == "q3ratio_result") { _handlerQ3RatioResult.q3RatioResult = &(analysisResult->q3RatioResult); return Handler::Status(Status::Delegate, &_handlerQ3RatioResult); } else { if (_log) *_log << ("[HandlerAnalysisResult] Ignoring non-essential element name : " + name).c_str() << endl; return Handler::Status::Ok; } } private: HandlerPeptideProphetResult _handlerPeptideProphetResult; HandlerQ3RatioResult _handlerQ3RatioResult; }; PWIZ_API_DECL void AnalysisResult::read(istream& is) { HandlerAnalysisResult handlerAnalysisResult(this); parse(is, handlerAnalysisResult); } PWIZ_API_DECL bool AnalysisResult::operator==(const AnalysisResult& that) const { return analysis == that.analysis && peptideProphetResult == that.peptideProphetResult && q3RatioResult == that.q3RatioResult ; } PWIZ_API_DECL bool AnalysisResult::operator!=(const AnalysisResult& that) const { return !(*this == that); } PWIZ_API_DECL void AlternativeProtein::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("protein", protein)); attributes.push_back(make_pair("protein_descr", proteinDescr)); attributes.push_back(make_pair("num_tol_term", numTolTerm)); writer.startElement("alternative_protein", attributes, XMLWriter::EmptyElement); } struct HandlerAlternativeProtein : public SAXParser::Handler { AlternativeProtein* alternativeProtein; HandlerAlternativeProtein(AlternativeProtein* _alternativeProtein = 0) : alternativeProtein(_alternativeProtein){} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if ( name == "alternative_protein" ) { getAttribute(attributes, "protein", alternativeProtein->protein); getAttribute(attributes, "protein_descr", alternativeProtein->proteinDescr); getAttribute(attributes, "num_tol_term", alternativeProtein->numTolTerm); return Handler::Status::Ok; } else { throw runtime_error(("[HandlerAlternativeProtein] Unexpected element name : " + name).c_str()); return Handler::Status::Done; } } }; PWIZ_API_DECL void AlternativeProtein::read(istream& is) { HandlerAlternativeProtein handlerAlternativeProtein(this); parse(is, handlerAlternativeProtein); } PWIZ_API_DECL bool AlternativeProtein::operator==(const AlternativeProtein& that) const { return protein == that.protein && proteinDescr == that.proteinDescr && numTolTerm == that.numTolTerm; } PWIZ_API_DECL bool AlternativeProtein::operator!=(const AlternativeProtein& that) const { return !(*this == that); } PWIZ_API_DECL void ModAminoAcidMass::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("position", boost::lexical_cast(position))); attributes.push_back(make_pair("mass", boost::lexical_cast(mass))); writer.startElement("mod_aminoacid_mass", attributes, XMLWriter::EmptyElement); } struct HandlerModAminoAcidMass : public SAXParser::Handler { ModAminoAcidMass* modAminoAcidMass; HandlerModAminoAcidMass( ModAminoAcidMass* _modAminoAcidMass = 0 ) : modAminoAcidMass( _modAminoAcidMass ) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if ( name == "mod_aminoacid_mass" ) { getAttribute(attributes, "position", modAminoAcidMass->position); getAttribute(attributes, "mass", modAminoAcidMass->mass); return Handler::Status::Ok; } else { throw runtime_error(("[HandlerModAminoAcidMass] : Unexpected element name : " + name).c_str()); return Handler::Status::Done; } } }; PWIZ_API_DECL void ModAminoAcidMass::read(istream& is) { HandlerModAminoAcidMass handler(this); parse(is, handler); } PWIZ_API_DECL bool ModAminoAcidMass::operator==(const ModAminoAcidMass& that) const { return position == that.position && mass == that.mass; } PWIZ_API_DECL bool ModAminoAcidMass::operator!=(const ModAminoAcidMass& that) const { return !(*this == that); } PWIZ_API_DECL void ModificationInfo::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("modified_peptide", modifiedPeptide)); writer.startElement("modification_info", attributes); modAminoAcidMass.write(writer); writer.endElement(); } struct HandlerModificationInfo : public SAXParser::Handler { ModificationInfo* modificationInfo; HandlerModificationInfo( ModificationInfo* _modificationInfo = 0) : modificationInfo( _modificationInfo ) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if ( name == "modification_info" ) { getAttribute(attributes, "modified_peptide", modificationInfo->modifiedPeptide); return Handler::Status::Ok; } else if ( name == "mod_aminoacid_mass" ) { _handlerModAminoAcidMass.modAminoAcidMass= &(modificationInfo->modAminoAcidMass); return Handler::Status(Status::Delegate, &(_handlerModAminoAcidMass)); } else { throw runtime_error(("[HandlerModificationInfo] Unexpected element name : " + name).c_str()); return Handler::Status::Done; } } private: HandlerModAminoAcidMass _handlerModAminoAcidMass; }; PWIZ_API_DECL void ModificationInfo::read(istream& is) { HandlerModificationInfo handler(this); parse(is, handler); } PWIZ_API_DECL bool ModificationInfo::operator==(const ModificationInfo& that) const { return modifiedPeptide == that.modifiedPeptide && modAminoAcidMass == that.modAminoAcidMass; } PWIZ_API_DECL bool ModificationInfo::operator!=(const ModificationInfo& that) const { return !(*this == that); } // // SearchScore // PWIZ_API_DECL void SearchScore::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("name", name)); attributes.push_back(make_pair("value", value)); writer.startElement("search_score", attributes, XMLWriter::EmptyElement); } struct HandlerSearchScore : public SAXParser::Handler { SearchScore* ss; HandlerSearchScore(SearchScore* ss_ = 0) : ss(ss_) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (ss == NULL) throw runtime_error("[HandlerSearchScore::startElement] Null SearchScore"); if (name == "search_score") { getAttribute(attributes, "name", ss->name); getAttribute(attributes, "value", ss->value); return Status::Ok; } else throw runtime_error(("[HandlerSearchScore::startElement] Unknown name "+name).c_str()); return Status::Ok; } }; PWIZ_API_DECL void SearchScore::read(istream& is) { HandlerSearchScore handler(this); parse(is, handler); } // // SearchHit // PWIZ_API_DECL void SearchHit::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("hit_rank", boost::lexical_cast(hitRank))); attributes.push_back(make_pair("peptide", peptide)); attributes.push_back(make_pair("peptide_prev_aa", peptidePrevAA)); attributes.push_back(make_pair("peptide_next_aa", peptideNextAA)); attributes.push_back(make_pair("protein", protein)); attributes.push_back(make_pair("protein_descr", proteinDescr)); attributes.push_back(make_pair("num_tot_proteins", boost::lexical_cast(numTotalProteins))); attributes.push_back(make_pair("num_matched_ions", boost::lexical_cast(numMatchedIons))); attributes.push_back(make_pair("tot_num_ions", boost::lexical_cast(totalNumIons))); attributes.push_back(make_pair("calc_neutral_pep_mass", boost::lexical_cast(calcNeutralPepMass))); attributes.push_back(make_pair("massdiff", boost::lexical_cast(massDiff))); attributes.push_back(make_pair("num_tol_term", boost::lexical_cast(numTolTerm))); attributes.push_back(make_pair("num_missed_cleavages", boost::lexical_cast(numMissedCleavages))); attributes.push_back(make_pair("is_rejected", boost::lexical_cast(isRejected))); writer.startElement("search_hit", attributes); analysisResult.write(writer); for (vector::const_iterator it = alternativeProteins.begin(); it != alternativeProteins.end(); ++it) { it->write(writer); } for (vector::const_iterator it=searchScore.begin(); it != searchScore.end(); it++) { (*it)->write(writer); } modificationInfo.write(writer); writer.endElement(); } struct HandlerSearchHit : public SAXParser::Handler { SearchHit* searchHit; HandlerSearchHit( SearchHit* _searchHit = 0) : searchHit( _searchHit ) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if ( name == "search_hit" ) { getAttribute(attributes, "hit_rank", searchHit->hitRank); getAttribute(attributes, "peptide", searchHit->peptide); getAttribute(attributes, "peptide_prev_aa", searchHit->peptidePrevAA); getAttribute(attributes, "peptide_next_aa", searchHit->peptideNextAA); getAttribute(attributes, "protein", searchHit->protein); getAttribute(attributes, "protein_descr", searchHit->proteinDescr); getAttribute(attributes, "num_tot_proteins", searchHit->numTotalProteins); getAttribute(attributes, "num_matched_ions", searchHit->numMatchedIons); getAttribute(attributes, "tot_num_ions", searchHit->totalNumIons); getAttribute(attributes, "calc_neutral_pep_mass", searchHit->calcNeutralPepMass); getAttribute(attributes, "massdiff", searchHit->massDiff); getAttribute(attributes, "num_tol_term", searchHit->numTolTerm); getAttribute(attributes, "num_missed_cleavages", searchHit->numMissedCleavages); getAttribute(attributes, "is_rejected", searchHit->isRejected); return Handler::Status::Ok; } else if ( name == "analysis_result" ) { _handlerAnalysisResult.analysisResult = &(searchHit->analysisResult); return Handler::Status(Status::Delegate, &(_handlerAnalysisResult)); } else if ( name == "alternative_protein" ) { searchHit->alternativeProteins.push_back(AlternativeProtein()); _handlerAlternativeProtein.alternativeProtein = &(searchHit->alternativeProteins.back()); return Handler::Status(Status::Delegate, &(_handlerAlternativeProtein)); } else if ( name == "modification_info" ) { _handlerModificationInfo.modificationInfo = &(searchHit->modificationInfo); return Handler::Status(Status::Delegate, &(_handlerModificationInfo)); } else if (name == "search_score") { // TODO handle SearchScore searchHit->searchScore.push_back(SearchScorePtr(new SearchScore())); handlerSearchScore.ss = searchHit->searchScore.back().get(); return Handler::Status(Status::Delegate, &handlerSearchScore); } else { if (_log) *_log << ("[HandlerSearchHit] Ignoring non-essential element name : " + name).c_str() << endl; return Handler::Status::Ok; } } private: HandlerSearchScore handlerSearchScore; HandlerAnalysisResult _handlerAnalysisResult; HandlerAlternativeProtein _handlerAlternativeProtein; HandlerModificationInfo _handlerModificationInfo; }; PWIZ_API_DECL void SearchHit::read(istream& is) { HandlerSearchHit handler(this); parse(is, handler); } PWIZ_API_DECL bool SearchHit::operator==(const SearchHit& that) const { return hitRank == that.hitRank&& peptide == that.peptide && peptidePrevAA == that.peptidePrevAA && peptideNextAA == that.peptideNextAA && protein == that.protein && proteinDescr == that.proteinDescr && numTotalProteins == that.numTotalProteins && numMatchedIons == that.numMatchedIons && totalNumIons == that.totalNumIons && calcNeutralPepMass == that.calcNeutralPepMass && massDiff == that.massDiff && numTolTerm == that.numTolTerm && numMissedCleavages == that.numMissedCleavages && isRejected == that.isRejected && proteinDescr == that.proteinDescr && analysisResult == that.analysisResult && alternativeProteins == that.alternativeProteins && modificationInfo == that.modificationInfo; } PWIZ_API_DECL bool SearchHit::operator!=(const SearchHit& that) const { return !(*this == that); } PWIZ_API_DECL void SearchResult::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("search_id", boost::lexical_cast(searchId))); writer.startElement("search_result", attributes); for (vector::const_iterator i=searchHit.begin(); i!=searchHit.end(); i++) (*i)->write(writer); writer.endElement(); } struct HandlerSearchResult : public SAXParser::Handler { SearchResult* searchresult; HandlerSearchResult( SearchResult* _searchresult = 0) : searchresult( _searchresult ) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if ( name == "search_result" ) { string value; getAttribute(attributes, "search_id", value); if (!value.empty()) searchresult->searchId = boost::lexical_cast(value); return Handler::Status::Ok; } else if ( name == "search_hit" ) { searchresult->searchHit.push_back(SearchHitPtr(new SearchHit())); _handlerSearchHit.searchHit= searchresult->searchHit.back().get(); return Handler::Status(Status::Delegate, &(_handlerSearchHit)); } else { throw runtime_error(("[HandlerSearchResult] Unexpected element name :" + name).c_str()); return Handler::Status::Done; } } private: HandlerSearchHit _handlerSearchHit; }; PWIZ_API_DECL void SearchResult::read(istream& is) { HandlerSearchResult handler(this); parse(is, handler); } PWIZ_API_DECL bool SearchResult::operator==(const SearchResult& that) const { return searchId == that.searchId && searchHit == that.searchHit; } PWIZ_API_DECL bool SearchResult::operator!=(const SearchResult& that) const { return !(*this == that); } namespace pwiz { namespace data { namespace pepxml { PWIZ_API_DECL bool operator==(const SearchSummaryPtr left, const SearchSummaryPtr right) { if (!left.get() && !right.get()) return true; else if (!(left.get() && right.get())) return false; return *left == *right; } PWIZ_API_DECL bool operator==(SearchHitPtr left, SearchHitPtr right) { if (!left.get() && !right.get()) return true; else if (!(left.get() && right.get())) return false; return *left == *right; } PWIZ_API_DECL bool operator==(SearchResultPtr left, SearchResultPtr right) { if (!left.get() && !right.get()) return true; else if (!(left.get() && right.get())) return false; return *left == *right; } PWIZ_API_DECL bool operator==(SpectrumQueryPtr left, SpectrumQueryPtr right) { if (!left.get() && !right.get()) return true; else if (!(left.get() && right.get())) return false; return *left == *right; } PWIZ_API_DECL bool operator==(const MatchPtr left, const MatchPtr right) { if (!left.get() && !right.get()) return true; else if (!(left.get() && right.get())) return false; return *left == *right; } } // namespace pepxml } // namespace data } // namespace pwiz PWIZ_API_DECL void EnzymaticSearchConstraint::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("enzyme", enzyme)); attributes.push_back(make_pair("max_num_internal_cleavages", boost::lexical_cast(maxNumInternalCleavages))); attributes.push_back(make_pair("min_number_termini", boost::lexical_cast(minNumTermini))); writer.startElement("enzymatic_search_constraint", attributes, XMLWriter::EmptyElement); } struct HandlerEnzymaticSearchConstraint : public SAXParser::Handler { EnzymaticSearchConstraint* enzymaticSearchConstraint; HandlerEnzymaticSearchConstraint( EnzymaticSearchConstraint* _enzymaticSearchConstraint = 0 ) : enzymaticSearchConstraint( _enzymaticSearchConstraint ) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if ( name == "enzymatic_search_constraint" ) { getAttribute(attributes, "enzyme", enzymaticSearchConstraint->enzyme); getAttribute(attributes, "max_num_internal_cleavages", enzymaticSearchConstraint->maxNumInternalCleavages); getAttribute(attributes, "min_number_termini", enzymaticSearchConstraint->minNumTermini); return Handler::Status::Ok; } else { throw runtime_error(("[HandlerEnzymaticSearchConstraint] : Unexpected element name : " + name).c_str()); return Handler::Status::Done; } } }; PWIZ_API_DECL void EnzymaticSearchConstraint::read(istream& is) { HandlerEnzymaticSearchConstraint handler(this); parse(is, handler); } PWIZ_API_DECL bool EnzymaticSearchConstraint::operator==(const EnzymaticSearchConstraint& that) const { return enzyme == that.enzyme && maxNumInternalCleavages == that.maxNumInternalCleavages && minNumTermini == that.minNumTermini; } PWIZ_API_DECL bool EnzymaticSearchConstraint::operator!=(const EnzymaticSearchConstraint& that) const { return !(*this == that); } PWIZ_API_DECL void AminoAcidModification::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("aminoacid", aminoAcid)); attributes.push_back(make_pair("massdiff", boost::lexical_cast(massDiff))); attributes.push_back(make_pair("mass", boost::lexical_cast(mass))); attributes.push_back(make_pair("variable", variable)); attributes.push_back(make_pair("peptide_terminus", peptideTerminus)); attributes.push_back(make_pair("binary", binary)); attributes.push_back(make_pair("description", description)); attributes.push_back(make_pair("symbol", symbol)); writer.startElement("aminoacid_modification", attributes, XMLWriter::EmptyElement); } struct HandlerAminoAcidModification : public SAXParser::Handler { AminoAcidModification* aminoAcidModification; HandlerAminoAcidModification( AminoAcidModification* _aminoAcidModification = 0) : aminoAcidModification( _aminoAcidModification ) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if ( name == "aminoacid_modification" ) { getAttribute(attributes, "aminoacid", aminoAcidModification->aminoAcid); getAttribute(attributes, "massdiff", aminoAcidModification->massDiff); getAttribute(attributes, "mass", aminoAcidModification->mass); getAttribute(attributes, "variable", aminoAcidModification->variable); getAttribute(attributes, "symbol", aminoAcidModification->symbol); return Handler::Status::Ok; } else { throw runtime_error(("[HandlerAminoAcidModification] : Unexpected element name : "+ name).c_str()); return Handler::Status::Done; } } }; PWIZ_API_DECL void AminoAcidModification::read(istream& is) { HandlerAminoAcidModification handler(this); parse(is, handler); } PWIZ_API_DECL bool AminoAcidModification::operator==(const AminoAcidModification& that) const { return aminoAcid == that.aminoAcid && massDiff == that.massDiff && mass == that.mass && variable == that.variable && symbol == that.symbol; } PWIZ_API_DECL bool AminoAcidModification::operator!=(const AminoAcidModification& that) const { return !(*this == that); } // // Parameter // PWIZ_API_DECL void Parameter::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("name", name)); attributes.push_back(make_pair("value", value)); writer.startElement("parameter", attributes, XMLWriter::EmptyElement); } struct HandlerParameter : public SAXParser::Handler { Parameter* param; HandlerParameter(Parameter* _param = 0) : param(_param) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!param) throw runtime_error("[HandlerParameter] Null Parameter"); if (name == "Parameter" || name == "parameter") { getAttribute(attributes, "name", param->name); getAttribute(attributes, "value", param->value); } else throw runtime_error(("[HandlerParameter] unknown tag "+name).c_str()); return Handler::Status::Ok; } }; PWIZ_API_DECL void Parameter::read(istream& is) { HandlerParameter handler(this); parse(is, handler); } PWIZ_API_DECL void SearchSummary::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("base_name", baseName)); attributes.push_back(make_pair("search_engine", searchEngine)); attributes.push_back(make_pair("precursor_mass_type", precursorMassType)); attributes.push_back(make_pair("fragment_mass_type", fragmentMassType)); attributes.push_back(make_pair("search_id", searchID)); writer.startElement("search_summary", attributes); searchDatabase.write(writer); enzymaticSearchConstraint.write(writer); vector::const_iterator it = aminoAcidModifications.begin(); for(; it != aminoAcidModifications.end(); ++it) { it->write(writer); } writer.endElement(); } struct HandlerSearchSummary : public SAXParser::Handler { SearchSummary* searchsummary; HandlerSearchSummary( SearchSummary* _searchsummary = 0) : searchsummary( _searchsummary ) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if ( name == "search_summary" ) { getAttribute(attributes, "base_name", searchsummary->baseName); getAttribute(attributes, "search_engine", searchsummary->searchEngine); getAttribute(attributes, "precursor_mass_type", searchsummary->precursorMassType); getAttribute(attributes, "fragment_mass_type", searchsummary->fragmentMassType); getAttribute(attributes, "search_id", searchsummary->searchID); return Handler::Status::Ok; } else if ( name == "search_database" ) { _handlerSearchDatabase.searchDatabase= &(searchsummary->searchDatabase); return Handler::Status(Status::Delegate, &(_handlerSearchDatabase)); } else if ( name == "enzymatic_search_constraint" ) { _handlerEnzymaticSearchConstraint.enzymaticSearchConstraint = &(searchsummary->enzymaticSearchConstraint); return Handler::Status(Status::Delegate, &(_handlerEnzymaticSearchConstraint)); } else if ( name == "aminoacid_modification" ) { searchsummary->aminoAcidModifications.push_back(AminoAcidModification()); _handlerAminoAcidModification.aminoAcidModification = &(searchsummary->aminoAcidModifications.back()); return Handler::Status(Status::Delegate, &(_handlerAminoAcidModification)); } else if (name == "parameter") { searchsummary->parameters.push_back(ParameterPtr(new Parameter())); _handlerParameter.param = searchsummary->parameters.back().get(); return Handler::Status(Status::Delegate, &_handlerParameter); } else { if (_log) *_log << ("[HandlerSearchSummary] Ignoring non-essential element name : " + name).c_str() << endl; return Handler::Status::Ok; } } private: HandlerSearchDatabase _handlerSearchDatabase; HandlerEnzymaticSearchConstraint _handlerEnzymaticSearchConstraint; HandlerAminoAcidModification _handlerAminoAcidModification; HandlerParameter _handlerParameter; }; PWIZ_API_DECL void SearchSummary::read(istream& is) { HandlerSearchSummary handler(this); parse(is, handler); } PWIZ_API_DECL bool SearchSummary::operator==(const SearchSummary& that) const { return baseName == that.baseName && searchEngine == that.searchEngine && precursorMassType == that.precursorMassType && fragmentMassType == that.fragmentMassType && searchID == that.searchID && searchDatabase == that.searchDatabase && enzymaticSearchConstraint == that.enzymaticSearchConstraint && aminoAcidModifications == that.aminoAcidModifications; } PWIZ_API_DECL bool SearchSummary::operator!=(const SearchSummary& that) const { return !(*this == that); } PWIZ_API_DECL void SpectrumQuery::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("spectrum", spectrum)); attributes.push_back(make_pair("start_scan", boost::lexical_cast(startScan))); attributes.push_back(make_pair("end_scan", boost::lexical_cast(endScan))); attributes.push_back(make_pair("precursor_neutral_mass", boost::lexical_cast(precursorNeutralMass))); attributes.push_back(make_pair("assumed_charge", boost::lexical_cast(assumedCharge))); attributes.push_back(make_pair("index", boost::lexical_cast(index))); attributes.push_back(make_pair("retention_time_sec", boost::lexical_cast(retentionTimeSec))); writer.startElement("spectrum_query", attributes); for(vector::const_iterator it=searchResult.begin(); it!=searchResult.end(); it++) (*it)->write(writer); writer.endElement(); } struct HandlerSpectrumQuery : public SAXParser::Handler { SpectrumQuery* spectrumQuery; HandlerSpectrumQuery( SpectrumQuery* _spectrumQuery = 0) : spectrumQuery( _spectrumQuery ) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if ( name == "spectrum_query" ) { string value; getAttribute(attributes, "spectrum", spectrumQuery->spectrum); getAttribute(attributes, "start_scan", value); spectrumQuery->startScan= boost::lexical_cast(value); getAttribute(attributes, "end_scan", spectrumQuery->endScan); getAttribute(attributes, "precursor_neutral_mass", spectrumQuery->precursorNeutralMass); getAttribute(attributes, "assumed_charge", spectrumQuery->assumedCharge); getAttribute(attributes, "index", spectrumQuery->index); getAttribute(attributes, "retention_time_sec", spectrumQuery->retentionTimeSec); return Handler::Status::Ok; } else if ( name == "search_result" ) { spectrumQuery->searchResult.push_back(SearchResultPtr(new SearchResult())); _handlerSearchResult.searchresult = spectrumQuery->searchResult.back().get(); return Handler::Status(Status::Delegate, &(_handlerSearchResult)); } else { throw runtime_error(("[HandlerSpectrumQuery] Unexpected element name : " + name).c_str()); return Handler::Status::Ok; } } private: HandlerSearchResult _handlerSearchResult; }; PWIZ_API_DECL void SpectrumQuery::read(istream& is) { HandlerSpectrumQuery handler(this); parse(is, handler); } PWIZ_API_DECL bool SpectrumQuery::operator==(const SpectrumQuery& that) const { return spectrum == that.spectrum && startScan == that.startScan && endScan == that.endScan && precursorNeutralMass == that.precursorNeutralMass && assumedCharge == that.assumedCharge && index == that.index && retentionTimeSec == that.retentionTimeSec && searchResult == that.searchResult; } PWIZ_API_DECL bool SpectrumQuery::operator!=(const SpectrumQuery& that) const { return !(*this == that); } PWIZ_API_DECL void MSMSRunSummary::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; writer.startElement("msms_run_summary", attributes); sampleEnzyme.write(writer); for (vector::const_iterator it=searchSummary.begin(); it != searchSummary.end(); it++) (*it)->write(writer); vector::const_iterator it = spectrumQueries.begin(); for(; it != spectrumQueries.end(); ++it) (*it)->write(writer); writer.endElement(); } struct HandlerMSMSRunSummary : public SAXParser::Handler { MSMSRunSummary* msmsrunsummary; HandlerMSMSRunSummary( MSMSRunSummary* _msmsrunsummary = 0 ) : msmsrunsummary( _msmsrunsummary ) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if ( name == "msms_run_summary" ) { getAttribute(attributes, "base_name", msmsrunsummary->base_name); getAttribute(attributes, "raw_data_type", msmsrunsummary->raw_data_type); getAttribute(attributes, "raw_data", msmsrunsummary->raw_data); getAttribute(attributes, "msManufacturer", msmsrunsummary->msManufacturer); getAttribute(attributes, "msModel", msmsrunsummary->msModel); getAttribute(attributes, "msIonization", msmsrunsummary->msIonization); getAttribute(attributes, "msMassAnalyzer", msmsrunsummary->msMassAnalyzer); getAttribute(attributes, "msDetector", msmsrunsummary->msDetector); return Handler::Status::Ok; } else if ( name == "sample_enzyme" ) { _handlerSampleEnzyme.sampleEnzyme= &(msmsrunsummary->sampleEnzyme); return Handler::Status(Status::Delegate, &(_handlerSampleEnzyme)); } else if ( name == "search_summary" ) { msmsrunsummary->searchSummary.push_back(SearchSummaryPtr(new SearchSummary())); _handlerSearchSummary.searchsummary= msmsrunsummary->searchSummary.back().get(); return Handler::Status(Status::Delegate, &(_handlerSearchSummary)); } else if ( name == "spectrum_query" ) { msmsrunsummary->spectrumQueries.push_back(SpectrumQueryPtr(new SpectrumQuery())); _handlerSpectrumQuery.spectrumQuery= msmsrunsummary->spectrumQueries.back().get(); return Handler::Status(Status::Delegate, &(_handlerSpectrumQuery)); } else { if (_log) *_log << ("[HandlerMSMSRunSummary] Ignoring non-essential element : " + name).c_str() << endl; return Handler::Status::Ok; } } private: HandlerSampleEnzyme _handlerSampleEnzyme; HandlerSearchSummary _handlerSearchSummary; HandlerSpectrumQuery _handlerSpectrumQuery; }; PWIZ_API_DECL void MSMSRunSummary::read(istream& is) { HandlerMSMSRunSummary handler(this); parse(is, handler); } PWIZ_API_DECL bool MSMSRunSummary::operator==(const MSMSRunSummary& that) const { return searchSummary == that.searchSummary && sampleEnzyme == that.sampleEnzyme && spectrumQueries == that.spectrumQueries; } PWIZ_API_DECL bool MSMSRunSummary::operator!=(const MSMSRunSummary& that) const { return !(*this == that); } PWIZ_API_DECL void MSMSPipelineAnalysis::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("date", date)); attributes.push_back(make_pair("summmary_xml", summaryXML)); attributes.push_back(make_pair("xmlns", xmlns)); attributes.push_back(make_pair("xmlns:xsi", xmlnsXSI)); attributes.push_back(make_pair("xsi:schemaLocation", XSISchemaLocation)); writer.startElement("msms_pipeline_analysis", attributes); msmsRunSummary.write(writer); writer.endElement(); } struct HandlerMSMSPipelineAnalysis : public SAXParser::Handler { MSMSPipelineAnalysis* msmspipelineanalysis; HandlerMSMSPipelineAnalysis( MSMSPipelineAnalysis* _msmspipelineanalysis = 0) : msmspipelineanalysis( _msmspipelineanalysis ) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if ( name == "msms_pipeline_analysis" ) { getAttribute(attributes, "date", msmspipelineanalysis->date); getAttribute(attributes, "summmary_xml", msmspipelineanalysis->summaryXML); getAttribute(attributes, "xmlns", msmspipelineanalysis->xmlns); getAttribute(attributes, "xmlns:xsi", msmspipelineanalysis->xmlnsXSI); getAttribute(attributes, "xsi:schemaLocation", msmspipelineanalysis->XSISchemaLocation); return Handler::Status::Ok; } else if ( name == "msms_run_summary" ) { _handlerMSMSRunSummary.msmsrunsummary= &(msmspipelineanalysis->msmsRunSummary); return Handler::Status(Status::Delegate, &(_handlerMSMSRunSummary)); } else { if (_log) *_log << ("[HandlerMSMSPipelineAnalysis] Ignoring non-essential element : " + name).c_str() << endl; //throw runtime_error(("[HandlerMSMSPipelineAnalysis] Unexpected element name : " + name).c_str()); return Handler::Status::Ok; } } private: HandlerMSMSRunSummary _handlerMSMSRunSummary; }; PWIZ_API_DECL void MSMSPipelineAnalysis::read(istream& is) { HandlerMSMSPipelineAnalysis handler(this); parse(is, handler); } PWIZ_API_DECL bool MSMSPipelineAnalysis::operator==(const MSMSPipelineAnalysis& that) const { return date == that.date && summaryXML == that.summaryXML && xmlns == that.xmlns && xmlnsXSI == that.xmlnsXSI && XSISchemaLocation == that.XSISchemaLocation; } PWIZ_API_DECL bool MSMSPipelineAnalysis::operator!=(const MSMSPipelineAnalysis& that) const { return !(*this == that); } PWIZ_API_DECL void Match::write(minimxml::XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("score", boost::lexical_cast(score))); writer.startElement("match", attributes); spectrumQuery.write(writer); feature->write(writer); writer.endElement(); } struct HandlerMatch : public SAXParser::Handler { Match* match; HandlerMatch(Match* _match = 0) : match(_match){} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if(name == "match") { getAttribute(attributes, "score", match->score); return Handler::Status::Ok; } else if (name == "spectrum_query") { _handlerSpectrumQuery.spectrumQuery = &(match->spectrumQuery); return Handler::Status(Status::Delegate, &_handlerSpectrumQuery); } else if (name == "feature") { _handlerFeature.feature = (match->feature).get(); return Handler::Status(Status::Delegate, &_handlerFeature); } else { throw runtime_error(("[HandlerMatch] Unexpected element name: " + name).c_str()); return Handler::Status::Done; } } private: HandlerFeature _handlerFeature; HandlerSpectrumQuery _handlerSpectrumQuery; }; PWIZ_API_DECL void Match::read(istream& is) { if (!this) throw runtime_error("not this"); HandlerMatch handlerMatch(this); SAXParser::parse(is, handlerMatch); } PWIZ_API_DECL bool Match::operator==(const Match& that) const { return score == that.score && spectrumQuery == (that.spectrumQuery) && *feature == *(that.feature); } PWIZ_API_DECL bool Match::operator!=(const Match& that) const { return !(*this == that); } PWIZ_API_DECL void MatchData::write(minimxml::XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("warpFunctionCalculator", warpFunctionCalculator)); attributes.push_back(make_pair("searchNbhdCalculator", searchNbhdCalculator)); writer.startElement("matchData", attributes); XMLWriter::Attributes attributes_m; attributes_m.push_back(make_pair("count", boost::lexical_cast(matches.size()))); writer.startElement("matches", attributes_m); vector::const_iterator match_it = matches.begin(); for(; match_it != matches.end(); ++match_it) { (*match_it)->write(writer); } writer.endElement(); writer.endElement(); } struct HandlerMatchData : public SAXParser::Handler { MatchData* matchData; HandlerMatchData(){} HandlerMatchData(MatchData* _matchData) : matchData(_matchData){} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if(name == "matchData") { getAttribute(attributes, "warpFunctionCalculator", matchData->warpFunctionCalculator); getAttribute(attributes, "searchNbhdCalculator", matchData->searchNbhdCalculator); return Handler::Status::Ok; } else if (name == "matches") { getAttribute(attributes, "count", _count); return Handler::Status::Ok; } else { if (name != "match") { throw runtime_error(("[HandlerMatchData] Unexpected element name : " + name).c_str()); return Handler::Status::Done; } matchData->matches.push_back(MatchPtr(new Match())); _handlerMatch.match = matchData->matches.back().get(); return Handler::Status(Status::Delegate, &_handlerMatch); } if (_count != matchData->matches.size()) { throw runtime_error("[HandlerMatchData] != matchData._matches.size()"); return Handler::Status::Done; } } private: HandlerMatch _handlerMatch; size_t _count; }; PWIZ_API_DECL void MatchData::read(istream& is) { HandlerMatchData handlerMatchData(this); parse(is, handlerMatchData); } PWIZ_API_DECL bool MatchData::operator==(const MatchData& that) const { return warpFunctionCalculator == that.warpFunctionCalculator && searchNbhdCalculator == that.searchNbhdCalculator && matches == that.matches; } PWIZ_API_DECL bool MatchData::operator!=(const MatchData& that) const { return !(*this == that); } pwiz/pwiz/data/misc/PeakData.hpp0000664000175100017510000002126612664775621020602 0ustar teamcityteamcity00000000000000// // $Id: PeakData.hpp 7297 2015-03-12 05:30:33Z paragmallick $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PEAKDATA_HPP_ #define _PEAKDATA_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "CalibrationParameters.hpp" #include "pwiz/utility/misc/MSIHandler.hpp" #include "pwiz/utility/minimxml/XMLWriter.hpp" #include "pwiz/utility/minimxml/SAXParser.hpp" #include "pwiz/utility/math/OrderedPair.hpp" #include "boost/shared_ptr.hpp" #include #include namespace pwiz { namespace data { namespace peakdata { using namespace pwiz::util; using namespace pwiz::minimxml; using namespace minimxml::SAXParser; const int PeakDataFormatVersion_Major = 1; const int PeakDataFormatVersion_Minor = 1; struct PWIZ_API_DECL Peak { int id; double mz; double retentionTime; double intensity; // peak height double area; // sum/total intensity double error; // error in model fit std::vector data; // optional attributes enum Attribute { Attribute_Frequency, Attribute_Phase, Attribute_Decay }; typedef std::map Attributes; Attributes attributes; Peak(double _mz = 0, double _retentionTime = 0); double getAttribute(Attribute attribute) const; bool operator==(const Peak& that) const; bool operator!=(const Peak& that) const; void write(minimxml::XMLWriter& writer) const; void read(std::istream& is); }; struct HandlerPeak : public SAXParser::Handler { Peak* peak; HandlerPeak(Peak* _peak = 0) : peak(_peak) { parseCharacters = true; autoUnescapeCharacters = false; } virtual Status startElement(const std::string& name, const Attributes& attributes, stream_offset position); virtual Status characters(const SAXParser::saxstring& text, stream_offset position); }; PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const Peak& peak); PWIZ_API_DECL std::istream& operator>>(std::istream& is, Peak& peak); struct PWIZ_API_DECL PeakFamily { double mzMonoisotopic; int charge; double score; std::vector peaks; PeakFamily() : mzMonoisotopic(0), charge(0), score(0) {} double sumAmplitude() const {return 0;} double sumArea() const {return 0;} void write(minimxml::XMLWriter& writer) const; void read(std::istream& is); bool operator==(const PeakFamily& that) const; bool operator!=(const PeakFamily& that) const; }; PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const PeakFamily& peakFamily); PWIZ_API_DECL std::istream& operator>>(std::istream& is, PeakFamily& peakFamily); struct PWIZ_API_DECL Scan { size_t index; std::string nativeID; int scanNumber; // TODO: remove double retentionTime; double observationDuration; CalibrationParameters calibrationParameters; std::vector peakFamilies; Scan() : index(0), scanNumber(0), retentionTime(0), observationDuration(0) {} void write(minimxml::XMLWriter& writer) const; void read(std::istream& is); bool operator==(const Scan& scan) const; bool operator!=(const Scan& scan) const; }; PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const Scan& scan); PWIZ_API_DECL std::istream& operator>>(std::istream& is, Scan& scan); struct PWIZ_API_DECL Software { std::string name; std::string version; std::string source; struct PWIZ_API_DECL Parameter { std::string name; std::string value; Parameter() : name(""), value("") {}; Parameter(std::string name_, std::string value_) : name(name_), value(value_) {} void write(minimxml::XMLWriter& xmlWriter) const; void read(std::istream& is); bool operator==(const Parameter& that) const; bool operator!=(const Parameter& that) const; }; std::vector parameters; Software() : name(""), version(""), source(""), parameters(0) {} void write(minimxml::XMLWriter& xmlWriter) const; void read(std::istream& is); bool operator==(const Software& that) const; bool operator!=(const Software& that) const; }; struct PWIZ_API_DECL PeakData { std::string sourceFilename; Software software; std::vector scans; void write(pwiz::minimxml::XMLWriter& xmlWriter) const; void read(std::istream& is); bool operator==(const PeakData& that) const; bool operator!=(const PeakData& that) const; }; PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const PeakData& pd); PWIZ_API_DECL std::istream& operator>>(std::istream& is, PeakData& pd); /// /// struct for an eluted peak (PEAK ELution) /// struct PWIZ_API_DECL Peakel { // metadata double mz; double retentionTime; double maxIntensity; double totalIntensity; double mzVariance; // peak data std::vector peaks; // construction Peakel(); Peakel(const Peak& peak); /// recalculates all metadata based on peak data void calculateMetadata(); // retention times grabbed from peak data; assume peaks are ordered by retention time double retentionTimeMin() const; double retentionTimeMax() const; void write(pwiz::minimxml::XMLWriter& xmlWriter) const; void read(std::istream& is); bool operator==(const Peakel& that) const; bool operator!=(const Peakel& that) const; }; typedef boost::shared_ptr PeakelPtr; struct HandlerPeakel : public SAXParser::Handler { Peakel* peakel; HandlerPeakel(Peakel* _peakel = 0) : peakel(_peakel){} virtual Status startElement(const std::string& name, const Attributes& attributes, stream_offset position); private: HandlerPeak _handlerPeak; size_t _peakCount; }; PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const Peakel& peakel); PWIZ_API_DECL std::istream& operator>>(std::istream& is, Peakel& peakel); struct PWIZ_API_DECL Feature { Feature(); Feature(const MSIHandler::Record& record); std::string id; // assigned by feature detection, for easier lookup double mz; double retentionTime; int charge; double totalIntensity; double rtVariance; double score; double error; std::vector peakels; void calculateMetadata(); // retention time range calculation based on first two Peakels double retentionTimeMin() const; double retentionTimeMax() const; void write(pwiz::minimxml::XMLWriter& xmlWriter) const; void read(std::istream& is); bool operator==(const Feature& that) const; bool operator!=(const Feature& that) const; // note: copy/assignment are shallow copy (same peakels) }; typedef boost::shared_ptr FeaturePtr; struct HandlerFeature : public SAXParser::Handler // included in header file for accession by MatchData { Feature* feature; HandlerFeature(Feature* _feature = 0) : feature(_feature){} virtual Status startElement(const std::string& name, const Attributes& attributes, stream_offset position); private: HandlerPeakel _handlerPeakel; size_t _peakelCount; }; PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const Feature& feature); PWIZ_API_DECL std::istream& operator>>(std::istream& is, Feature& feature); struct PWIZ_API_DECL FeatureFile { FeatureFile(){} std::vector features; void write(pwiz::minimxml::XMLWriter& xmlWriter) const; void read(std::istream& is); private: FeatureFile(FeatureFile&); FeatureFile operator=(FeatureFile&); }; } // namespace peakdata } // namespace data } // namespace pwiz #endif // _PEAKDATA_HPP_ pwiz/pwiz/data/misc/PeakData.cpp0000664000175100017510000010545712664775621020602 0ustar teamcityteamcity00000000000000// // $Id: PeakData.cpp 3068 2011-10-21 03:58:47Z pcbrefugee $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "PeakData.hpp" #include #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace data { namespace peakdata { using namespace pwiz::minimxml; using namespace pwiz::math; using namespace minimxml::SAXParser; // // Peak // PWIZ_API_DECL Peak::Peak(double _mz, double _retentionTime) : id(0), mz(_mz), retentionTime(_retentionTime), intensity(0), area(0), error(0) {} PWIZ_API_DECL double Peak::getAttribute(Attribute attribute) const { Attributes::const_iterator it = attributes.find(attribute); if (it == attributes.end()) throw runtime_error("[Peak::getAttribute] Attribute not found."); return it->second; } PWIZ_API_DECL bool Peak::operator==(const Peak& that) const { bool result = (id == that.id && mz == that.mz && retentionTime == that.retentionTime && intensity == that.intensity && area == that.area && error == that.error && data == that.data); if (!result) return false; // check attributes for (Attributes::const_iterator it=attributes.begin(); it!=attributes.end(); ++it) { Attributes::const_iterator jt=that.attributes.find(it->first); if (jt==that.attributes.end() || jt->second!=it->second) return false; } for (Attributes::const_iterator it=that.attributes.begin(); it!=that.attributes.end(); ++it) { Attributes::const_iterator jt=attributes.find(it->first); if (jt==attributes.end() || jt->second!=it->second) return false; } return true; } PWIZ_API_DECL bool Peak::operator!=(const Peak& that) const { return !(*this==that); } namespace { struct AttributeNameEntry { Peak::Attribute attribute; const char* name; }; AttributeNameEntry attributeNameTable_[] = { {Peak::Attribute_Frequency, "frequency"}, {Peak::Attribute_Phase, "phase"}, {Peak::Attribute_Decay, "decay"} }; const size_t attributeNameTableSize_ = sizeof(attributeNameTable_)/sizeof(AttributeNameEntry); map attributeNameMap_; map nameAttributeMap_; void initializeAttributeNameMaps() { attributeNameMap_.clear(); nameAttributeMap_.clear(); for (const AttributeNameEntry* p=attributeNameTable_; p!=attributeNameTable_+attributeNameTableSize_; ++p) { attributeNameMap_[p->attribute] = p->name; nameAttributeMap_[p->name] = p->attribute; } } string attributeToString(Peak::Attribute attribute) { if (attributeNameMap_.empty()) initializeAttributeNameMaps(); map::const_iterator it=attributeNameMap_.find(attribute); if (it == attributeNameMap_.end()) throw runtime_error("[PeakData::attributeToString()] Attribute not found."); return it->second; } Peak::Attribute stringToAttribute(string name) { if (nameAttributeMap_.empty()) initializeAttributeNameMaps(); map::const_iterator it=nameAttributeMap_.find(name); if (it == nameAttributeMap_.end()) throw runtime_error(("[PeakData::stringToAttribute()] Unknown attribute: " + name).c_str()); return it->second; } } // namespace PWIZ_API_DECL void Peak::write(minimxml::XMLWriter& writer) const { XMLWriter::Attributes xmlAttributes; xmlAttributes.push_back(make_pair("id", lexical_cast(id))); xmlAttributes.push_back(make_pair("mz", lexical_cast(mz))); xmlAttributes.push_back(make_pair("retentionTime", lexical_cast(retentionTime))); xmlAttributes.push_back(make_pair("intensity", lexical_cast(intensity))); xmlAttributes.push_back(make_pair("area", lexical_cast(area))); xmlAttributes.push_back(make_pair("error", lexical_cast(error))); for (Attributes::const_iterator it=attributes.begin(); it!=attributes.end(); ++it) xmlAttributes.push_back(make_pair(attributeToString(it->first), lexical_cast(it->second))); if (data.empty()) { writer.startElement("peak", xmlAttributes, XMLWriter::EmptyElement); } else { writer.startElement("peak", xmlAttributes); writer.startElement("data"); ostringstream oss; copy(data.begin(), data.end(), ostream_iterator(oss, " ")); writer.characters(oss.str()); writer.endElement(); writer.endElement(); } } SAXParser::Handler::Status HandlerPeak::startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!peak) throw runtime_error("[PeakData::HandlerPeak::startElement()] Null peak."); if (name == "peak") { for (Attributes::attribute_list::const_iterator it=attributes.begin(); it!=attributes.end(); ++it) { if (it->matchName("id")) peak->id = lexical_cast(it->getValue()); else if (it->matchName("mz")) peak->mz = lexical_cast(it->getValue(NoXMLUnescape)); else if (it->matchName("retentionTime")) peak->retentionTime = lexical_cast(it->getValue(NoXMLUnescape)); else if (it->matchName("intensity")) peak->intensity = lexical_cast(it->getValue(NoXMLUnescape)); else if (it->matchName("area")) peak->area = lexical_cast(it->getValue(NoXMLUnescape)); else if (it->matchName("error")) peak->error = lexical_cast(it->getValue(NoXMLUnescape)); else { Peak::Attribute a = stringToAttribute(it->getName()); peak->attributes[a] = lexical_cast(it->getValue(NoXMLUnescape)); } } return Status::Ok; } else if (name == "data") { return Status::Ok; } throw runtime_error(("[HandlerPeak] Unexpected element name: " + name).c_str()); } SAXParser::Handler::Status HandlerPeak::characters(const SAXParser::saxstring& text, stream_offset position) { if (!peak) throw runtime_error("[PeakData::HandlerPeak::characters()] Null peak."); peak->data.clear(); istringstream iss(text.c_str()); copy(istream_iterator(iss), istream_iterator(), back_inserter(peak->data)); return Status::Ok; } PWIZ_API_DECL void Peak::read(istream& is) { HandlerPeak handler(this); SAXParser::parse(is, handler); } PWIZ_API_DECL ostream& operator<<(ostream& os, const Peak& peak) { XMLWriter writer(os); peak.write(writer); return os; } PWIZ_API_DECL std::istream& operator>>(std::istream& is, Peak& peak) { peak.read(is); return is; } // // PeakFamily // PWIZ_API_DECL void PeakFamily::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("mzMonoisotopic", boost::lexical_cast(mzMonoisotopic))); attributes.push_back(make_pair("charge", boost::lexical_cast(charge))); attributes.push_back(make_pair("score", boost::lexical_cast(score))); writer.startElement("peakFamily", attributes); XMLWriter::Attributes attributes_pks; attributes_pks.push_back(make_pair("count", boost::lexical_cast(peaks.size()))); writer.startElement("peaks", attributes_pks); for (vector::const_iterator it = peaks.begin(); it != peaks.end(); ++it) { it->write(writer); } writer.endElement(); writer.endElement(); } struct HandlerPeakFamily : public SAXParser::Handler { PeakFamily* peakFamily; HandlerPeakFamily(PeakFamily* _peakFamily = 0) : peakFamily(_peakFamily){} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if(name == "peakFamily") { getAttribute(attributes, "mzMonoisotopic", peakFamily->mzMonoisotopic); getAttribute(attributes, "charge", peakFamily->charge); getAttribute(attributes, "score", peakFamily->score); return Handler::Status::Ok; } else if (name == "peaks") { getAttribute(attributes, "count", _peaksCount); return Handler::Status::Ok; } else { if (name != "peak") { throw runtime_error(("[HandlerPeakFamily] Unexpected element found: " + name).c_str()); return Handler::Status::Done; } peakFamily->peaks.push_back(Peak()); _handlerPeak.peak = &(peakFamily->peaks.back()); return Handler::Status(Status::Delegate, &_handlerPeak); } if (_peaksCount != peakFamily->peaks.size()) { throw runtime_error("[HandlerPeakFamily] != peakFamily->peaks.size()"); return Handler::Status::Done; } } private: HandlerPeak _handlerPeak; size_t _peaksCount; }; PWIZ_API_DECL void PeakFamily::read(istream& is) { HandlerPeakFamily handlerPeakFamily(this); SAXParser::parse(is, handlerPeakFamily); } PWIZ_API_DECL bool PeakFamily::operator==(const PeakFamily& that) const { return mzMonoisotopic == that.mzMonoisotopic && charge == that.charge && score == that.score&& peaks == that.peaks; } PWIZ_API_DECL bool PeakFamily::operator!=(const PeakFamily& that) const { return !(*this == that); } PWIZ_API_DECL ostream& operator<<(ostream& os, const PeakFamily& pf) { XMLWriter writer(os); pf.write(writer); return os; } PWIZ_API_DECL std::istream& operator>>(std::istream& is, PeakFamily& peakFamily) { peakFamily.read(is); return is; } // // Scan // PWIZ_API_DECL void Scan::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("index", boost::lexical_cast(index))); attributes.push_back(make_pair("nativeID", boost::lexical_cast(nativeID))); attributes.push_back(make_pair("scanNumber", boost::lexical_cast(scanNumber))); attributes.push_back(make_pair("retentionTime", boost::lexical_cast(retentionTime))); attributes.push_back(make_pair("observationDuration", boost::lexical_cast(observationDuration))); writer.startElement("scan", attributes); XMLWriter::Attributes attributes_cp; attributes_cp.push_back(make_pair("A", boost::lexical_cast(calibrationParameters.A))); attributes_cp.push_back(make_pair("B",boost::lexical_cast(calibrationParameters.B))); writer.startElement("calibrationParameters",attributes_cp,XMLWriter::EmptyElement); XMLWriter::Attributes attributes_pf; attributes_pf.push_back(make_pair("count", boost::lexical_cast(peakFamilies.size()))); writer.startElement("peakFamilies", attributes_pf); for (vector::const_iterator it = peakFamilies.begin(); it != peakFamilies.end(); ++it) it->write(writer); writer.endElement(); writer.endElement(); } struct HandlerScan : public SAXParser::Handler { Scan* scan; HandlerScan(Scan* _scan = 0) : scan(_scan){} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if(name == "scan") { getAttribute(attributes, "index", scan->index); getAttribute(attributes, "nativeID", scan->nativeID); getAttribute(attributes, "scanNumber", scan->scanNumber); getAttribute(attributes, "retentionTime", scan->retentionTime); getAttribute(attributes, "observationDuration", scan->observationDuration); return Handler::Status::Ok; } else if(name == "calibrationParameters") { getAttribute(attributes, "A", scan->calibrationParameters.A); getAttribute(attributes, "B", scan->calibrationParameters.B); return Handler::Status::Ok; } else if(name == "peakFamilies") { getAttribute(attributes,"count", _peakFamilyCount); return Handler::Status::Ok; } else { if(name != "peakFamily") { throw runtime_error(("[HandlerScan] Unexpected element name : " + name).c_str()); return Handler::Status::Done; } scan->peakFamilies.push_back(PeakFamily()); PeakFamily& peakFamily = scan->peakFamilies.back(); _handlerPeakFamily.peakFamily = &peakFamily; return Handler::Status(Status::Delegate,&_handlerPeakFamily); } if( _peakFamilyCount != scan->peakFamilies.size()) { throw runtime_error("[HandlerScan] != scan->peakFamilies.size()"); return Handler::Status::Done; } } private: HandlerPeakFamily _handlerPeakFamily; size_t _peakFamilyCount; }; PWIZ_API_DECL void Scan::read(istream& is) { HandlerScan handlerScan(this); parse(is, handlerScan); } PWIZ_API_DECL bool Scan::operator==(const Scan& scan) const { return index == scan.index && nativeID == scan.nativeID && scanNumber == scan.scanNumber && retentionTime == scan.retentionTime && observationDuration == scan.observationDuration && calibrationParameters.A == scan.calibrationParameters.A && calibrationParameters.B == scan.calibrationParameters.B && peakFamilies == scan.peakFamilies; } PWIZ_API_DECL bool Scan::operator!=(const Scan& scan) const { return !(*this == scan); } PWIZ_API_DECL ostream& operator<<(ostream& os, const Scan& scan) { XMLWriter writer(os); scan.write(writer); return os; } PWIZ_API_DECL std::istream& operator>>(std::istream& is, Scan& scan) { scan.read(is); return is; } // // Software // PWIZ_API_DECL void Software::Parameter::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("name", boost::lexical_cast(name))); attributes.push_back(make_pair("value", boost::lexical_cast(value))); writer.startElement("parameter", attributes, XMLWriter::EmptyElement); } PWIZ_API_DECL void Software::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("name", boost::lexical_cast(name))); attributes.push_back(make_pair("version", boost::lexical_cast(version))); attributes.push_back(make_pair("source", boost::lexical_cast(source))); writer.startElement("software", attributes); XMLWriter::Attributes attributes_p; attributes_p.push_back(make_pair("count", boost::lexical_cast(parameters.size()))); writer.startElement("parameters", attributes_p); for (vector::const_iterator it = parameters.begin(); it != parameters.end(); ++it) { it->write(writer); } writer.endElement(); writer.endElement(); } struct HandlerParameter : public SAXParser::Handler { Software::Parameter* parameter; HandlerParameter(Software::Parameter* _parameter = 0) : parameter(_parameter){} virtual Status startElement(const string& current, const Attributes& attributes, stream_offset position) { if(current != "parameter") { throw runtime_error(("[HandlerParameter] Something strange in the neighborhood ... " + current).c_str()); } getAttribute(attributes,"name", parameter->name); getAttribute(attributes,"value", parameter->value); return Status::Ok; } }; struct HandlerSoftware : public SAXParser::Handler { Software* software; HandlerSoftware(Software* _software = 0) : software(_software) {} virtual Status startElement(const string& current, const Attributes& attributes, stream_offset position) { if(current == "software") { getAttribute(attributes, "name", software->name); getAttribute(attributes, "version", software->version); getAttribute(attributes, "source", software->source); return Status::Ok; } else if(current == "parameters") { getAttribute(attributes, "count", _parameterCount); return Status::Ok; } else { if(current != "parameter") { throw runtime_error(("[HandlerSoftware] Unexpected element found : " + current).c_str()); return Status::Done; } software->parameters.push_back(Software::Parameter()); _handlerParameter.parameter = &(software->parameters.back()); return Status(Status::Delegate, &_handlerParameter); } if (_parameterCount != software->parameters.size()) { throw runtime_error("[HandlerSoftware] != software-> parameters.size() "); return Status::Done; } } private: HandlerParameter _handlerParameter; size_t _parameterCount; }; PWIZ_API_DECL void Software::Parameter::read(istream& is) { HandlerParameter handlerParameter(this); parse(is, handlerParameter); } PWIZ_API_DECL void Software::read(istream& is) { HandlerSoftware handlerSoftware(this); parse(is, handlerSoftware); } PWIZ_API_DECL bool Software::Parameter::operator==(const Software::Parameter& that) const { return name == that.name && value == that.value; } PWIZ_API_DECL bool Software::Parameter::operator!=(const Software::Parameter& that) const { return !(*this == that); } PWIZ_API_DECL bool Software::operator==(const Software& that) const { return name == that.name && version == that.version && source == that.source && parameters == that.parameters; } PWIZ_API_DECL bool Software::operator!=(const Software& that) const { return !(*this == that); } // // PeakData // PWIZ_API_DECL void PeakData::write(XMLWriter& writer) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("sourceFilename",sourceFilename)); writer.startElement("peakData",attributes); software.write(writer); XMLWriter::Attributes attributes_scans; attributes_scans.push_back(make_pair("count", boost::lexical_cast(scans.size()))); writer.startElement("scans", attributes_scans); vector::const_iterator it = scans.begin(); for(; it != scans.end(); ++it) it->write(writer); writer.endElement(); writer.endElement(); } struct HandlerPeakData : public SAXParser::Handler { PeakData* peakData; HandlerPeakData(PeakData* _peakData) : peakData(_peakData) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "peakData") { getAttribute(attributes, "sourceFilename", peakData->sourceFilename); return Status::Ok; } else if (name == "software") { _handlerSoftware.software = &(peakData->software); return Status(Status::Delegate, &_handlerSoftware); } else if (name == "scans") { getAttribute(attributes, "count", _scanCount); return Status::Ok; } else { if (name != "scan") { throw runtime_error(("[HandlerPeakData] Unexpected element found : " + name).c_str()); return Status::Done; } peakData->scans.push_back(Scan()); _handlerScan.scan = &(peakData->scans.back()); return Status(Status::Delegate, &_handlerScan); } if(_scanCount != peakData->scans.size()) { throw runtime_error("[HandlerPeakData] != peakData->scans.size()"); return Status::Done; } } private: HandlerSoftware _handlerSoftware; HandlerScan _handlerScan; size_t _scanCount; }; PWIZ_API_DECL void PeakData::read(istream& is) { HandlerPeakData handlerPeakData(this); SAXParser::parse(is, handlerPeakData); } PWIZ_API_DECL bool PeakData::operator==(const PeakData& that) const { return sourceFilename == that.sourceFilename && software == that.software && scans == that.scans; } PWIZ_API_DECL bool PeakData::operator!=(const PeakData& that) const { return !(*this == that); } PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const PeakData& pd) { XMLWriter writer(os); pd.write(writer); return os; } PWIZ_API_DECL std::istream& operator>>(std::istream& is, PeakData& pd) { pd.read(is); return is; } /// /// Peakel /// PWIZ_API_DECL Peakel::Peakel() : mz(0), retentionTime(0), maxIntensity(0), totalIntensity(0), mzVariance(0) {} PWIZ_API_DECL Peakel::Peakel(const Peak& peak) : mz(peak.mz), retentionTime(peak.retentionTime), maxIntensity(0), totalIntensity(0), mzVariance(0) { peaks.push_back(peak); } PWIZ_API_DECL void Peakel::calculateMetadata() { // wipe out any metadata that may have been set mz = 0; retentionTime = 0; mzVariance = 0; maxIntensity = 0; totalIntensity = 0; // calculate intensity metadata vector::iterator calc_intensity_it = peaks.begin(); for(; calc_intensity_it != peaks.end(); ++calc_intensity_it) { if (calc_intensity_it->intensity > maxIntensity) maxIntensity = calc_intensity_it->intensity; totalIntensity += calc_intensity_it->intensity; } // ignore peakels of total intensity zero in rt calculations to avoid div by zero // peakels will still be reported in feature // calculate mz and retentionTime mean vector::iterator calc_mean_it = peaks.begin(); for(; calc_mean_it != peaks.end(); ++calc_mean_it) { mz += calc_mean_it->mz; if (totalIntensity != 0) retentionTime += (calc_mean_it->retentionTime)*(calc_mean_it->intensity)/totalIntensity; //weighted average } mz = mz / peaks.size(); // calculate mz variance vector::iterator calc_var_it = peaks.begin(); for(; calc_var_it != peaks.end(); ++calc_var_it) { mzVariance += (calc_var_it->mz - mz)*(calc_var_it->mz - mz); } mzVariance = mzVariance / peaks.size(); return; } PWIZ_API_DECL double Peakel::retentionTimeMin() const { return peaks.empty() ? retentionTime : peaks.front().retentionTime; } PWIZ_API_DECL double Peakel::retentionTimeMax() const { return peaks.empty() ? retentionTime : peaks.back().retentionTime; } PWIZ_API_DECL void Peakel::write(pwiz::minimxml::XMLWriter& xmlWriter) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("mz", boost::lexical_cast(mz))); attributes.push_back(make_pair("retentionTime",boost::lexical_cast(retentionTime))); attributes.push_back(make_pair("maxIntensity", boost::lexical_cast(maxIntensity))); attributes.push_back(make_pair("totalIntensity", boost::lexical_cast(totalIntensity))); attributes.push_back(make_pair("mzVariance", boost::lexical_cast(mzVariance))); xmlWriter.startElement("peakel", attributes); XMLWriter::Attributes attributes_p; attributes_p.push_back(make_pair("count", boost::lexical_cast(peaks.size()))); xmlWriter.startElement("peaks", attributes_p); vector::const_iterator peak_it = peaks.begin(); for(; peak_it != peaks.end(); ++peak_it) peak_it->write(xmlWriter); xmlWriter.endElement(); xmlWriter.endElement(); } PWIZ_API_DECL void Peakel::read(istream& is) { HandlerPeakel handlerPeakel(this); parse(is, handlerPeakel); } PWIZ_API_DECL bool Peakel::operator==(const Peakel& that) const { return mz == that.mz && retentionTime == that.retentionTime && maxIntensity == that.maxIntensity && totalIntensity == that.totalIntensity && mzVariance == that.mzVariance && peaks == that.peaks; } PWIZ_API_DECL bool Peakel::operator!=(const Peakel& that) const { return !(*this == that); } PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const Peakel& peakel) { XMLWriter writer(os); peakel.write(writer); return os; } PWIZ_API_DECL std::istream& operator>>(std::istream& is, Peakel& peakel) { peakel.read(is); return is; } SAXParser::Handler::Status HandlerPeakel::startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "peakel") { getAttribute(attributes,"mz", peakel->mz); getAttribute(attributes,"retentionTime", peakel->retentionTime); getAttribute(attributes,"maxIntensity", peakel->maxIntensity); getAttribute(attributes,"totalIntensity", peakel->totalIntensity); getAttribute(attributes,"mzVariance", peakel->mzVariance); return Handler::Status::Ok; } else if (name=="peaks") { getAttribute(attributes,"count", _peakCount); return Status::Ok; } else { if (name != "peak") { throw runtime_error(("[HandlerPeakel] Unexpected element name: " + name).c_str()); return Status::Done; } else { peakel->peaks.push_back(Peak()); _handlerPeak.peak = &(peakel->peaks.back()); return Status(Status::Delegate, &_handlerPeak); } } if (_peakCount != peakel->peaks.size()) { throw runtime_error("[HandlerPeakel] != peakel->peaks.size()"); return Status::Done; } } /// /// Feature /// PWIZ_API_DECL Feature::Feature() : mz(0), retentionTime(0), charge(0), totalIntensity(0), rtVariance(0), score(0), error(0) {} PWIZ_API_DECL void Feature::calculateMetadata() { // wipe out any metadata that may have been set mz = 0; retentionTime = 0; rtVariance = 0; totalIntensity = 0; score = 0; error = 0; // calculate metadata of each peakel vector::iterator calc_pkl_it = peakels.begin(); for(; calc_pkl_it != peakels.end(); ++calc_pkl_it) { (*calc_pkl_it)->calculateMetadata(); } // write mz (mz of first peakel) mz = peakels.front()->mz; // calculate totalIntensity and maxIntensity vector::iterator calc_intensity_it = peakels.begin(); for(; calc_intensity_it != peakels.end(); ++calc_intensity_it) { totalIntensity += (*calc_intensity_it)->totalIntensity; } // calculate retentionTime (weighted mean of peakel retentionTimes) vector::iterator calc_mean_it = peakels.begin(); for(; calc_mean_it != peakels.end(); ++calc_mean_it) { retentionTime += ((*calc_mean_it)->retentionTime) * ((*calc_mean_it)->totalIntensity)/totalIntensity; //weighted average } // calculate rtVariance ( variance of peakel retentionTimes) vector::iterator calc_var_it = peakels.begin(); for(; calc_var_it != peakels.end(); ++calc_var_it) { rtVariance += ((*calc_var_it)->retentionTime - retentionTime) * ((*calc_var_it)->retentionTime - retentionTime); } rtVariance = rtVariance / peakels.size(); return; } namespace { const int maxPeakelsToCheck_ = 2; } // namespace PWIZ_API_DECL double Feature::retentionTimeMin() const { double result = retentionTime; vector::const_iterator begin = peakels.begin(); vector::const_iterator end = peakels.end(); if (end-begin>maxPeakelsToCheck_) end = begin+maxPeakelsToCheck_; for (vector::const_iterator it=begin; it!=end; ++it) { double min = (*it)->retentionTimeMin(); if (min < result) result = min; } return result; } PWIZ_API_DECL double Feature::retentionTimeMax() const { double result = retentionTime; vector::const_iterator begin = peakels.begin(); vector::const_iterator end = peakels.end(); if (end-begin>maxPeakelsToCheck_) end = begin+maxPeakelsToCheck_; for (vector::const_iterator it=begin; it!=end; ++it) { double max = (*it)->retentionTimeMax(); if (max > result) result = max; } return result; } PWIZ_API_DECL void Feature::write(pwiz::minimxml::XMLWriter& xmlWriter) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("id", boost::lexical_cast(id))); attributes.push_back(make_pair("mz", boost::lexical_cast(mz))); attributes.push_back(make_pair("retentionTime", boost::lexical_cast(retentionTime))); attributes.push_back(make_pair("charge", boost::lexical_cast(charge))); attributes.push_back(make_pair("totalIntensity", boost::lexical_cast(totalIntensity))); attributes.push_back(make_pair("rtVariance", boost::lexical_cast(rtVariance))); attributes.push_back(make_pair("score", boost::lexical_cast(score))); attributes.push_back(make_pair("error", boost::lexical_cast(error))); xmlWriter.startElement("feature",attributes); XMLWriter::Attributes attributes_pkl; attributes_pkl.push_back(make_pair("count", boost::lexical_cast(peakels.size()))); xmlWriter.startElement("peakels",attributes_pkl); vector::const_iterator pkl_it = peakels.begin(); for(; pkl_it != peakels.end(); ++pkl_it) (*pkl_it)->write(xmlWriter); xmlWriter.endElement(); xmlWriter.endElement(); } SAXParser::Handler::Status HandlerFeature::startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "feature") { getAttribute(attributes,"id", feature->id); getAttribute(attributes,"mz", feature->mz); getAttribute(attributes,"retentionTime", feature->retentionTime); getAttribute(attributes,"charge", feature->charge); getAttribute(attributes,"totalIntensity", feature->totalIntensity); getAttribute(attributes,"rtVariance", feature->rtVariance); getAttribute(attributes,"score", feature->score); getAttribute(attributes,"error", feature->error); return Handler::Status::Ok; } else if (name=="peakels") { getAttribute(attributes,"count", _peakelCount); return Status::Ok; } else { if (name != "peakel") { throw runtime_error(("[HandlerFeature] Unexpected element name: " + name).c_str()); return Status::Done; } else { feature->peakels.push_back(PeakelPtr(new Peakel)); _handlerPeakel.peakel = feature->peakels.back().get(); return Status(Status::Delegate, &_handlerPeakel); } } if (_peakelCount != feature->peakels.size()) { throw runtime_error("[HandlerFeature]: != feature->peakels.size()"); return Status::Done; } } PWIZ_API_DECL Feature::Feature(const MSIHandler::Record& record) { mz = record.mz; retentionTime = record.time; charge = record.charge; totalIntensity = record.intensity; rtVariance = 0; score = 0; error = 0; } PWIZ_API_DECL void Feature::read(istream& is) { HandlerFeature handlerFeature(this); parse(is, handlerFeature); } PWIZ_API_DECL bool Feature::operator==(const Feature& that) const { bool result = (id == that.id && mz == that.mz && retentionTime == that.retentionTime && charge == that.charge && totalIntensity == that.totalIntensity && rtVariance == that.rtVariance && score == that.score && error == that.error); if (!result) return false; if (peakels.size() != that.peakels.size()) return false; for (vector::const_iterator it=peakels.begin(), jt=that.peakels.begin(); it!=peakels.end(); ++it, ++jt) if (**it != **jt) return false; return true; } PWIZ_API_DECL bool Feature::operator!=(const Feature& that) const { return !(*this==that); } PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const Feature& feature) { XMLWriter writer(os); feature.write(writer); return os; } PWIZ_API_DECL std::istream& operator>>(std::istream& is, Feature& feature) { feature.read(is); return is; } PWIZ_API_DECL void FeatureFile::write(pwiz::minimxml::XMLWriter& xmlWriter) const { XMLWriter::Attributes attributes; attributes.push_back(make_pair("count", boost::lexical_cast(features.size()))); xmlWriter.startElement("features",attributes); vector::const_iterator feat_it = features.begin(); for(; feat_it != features.end(); ++feat_it) (*feat_it)->write(xmlWriter); xmlWriter.endElement(); return; } struct HandlerFeatureFile : public SAXParser::Handler { HandlerFeatureFile(FeatureFile* _featureFile = 0) : featureFile(_featureFile){} FeatureFile* featureFile; virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "features") { return Handler::Status::Ok; } else if (name=="feature") { // TODO implement getAttribute(attributes,"count", _peakelCount); featureFile->features.push_back(FeaturePtr(new Feature)); _handlerFeature.feature = featureFile->features.back().get(); return Status(Status::Delegate, &_handlerFeature); } else { throw runtime_error(("Unexpected element in FeatureFile: " + name).c_str()); return Handler::Status::Done; } } private: HandlerFeature _handlerFeature; }; PWIZ_API_DECL void FeatureFile::read(istream& is) { HandlerFeatureFile handlerFeatureFile(this); parse(is,handlerFeatureFile); return; } } // namespace peakdata } // namespace data } // namespace pwiz pwiz/pwiz/data/misc/FrequencyDataTestData.cpp0000664000175100017510000014360112664775621023306 0ustar teamcityteamcity00000000000000// // $Id: FrequencyDataTestData.cpp 1195 2009-08-14 22:12:04Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "FrequencyDataTestData.hpp" RawMassDatum sampleMassData_[] = { {676.3781485, 6908.006348}, {676.3753787, 8325.94043}, {676.372609, 8524.166016}, {676.3698393, 8201.929688}, {676.3670696, 6866.17041}, {676.3642999, 4521.778809}, {676.3615303, 2167.997314}, {676.3587607, 788.0887451}, {676.3559911, 202.7794037}, {676.3532215, 2121.27002}, {676.350452, 5040.513184}, {676.3476825, 7682.216797}, {676.344913, 8698.469727}, {676.3421435, 7576.531738}, {676.339374, 5292.755859}, {676.3366046, 3796.708984}, {676.3338352, 3446.091309}, {676.3310658, 2804.714355}, {676.3282964, 1735.031738}, {676.3255271, 1361.59021}, {676.3227578, 1742.776855}, {676.3199885, 1854.268677}, {676.3172192, 1694.57959}, {676.31445, 1452.604736}, {676.3116807, 1474.278198}, {676.3089115, 2217.81958}, {676.3061423, 2846.165039}, {676.3033732, 2625.031982}, {676.300604, 1761.301636}, {676.2978349, 967.4257202}, {676.2950658, 611.4064941}, {676.2922968, 1074.055664}, {676.2895277, 2059.4021}, {676.2867587, 3028.92749}, {676.2839897, 3732.032959}, {676.2812207, 4093.032227}, {676.2784518, 4153.280273}, {676.2756828, 3885.000732}, {676.2729139, 3354.821045}, {676.270145, 3042.557373}, {676.2673762, 3064.000732}, {676.2646073, 2794.801758}, {676.2618385, 2022.390991}, {676.2590697, 1221.84021}, {676.2563009, 923.5252075}, {676.2535322, 789.9469604}, {676.2507635, 788.1323853}, {676.2479948, 969.4432373}, {676.2452261, 853.1880493}, {676.2424574, 931.2061768}, {676.2396888, 1494.341675}, {676.2369202, 1783.229126}, {676.2341516, 1529.899658}, {676.231383, 920.2738037}, {676.2286144, 525.0412598}, {676.2258459, 916.4795532}, {676.2230774, 1917.24292}, {676.2203089, 2726.755615}, {676.2175405, 2889.875244}, {676.214772, 2522.675293}, {676.2120036, 1908.580811}, {676.2092352, 1410.317261}, {676.2064669, 1563.266602}, {676.2036985, 1828.568726}, {676.2009302, 1467.953003}, {676.1981619, 813.2462769}, {676.1953936, 1585.572754}, {676.1926254, 2824.083008}, {676.1898572, 3436.904541}, {676.187089, 2888.573975}, {676.1843208, 1380.599121}, {676.1815526, 296.726532}, {676.1787845, 1166.725708}, {676.1760164, 1529.677246}, {676.1732483, 2034.930298}, {676.1704802, 2749.771729}, {676.1677121, 3121.559082}, {676.1649441, 2718.746582}, {676.1621761, 1702.927734}, {676.1594081, 850.8549194}, {676.1566402, 533.7766724}, {676.1538722, 597.4779663}, {676.1511043, 1237.397095}, {676.1483364, 1337.354736}, {676.1455686, 728.7314453}, {676.1428007, 684.5762939}, {676.1400329, 1207.466187}, {676.1372651, 1490.667603}, {676.1344973, 2079.553955}, {676.1317296, 3254.888184}, {676.1289618, 4364.762695}, {676.1261941, 4582.788086}, {676.1234264, 3705.047363}, {676.1206588, 2311.991455}, {676.1178911, 1283.987061}, {676.1151235, 1339.348877}, {676.1123559, 1981.695557}, {676.1095883, 2285.52832}, {676.1068208, 2000.625366}, {676.1040533, 1632.976196}, {676.1012858, 1475.346436}, {676.0985183, 1122.883545}, {676.0957508, 608.8710938}, {676.0929834, 376.2699585}, {676.090216, 1237.255249}, {676.0874486, 1957.260986}, {676.0846812, 1853.558716}, {676.0819139, 960.873291}, {676.0791465, 113.1415253}, {676.0763792, 852.039917}, {676.073612, 1297.272705}, {676.0708447, 1622.380127}, {676.0680775, 1711.844116}, {676.0653103, 1617.052124}, {676.0625431, 1538.884399}, {676.0597759, 1375.489014}, {676.0570088, 1480.498291}, {676.0542416, 2391.318604}, {676.0514745, 3169.324707}, {676.0487075, 2879.539551}, {676.0459404, 1577.928833}, {676.0431734, 1717.146484}, {676.0404064, 2861.393066}, {676.0376394, 2838.506836}, {676.0348724, 1808.579834}, {676.0321055, 1075.865234}, {676.0293386, 1946.747925}, {676.0265717, 2594.352783}, {676.0238048, 2304.370361}, {676.021038, 1305.956177}, {676.0182711, 484.813324}, {676.0155043, 811.4865112}, {676.0127376, 1125.836182}, {676.0099708, 1722.810669}, {676.0072041, 2699.725586}, {676.0044374, 3589.418457}, {676.0016707, 4057.317139}, {675.998904, 4005.996338}, {675.9961374, 3577.808105}, {675.9933707, 3095.560303}, {675.9906041, 2665.915527}, {675.9878376, 2118.81665}, {675.985071, 1600.550415}, {675.9823045, 1646.337769}, {675.979538, 1987.083984}, {675.9767715, 2085.007324}, {675.974005, 2007.703857}, {675.9712386, 2000.571167}, {675.9684722, 2088.513672}, {675.9657058, 2105.298096}, {675.9629394, 1957.5354}, {675.960173, 1874.454346}, {675.9574067, 2076.026855}, {675.9546404, 2350.240723}, {675.9518741, 2313.373291}, {675.9491079, 1973.003662}, {675.9463416, 1736.789795}, {675.9435754, 1776.846558}, {675.9408092, 1660.791504}, {675.9380431, 1091.845093}, {675.9352769, 1331.780396}, {675.9325108, 2516.737793}, {675.9297447, 3238.097656}, {675.9269786, 3216.818848}, {675.9242126, 2709.942871}, {675.9214465, 2135.876465}, {675.9186805, 1709.116821}, {675.9159145, 1485.066528}, {675.9131486, 1862.881958}, {675.9103826, 2354.456787}, {675.9076167, 2358.757813}, {675.9048508, 1957.477905}, {675.9020849, 1449.99292}, {675.8993191, 1307.253662}, {675.8965532, 2130.765869}, {675.8937874, 3092.213623}, {675.8910217, 3445.633545}, {675.8882559, 1919.283813}, {675.8854902, 3934.444092}, {675.8827244, 15922.22363}, {675.8799587, 31954.54102}, {675.8771931, 42402.26953}, {675.8744274, 38299.97266}, {675.8716618, 21793.875}, {675.8688962, 8429.955078}, {675.8661306, 9877.270508}, {675.8633651, 7313.313965}, {675.8605995, 2986.85498}, {675.857834, 1778.993164}, {675.8550685, 990.4505005}, {675.8523031, 954.7762451}, {675.8495376, 1378.780884}, {675.8467722, 1576.723389}, {675.8440068, 1830.042358}, {675.8412414, 2732.257813}, {675.8384761, 2810.94165}, {675.8357107, 1943.007568}, {675.8329454, 1218.158203}, {675.8301801, 1089.638672}, {675.8274149, 1193.17981}, {675.8246496, 1452.96582}, {675.8218844, 1506.507568}, {675.8191192, 1090.441284}, {675.816354, 560.348938}, {675.8135889, 1000.985657}, {675.8108238, 1563.696289}, {675.8080587, 1814.017456}, {675.8052936, 1844.746094}, {675.8025285, 1821.392944}, {675.7997635, 1725.908569}, {675.7969985, 1317.565063}, {675.7942335, 650.6932373}, {675.7914685, 1155.004883}, {675.7887036, 2365.357666}, {675.7859386, 3581.433594}, {675.7831737, 4302.118164}, {675.7804089, 3992.665039}, {675.777644, 2944.106201}, {675.7748792, 1963.202271}, {675.7721144, 1315.855469}, {675.7693496, 1071.823486}, {675.7665848, 1158.229492}, {675.7638201, 1166.97876}, {675.7610553, 1438.192261}, {675.7582906, 1837.428833}, {675.755526, 1568.014893}, {675.7527613, 1159.437744}, {675.7499967, 1635.091797}, {675.7472321, 2363.089111}, {675.7444675, 3271.952637}, {675.7417029, 3964.725586}, {675.7389384, 3765.501953}, {675.7361739, 2440.819824}, {675.7334094, 468.3238525}, {675.7306449, 1287.771362}, {675.7278805, 2075.784912}, {675.725116, 1721.250732}, {675.7223516, 842.2559814}, {675.7195873, 442.2115479}, {675.7168229, 758.901123}, {675.7140586, 1476.26709}, {675.7112942, 1596.448608}, {675.70853, 1163.667603}, {675.7057657, 1968.845825}, {675.7030014, 2925.639648}, {675.7002372, 2589.946045}, {675.697473, 1135.681885}, {675.6947088, 467.8063965}, {675.6919447, 897.4993896}, {675.6891806, 722.1495361}, {675.6864164, 1670.047852}, {675.6836524, 2909.208496}, {675.6808883, 3586.191895}, {675.6781243, 3593.170654}, {675.6753602, 3377.664307}, {675.6725962, 3277.290283}, {675.6698323, 3157.245117}, {675.6670683, 2777.567871}, {675.6643044, 2005.026855}, {675.6615405, 987.5808105}, {675.6587766, 1046.320923}, {675.6560127, 1949.147339}, {675.6532489, 2050.642578}, {675.6504851, 1373.130737}, {675.6477213, 1709.638306}, {675.6449575, 2695.37207}, {675.6421938, 3248.082031}, {675.63943, 3513.311035}, {675.6366663, 3500.711182}, {675.6339027, 2896.30835}, {675.631139, 1665.753662}, {675.6283754, 452.9361877}, {675.6256118, 796.1696777}, {675.6228482, 1223.351807}, {675.6200846, 1604.991577}, {675.6173211, 2122.63501}, {675.6145575, 2711.922607}, {675.611794, 2711.219971}, {675.6090306, 1550.381592}, {675.6062671, 413.7042236}, {675.6035037, 1796.509399}, {675.6007403, 2526.391602}, {675.5979769, 3281.082275}, {675.5952135, 4194.502441}, {675.5924502, 4731.30127}, {675.5896869, 4669.61377}, {675.5869236, 4068.651855}, {675.5841603, 3134.30127}, {675.581397, 2198.210205}, {675.5786338, 1366.322388}, {675.5758706, 1266.662476}, {675.5731074, 2608.709961}, {675.5703443, 3447.631348}, {675.5675811, 2790.967041}, {675.564818, 1202.448242}, {675.5620549, 973.6413574}, {675.5592918, 1328.671631}, {675.5565288, 1301.22522}, {675.5537658, 1369.235596}, {675.5510028, 1283.686768}, {675.5482398, 802.4091187}, {675.5454768, 566.8187256}, {675.5427139, 1150.43396}, {675.539951, 1434.704834}, {675.5371881, 1279.977661}, {675.5344252, 1459.455933}, {675.5316624, 2083.875}, {675.5288996, 2524.698242}, {675.5261368, 2696.900391}, {675.523374, 2517.855713}, {675.5206112, 1834.391724}, {675.5178485, 1193.908691}, {675.5150858, 1415.326416}, {675.5123231, 1512.798462}, {675.5095605, 1399.47998}, {675.5067978, 1745.74353}, {675.5040352, 2569.477539}, {675.5012726, 3493.688721}, {675.49851, 4068.449951}, {675.4957475, 3748.615967}, {675.492985, 2407.814453}, {675.4902224, 1133.511597}, {675.48746, 1517.33252}, {675.4846975, 1968.585083}, {675.4819351, 2102.836426}, {675.4791727, 1821.713745}, {675.4764103, 1533.25354}, {675.4736479, 1882.138306}, {675.4708855, 2475.824463}, {675.4681232, 3034.681885}, {675.4653609, 3480.579346}, {675.4625986, 3259.221924}, {675.4598364, 2144.9375}, {675.4570742, 1008.018921}, {675.4543119, 884.3475342}, {675.4515498, 1110.799561}, {675.4487876, 2046.993896}, {675.4460254, 3076.978516}, {675.4432633, 3223.894775}, {675.4405012, 2316.321289}, {675.4377392, 882.9598389}, {675.4349771, 1145.708862}, {675.4322151, 2190.633057}, {675.4294531, 2623.345703}, {675.4266911, 2535.549316}, {675.4239291, 2074.421143}, {675.4211672, 1650.293945}, {675.4184053, 1295.122681}, {675.4156434, 1031.173828}, {675.4128815, 1500.885742}, {675.4101196, 1255.178589}, {675.4073578, 578.6574097}, {675.404596, 1336.253174}, {675.4018342, 2097.073975}, {675.3990725, 3746.538574}, {675.3963107, 4194.332031}, {675.393549, 2988.430664}, {675.3907873, 3087.300781}, {675.3880257, 2596.1521}, {675.385264, 3775.312256}, {675.3825024, 28447.92188}, {675.3797408, 73531.86719}, {675.3769792, 116067.2422}, {675.3742177, 125616.0391}, {675.3714561, 96175.76563}, {675.3686946, 54535.55078}, {675.3659331, 29965.24414}, {675.3631717, 16566.83203}, {675.3604102, 4437.322266}, {675.3576488, 1659.719238}, {675.3548874, 1533.13855}, {675.352126, 1267.342407}, {675.3493647, 2085.241211}, {675.3466033, 1133.588379}, {675.343842, 537.0843506}, {675.3410807, 1779.976563}, {675.3383195, 2672.36792}, {675.3355582, 2968.611816}, {675.332797, 2848.094482}, {675.3300358, 2259.621338}, {675.3272747, 857.9924927}, {675.3245135, 1707.045044}, {675.3217524, 3239.967041}, {675.3189913, 3750.874023}, {675.3162302, 3781.594727}, {675.3134691, 3866.938965}, {675.3107081, 3775.527344}, {675.3079471, 3376.024414}, {675.3051861, 3132.815674}, {675.3024251, 3222.619873}, {675.2996642, 3054.687256}, {675.2969033, 2256.658447}, {675.2941424, 1332.876099}, {675.2913815, 696.0239258}, {675.2886206, 102.2348022}, {675.2858598, 515.824646}, {675.283099, 927.5770264}, {675.2803382, 1086.114502}, {675.2775774, 1103.259766}, {675.2748167, 957.9190674}, {675.272056, 876.5166626}, {675.2692953, 828.4721069}, {675.2665346, 618.425293}, {675.2637739, 449.1333923}, {675.2610133, 634.9506226}, {675.2582527, 781.8742676}, {675.2554921, 841.5576172}, {675.2527315, 708.112854}, {675.249971, 573.0977173}, {675.2472105, 2094.992188}, {675.24445, 3529.406738}, {675.2416895, 4095.324951}, {675.2389291, 3941.611328}, {675.2361686, 3439.070313}, {675.2334082, 2887.061523}, {675.2306479, 2938.27002}, {675.2278875, 3219.418945}, {675.2251272, 2799.475586}, {675.2223668, 1712.228882}, {675.2196066, 436.2648315}, {675.2168463, 709.4594727}, {675.214086, 1284.770874}, {675.2113258, 1452.133667}, {675.2085656, 1447.319946}, {675.2058054, 1155.190918}, {675.2030453, 676.6842041}, {675.2002851, 1319.274414}, {675.197525, 1539.662842}, {675.1947649, 441.7297363}, {675.1920049, 1308.745605}, {675.1892448, 2233.919189}, {675.1864848, 1928.362549}, {675.1837248, 1345.46521}, {675.1809648, 1348.704346}, {675.1782049, 1615.440552}, {675.175445, 1973.635986}, {675.1726851, 2237.685791}, {675.1699252, 2274.393066}, {675.1671653, 2072.248291}, {675.1644055, 1635.945068}, {675.1616456, 1060.800659}, {675.1588858, 1033.893677}, {675.1561261, 1527.780884}, {675.1533663, 1791.394409}, {675.1506066, 1715.693115}, {675.1478469, 1337.357422}, {675.1450872, 649.0513306}, {675.1423276, 496.4603271}, {675.1395679, 1248.529175}, {675.1368083, 1527.616455}, {675.1340487, 1370.387695}, {675.1312891, 998.8162231}, {675.1285296, 435.3985901}, {675.1257701, 230.8042145}, {675.1230106, 707.5698242}, {675.1202511, 1081.781494}, {675.1174916, 1640.292114}, {675.1147322, 1980.82666}, {675.1119728, 1458.744751}, {675.1092134, 309.8274841}, {675.106454, 1083.613647}, {675.1036947, 1823.574829}, {675.1009354, 2460.578125}, {675.0981761, 3171.237305}, {675.0954168, 3543.184082}, {675.0926575, 3091.75415}, {675.0898983, 1768.549805}, {675.0871391, 479.8030396}, {675.0843799, 1509.191895}, {675.0816207, 2412.253418}, {675.0788616, 2843.667236}, {675.0761025, 2902.78833}, {675.0733434, 3076.933838}, {675.0705843, 3509.866455}, {675.0678253, 3518.695068}, {675.0650662, 2602.770264}, {675.0623072, 1383.766479}, {675.0595482, 2061.293945}, {675.0567893, 3118.94751}, {675.0540303, 2789.432373}, {675.0512714, 1287.244263}, {675.0485125, 772.3991699}, {675.0457537, 1072.069458}, {675.0429948, 1222.008911}, {675.040236, 1972.176636}, {675.0374772, 2607.870605}, {675.0347184, 2814.466553}, {675.0319597, 2059.471436}, {675.0292009, 279.0333862}, {675.0264422, 2341.075928}, {675.0236835, 3089.121582}, {675.0209248, 2221.579102}, {675.0181662, 1234.88623}, {675.0154076, 1092.3125}, {675.012649, 1077.821655}, {675.0098904, 693.5176392}, {675.0071318, 387.7669983}, {675.0043733, 396.8587036}, {675.0016148, 723.9761963}, {674.9988563, 1051.822754}, {674.9960979, 1451.745972}, {674.9933394, 1544.654663}, {674.990581, 1023.750671}, {674.9878226, 988.1325073}, {674.9850642, 1813.221069}, {674.9823059, 1866.448608}, {674.9795475, 1719.127319}, {674.9767892, 2296.617676}, {674.974031, 2565.015869}, {674.9712727, 2471.682617}, {674.9685144, 2074.21582}, {674.9657562, 1297.69397}, {674.962998, 1021.461365}, {674.9602399, 1058.229492}, {674.9574817, 1480.281738}, {674.9547236, 2522.341797}, {674.9519655, 3447.219482}, {674.9492074, 3564.958252}, {674.9464493, 3133.591553}, {674.9436913, 2793.955811}, {674.9409333, 2867.115723}, {674.9381753, 3673.512451}, {674.9354173, 3851.987793}, {674.9326594, 3122.599609}, {674.9299015, 2867.618164}, {674.9271436, 2717.000977}, {674.9243857, 1845.55481}, {674.9216278, 1571.527954}, {674.91887, 1478.94165}, {674.9161122, 711.4684448}, {674.9133544, 1001.711731}, {674.9105966, 2181.034668}, {674.9078389, 2994.979248}, {674.9050812, 2867.082764}, {674.9023235, 1711.101074}, {674.8995658, 1368.897949}, {674.8968081, 1386.59668}, {674.8940505, 1179.960938}, {674.8912929, 2325.220215}, {674.8885353, 3447.293945}, {674.8857778, 2117.488281}, {674.8830202, 16993.85156}, {674.8802627, 98342.50781}, {674.8775052, 243059.2656}, {674.8747477, 377339.75}, {674.8719903, 406940.5938}, {674.8692329, 310894.9688}, {674.8664754, 163930.0625}, {674.8637181, 59964.55859}, {674.8609607, 23675.35547}, {674.8582034, 10168.18066}, {674.8554461, 5918.285645}, {674.8526888, 4999.23291}, {674.8499315, 2973.062988}, {674.8471742, 5029.340332}, {674.844417, 4486.730957}, {674.8416598, 1455.366821}, {674.8389026, 540.0476685}, {674.8361455, 1274.473267}, {674.8333883, 729.531311}, {674.8306312, 767.3745728}, {674.8278741, 1743.136108}, {674.8251171, 2233.568359}, {674.82236, 1434.608398}, {674.819603, 1815.842651}, {674.816846, 2192.672852}, {674.814089, 1710.250122}, {674.8113321, 1630.876587}, {674.8085751, 1435.52478}, {674.8058182, 491.1956787}, {674.8030613, 958.8461304}, {674.8003045, 1384.473267}, {674.7975476, 1982.851318}, {674.7947908, 2229.187744}, {674.792034, 1331.755981}, {674.7892772, 345.0233154}, {674.7865205, 1087.534302}, {674.7837638, 261.9281006}, {674.7810071, 1267.17041}, {674.7782504, 2017.687012}, {674.7754937, 2018.028809}, {674.7727371, 1322.156616}, {674.7699805, 18.05745125}, {674.7672239, 1621.014893}, {674.7644673, 2541.158203}, {674.7617107, 2543.519775}, {674.7589542, 2290.499756}, {674.7561977, 2170.130859}, {674.7534412, 2569.070068}, {674.7506848, 2952.661377}, {674.7479283, 2941.827148}, {674.7451719, 2531.496826}, {674.7424155, 2130.289795}, {674.7396592, 1931.687378}, {674.7369028, 1317.456299}, {674.7341465, 882.3710938}, {674.7313902, 1081.266235}, {674.7286339, 630.9973145}, {674.7258777, 907.1119995}, {674.7231214, 1721.054688}, {674.7203652, 2294.809082}, {674.717609, 2346.437256}, {674.7148529, 2374.180908}, {674.7120967, 2361.521973}, {674.7093406, 1956.668579}, {674.7065845, 822.624939}, {674.7038284, 667.9483032}, {674.7010724, 1559.463745}, {674.6983163, 1987.799438}, {674.6955603, 2082.274658}, {674.6928043, 1623.520142}, {674.6900484, 775.8206787}, {674.6872924, 485.0063782}, {674.6845365, 265.7205811}, {674.6817806, 843.782959}, {674.6790247, 1239.684448}, {674.6762689, 1748.32373}, {674.6735131, 2102.503662}, {674.6707573, 2254.043213}, {674.6680015, 4115.34668}, {674.6652457, 5938.141113}, {674.66249, 5936.261719}, {674.6597343, 4583.389648}, {674.6569786, 3024.423584}, {674.6542229, 1476.929932}, {674.6514672, 514.477478}, {674.6487116, 1263.25647}, {674.645956, 1297.599121}, {674.6432004, 972.5446167}, {674.6404449, 868.1560669}, {674.6376893, 1179.534424}, {674.6349338, 1492.49292}, {674.6321783, 1636.060303}, {674.6294229, 1489.988525}, {674.6266674, 1321.480103}, {674.623912, 917.8769531}, {674.6211566, 591.8057251}, {674.6184012, 1562.333862}, {674.6156459, 2725.339355}, {674.6128905, 3542.870605}, {674.6101352, 3237.626709}, {674.6073799, 1963.685059}, {674.6046247, 948.4092407}, {674.6018694, 754.2011108}, {674.5991142, 769.739624}, {674.596359, 1164.165527}, {674.5936038, 2098.279785}, {674.5908487, 2958.445557}, {674.5880935, 3668.697754}, {674.5853384, 4153.015625}, {674.5825833, 4635.314453}, {674.5798283, 5073.393555}, {674.5770732, 4817.368164}, {674.5743182, 3654.49585}, {674.5715632, 2332.06958}, {674.5688083, 1593.56311}, {674.5660533, 1382.949219}, {674.5632984, 1220.268066}, {674.5605435, 770.4715576}, {674.5577886, 833.562439}, {674.5550337, 807.7918701}, {674.5522789, 1478.803467}, {674.5495241, 3074.471436}, {674.5467693, 3869.310547}, {674.5440145, 3652.764893}, {674.5412598, 2917.725098}, {674.538505, 2115.982178}, {674.5357503, 1737.807739}, {674.5329956, 1335.924194}, {674.530241, 1136.352783}, {674.5274864, 1406.706299}, {674.5247317, 773.0444336}, {674.5219771, 446.787262}, {674.5192226, 1301.657715}, {674.516468, 1994.447998}, {674.5137135, 2362.033691}, {674.510959, 2391.580322}, {674.5082045, 1797.274536}, {674.5054501, 567.8452759}, {674.5026956, 811.9489746}, {674.4999412, 1526.783203}, {674.4971868, 1631.797363}, {674.4944325, 2083.518555}, {674.4916781, 3012.389893}, {674.4889238, 3342.541748}, {674.4861695, 2771.74707}, {674.4834152, 2379.067139}, {674.480661, 2752.13501}, {674.4779068, 3565.534668}, {674.4751525, 3989.14917}, {674.4723984, 3104.87207}, {674.4696442, 1314.490356}, {674.4668901, 803.4127808}, {674.4641359, 2336.768311}, {674.4613818, 2973.858887}, {674.4586278, 2018.856445}, {674.4558737, 1096.974243}, {674.4531197, 1139.965698}, {674.4503657, 1163.758423}, {674.4476117, 1225.935791}, {674.4448577, 1268.814819}, {674.4421038, 603.9320679}, {674.4393499, 217.1664276}, {674.436596, 1121.991089}, {674.4338421, 2585.576172}, {674.4310883, 3080.650391}, {674.4283344, 2390.54834}, {674.4255806, 1214.224243}, {674.4228269, 566.7775879}, {674.4200731, 811.6956787}, {674.4173194, 913.7035522}, {674.4145657, 1546.883301}, {674.411812, 2253.363281}, {674.4090583, 2530.631348}, {674.4063046, 2404.542969}, {674.403551, 3007.831299}, {674.4007974, 1482.311401}, {674.3980438, 1922.084106}, {674.3952903, 1951.040771}, {674.3925368, 1510.865601}, {674.3897832, 2077.196533}, {674.3870298, 3618.857178}, {674.3842763, 5425.393555}, {674.3815228, 15564.97363}, {674.3787694, 116870.0469}, {674.376016, 312874.4688}, {674.3732626, 512659.7813}, {674.3705093, 580827.25}, {674.367756, 468018.5313}, {674.3650027, 261761.0156}, {674.3622494, 95720.50781}, {674.3594961, 29205.36133}, {674.3567429, 13922.30664}, {674.3539896, 8309.356445}, {674.3512364, 6197.816406}, {674.3484833, 2457.318359}, {674.3457301, 7294.287598}, {674.342977, 8135.105957}, {674.3402239, 4464.359863}, {674.3374708, 2911.270264}, {674.3347177, 4860.013184}, {674.3319647, 5072.168945}, {674.3292117, 4278.435059}, {674.3264587, 3826.949951}, {674.3237057, 2780.50415}, {674.3209528, 2858.534912}, {674.3181998, 3353.280273}, {674.3154469, 1850.38916}, {674.3126941, 198.342392}, {674.3099412, 657.7745972}, {674.3071884, 347.2738647}, {674.3044355, 361.0331421}, {674.3016828, 784.906189}, {674.29893, 1836.144043}, {674.2961772, 2666.059814}, {674.2934245, 1952.458374}, {674.2906718, 835.5542603}, {674.2879191, 588.3599243}, {674.2851665, 164.3770294}, {674.2824138, 347.4847412}, {674.2796612, 447.9833069}, {674.2769086, 651}, {674.2741561, 340.9006958}, {674.2714035, 1115.292236}, {674.268651, 2257.663086}, {674.2658985, 2196.981445}, {674.263146, 1484.213867}, {674.2603936, 1667.801025}, {674.2576411, 2162.061523}, {674.2548887, 1886.047607}, {674.2521363, 1296.561768}, {674.249384, 879.8372192}, {674.2466316, 685.8312988}, {674.2438793, 1103.910889}, {674.241127, 1264.370605}, {674.2383747, 730.1365967}, {674.2356225, 632.3787231}, {674.2328703, 556.3587036}, {674.2301181, 777.828125}, {674.2273659, 2001.377563}, {674.2246137, 3243.102539}, {674.2218616, 3933.940918}, {674.2191095, 3342.487305}, {674.2163574, 1638.602417}, {674.2136053, 558.2545776}, {674.2108532, 1076.176636}, {674.2081012, 1584.407715}, {674.2053492, 2164.473877}, {674.2025972, 2045.957764}, {674.1998453, 1279.465454}, {674.1970933, 1274.143921}, {674.1943414, 1251.730469}, {674.1915895, 846.6213379}, {674.1888376, 893.8978271}, {674.1860858, 752.5766602}, {674.183334, 394.3918152}, {674.1805822, 962.673645}, {674.1778304, 1397.615967}, {674.1750786, 1493.608276}, {674.1723269, 1373.629761}, {674.1695752, 1204.284668}, {674.1668235, 1339.834717}, {674.1640718, 1411.848389}, {674.1613202, 1078.794189}, {674.1585685, 689.6085815}, {674.1558169, 630.2418823}, {674.1530654, 1370.324463}, {674.1503138, 2530.2146}, {674.1475623, 3243.492188}, {674.1448108, 3186.416504}, {674.1420593, 2700.454834}, {674.1393078, 1813.867188}, {674.1365564, 851.7230835}, {674.1338049, 861.3334961}, {674.1310535, 1114.391724}, {674.1283022, 1177.304199}, {674.1255508, 1445.869141}, {674.1227995, 2016.13147}, {674.1200482, 2584.033203}, {674.1172969, 3098.719971}, {674.1145456, 3486.729492}, {674.1117944, 3415.645996}, {674.1090432, 2704.50708}, {674.106292, 1798.821045}, {674.1035408, 1181.923462}, {674.1007896, 635.6556396}, {674.0980385, 311.4511719}, {674.0952874, 722.1294556}, {674.0925363, 1432.299316}, {674.0897853, 1731.50415}, {674.0870342, 1448.115234}, {674.0842832, 680.15979}, {674.0815322, 664.9151611}, {674.0787812, 1989.189087}, {674.0760303, 2532.318115}, {674.0732794, 1971.571777}, {674.0705285, 1396.751587}, {674.0677776, 1623.326904}, {674.0650267, 1611.725952}, {674.0622759, 1125.2146}, {674.0595251, 373.2664185}, {674.0567743, 633.1131592}, {674.0540235, 1279.297363}, {674.0512727, 1556.98877}, {674.048522, 1641.555664}, {674.0457713, 1820.20752}, {674.0430206, 2083.088379}, {674.04027, 2313.998047}, {674.0375193, 2746.805664}, {674.0347687, 3363.490723}, {674.0320181, 3465.371826}, {674.0292676, 2664.765381}, {674.026517, 1349.442749}, {674.0237665, 451.6225281}, {674.021016, 903.6030884}, {674.0182655, 1182.672729}, {674.0155151, 1180.812378}, {674.0127646, 1330.194214}, {674.0100142, 1593.366699}, {674.0072638, 1595.649414}, {674.0045135, 1395.937378}, {674.0017631, 1116.376343} }; // sampleMassData_ const unsigned int sampleMassDataSize_ = sizeof(sampleMassData_)/sizeof(RawMassDatum); const char* sampleFrequencyData_ = "<158981.770800;(-5439.968005,19698.313350)>\n" "<158983.072900;(16855.795550,11971.275420)>\n" "<158984.375000;(7579.862497,-8411.025030)>\n" "<158985.677100;(1495.080128,-684.037850)>\n" "<158986.979200;(-583.143160,-1294.620782)>\n" "<158988.281200;(-3191.215007,-2123.965274)>\n" "<158989.583300;(6288.097808,13471.747780)>\n" "<158990.885400;(281.171354,-2368.558610)>\n" "<158992.187500;(6727.998171,-637.150071)>\n" "<158993.489600;(90.481062,-2645.529419)>\n" "<158994.791700;(-1910.952406,462.415227)>\n" "<158996.093800;(2059.954130,-556.405563)>\n" "<158997.395800;(-853.281447,-976.494563)>\n" "<158998.697900;(427.634375,-5805.819177)>\n" "<159000.000000;(1995.541301,684.000628)>\n" "<159001.302100;(371.037816,710.206471)>\n" "<159002.604200;(230.993848,2576.541884)>\n" "<159003.906200;(2991.913376,-3229.454358)>\n" "<159005.208300;(10.089849,4874.712579)>\n" "<159006.510400;(671.270338,-3402.210367)>\n" "<159007.812500;(-4667.111008,394.130011)>\n" "<159009.114600;(2042.160737,1476.737853)>\n" "<159010.416700;(1027.787493,-224.256592)>\n" "<159011.718800;(921.559699,1753.042683)>\n" "<159013.020800;(-2079.934743,2446.940865)>\n" "<159014.322900;(-2668.935351,950.226079)>\n" "<159015.625000;(-391.739889,5028.884809)>\n" "<159016.927100;(267.066230,3494.638846)>\n" "<159018.229200;(643.189814,4288.823088)>\n" "<159019.531200;(-1866.926347,-1788.491729)>\n" "<159020.833300;(1787.937165,2285.628296)>\n" "<159022.135400;(-1073.928213,2224.735823)>\n" "<159023.437500;(588.943389,-2456.921213)>\n" "<159024.739600;(3023.425549,-1034.720299)>\n" "<159026.041700;(2176.762945,5880.419895)>\n" "<159027.343800;(641.724507,-1220.473197)>\n" "<159028.645800;(-444.786593,-2747.717675)>\n" "<159029.947900;(-709.886620,340.651628)>\n" "<159031.250000;(3528.362712,-3680.032188)>\n" "<159032.552100;(-233.347710,1986.951261)>\n" "<159033.854200;(-1867.005685,1201.270154)>\n" "<159035.156200;(-2138.743297,2104.050522)>\n" "<159036.458300;(1129.120536,-373.835411)>\n" "<159037.760400;(1411.508988,-2314.103875)>\n" "<159039.062500;(459.005526,342.158393)>\n" "<159040.364600;(6649.260712,-1753.456769)>\n" "<159041.666700;(-4340.430084,-256.547987)>\n" "<159042.968800;(-395.890304,320.711706)>\n" "<159044.270800;(-1369.574330,2257.823209)>\n" "<159045.572900;(1465.305975,-2808.272431)>\n" "<159046.875000;(3357.053714,93.570172)>\n" "<159048.177100;(1569.162340,-1683.677327)>\n" "<159049.479200;(1133.972086,-1496.256356)>\n" "<159050.781200;(-3324.508009,1612.518525)>\n" "<159052.083300;(-1561.238172,552.300996)>\n" "<159053.385400;(497.701663,-663.419030)>\n" "<159054.687500;(891.910214,3334.854884)>\n" "<159055.989600;(-1779.677159,1211.342366)>\n" "<159057.291700;(1656.064322,869.604477)>\n" "<159058.593800;(2140.570945,5954.845552)>\n" "<159059.895800;(1959.202585,-1749.406764)>\n" "<159061.197900;(5719.167019,-4067.657528)>\n" "<159062.500000;(2346.107840,2731.616492)>\n" "<159063.802100;(-589.045973,2030.711877)>\n" "<159065.104200;(3019.165763,-3643.967824)>\n" "<159066.406200;(1875.484670,-1332.308318)>\n" "<159067.708300;(-395.486642,-806.344388)>\n" "<159069.010400;(639.592737,-3750.512656)>\n" "<159070.312500;(3374.705947,4023.004262)>\n" "<159071.614600;(-3720.138802,-1426.572017)>\n" "<159072.916700;(2905.031755,-2311.905988)>\n" "<159074.218800;(-723.991388,43.232600)>\n" "<159075.520800;(2011.255325,2387.881853)>\n" "<159076.822900;(-788.267597,-853.484402)>\n" "<159078.125000;(2661.376320,1226.661472)>\n" "<159079.427100;(728.053285,-2941.263977)>\n" "<159080.729200;(1850.278674,102.167454)>\n" "<159082.031200;(1370.047440,-5141.024415)>\n" "<159083.333300;(865.889278,-1267.050352)>\n" "<159084.635400;(4339.020751,-3524.042993)>\n" "<159085.937500;(2367.898540,-2418.438207)>\n" "<159087.239600;(-1774.361566,-6306.716212)>\n" "<159088.541700;(3742.813018,-1302.626339)>\n" "<159089.843800;(3464.434756,-5646.707620)>\n" "<159091.145800;(4275.161007,-3577.038735)>\n" "<159092.447900;(820.318085,-7627.831353)>\n" "<159093.750000;(4975.180414,-5661.637546)>\n" "<159095.052100;(5474.716606,-7742.121772)>\n" "<159096.354200;(6110.160151,-1859.085474)>\n" "<159097.656200;(10821.048330,-11266.123780)>\n" "<159098.958300;(28641.276320,-30905.514880)>\n" "<159100.260400;(-84678.853340,-40217.694600)>\n" "<159101.562500;(-56285.994110,4998.112006)>\n" "<159102.864600;(-18005.111730,17583.779360)>\n" "<159104.166700;(-7501.423711,11341.664310)>\n" "<159105.468800;(-6187.376492,8297.369033)>\n" "<159106.770800;(-4992.361000,10888.878590)>\n" "<159108.072900;(-8844.919803,10622.088070)>\n" "<159109.375000;(-3937.349522,4689.713808)>\n" "<159110.677100;(-3430.424072,6209.074338)>\n" "<159111.979200;(-5541.112901,4662.864005)>\n" "<159113.281200;(-2434.716269,6077.530887)>\n" "<159114.583300;(-3145.571507,5518.571998)>\n" "<159115.885400;(-1714.773982,1972.806516)>\n" "<159117.187500;(-5581.757849,4031.096278)>\n" "<159118.489600;(-2211.040419,6795.404906)>\n" "<159119.791700;(-1203.705045,4841.569662)>\n" "<159121.093800;(-4335.241713,1049.150308)>\n" "<159122.395800;(4943.052879,5312.172365)>\n" "<159123.697900;(-1440.849153,6557.797553)>\n" "<159125.000000;(-640.387790,4691.759996)>\n" "<159126.302100;(-3954.283811,4475.147649)>\n" "<159127.604200;(-3690.752905,7641.730382)>\n" "<159128.906200;(-1200.793208,4074.824688)>\n" "<159130.208300;(-3462.686251,973.835413)>\n" "<159131.510400;(3454.157540,85.662417)>\n" "<159132.812500;(-4904.355428,4712.140154)>\n" "<159134.114600;(-4188.123617,5752.255884)>\n" "<159135.416700;(1760.812170,6184.060635)>\n" "<159136.718800;(781.766563,6340.400148)>\n" "<159138.020800;(1499.869462,6369.819641)>\n" "<159139.322900;(-2942.217750,3860.610281)>\n" "<159140.625000;(-6807.281153,6453.963792)>\n" "<159141.927100;(-629.052799,3185.250377)>\n" "<159143.229200;(1624.110304,2658.798529)>\n" "<159144.531200;(147.687087,1255.038198)>\n" "<159145.833300;(-6118.284961,4702.102864)>\n" "<159147.135400;(1185.673543,3408.352342)>\n" "<159148.437500;(-5252.093269,1350.906877)>\n" "<159149.739600;(813.367279,735.779308)>\n" "<159151.041700;(-1202.886100,1500.271293)>\n" "<159152.343800;(-3037.066664,6633.504803)>\n" "<159153.645800;(-4058.074852,3654.688066)>\n" "<159154.947900;(1563.077856,1260.102095)>\n" "<159156.250000;(-5887.581550,1610.692100)>\n" "<159157.552100;(767.861333,1714.276245)>\n" "<159158.854200;(870.064588,61.929656)>\n" "<159160.156200;(-2578.993837,-1755.504983)>\n" "<159161.458300;(-6210.994979,2935.083000)>\n" "<159162.760400;(895.058631,5523.714674)>\n" "<159164.062500;(1735.383535,6750.773795)>\n" "<159165.364600;(-3627.940900,4553.592212)>\n" "<159166.666700;(4086.802120,31.520526)>\n" "<159167.968800;(-4072.988175,6367.422998)>\n" "<159169.270800;(106.220232,2127.072071)>\n" "<159170.572900;(-3300.432149,2859.806769)>\n" "<159171.875000;(-8688.687337,-1228.448340)>\n" "<159173.177100;(-1782.111055,752.812408)>\n" "<159174.479200;(53.870446,3484.151425)>\n" "<159175.781200;(-188.513038,1072.991758)>\n" "<159177.083300;(-1583.972480,4180.451185)>\n" "<159178.385400;(-2785.405137,4231.601326)>\n" "<159179.687500;(656.560564,4150.241225)>\n" "<159180.989600;(-487.628122,6740.784678)>\n" "<159182.291700;(-767.033722,1256.392951)>\n" "<159183.593800;(-4311.453629,6605.107654)>\n" "<159184.895800;(-1871.469309,8137.431442)>\n" "<159186.197900;(-1239.425311,4526.802799)>\n" "<159187.500000;(-225.425146,6784.393319)>\n" "<159188.802100;(-3432.968781,-161.261639)>\n" "<159190.104200;(-1909.941585,8936.563229)>\n" "<159191.406200;(-3430.958675,9239.555367)>\n" "<159192.708300;(1010.657817,9537.311164)>\n" "<159194.010400;(-1658.679193,5498.717861)>\n" "<159195.312500;(-4773.350496,7992.304522)>\n" "<159196.614600;(-4021.448387,1709.859543)>\n" "<159197.916700;(-3107.202019,9788.097869)>\n" "<159199.218800;(-4228.733507,9815.415781)>\n" "<159200.520800;(-2651.270427,12357.926990)>\n" "<159201.822900;(3851.298487,9064.783009)>\n" "<159203.125000;(-1924.542150,11609.087830)>\n" "<159204.427100;(-5825.604783,12069.921890)>\n" "<159205.729200;(-1600.976854,16263.997290)>\n" "<159207.031200;(-3599.867111,12784.867080)>\n" "<159208.333300;(-2938.354155,16039.149890)>\n" "<159209.635400;(-7267.016397,20478.321400)>\n" "<159210.937500;(-8427.080759,23473.785590)>\n" "<159212.239600;(-10474.948520,22788.628440)>\n" "<159213.541700;(-4489.906265,36117.666090)>\n" "<159214.843800;(-12436.337760,49901.294540)>\n" "<159216.145800;(-13427.643390,79766.286270)>\n" "<159217.447900;(-6343.080666,233755.228000)>\n" "<159218.750000;(186155.668300,-40556.199420)>\n" "<159220.052100;(64189.621570,-91295.687310)>\n" "<159221.354200;(32424.211960,-52622.907170)>\n" "<159222.656200;(18946.522490,-37732.999750)>\n" "<159223.958300;(12784.366660,-34534.137270)>\n" "<159225.260400;(9098.126127,-27882.109590)>\n" "<159226.562500;(4195.754231,-22873.668290)>\n" "<159227.864600;(9319.097090,-16410.661240)>\n" "<159229.166700;(4467.122137,-18129.474850)>\n" "<159230.468800;(-24.479607,-17886.409120)>\n" "<159231.770800;(4279.244923,-9310.987306)>\n" "<159233.072900;(1920.153196,-15702.715960)>\n" "<159234.375000;(2877.375034,-8318.654343)>\n" "<159235.677100;(3457.597124,-14376.066460)>\n" "<159236.979200;(4012.857036,-8963.765447)>\n" "<159238.281200;(3778.415246,-9591.893603)>\n" "<159239.583300;(3701.717212,-10664.411330)>\n" "<159240.885400;(1151.368415,-9719.520455)>\n" "<159242.187500;(2966.087089,-8103.541129)>\n" "<159243.489600;(1436.212500,-7982.315732)>\n" "<159244.791700;(2343.765434,-7666.413792)>\n" "<159246.093800;(1488.237202,-6059.628145)>\n" "<159247.395800;(1704.206576,-8349.027693)>\n" "<159248.697900;(-85.107272,-12149.848750)>\n" "<159250.000000;(1632.378781,-2673.930787)>\n" "<159251.302100;(416.391576,-9485.246062)>\n" "<159252.604200;(-4854.707157,-5884.444406)>\n" "<159253.906200;(1962.092267,-7319.054784)>\n" "<159255.208300;(2611.355820,-5796.919636)>\n" "<159256.510400;(629.767142,-3323.924640)>\n" "<159257.812500;(4347.692973,-3310.141103)>\n" "<159259.114600;(3732.282400,-2696.092226)>\n" "<159260.416700;(1470.871277,-7447.247763)>\n" "<159261.718800;(430.955976,-11183.078150)>\n" "<159263.020800;(-1177.646709,-6366.481012)>\n" "<159264.322900;(1662.812113,-5041.883845)>\n" "<159265.625000;(-2056.862302,-4255.986240)>\n" "<159266.927100;(3222.592947,-3993.875189)>\n" "<159268.229200;(343.662135,-5592.187310)>\n" "<159269.531200;(1665.777689,-6885.102869)>\n" "<159270.833300;(-1076.962602,-3906.347238)>\n" "<159272.135400;(1180.640529,-6193.647436)>\n" "<159273.437500;(2714.383691,-6273.368245)>\n" "<159274.739600;(316.460424,-3462.245398)>\n" "<159276.041700;(1485.881866,-5327.106641)>\n" "<159277.343800;(1971.431973,-5872.258807)>\n" "<159278.645800;(2047.312724,-3882.807649)>\n" "<159279.947900;(193.293208,-8648.575640)>\n" "<159281.250000;(442.595552,-8246.945573)>\n" "<159282.552100;(-740.978824,-4126.048160)>\n" "<159283.854200;(6216.864780,-6265.622693)>\n" "<159285.156200;(-1097.916956,-7309.903843)>\n" "<159286.458300;(-1448.970643,-6690.837424)>\n" "<159287.760400;(3712.870417,-9411.523403)>\n" "<159289.062500;(560.668359,-4795.552450)>\n" "<159290.364600;(2544.618706,-12069.870370)>\n" "<159291.666700;(3228.511729,-5598.378573)>\n" "<159292.968800;(8115.521285,-3562.990038)>\n" "<159294.270800;(2427.692111,-8242.402241)>\n" "<159295.572900;(-423.122160,-8657.554595)>\n" "<159296.875000;(1421.960140,-9889.042938)>\n" "<159298.177100;(1321.828343,-3798.104906)>\n" "<159299.479200;(-1376.640023,-9441.653413)>\n" "<159300.781200;(-5289.218497,-15331.860700)>\n" "<159302.083300;(-2331.869584,-11567.711800)>\n" "<159303.385400;(-1056.435526,-13510.613120)>\n" "<159304.687500;(-1731.216734,-12417.323890)>\n" "<159305.989600;(-1115.927554,-12630.150290)>\n" "<159307.291700;(-2184.059829,-11215.706020)>\n" "<159308.593800;(2547.786122,-12107.242040)>\n" "<159309.895800;(3388.769320,-14377.311590)>\n" "<159311.197900;(532.782648,-11016.397210)>\n" "<159312.500000;(-3306.963338,-15289.013070)>\n" "<159313.802100;(2957.774203,-17201.439700)>\n" "<159315.104200;(1323.364878,-17794.044510)>\n" "<159316.406200;(2415.941356,-16071.043030)>\n" "<159317.708300;(5632.335146,-21132.168520)>\n" "<159319.010400;(-805.629233,-17789.569740)>\n" "<159320.312500;(4050.437556,-22366.137430)>\n" "<159321.614600;(-2050.155004,-29216.775300)>\n" "<159322.916700;(2646.775097,-25968.076930)>\n" "<159324.218800;(-2594.470687,-29517.088160)>\n" "<159325.520800;(162.084295,-34808.531580)>\n" "<159326.822900;(1066.760777,-36977.019940)>\n" "<159328.125000;(2438.146470,-45765.562070)>\n" "<159329.427100;(-4959.946379,-50662.135900)>\n" "<159330.729200;(-4482.799904,-61652.462400)>\n" "<159332.031200;(-8066.221272,-79942.851830)>\n" "<159333.333300;(-10594.081740,-119636.552900)>\n" "<159334.635400;(-25691.005050,-200410.834800)>\n" "<159335.937500;(-213658.594500,-659934.363200)>\n" "<159337.239600;(-195277.448400,381806.735600)>\n" "<159338.541700;(-3607.814104,174096.698700)>\n" "<159339.843800;(-20174.582830,107351.229200)>\n" "<159341.145800;(-6489.370161,89465.967770)>\n" "<159342.447900;(-10065.636760,79291.198420)>\n" "<159343.750000;(-3053.407326,60874.219410)>\n" "<159345.052100;(-568.638097,51714.699570)>\n" "<159346.354200;(-954.716555,44697.791940)>\n" "<159347.656200;(2457.422718,40989.867110)>\n" "<159348.958300;(-1137.727536,36115.555170)>\n" "<159350.260400;(777.406151,28617.133270)>\n" "<159351.562500;(590.494564,30001.331610)>\n" "<159352.864600;(175.131267,27711.513630)>\n" "<159354.166700;(-2963.681502,24936.186580)>\n" "<159355.468800;(1870.842411,26613.483300)>\n" "<159356.770800;(3266.462896,26342.258940)>\n" "<159358.072900;(2869.948307,23894.122540)>\n" "<159359.375000;(4622.374623,18137.151440)>\n" "<159360.677100;(1027.487194,19740.217960)>\n" "<159361.979200;(-2276.143617,22751.449920)>\n" "<159363.281200;(2568.704705,20532.513670)>\n" "<159364.583300;(-1651.158674,20017.495250)>\n" "<159365.885400;(4164.543009,17838.274640)>\n" "<159367.187500;(-1679.470525,14917.731740)>\n" "<159368.489600;(-2000.857508,19807.544810)>\n" "<159369.791700;(-51.237545,21050.681960)>\n" "<159371.093800;(-473.687647,19895.121750)>\n" "<159372.395800;(2666.925339,20566.692750)>\n" "<159373.697900;(-2243.690458,18252.294130)>\n" "<159375.000000;(1946.285694,20794.426280)>\n" "<159376.302100;(2510.830953,17605.611180)>\n" "<159377.604200;(2140.181099,13032.226930)>\n" "<159378.906200;(-485.580520,17249.702250)>\n" "<159380.208300;(258.969393,16760.700020)>\n" "<159381.510400;(-739.481390,16072.127040)>\n" "<159382.812500;(-1277.497733,12950.309490)>\n" "<159384.114600;(3716.176611,15534.955680)>\n" "<159385.416700;(1245.826083,24235.335490)>\n" "<159386.718800;(1173.111379,9968.588994)>\n" "<159388.020800;(2353.787670,15302.046560)>\n" "<159389.322900;(3051.853397,15779.747670)>\n" "<159390.625000;(-86.058751,13718.586820)>\n" "<159391.927100;(-316.311728,15412.776160)>\n" "<159393.229200;(2753.906724,14500.974560)>\n" "<159394.531200;(-762.264559,13490.965480)>\n" "<159395.833300;(1038.288211,12146.380050)>\n" "<159397.135400;(2089.210506,9333.127557)>\n" "<159398.437500;(2069.171408,18204.429240)>\n" "<159399.739600;(870.096511,14824.452060)>\n" "<159401.041700;(272.972680,16110.248280)>\n" "<159402.343800;(-2183.150454,16170.548980)>\n" "<159403.645800;(3815.840070,17776.030460)>\n" "<159404.947900;(-66.503788,9233.706607)>\n" "<159406.250000;(-2706.892541,20304.237840)>\n" "<159407.552100;(1148.909600,13902.286780)>\n" "<159408.854200;(-1044.981140,15580.827210)>\n" "<159410.156200;(1557.583388,15674.443000)>\n" "<159411.458300;(1420.642527,18389.776050)>\n" "<159412.760400;(-1094.786294,19843.799370)>\n" "<159414.062500;(4896.668391,13128.510720)>\n" "<159415.364600;(108.289618,17463.498590)>\n" "<159416.666700;(3186.277183,19436.678440)>\n" "<159417.968800;(1081.737916,21716.285130)>\n" "<159419.270800;(1328.018494,20008.046950)>\n" "<159420.572900;(3325.989555,19880.576640)>\n" "<159421.875000;(-2644.088666,19243.843650)>\n" "<159423.177100;(922.144370,21196.913040)>\n" "<159424.479200;(2723.078015,22766.318380)>\n" "<159425.781200;(1446.660903,20234.297580)>\n" "<159427.083300;(1371.925129,27403.440390)>\n" "<159428.385400;(3808.706272,22703.076670)>\n" "<159429.687500;(-1428.961239,25113.191770)>\n" "<159430.989600;(7822.295405,27516.223450)>\n" "<159432.291700;(4996.267312,28721.847580)>\n" "<159433.593800;(1761.480415,35031.878640)>\n" "<159434.895800;(1261.978898,31675.732630)>\n" "<159436.197900;(1145.721734,34949.097560)>\n" "<159437.500000;(3586.332328,36847.600870)>\n" "<159438.802100;(1564.219364,37959.416530)>\n" "<159440.104200;(158.173057,41454.351340)>\n" "<159441.406200;(7524.639829,42235.338990)>\n" "<159442.708300;(4877.101315,44697.124220)>\n" "<159444.010400;(4080.603141,50558.420710)>\n" "<159445.312500;(6577.789977,58423.297650)>\n" "<159446.614600;(12831.995710,62206.404670)>\n" "<159447.916700;(12432.574750,78692.367570)>\n" "<159449.218800;(14863.217740,97002.269610)>\n" "<159450.520800;(20799.473080,118598.677800)>\n" "<159451.822900;(22593.311980,165638.891700)>\n" "<159453.125000;(47599.335840,277486.399800)>\n" "<159454.427100;(286144.990400,833086.497200)>\n" "<159455.729200;(185071.679600,-646557.315700)>\n" "<159457.031200;(-17704.581440,-233633.298900)>\n" "<159458.333300;(12582.540060,-142740.249800)>\n" "<159459.635400;(-4281.026921,-119490.160700)>\n" "<159460.937500;(-2407.375413,-104118.820900)>\n" "<159462.239600;(-6020.466709,-71343.604500)>\n" "<159463.541700;(-6861.637568,-64726.618340)>\n" "<159464.843800;(4448.264865,-50486.194870)>\n" "<159466.145800;(-2683.225884,-43254.466920)>\n" "<159467.447900;(-1409.582306,-46362.112560)>\n" "<159468.750000;(-901.917142,-39197.029140)>\n" "<159470.052100;(-726.541158,-34237.362550)>\n" "<159471.354200;(352.485137,-32437.557050)>\n" "<159472.656200;(-2127.182747,-33974.198590)>\n" "<159473.958300;(-3242.789607,-27050.131790)>\n" "<159475.260400;(-1547.455150,-23083.704950)>\n" "<159476.562500;(-935.286804,-20857.628780)>\n" "<159477.864600;(-612.779078,-22032.472190)>\n" "<159479.166700;(452.453592,-23621.175920)>\n" "<159480.468800;(-1525.529117,-17904.755700)>\n" "<159481.770800;(-3100.586634,-19514.288390)>\n" "<159483.072900;(1008.758808,-15846.074870)>\n" "<159484.375000;(-127.895811,-14624.515230)>\n" "<159485.677100;(165.146018,-16758.957650)>\n" "<159486.979200;(-700.841593,-14797.912350)>\n" "<159488.281200;(511.814166,-12086.065760)>\n" "<159489.583300;(-234.976704,-7792.639622)>\n" "<159490.885400;(232.878319,-17402.849940)>\n" "<159492.187500;(-907.310367,-14336.829840)>\n" "<159493.489600;(-56.307938,-11496.904200)>\n" "<159494.791700;(-4488.884838,-13671.545780)>\n" "<159496.093800;(-1537.873247,-13450.963810)>\n" "<159497.395800;(-1269.353491,-9392.217590)>\n" "<159498.697900;(-3329.717995,-8884.638460)>\n" "<159500.000000;(-2548.554362,-9054.318285)>\n" "<159501.302100;(356.446580,-6484.250542)>\n" "<159502.604200;(-2093.093433,-7514.297621)>\n" "<159503.906200;(76.349843,-10190.160150)>\n" "<159505.208300;(368.091387,-7901.348925)>\n" "<159506.510400;(1136.846862,-8966.137390)>\n" "<159507.812500;(-3421.439131,-11906.911110)>\n" "<159509.114600;(4180.383572,-10307.527550)>\n" "<159510.416700;(1098.526119,-7472.453313)>\n" "<159511.718800;(-369.327262,-8346.637434)>\n" "<159513.020800;(1233.861802,-6290.960060)>\n" "<159514.322900;(-2639.342820,-6260.011947)>\n" "<159515.625000;(3864.767793,-6636.383515)>\n" "<159516.927100;(-3769.148438,-6986.464212)>\n" "<159518.229200;(-635.477924,-8819.456939)>\n" "<159519.531200;(-1044.541484,-7989.777441)>\n" "<159520.833300;(-1079.298437,-8769.949667)>\n" "<159522.135400;(-215.466848,-4330.371898)>\n" "<159523.437500;(-961.581268,-6154.600524)>\n" "<159524.739600;(-3940.764238,-10223.271770)>\n" "<159526.041700;(-376.770403,-6940.595355)>\n" "<159527.343800;(-2650.722101,-3603.928142)>\n" "<159528.645800;(-399.944733,-5303.995691)>\n" "<159529.947900;(1449.245652,-5796.593595)>\n" "<159531.250000;(-891.474849,-3515.267543)>\n" "<159532.552100;(2034.532694,-5561.745413)>\n" "<159533.854200;(-327.464439,-1401.321585)>\n" "<159535.156200;(-2604.135031,-8559.828372)>\n" "<159536.458300;(-854.079618,-2473.551958)>\n" "<159537.760400;(877.477740,-2005.068660)>\n" "<159539.062500;(447.877941,-4758.213608)>\n" "<159540.364600;(3182.238834,-4033.452087)>\n" "<159541.666700;(125.690950,-6004.211682)>\n" "<159542.968800;(472.321287,-3782.142445)>\n" "<159544.270800;(-2322.356411,-4523.148313)>\n" "<159545.572900;(-1544.541889,-4125.527520)>\n" "<159546.875000;(2744.024998,-124.498868)>\n" "<159548.177100;(1214.952943,-4915.178682)>\n" "<159549.479200;(-1851.299452,-3969.540991)>\n" "<159550.781200;(1929.802295,-6993.515114)>\n" "<159552.083300;(-2383.743053,-4257.875278)>\n" "<159553.385400;(-1565.992999,-2133.806117)>\n" "<159554.687500;(335.881485,-1297.322869)>\n" "<159555.989600;(309.204915,-4467.843686)>\n" "<159557.291700;(838.688853,-3988.710243)>\n" "<159558.593800;(2048.608531,-1501.838855)>\n" "<159559.895800;(-2828.295503,222.822319)>\n" "<159561.197900;(-704.390913,-2799.147518)>\n" "<159562.500000;(-3114.714576,-4921.409029)>\n" "<159563.802100;(2186.784077,-1939.786003)>\n" "<159565.104200;(-2875.736581,-1628.718419)>\n" "<159566.406200;(-1778.128652,-4624.060459)>\n" "<159567.708300;(799.193453,-3489.320834)>\n" ; // sampleFrequencyData_ pwiz/pwiz/data/misc/MinimumPepXMLTest.cpp0000664000175100017510000004443512664775621022427 0ustar teamcityteamcity00000000000000// // $Id: MinimumPepXMLTest.cpp 4140 2012-11-22 01:07:16Z pcbrefugee $ // // Original author: Kate Hoff // // Copyright 2009 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "MinimumPepXML.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::data::pepxml; using namespace pwiz::util; ostream* os_ = 0; Specificity makeSpecificity() { Specificity specificity; specificity.cut = "theCake"; specificity.noCut = "notTheCake"; specificity.sense = "non"; specificity.minSpace = 2; return specificity; } SampleEnzyme makeSampleEnzyme() { SampleEnzyme sampleEnzyme; sampleEnzyme.name = "oxiclean"; sampleEnzyme.description = "makes your whites whiter."; sampleEnzyme.fidelity = "scoundrel"; sampleEnzyme.independent = true; Specificity specificity = makeSpecificity(); sampleEnzyme.specificity = specificity; return sampleEnzyme; } SearchDatabase makeSearchDatabase() { SearchDatabase searchDatabase; searchDatabase.localPath = "http://www.eharmony.com"; searchDatabase.databaseName = "yenta"; searchDatabase.databaseReleaseIdentifier = "village busy body"; searchDatabase.sizeInDbEntries = 2; searchDatabase.sizeOfResidues = 3; searchDatabase.type = "online dating service"; return searchDatabase; } Q3RatioResult makeQ3RatioResult() { Q3RatioResult q; q.lightFirstScan = 1; q.lightLastScan = 3; q.lightMass = 100; q.heavyFirstScan = 2; q.heavyLastScan = 4; q.heavyMass = 101; q.lightArea = 50; q.heavyArea = 55; q.q2LightArea = 25; q.q2HeavyArea = 30; q.decimalRatio = 0.85; return q; } PeptideProphetResult makePeptideProphetResult() { PeptideProphetResult peptideProphetResult; peptideProphetResult.probability = 0.98; peptideProphetResult.allNttProb.push_back(0.0000); peptideProphetResult.allNttProb.push_back(0.0000); peptideProphetResult.allNttProb.push_back(0.780); return peptideProphetResult; } AnalysisResult makeAnalysisResult() { AnalysisResult analysisResult; analysisResult.analysis = "peptideprophet"; PeptideProphetResult pp = makePeptideProphetResult(); analysisResult.peptideProphetResult = pp; return analysisResult; } AlternativeProtein makeAlternativeProtein() { AlternativeProtein alternativeProtein; alternativeProtein.protein = "Dos Pinos"; alternativeProtein.proteinDescr = "leche"; alternativeProtein.numTolTerm = "5"; return alternativeProtein; } ModAminoAcidMass makeModAminoAcidMass() { ModAminoAcidMass modAminoAcidMass; modAminoAcidMass.position = 2; modAminoAcidMass.mass = 12.345; return modAminoAcidMass; } ModificationInfo makeModificationInfo() { ModificationInfo modificationInfo; modificationInfo.modifiedPeptide = "GATO"; modificationInfo.modAminoAcidMass = makeModAminoAcidMass(); return modificationInfo; } SearchHit makeSearchHit() { SearchHit searchHit; searchHit.hitRank = 1; searchHit.peptide = "RAGMALLICK"; searchHit.peptidePrevAA = "R"; searchHit.peptideNextAA = "V"; searchHit.protein = "PA"; searchHit.proteinDescr = "Bioinfomagicist"; searchHit.numTotalProteins = 1; searchHit.numMatchedIons = 9; searchHit.calcNeutralPepMass = 4.21399; searchHit.massDiff = .0004; searchHit.numTolTerm = 2; searchHit.numMissedCleavages = 3; searchHit.isRejected = 0; AnalysisResult analysisResult = makeAnalysisResult(); searchHit.analysisResult = analysisResult; AlternativeProtein alternativeProtein = makeAlternativeProtein(); searchHit.alternativeProteins.push_back(alternativeProtein); searchHit.modificationInfo = makeModificationInfo(); return searchHit; } EnzymaticSearchConstraint makeEnzymaticSearchConstraint() { EnzymaticSearchConstraint enzymaticSearchConstraint; enzymaticSearchConstraint.enzyme = "emyzne"; enzymaticSearchConstraint.maxNumInternalCleavages = 1; enzymaticSearchConstraint.minNumTermini = 1; return enzymaticSearchConstraint; } AminoAcidModification makeAminoAcidModification() { AminoAcidModification aminoAcidModification; aminoAcidModification.aminoAcid = "pm"; aminoAcidModification.massDiff = 9.63333; aminoAcidModification.mass = 82.65; aminoAcidModification.variable = "c"; aminoAcidModification.symbol = "r"; return aminoAcidModification; } SearchSummary makeSearchSummary() { SearchSummary searchSummary; searchSummary.baseName = "mseharmony"; searchSummary.searchEngine = "yahooooo"; searchSummary.precursorMassType = "A"; searchSummary.fragmentMassType = "B"; searchSummary.searchID = "ego"; EnzymaticSearchConstraint enzymaticSearchConstraint = makeEnzymaticSearchConstraint(); searchSummary.enzymaticSearchConstraint = enzymaticSearchConstraint; AminoAcidModification aminoAcidModification = makeAminoAcidModification(); searchSummary.aminoAcidModifications.push_back(aminoAcidModification); searchSummary.aminoAcidModifications.push_back(aminoAcidModification); SearchDatabase searchDatabase = makeSearchDatabase(); searchSummary.searchDatabase = searchDatabase; return searchSummary; } SearchResult makeSearchResult() { SearchResult searchResult; SearchHit searchHit = makeSearchHit(); searchResult.searchHit.push_back(SearchHitPtr(new SearchHit(searchHit))); return searchResult; } SpectrumQuery makeSpectrumQuery() { SpectrumQuery spectrumQuery; spectrumQuery.spectrum = "ultraviolet"; spectrumQuery.startScan = 19120414; spectrumQuery.endScan = 19120415; spectrumQuery.precursorNeutralMass = 46328; spectrumQuery.assumedCharge = 1; spectrumQuery.index = 3547; spectrumQuery.retentionTimeSec = 432000; SearchResult searchResult = makeSearchResult(); SearchResultPtr srp(new SearchResult(searchResult)); spectrumQuery.searchResult.push_back(srp); return spectrumQuery; } MSMSRunSummary makeMSMSRunSummary() { MSMSRunSummary msmsRunSummary; SampleEnzyme sampleEnzyme = makeSampleEnzyme(); msmsRunSummary.sampleEnzyme = makeSampleEnzyme(); SearchSummary searchSummary = makeSearchSummary(); msmsRunSummary.searchSummary.push_back(SearchSummaryPtr(new SearchSummary(searchSummary))); SpectrumQuery spectrumQuery = makeSpectrumQuery(); msmsRunSummary.spectrumQueries.push_back(SpectrumQueryPtr(new SpectrumQuery(spectrumQuery))); msmsRunSummary.spectrumQueries.push_back(SpectrumQueryPtr(new SpectrumQuery(spectrumQuery))); return msmsRunSummary; } MatchPtr makeMatch() { MatchPtr match(new Match()); match->spectrumQuery = makeSpectrumQuery(); match->feature->mz = 1.234; match->feature->retentionTime = 5.678; return match; } void testSpecificity() { if (os_) *os_ << "\ntestSpecificity() ... \n"; Specificity specificity = makeSpecificity(); ostringstream oss; XMLWriter writer(oss); specificity.write(writer); Specificity readSpecificity; istringstream iss(oss.str()); readSpecificity.read(iss); unit_assert(specificity == readSpecificity); if (os_) *os_ << oss.str() << endl; } void testSampleEnzyme() { if (os_) *os_ << "\ntestSampleEnzyme() ... \n"; SampleEnzyme sampleEnzyme = makeSampleEnzyme(); ostringstream oss; XMLWriter writer(oss); sampleEnzyme.write(writer); SampleEnzyme readSampleEnzyme; istringstream iss(oss.str()); readSampleEnzyme.read(iss); unit_assert(sampleEnzyme == readSampleEnzyme); if (os_) *os_ << oss.str() << endl; } void testSearchDatabase() { if (os_) *os_ << "\ntestSearchDatabase() ... \n"; SearchDatabase searchDatabase = makeSearchDatabase(); ostringstream oss; XMLWriter writer(oss); searchDatabase.write(writer); SearchDatabase readSearchDatabase; istringstream iss(oss.str()); readSearchDatabase.read(iss); unit_assert(searchDatabase == readSearchDatabase); if (os_) *os_ << oss.str() << endl; } void testQ3RatioResult() { if (os_) *os_ << "\ntestQ3RatioResult() ... \n"; Q3RatioResult q = makeQ3RatioResult(); ostringstream oss; XMLWriter writer(oss); q.write(writer); Q3RatioResult readQ; istringstream iss(oss.str()); readQ.read(iss); unit_assert(q == readQ); if (os_) *os_ << oss.str() << endl; } void testPeptideProphetResult() { if (os_) *os_ << "\ntestPeptideProphetResult() ... \n"; PeptideProphetResult pp = makePeptideProphetResult(); ostringstream oss; XMLWriter writer(oss); pp.write(writer); PeptideProphetResult readPeptideProphetResult; istringstream iss(oss.str()); readPeptideProphetResult.read(iss); unit_assert(pp == readPeptideProphetResult); if (os_) *os_ << oss.str() << endl; } void testAnalysisResult() { if (os_) *os_ << "\ntestAnalysisResult() ...\n"; AnalysisResult analysisResult = makeAnalysisResult(); ostringstream oss; XMLWriter writer(oss); analysisResult.write(writer); AnalysisResult readAnalysisResult; istringstream iss(oss.str()); readAnalysisResult.read(iss); unit_assert(analysisResult == readAnalysisResult); if(os_) *os_ << oss.str() << endl; AnalysisResult analysisResult2; analysisResult2.analysis = "q3"; analysisResult2.q3RatioResult = makeQ3RatioResult(); ostringstream oss2; XMLWriter writer2(oss2); analysisResult2.write(writer2); AnalysisResult readAnalysisResult2; istringstream iss2(oss2.str()); readAnalysisResult2.read(iss2); unit_assert(analysisResult2 == readAnalysisResult2); if(os_) *os_ << oss2.str() << endl; } void testAlternativeProtein() { if (os_) *os_ << "\ntestAlternativeProtein() ...\n"; AlternativeProtein alternativeProtein = makeAlternativeProtein(); ostringstream oss; XMLWriter writer(oss); alternativeProtein.write(writer); AlternativeProtein readAlternativeProtein; istringstream iss(oss.str()); readAlternativeProtein.read(iss); unit_assert(alternativeProtein == readAlternativeProtein); if(os_) *os_ << oss.str() << endl; } void testModAminoAcidMass() { if (os_) *os_ << "\ntestModAminoAcidMass() ...\n"; ModAminoAcidMass modAminoAcidMass = makeModAminoAcidMass(); ostringstream oss; XMLWriter writer(oss); modAminoAcidMass.write(writer); ModAminoAcidMass readModAminoAcidMass; istringstream iss(oss.str()); readModAminoAcidMass.read(iss); unit_assert(modAminoAcidMass == readModAminoAcidMass); if(os_) *os_ << oss.str() << endl; } void testModificationInfo() { if (os_) *os_ << "\ntestModificationInfo() ...\n"; ModificationInfo modificationInfo = makeModificationInfo(); ostringstream oss; XMLWriter writer(oss); modificationInfo.write(writer); ModificationInfo readModificationInfo; istringstream iss(oss.str()); readModificationInfo.read(iss); unit_assert(modificationInfo == readModificationInfo); if(os_) *os_ << oss.str() << endl; } void testSearchHit() { if (os_) *os_ << "\ntestSearchHit() ...\n"; SearchHit searchHit = makeSearchHit(); ostringstream oss; XMLWriter writer(oss); searchHit.write(writer); SearchHit readSearchHit; istringstream iss(oss.str()); readSearchHit.read(iss); unit_assert(searchHit == readSearchHit); if(os_) *os_ << oss.str() << endl; } void testSearchResult() { if(os_) *os_ << "\ntestSearchResult() ... \n"; SearchResult searchResult = makeSearchResult(); ostringstream oss; XMLWriter writer(oss); searchResult.write(writer); SearchResult readSearchResult; istringstream iss(oss.str()); readSearchResult.read(iss); unit_assert(searchResult == readSearchResult); if(os_) *os_ << oss.str() << endl; } void testEnzymaticSearchConstraint() { if (os_) *os_ << "\ntestEnzymaticSearchConstraint() ... \n"; EnzymaticSearchConstraint enzymaticSearchConstraint = makeEnzymaticSearchConstraint(); ostringstream oss; XMLWriter writer(oss); enzymaticSearchConstraint.write(writer); EnzymaticSearchConstraint readEnzymaticSearchConstraint; istringstream iss(oss.str()); readEnzymaticSearchConstraint.read(iss); unit_assert(enzymaticSearchConstraint == readEnzymaticSearchConstraint); if(os_) *os_ << oss.str() << endl; } void testAminoAcidModification() { if (os_) *os_ << "\ntestAminoAcidModification() ... \n"; AminoAcidModification aminoAcidModification = makeAminoAcidModification(); ostringstream oss; XMLWriter writer(oss); aminoAcidModification.write(writer); AminoAcidModification readAminoAcidModification; istringstream iss(oss.str()); readAminoAcidModification.read(iss); unit_assert(aminoAcidModification == readAminoAcidModification); if(os_) *os_ << oss.str() << endl; } void testSearchSummary() { if(os_) *os_ << "\ntestSearchSummary() ... \n"; SearchSummary searchSummary = makeSearchSummary(); ostringstream oss; XMLWriter writer(oss); searchSummary.write(writer); SearchSummary readSearchSummary; istringstream iss(oss.str()); readSearchSummary.read(iss); unit_assert(searchSummary == readSearchSummary); if(os_) *os_ << oss.str() << endl; } void testSpectrumQuery() { if(os_) *os_ << "\ntestSpectrumQuery() ... \n"; SpectrumQuery spectrumQuery = makeSpectrumQuery(); ostringstream oss; XMLWriter writer(oss); spectrumQuery.write(writer); if(os_) *os_ << oss.str() << endl; SpectrumQuery readSpectrumQuery; istringstream iss(oss.str()); readSpectrumQuery.read(iss); readSpectrumQuery.write(writer); if(os_) *os_ << oss.str() << endl; unit_assert(spectrumQuery == readSpectrumQuery); if(os_) *os_ << oss.str() << endl; } void testMSMSRunSummary() { if(os_) *os_ << "\ntestMSMSRunSummary() ... \n"; MSMSRunSummary msmsRunSummary = makeMSMSRunSummary(); ostringstream oss; XMLWriter writer(oss); msmsRunSummary.write(writer); MSMSRunSummary readMSMSRunSummary; istringstream iss(oss.str()); readMSMSRunSummary.read(iss); unit_assert(msmsRunSummary == readMSMSRunSummary); if(os_) *os_ << oss.str() << endl; } void testMSMSPipelineAnalysis() { if(os_) *os_ << "\ntestMSMSPipelineAnalysis() ... \n"; MSMSPipelineAnalysis msmsPipelineAnalysis; msmsPipelineAnalysis.date = "20000101"; msmsPipelineAnalysis.summaryXML = "/2000/01/20000101/20000101.xml"; msmsPipelineAnalysis.xmlns = "http://regis-web.systemsbiology.net/pepXML"; msmsPipelineAnalysis.xmlnsXSI = "aruba"; msmsPipelineAnalysis.XSISchemaLocation = "jamaica"; MSMSRunSummary msrs = makeMSMSRunSummary(); msmsPipelineAnalysis.msmsRunSummary = msrs; ostringstream oss; XMLWriter writer(oss); msmsPipelineAnalysis.write(writer); MSMSPipelineAnalysis readMSMSPipelineAnalysis; istringstream iss(oss.str()); readMSMSPipelineAnalysis.read(iss); unit_assert(msmsPipelineAnalysis == readMSMSPipelineAnalysis); if(os_) *os_ << oss.str() << endl; } void testMatch() { if(os_) *os_ << "\ntestMatch() ... \n"; MatchPtr match = makeMatch(); ostringstream oss; XMLWriter writer(oss); match->write(writer); Match readMatch; istringstream iss(oss.str()); readMatch.read(iss); ostringstream checkstream; XMLWriter check(checkstream); readMatch.write(check); // unit_assert(*match == readMatch); if(os_) *os_ << oss.str() << endl; if(os_) *os_ << checkstream.str() << endl; unit_assert(*match == readMatch); } void testMatchData() { if(os_) *os_ << "\ntestMatchData() ... \n"; MatchData matchData; matchData.warpFunctionCalculator = "Spock"; matchData.searchNbhdCalculator = "Mr. Rogers"; matchData.matches.push_back(makeMatch()); matchData.matches.push_back(makeMatch()); ostringstream oss; XMLWriter writer(oss); matchData.write(writer); MatchData readMatchData; istringstream iss(oss.str()); readMatchData.read(iss); ostringstream checkstream; XMLWriter check(checkstream); readMatchData.write(check); // unit_assert(*match == readMatch); if(os_) *os_ << oss.str() << endl; if(os_) *os_ << checkstream.str() << endl; unit_assert(matchData == readMatchData); if(os_) *os_ << oss.str() << endl; } void testInvarianceUnderProteinProphet() { ifstream ifs("20080619-A-6mixtestRG_Data10_msprefix.pep.xml"); if (!(ifs.good()) ) { throw runtime_error("bad ifs"); return; } MSMSPipelineAnalysis msmsPipelineAnalysis; msmsPipelineAnalysis.read(ifs); ofstream ofs("test.pep.xml", ios::app); XMLWriter writer(ofs); msmsPipelineAnalysis.write(writer); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; if (os_) *os_ << "MinimumPepXMLTest ... \n"; testSpecificity(); testSampleEnzyme(); testSearchDatabase(); testQ3RatioResult(); testPeptideProphetResult(); testAnalysisResult(); testAlternativeProtein(); testModAminoAcidMass(); testModificationInfo(); testSearchHit(); testSearchResult(); testEnzymaticSearchConstraint(); testAminoAcidModification(); testSearchSummary(); testSpectrumQuery(); testMSMSRunSummary(); testMSMSPipelineAnalysis(); testMatch(); testMatchData(); //testInvarianceUnderProteinProphet(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/misc/FrequencyData.hpp0000664000175100017510000001213512664775621021656 0ustar teamcityteamcity00000000000000// // $Id: FrequencyData.hpp 1195 2009-08-14 22:12:04Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _FREQUENCYDATA_HPP_ #define _FREQUENCYDATA_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "SampleDatum.hpp" #include "CalibrationParameters.hpp" #include #include #include namespace pwiz { namespace data { typedef SampleDatum< double, std::complex > FrequencyDatum; /// Class for binary storage of complex frequency data. /// Stores raw frequency-domain data, as well as meta-data. Also includes /// basic access and analysis functions. class PWIZ_API_DECL FrequencyData { public: /// \name types //@{ enum PWIZ_API_DECL IOMode {Binary, Text, Automatic}; typedef std::vector container; typedef container::iterator iterator; typedef container::const_iterator const_iterator; //@} /// \name instantiation //@{ FrequencyData(); FrequencyData(const std::string& filename, IOMode mode=Automatic); FrequencyData(const FrequencyData& that, const_iterator begin, const_iterator end); FrequencyData(const FrequencyData& that, const_iterator center, int radius); ~FrequencyData(); //@} /// \name I/O //@{ void read(const std::string& filename, IOMode mode=Automatic); void read(std::istream& is, IOMode mode=Binary); void write(const std::string& filename, IOMode mode=Binary) const; void write(std::ostream& os, IOMode mode=Binary) const; //@} /// \name data access //@{ /// const access to underlying data const container& data() const; /// non-const access to underlying data -- must call analyze() to recache after any changes container& data(); //@} /// \name metadata //@{ int scanNumber() const; void scanNumber(int value); double retentionTime() const; void retentionTime(double value); const CalibrationParameters& calibrationParameters() const; void calibrationParameters(const CalibrationParameters& cp); double observationDuration() const; void observationDuration(double value); double noiseFloor() const; void noiseFloor(double value); //@} /// \name data transformation //@{ /// transform all underlying data: (x,y) -> (x+shift,y*scale) void transform(double shift, std::complex scale); /// return current shift of data (compared to original) double shift() const; /// return current scale of data (compared to original) std::complex scale() const; /// normalize by transform( -max.x, 1/abs(max.y) ) void normalize(); /// addition void operator+=(const FrequencyData& that); //@} /// \name analysis //@{ /// recache statistics calculations after any direct data changes via non-const data() void analyze(); /// returns an iterator to FrequencyDatum with highest magnitude const_iterator max() const; double mean() const; double meanSquare() const; double sumSquares() const; double variance() const; /// special calculation of noise floor for data with zero holes, /// e.g. data obtained from RAW file m/z-intensity pairs double cutoffNoiseFloor() const; /// calculation of the observation duration from the data double observationDurationEstimatedFromData() const; //@} /// \name auxilliary //@{ /// Finds the FrequencyDatum nearest the desired frequency. const_iterator findNearest(double frequency) const; //@} /// \name auxilliary functions //@{ /// Returns a pair. static std::pair magnitudeSample(const FrequencyDatum& datum); //@} private: struct Impl; std::auto_ptr impl_; /// Hidden to prevent unintended copying of large amounts of data. FrequencyData(FrequencyData& that); /// Hidden to prevent unintended copying of large amounts of data. FrequencyData& operator=(FrequencyData& that); }; } // namespace data } // namespace pwiz #endif // _FREQUENCYDATA_HPP_ pwiz/pwiz/data/misc/FrequencyDataTest.cpp0000664000175100017510000002002512664775621022506 0ustar teamcityteamcity00000000000000// // $Id: FrequencyDataTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "FrequencyData.hpp" #include "FrequencyDataTestData.hpp" #include "pwiz/data/misc/CalibrationParameters.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::data; ostream* os_; void diff(const string& filename1, const string& filename2) { ifstream file1(filename1.c_str()), file2(filename2.c_str()); string line1, line2; while (getline(file1, line1) && getline(file2, line2)) unit_assert(line1 == line2); if (os_) *os_ << "diff " << filename1 << " " << filename2 << ": success\n"; } string filename1 = "FrequencyDataTest.output1.txt"; void test() { // create some data, f(x) = abs(5-(x-2)) FrequencyData fd; FrequencyData::container& data = fd.data(); for (int i=-5; i<=5; i++) data.push_back(FrequencyDatum(i+2, 5-abs(i))); fd.analyze(); // recache after changing data // verify peak() FrequencyData::const_iterator max = fd.max(); unit_assert(max->x == 2); unit_assert(max->y == 5.); // verify stats unit_assert(fd.mean() == 25./11); unit_assert(fd.meanSquare() == 85./11); unit_assert(fd.sumSquares() == 85.); unit_assert_equal(fd.variance(), 85./11 - 25.*25/11/11, 1e-12); // write out data if (os_) *os_ << "Writing " << filename1 << endl; fd.write(filename1, FrequencyData::Text); // read into const FrequencyData string filename2 = "FrequencyDataTest.output2.txt"; FrequencyData fd2(filename1, FrequencyData::Text); // verify normalize() fd2.normalize(); unit_assert(fd2.shift() == -2); unit_assert(fd2.scale() == 1./5); max = fd2.max(); unit_assert(max->x == 0); unit_assert(max->y == 1.); // verify transform(shift, scale) fd2.transform(-fd2.shift(), 1./fd2.scale()); // verify read/write if (os_) *os_ << "Writing " << filename2 << endl; fd2.write(filename2, FrequencyData::Text); diff(filename1, filename2); // test subrange string filename3 = "FrequencyDataTest.output3.txt"; FrequencyData fd3(fd2, fd2.data().begin(), fd2.max()); // copy first half if (os_) *os_ << "Writing " << filename3 << endl; fd3.write(filename3, FrequencyData::Text); FrequencyData fd4(fd2, fd2.max(), fd2.data().end()); // copy second half ofstream os(filename3.c_str(), ios::app); fd4.write(os, FrequencyData::Text); os.close(); diff(filename1, filename3); // read/write binary, and metadata fd.scanNumber(555); fd.retentionTime(444); fd.calibrationParameters(CalibrationParameters(1,1)); fd.observationDuration(666); fd.noiseFloor(777); string filename4a = "FrequencyDataTest.output4a.txt"; if (os_) *os_ << "Writing " << filename4a << endl; fd.write(filename4a, FrequencyData::Text); string filenameBinary1 = "FrequencyDataTest.output1.cfd"; if (os_) *os_ << "Writing " << filenameBinary1 << endl; fd.write(filenameBinary1); FrequencyData fd5(filenameBinary1); unit_assert(fd5.observationDuration() == 666); fd5.observationDuration(fd.observationDurationEstimatedFromData()); unit_assert(fd5.scanNumber() == 555); unit_assert(fd5.retentionTime() == 444); unit_assert(fd5.observationDuration() == 1); unit_assert(fd5.noiseFloor() == 777); if (os_) *os_ << "Calibration: " << fd5.calibrationParameters().A << " " << fd5.calibrationParameters().B << endl; string filename4b = "FrequencyDataTest.output4b.txt"; if (os_) *os_ << "Writing " << filename4b << endl; fd5.write(filename4b, FrequencyData::Text); diff(filename4a, filename4b); fd.calibrationParameters(CalibrationParameters()); // test window FrequencyData window1(fd, data.begin()+1, 2); FrequencyData window2(fd, fd.max(), 1); FrequencyData window3(fd, data.end()-2, 2); string filename5 = "FrequencyDataTest.output5.txt"; if (os_) *os_ << "Writing " << filename5 << endl; ofstream os5(filename5.c_str()); window1.write(os5, FrequencyData::Text); window2.write(os5, FrequencyData::Text); window3.write(os5, FrequencyData::Text); os5.close(); diff(filename1, filename5); } void testFind() { const FrequencyData fd(filename1); FrequencyData::const_iterator it = fd.findNearest(-.2); unit_assert(it!=fd.data().end() && it->x==0); it = fd.findNearest(.2); unit_assert(it!=fd.data().end() && it->x==0); it = fd.findNearest(6.1); unit_assert(it!=fd.data().end() && it->x==6); it = fd.findNearest(7.1); unit_assert(it!=fd.data().end() && it->x==7); it = fd.findNearest(666); unit_assert(it!=fd.data().end() && it->x==7); it = fd.findNearest(-666); unit_assert(it==fd.data().begin()); } void testAddition() { FrequencyData fd(filename1); FrequencyData fd2(filename1); fd += fd; for (FrequencyData::const_iterator it=fd.data().begin(), jt=fd2.data().begin(); it!=fd.data().end(); ++it, ++jt) unit_assert(it->y == 2.*jt->y); fd2.transform(0, -2.); fd += fd2; for (FrequencyData::const_iterator it=fd.data().begin(); it!=fd.data().end(); ++it) unit_assert(it->y == 0.); } void testNoiseFloor() { FrequencyData fd(filename1); if (os_) *os_ << "variance: " << fd.variance() << endl; if (os_) *os_ << "noiseFloor: " << fd.noiseFloor() << endl; } void cleanTests() { if (os_) *os_ << "Deleting FrequencyDataTest.output*.txt\n"; vector filepaths; expand_pathmask("FrequencyDataTest.output*.*", filepaths); for (size_t i=0; i < filepaths.size(); ++i) boost::filesystem::remove(filepaths[i]); } void testNoiseFloorVarianceCalculation() { if (os_) *os_ << "testNoiseFloorVarianceCalculation()\n"; if (os_) *os_ << setprecision(10); // test noise floor calculation on sample frequency data string filename = "FrequencyDataTest.cfd.temp.txt"; ofstream temp(filename.c_str()); temp << sampleFrequencyData_; temp.close(); FrequencyData fd(filename); boost::filesystem::remove(filename); double result = fd.cutoffNoiseFloor(); if (os_) *os_ << "result: " << result << endl; unit_assert_equal(result, 29000, 1000); // test noise floor calculation on sample mass data FrequencyData fdMasses; CalibrationParameters cp = CalibrationParameters::thermo_FT(); for (RawMassDatum* p=sampleMassData_; p!=sampleMassData_+sampleMassDataSize_; ++p) fdMasses.data().push_back(FrequencyDatum(cp.frequency(p->mz), p->intensity)); fdMasses.analyze(); double result2 = fdMasses.cutoffNoiseFloor(); if (os_) *os_ << "result2: " << result2 << endl; unit_assert_equal(result2, 6000, 1000); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) // verbose os_ = &cout; if (os_) *os_ << "FrequencyDataTest\n"; test(); testFind(); testAddition(); testNoiseFloor(); cleanTests(); testNoiseFloorVarianceCalculation(); if (os_) *os_ << "success\n"; } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/misc/MinimumPepXML.hpp0000664000175100017510000004254212664775621021571 0ustar teamcityteamcity00000000000000// // $Id: MinimumPepXML.hpp 1970 2010-05-11 20:23:31Z broter $ // // // Original author: Kate Hoff // // Copyright 2009 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _MINIMUMPEPXML_HPP_ #define _MINIMUMPEPXML_HPP_ #include "pwiz/utility/minimxml/XMLWriter.hpp" #include "pwiz/data/misc/PeakData.hpp" #include "boost/shared_ptr.hpp" #include "boost/logic/tribool.hpp" #include #include using namespace pwiz::minimxml; using namespace pwiz::data::peakdata; namespace pwiz{ namespace data{ namespace pepxml{ void setLogStream(std::ostream& os); struct PWIZ_API_DECL Specificity { Specificity() : minSpace(1) {} /// One or more 1-letter residue codes. Enzyme cleaves on the /// sense side of the residue(s) listed in cut unless one of the /// residues listed in no_cut is adjacent to the potential /// cleavage site. std::string cut; /// Zero or more 1-letter residue codes. Enzyme cleaves on the /// sense side of the residue(s) listed in cut unless one of the /// residues listed in no_cut is adjacent to the potential /// cleavage site. std::string noCut; /// Defines whether cleavage occurs on the C-terminal or /// N-terminal side of the residue(s) listed in cut (values "C" or /// "N") std::string sense; /// minimum separation between adjacent cleavages. default 1. size_t minSpace; void write(XMLWriter& writer) const; void read(std::istream& is); bool operator==(const Specificity& that) const; bool operator!=(const Specificity& that) const; }; struct PWIZ_API_DECL SampleEnzyme { SampleEnzyme() : independent(boost::indeterminate) {} /// Controlled code name for the enzyme that can be referred to by /// applications. std::string name; /// Free text to describe alternative names, special conditions, /// etc. std::string description; /// Semispecific means that at least one end of a pepide must /// conform to the cleavage specificity, (unless the peptide was /// at the terminus of the parent sequence). Nonspecific means /// that neither end of a peptide must conform to the cleavage /// specificity. std::string fidelity; /// If there are multiple specificities and independent is true, /// then a single peptide cannot exhibit one specificity at one /// terminus and a different specificity at the other. If /// independent is false, then a single peptide can exhibit mixed /// specificities. boost::tribool independent; Specificity specificity; void write(XMLWriter& writer) const; void read(std::istream& is); bool operator==(const SampleEnzyme& that) const; bool operator!=(const SampleEnzyme& that) const; }; struct PWIZ_API_DECL SearchDatabase { SearchDatabase(){} std::string localPath; std::string databaseName; std::string databaseReleaseIdentifier; size_t sizeInDbEntries; size_t sizeOfResidues; std::string type; void write(XMLWriter& writer) const; void read(std::istream& is); bool operator==(const SearchDatabase& that) const; bool operator!=(const SearchDatabase& that) const; }; struct PWIZ_API_DECL Q3RatioResult { Q3RatioResult() : lightFirstScan(0), lightLastScan(0), lightMass(0), heavyFirstScan(0), heavyLastScan(0), heavyMass(0), lightArea(0), heavyArea(0), q2LightArea(0), q2HeavyArea(0), decimalRatio(0) {} int lightFirstScan; int lightLastScan; double lightMass; int heavyFirstScan; int heavyLastScan; double heavyMass; double lightArea; double heavyArea; double q2LightArea; double q2HeavyArea; double decimalRatio; void write(XMLWriter& writer) const; void read(std::istream& is); bool operator==(const Q3RatioResult& that) const; bool operator!=(const Q3RatioResult& that) const; }; struct PWIZ_API_DECL RocDataPoint { double min_prob; double sensitivity; double error; long num_corr; long num_incorr; }; struct PWIZ_API_DECL ErrorPoint { double error; double min_prob; long num_corr; long num_incorr; }; struct PWIZ_API_DECL DistributionPoint { double fvalue; long obs_1_distr; double model_1_pos_distr; double model_1_neg_distr; long obs_2_distr; double model_2_pos_distr; double model_2_neg_distr; long obs_3_distr; double model_3_pos_distr; double model_3_neg_distr; }; struct PWIZ_API_DECL MixtureModel { long precursor_ion_charge; std::string comments; double prior_probability; double est_tot_correct; long tot_num_spectra; long num_iterations; // TODO Child tags go here... Don't forget to add the struct for // them too }; struct PWIZ_API_DECL PeptideProphetSummary { std::string version; std::string author; double min_prob; std::string options; double est_tot_num_correct; std::vector inputFile; std::vector roc_data_point; std::vector error_point; std::vector distribution_point; std::vector mixture_model; }; struct PWIZ_API_DECL PeptideProphetResult { PeptideProphetResult() : probability(0) {} double probability; std::vector allNttProb; std::string analysis; // TODO add search_score_summary and its parameter (2+ occurances) void write(XMLWriter& writer) const; void read(std::istream& is); bool operator==(const PeptideProphetResult& that) const; bool operator!=(const PeptideProphetResult& that) const; }; struct PWIZ_API_DECL AnalysisResult { AnalysisResult() : analysis("peptideprophet_result") {} std::string analysis; PeptideProphetResult peptideProphetResult; Q3RatioResult q3RatioResult; void write(XMLWriter& writer) const; void read(std::istream& is); bool operator==(const AnalysisResult& that) const; bool operator!=(const AnalysisResult& that) const; }; struct PWIZ_API_DECL AlternativeProtein { AlternativeProtein(){} std::string protein; std::string proteinDescr; std::string numTolTerm; void write(XMLWriter& writer) const; void read(std::istream& is); bool operator==(const AlternativeProtein& that) const; bool operator!=(const AlternativeProtein& that) const; }; struct PWIZ_API_DECL ModAminoAcidMass { ModAminoAcidMass() : position(0), mass(0) {} int position; double mass; void write(XMLWriter& writer) const; void read(std::istream& is); bool operator==(const ModAminoAcidMass& that) const; bool operator!=(const ModAminoAcidMass& that) const; }; struct PWIZ_API_DECL ModificationInfo { ModificationInfo(){} std::string modifiedPeptide; ModAminoAcidMass modAminoAcidMass; void write(XMLWriter& writer) const; void read(std::istream& is); bool operator==(const ModificationInfo& that) const; bool operator!=(const ModificationInfo& that) const; }; struct PWIZ_API_DECL Parameter { Parameter(const std::string& name = "", const std::string& value = "") : name(name), value(value) {} std::string name; std::string value; void write(XMLWriter& writer) const; void read(std::istream& is); bool operator==(const Parameter& that) const; bool operator!=(const Parameter& that) const; }; typedef boost::shared_ptr ParameterPtr; struct PWIZ_API_DECL SearchScore : Parameter { SearchScore(const std::string& name = "", const std::string& value = "") : Parameter(name, value) {} void write(XMLWriter& writer) const; void read(std::istream& is); }; typedef boost::shared_ptr SearchScorePtr; struct PWIZ_API_DECL SearchHit { SearchHit() : hitRank(0),numTotalProteins(0), numMatchedIons(0), totalNumIons(0), calcNeutralPepMass(0), massDiff(0), numTolTerm(0), numMissedCleavages(0), isRejected(0) {} int hitRank; std::string peptide; std::string peptidePrevAA; std::string peptideNextAA; std::string protein; std::string proteinDescr; int numTotalProteins; int numMatchedIons; int totalNumIons; double calcNeutralPepMass; double massDiff; int numTolTerm; int numMissedCleavages; int isRejected; // bool? AnalysisResult analysisResult; std::vector alternativeProteins; ModificationInfo modificationInfo; std::vector searchScore; void write(XMLWriter& writer) const; void read(std::istream& is); bool operator==(const SearchHit& that) const; bool operator!=(const SearchHit& that) const; }; typedef boost::shared_ptr SearchHitPtr; PWIZ_API_DECL bool operator==(const SearchHitPtr left, const SearchHitPtr right); struct PWIZ_API_DECL SearchResult { SearchResult(size_t searchId = 0) :searchId(searchId){} /// Unique identifier to search summary size_t searchId; std::vector searchHit; void write(XMLWriter& writer) const; void read(std::istream& is); bool operator==(const SearchResult& that) const; bool operator!=(const SearchResult& that) const; }; typedef boost::shared_ptr SearchResultPtr; PWIZ_API_DECL bool operator==(SearchResultPtr left, SearchResultPtr right); struct PWIZ_API_DECL EnzymaticSearchConstraint { EnzymaticSearchConstraint() : maxNumInternalCleavages(0), minNumTermini(0){} std::string enzyme; int maxNumInternalCleavages; int minNumTermini; void write(XMLWriter& writer) const; void read(std::istream& is); bool operator==(const EnzymaticSearchConstraint& that) const; bool operator!=(const EnzymaticSearchConstraint& that) const; }; struct PWIZ_API_DECL AminoAcidModification { AminoAcidModification() : massDiff(0), mass(0) {} std::string aminoAcid; double massDiff; double mass; std::string variable; std::string peptideTerminus; std::string binary; std::string description; std::string symbol; void write(XMLWriter& writer) const; void read(std::istream& is); bool operator==(const AminoAcidModification& that) const; bool operator!=(const AminoAcidModification& that) const; }; /// Database search settings struct PWIZ_API_DECL SearchSummary { SearchSummary(){} /// Full path location of mzXML file for this search run (without /// the .mzXML extension) std::string baseName; /// SEQUEST, Mascot, COMET, etc std::string searchEngine; /// average or monoisotopic std::string precursorMassType; /// average or monoisotopic std::string fragmentMassType; /// Format of file storing the runner up peptides (if not present /// in pepXML) std::string searchID; /// runner up search hit data type extension (e.g. .tgz) SearchDatabase searchDatabase; /// matches id in search hit size_t search_id; EnzymaticSearchConstraint enzymaticSearchConstraint; std::vector aminoAcidModifications; std::vector parameters; void write(XMLWriter& writer) const; void read(std::istream& is); bool operator==(const SearchSummary& that) const; bool operator!=(const SearchSummary& that) const; }; typedef boost::shared_ptr SearchSummaryPtr; PWIZ_API_DECL bool operator==(const SearchSummaryPtr left, const SearchSummaryPtr right); /// Reference for analysis applied to current run (time corresponds /// with analysis_summary/@time, id corresponds with /// analysis_result/@id) struct PWIZ_API_DECL AnalysisTimestamp { /// Date of analysis std::string time; /// Analysis name std::string analsysis; /// Unique identifier for each type of analysis size_t id; // Evil ##any data goes here }; struct PWIZ_API_DECL SpectrumQuery { SpectrumQuery() : startScan(0), endScan(0), precursorNeutralMass(0), assumedCharge(0), index(0), retentionTimeSec(0) {} std::string spectrum; /// first scan number integrated into MS/MS spectrum int startScan; /// last scan number integrated into MS/MS spectrum int endScan; double precursorNeutralMass; /// Precursor ion charge used for search int assumedCharge; /// Search constraint applied specifically to this query int index; /// Unique identifier double retentionTimeSec; std::vector searchResult; void write(XMLWriter& writer) const; void read(std::istream& is); bool operator==(const SpectrumQuery& that) const; bool operator!=(const SpectrumQuery& that) const; }; typedef boost::shared_ptr SpectrumQueryPtr; PWIZ_API_DECL bool operator==(const SpectrumQueryPtr left, const SpectrumQueryPtr right); struct PWIZ_API_DECL MSMSRunSummary { MSMSRunSummary(){} std::string base_name; std::string raw_data_type; std::string raw_data; std::string msManufacturer; std::string msModel; std::string msIonization; std::string msMassAnalyzer; std::string msDetector; SampleEnzyme sampleEnzyme; std::vector searchSummary; std::vector spectrumQueries; void write(XMLWriter& writer) const; void read(std::istream& is); bool operator==(const MSMSRunSummary& that) const; bool operator!=(const MSMSRunSummary& that) const; }; struct PWIZ_API_DECL AnalysisSummary { /// Time analysis complete (unique id) std::string time; /// Name of analysis program std::string analysis; /// Release std::string version; // All the unknown stuff goes here // TODO deal with the results of // std::vector peptideprophet_summary; }; typedef boost::shared_ptr AnalysisSummaryPtr; struct PWIZ_API_DECL DataFilter { size_t number; /// File from which derived std::string parent_file; std::string windows_parent; /// filtering criteria applied to data std::string description; }; typedef boost::shared_ptr DataFilterPtr; /// Source and filtering criteria used to generate dataset struct PWIZ_API_DECL DatasetDerivation { /// number preceding filter generations size_t generation_no; std::vector dataFilters; }; typedef boost::shared_ptr DatasetDerivationPtr; struct PWIZ_API_DECL MSMSPipelineAnalysis { MSMSPipelineAnalysis(){} std::string date; std::string summaryXML; std::string xmlns; std::string xmlnsXSI; std::string XSISchemaLocation; /// full path file name of mzXML (minus the .mzXML) std::string baseName; /// raw data type extension (e.g. .mzXML) std::string raw_data_type; /// raw data type extension (e.g. .mzXML) std::string raw_data; /// Manufacturer of MS/MS instrument std::string msManufacturer; /// Instrument model (cf mzXML) std::string msModel; /// Instrument model (cf mzXML) std::string msIonization; /// Ion trap, etc (cf mzXML) std::string msMassAnalyzer; /// EMT, etc(cf mzXML) std::string msDetector; AnalysisSummaryPtr analysisSummary; DatasetDerivationPtr datasetDerivation; MSMSRunSummary msmsRunSummary; void write(XMLWriter& writer) const; void read(std::istream& is); bool operator==(const MSMSPipelineAnalysis& that) const; bool operator!=(const MSMSPipelineAnalysis& that) const; }; struct PWIZ_API_DECL Match { Match() : score(0), feature(new Feature()) {} Match(const SpectrumQuery& _spectrumQuery, FeaturePtr _feature, double _score = 0) : score(_score), spectrumQuery(_spectrumQuery), feature(_feature) {} double score; double calculatedMass; double massDeviation; // ( feature mz - proton mass ) * charge - calculatedMass (not absolute val!) SpectrumQuery spectrumQuery; FeaturePtr feature; void write(minimxml::XMLWriter& writer) const; void read(std::istream& is); bool operator==(const Match& that) const; bool operator!=(const Match& that) const; private: Match(Match&); Match operator=(Match&); }; typedef boost::shared_ptr MatchPtr; PWIZ_API_DECL bool operator==(const MatchPtr left, const MatchPtr right); struct PWIZ_API_DECL MatchData { MatchData(){} MatchData(std::string wfc, std::string snc) : warpFunctionCalculator(wfc), searchNbhdCalculator(snc) {} MatchData(std::vector _matches) : matches(_matches){} std::string warpFunctionCalculator; std::string searchNbhdCalculator; std::vector matches; void write(minimxml::XMLWriter& writer) const; void read(std::istream& is); bool operator==(const MatchData& that) const; bool operator!=(const MatchData& that) const; }; } // namespace pepxml } // namespace data } // namespace pwiz #endif // _MINIMUMPEPXML_HPP_ // LocalWords: RatioResult pwiz/pwiz/data/misc/CalibrationParametersTest.cpp0000664000175100017510000000375012664775621024234 0ustar teamcityteamcity00000000000000// // $Id: CalibrationParametersTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "CalibrationParameters.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::data; ostream* os_ = 0; void test() { CalibrationParameters p = CalibrationParameters::thermo_FT(); CalibrationParameters q(0,1); unit_assert(p!=q); q.A = thermoA_FT_; q.B = thermoB_FT_; unit_assert(p==q); double dummy = 420; double epsilon = 1e-13; unit_assert_equal(dummy, p.mz(p.frequency(dummy)), epsilon); unit_assert_equal(dummy, p.frequency(p.mz(dummy)), epsilon); CalibrationParameters p2 = CalibrationParameters::thermo_Orbitrap(); unit_assert_equal(dummy, p2.mz(p2.frequency(dummy)), epsilon); unit_assert_equal(dummy, p2.frequency(p2.mz(dummy)), epsilon); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; if (os_) *os_ << "CalibrationParametersTest\n"; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/misc/PeakDataTest.cpp0000664000175100017510000002472212664775621021435 0ustar teamcityteamcity00000000000000// // $Id: PeakDataTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "PeakData.hpp" #include "pwiz/utility/misc/unit.hpp" #include #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::minimxml; using namespace pwiz::math; using namespace pwiz::data::peakdata; ostream* os_ = 0; PeakFamily initializePeakFamily() { PeakFamily peakFamily; peakFamily.mzMonoisotopic = 329.86; peakFamily.charge = 3; peakFamily.score = 0.11235811; Peak peak; Peak a; Peak boo; peak.mz = 329.86; a.mz = 109.87; boo.mz = 6.022141730; peakFamily.peaks.push_back(peak); peakFamily.peaks.push_back(a); peakFamily.peaks.push_back(boo); return peakFamily; } Scan initializeScan() { Scan scan; scan.index = 12; scan.nativeID = "24"; scan.scanNumber = 24; scan.retentionTime = 12.345; scan.observationDuration = 6.78; scan.calibrationParameters.A = 987.654; scan.calibrationParameters.B = 321.012; PeakFamily flintstones = initializePeakFamily(); PeakFamily jetsons = initializePeakFamily(); scan.peakFamilies.push_back(flintstones); scan.peakFamilies.push_back(jetsons); return scan; } Software initializeSoftware() { Software software; software.name = "World of Warcraft"; software.version = "Wrath of the Lich King"; software.source = "Blizzard Entertainment"; Software::Parameter parameter1("Burke ping","level 70"); Software::Parameter parameter2("Kate ping", "level 0"); software.parameters.push_back(parameter1); software.parameters.push_back(parameter2); return software; } PeakData initializePeakData() { PeakData pd; Software software = initializeSoftware(); pd.software = software; Scan scan = initializeScan(); pd.scans.push_back(scan); pd.scans.push_back(scan); return pd; } PeakelPtr initializePeakel() { PeakelPtr pkl(new Peakel); pkl->mz = 432.1; pkl->retentionTime = 1234.56; pkl->maxIntensity = 9876.54; pkl->totalIntensity = 32123.45; pkl->mzVariance = 6.023; PeakFamily peakFamily = initializePeakFamily(); pkl->peaks = peakFamily.peaks; return pkl; } void testPeakEquality() { if (os_) *os_ << "testPeakEquality()" <write(writer_pkl); // instantiate another Peakel Peakel gherkin; // read into it istringstream iss_pkl(oss_pkl.str()); gherkin.read(iss_pkl); // assert that the two Peakels are equal unit_assert(*dill == gherkin); if (os_) *os_ << "Testing Peakel ... " << endl << oss_pkl.str() << endl; } void testPeakelAux() { Peakel p; p.retentionTime = 420; unit_assert(p.retentionTimeMin() == 420); unit_assert(p.retentionTimeMax() == 420); p.peaks.resize(2); p.peaks[0].retentionTime = 666; p.peaks[1].retentionTime = 667; unit_assert(p.retentionTimeMin() == 666); unit_assert(p.retentionTimeMax() == 667); } void testPeakelConstruction() { Peak peak(420, 666); Peakel peakel(Peak(420,666)); unit_assert(peakel.mz == 420); unit_assert(peakel.retentionTime == 666); unit_assert(peakel.peaks.size() == 1); unit_assert(peakel.peaks[0] == peak); } void testFeature() { // initialize a new Feature Feature feature; feature.mz = 1863.0101; feature.retentionTime = 1492.1012; feature.charge = 3; feature.totalIntensity = 1776.0704; feature.rtVariance = 1969.0720; feature.score = 420.0; feature.error = 666.0; PeakelPtr stateFair = initializePeakel(); PeakelPtr deli = initializePeakel(); feature.peakels.push_back(stateFair); feature.peakels.push_back(deli); // write it out ostringstream oss_f; XMLWriter writer_f(oss_f); feature.write(writer_f); // instantiate another feature Feature feature2; // read into it istringstream iss(oss_f.str()); feature2.read(iss); // assert that the two Features are equal if (os_) { *os_ << "Testing Feature ... " << endl << oss_f.str() << endl; *os_ << "feature2:\n"; XMLWriter writer(*os_); feature2.write(writer); } unit_assert(feature == feature2); } void testFeatureAux() { Feature feature; feature.retentionTime = 420; unit_assert(feature.retentionTimeMin() == 420); unit_assert(feature.retentionTimeMax() == 420); // retention time ranges determined by first two peakels PeakelPtr dill(new Peakel); dill->peaks.push_back(Peak(666,419)); dill->peaks.push_back(Peak(666,423)); PeakelPtr sweet(new Peakel); sweet->peaks.push_back(Peak(666,421)); sweet->peaks.push_back(Peak(666,424)); PeakelPtr gherkin(new Peakel); gherkin->peaks.push_back(Peak(666,418)); gherkin->peaks.push_back(Peak(666,425)); feature.peakels.push_back(dill); feature.peakels.push_back(sweet); feature.peakels.push_back(gherkin); unit_assert(feature.retentionTimeMin() == 419); unit_assert(feature.retentionTimeMax() == 424); } void test() { testPeakEquality(); testPeak(); testPeakFamily(); testScan(); testSoftware(); testPeakData(); testPeakel(); testPeakelAux(); testPeakelConstruction(); testFeature(); testFeatureAux(); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; if (os_) *os_ << "PeakDataTest\n"; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/peakdetect/PeakFamilyDetectorFT.hpp0000664000175100017510000000417112664775614025164 0ustar teamcityteamcity00000000000000// // $Id: PeakFamilyDetectorFT.hpp 1191 2009-08-14 19:33:05Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PEAKFAMILYDETECTORFT_HPP_ #define _PEAKFAMILYDETECTORFT_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "PeakFamilyDetector.hpp" #include "pwiz/data/misc/PeakData.hpp" namespace pwiz { namespace analysis { /// /// FT-specific implementation of PeakFamilyDetector /// class PWIZ_API_DECL PeakFamilyDetectorFT : public PeakFamilyDetector { public: struct PWIZ_API_DECL Config { std::ostream* log; data::CalibrationParameters cp; Config() : log(0) {} }; PeakFamilyDetectorFT(const Config& config); /// find peak families in a specified array of MZIntensityPair virtual void detect(const MZIntensityPair* begin, const MZIntensityPair* end, std::vector& result); /// FT-specific exception struct NoDataException : public std::runtime_error { NoDataException() : std::runtime_error("[PeakFamilyDetectorFT::NoDataException]") {} }; private: class Impl; boost::shared_ptr impl_; PeakFamilyDetectorFT(PeakFamilyDetectorFT&); PeakFamilyDetectorFT& operator=(PeakFamilyDetectorFT&); }; } // namespace analysis } // namespace pwiz #endif // _PEAKFAMILYDETECTORFT_HPP_ pwiz/pwiz/analysis/peakdetect/PeakelPicker.cpp0000664000175100017510000001652712664775614023560 0ustar teamcityteamcity00000000000000// // $Id: PeakelPicker.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "PeakelPicker.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace analysis { using namespace pwiz::data::peakdata; namespace { class BasicPickImpl { public: BasicPickImpl(PeakelField& peakelField, FeatureField& featureField, const PeakelPicker_Basic::Config& config) : peakelField_(peakelField), featureField_(featureField), config_(config) {} void pick(); private: PeakelField& peakelField_; FeatureField& featureField_; const PeakelPicker_Basic::Config& config_; PeakelPtr getPeakelIsotope(const PeakelPtr& monoisotopicPeakel, size_t charge, size_t neutronNumber); void getFeatureCandidate(const PeakelPtr& peakel, size_t charge, vector& result); FeaturePtr findFeature(const PeakelPtr& peakel); PeakelField::iterator removeFromPeakelField(const Feature& feature); PeakelField::iterator process(PeakelField::iterator it); }; PeakelPtr BasicPickImpl::getPeakelIsotope(const PeakelPtr& monoisotopicPeakel, size_t charge, size_t neutronNumber) { if (config_.log) *config_.log << "[PeakelPicker_Basic] getPeakelIsotope(): charge=" << charge << " neutron=" << neutronNumber << endl; // find the peakel: // - m/z must be within mzTolerance of the theoretical m/z // - retention time range must be contained within the monoisotopic peakel range double mzTarget = monoisotopicPeakel->mz + 1./charge*neutronNumber; vector isotopeCandidates = peakelField_.find(mzTarget, config_.mzTolerance, RTMatches_IsContainedIn(*monoisotopicPeakel, config_.rtTolerance)); // TODO: restrict based on retentionTimeMax() of isotopeCandidates, since find() // uses retentionTimeMin() (via metadata) if (config_.log) { /* *config_.log << "mzTarget: " << mzTarget << endl << "rtTarget: " << rtTarget << endl << "rtTolerance: " << rtTolerance << endl; */ *config_.log << "[PeakelPicker_Basic] isotopeCandidates: " << isotopeCandidates.size() << endl; for (vector::const_iterator it=isotopeCandidates.begin(); it!=isotopeCandidates.end(); ++it) *config_.log << **it; } // if there are multiple candidates, may need to merge if (isotopeCandidates.empty()) return PeakelPtr(); else if (isotopeCandidates.size() == 1) return isotopeCandidates[0]; else { if (config_.log) { *config_.log << "[PeakelPicker_Basic::getPeakelIsotope()] Warning: multiple isotope candidates.\n" << "isotopeCandidates: " << isotopeCandidates.size() << endl; for (vector::const_iterator it=isotopeCandidates.begin(); it!=isotopeCandidates.end(); ++it) *config_.log << **it << endl; } return isotopeCandidates[0]; // TODO } } void BasicPickImpl::getFeatureCandidate(const PeakelPtr& peakel, size_t charge, vector& result) { if (config_.log) *config_.log << "[PeakelPicker_Basic] getFeatureCandidate(): z=" << charge << endl; FeaturePtr feature(new Feature); feature->peakels.push_back(peakel); const size_t maxNeutronNumber = 6; for (size_t neutronNumber=1; neutronNumber<=maxNeutronNumber; neutronNumber++) { PeakelPtr peakelIsotope = getPeakelIsotope(peakel, charge, neutronNumber); if (!peakelIsotope.get()) break; feature->peakels.push_back(peakelIsotope); } if (feature->peakels.size() >= config_.minPeakelCount) { // set feature basic metadata // can't do full recalculation until peakels removed from peakelField feature->mz = peakel->mz; feature->retentionTime = peakel->retentionTime; feature->charge = charge; result.push_back(feature); if (config_.log) *config_.log << "[PeakelPicker_Basic] Found feature candidate:\n" << *feature << endl; } } FeaturePtr BasicPickImpl::findFeature(const PeakelPtr& peakel) { if (config_.log) *config_.log << "[PeakelPicker_Basic] findFeature():\n" << *peakel; if (peakel->peaks.size() < config_.minMonoisotopicPeakelSize) return FeaturePtr(); vector candidates; for (size_t z=config_.minCharge; z<=config_.maxCharge; z++) getFeatureCandidate(peakel, z, candidates); if (candidates.empty()) return FeaturePtr(); else if (candidates.size() == 1) return candidates[0]; else { if (config_.log) { *config_.log << "[PeakelPicker_Basic::findFeature()] Warning: multiple charge state candidates." << "candidates: " << candidates.size() << endl; for (vector::const_iterator it=candidates.begin(); it!=candidates.end(); ++it) *config_.log << **it << endl; } return candidates[0]; } } PeakelField::iterator BasicPickImpl::removeFromPeakelField(const Feature& feature) { if (feature.peakels.empty()) throw runtime_error("[PeakelPicker::removeFromPeakelField()] Empty feature."); // remove feature's peakels from peakelField for (vector::const_iterator it=feature.peakels.begin(); it!=feature.peakels.end(); ++it) peakelField_.remove(*it); // return the next valid iterator after the monoisotopic peakel return peakelField_.upper_bound(feature.peakels.front()); } PeakelField::iterator BasicPickImpl::process(PeakelField::iterator it) { FeaturePtr feature = findFeature(*it); if (feature.get()) { if (config_.log) *config_.log << "[PeakelPicker_Basic] Feature found:\n" << *feature << endl; featureField_.insert(feature); return removeFromPeakelField(*feature); } else { return ++it; } } void BasicPickImpl::pick() { if (config_.log) *config_.log << "[PeakelPicker_Basic] pick() begin\n\n" << peakelField_ << endl; PeakelField::iterator it = peakelField_.begin(); PeakelField::iterator end = peakelField_.end(); while (it != end) it = process(it); if (config_.log) *config_.log << "[PeakelPicker_Basic] pick() end\n\n"; } } // namespace void PeakelPicker_Basic::pick(PeakelField& peakels, FeatureField& features) const { BasicPickImpl impl(peakels, features, config_); impl.pick(); } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/peakdetect/PeakFamilyDetectorFTTestData.cpp0000664000175100017510000001435112664775614026612 0ustar teamcityteamcity00000000000000// // $Id: PeakFamilyDetectorFTTestData.cpp 1191 2009-08-14 19:33:05Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // double peakFamilyDetectorFTTestData_[] = { 810.002100, 0.000000, 810.006100, 0.000000, 810.010100, 0.000000, 810.026000, 0.000000, 810.030000, 0.000000, 810.033900, 0.000000, 810.037900, 0.000000, 810.041900, 1012.938500, 810.045800, 1187.492400, 810.049800, 0.000000, 810.053800, 0.000000, 810.057700, 0.000000, 810.061700, 0.000000, 810.065700, 0.000000, 810.113400, 0.000000, 810.117400, 0.000000, 810.121300, 0.000000, 810.125300, 0.000000, 810.129300, 0.000000, 810.133200, 1262.221700, 810.137200, 830.308500, 810.141200, 0.000000, 810.145200, 0.000000, 810.149200, 0.000000, 810.153100, 0.000000, 810.169000, 0.000000, 810.173000, 0.000000, 810.176900, 0.000000, 810.181000, 0.000000, 810.184900, 343.421000, 810.188900, 2050.338100, 810.192900, 1079.034400, 810.196800, 0.000000, 810.200800, 670.116900, 810.204800, 2292.352800, 810.208700, 1489.443100, 810.212700, 537.434500, 810.216700, 1382.132300, 810.220700, 2303.807900, 810.224700, 706.400200, 810.228600, 0.000000, 810.232600, 39.931200, 810.236600, 1200.312500, 810.240500, 207.038100, 810.244500, 0.000000, 810.248500, 740.042100, 810.252500, 2486.042200, 810.256500, 571.452800, 810.260400, 0.000000, 810.264400, 0.000000, 810.268400, 0.000000, 810.272300, 0.000000, 810.276300, 1510.155500, 810.280300, 0.000000, 810.284300, 0.000000, 810.288300, 0.000000, 810.292200, 0.000000, 810.296200, 130.314100, 810.300200, 2289.245600, 810.304100, 282.176700, 810.308100, 0.000000, 810.312100, 0.000000, 810.316100, 1960.466600, 810.320100, 640.229700, 810.324000, 2398.523200, 810.328000, 0.000000, 810.332000, 2115.042500, 810.335900, 96.155200, 810.339900, 919.178400, 810.343900, 2285.743700, 810.347900, 5586.711400, 810.351900, 1804.999800, 810.355800, 1819.686500, 810.359800, 1774.668900, 810.363800, 4523.286600, 810.367700, 4640.553200, 810.371800, 7331.667500, 810.375700, 8467.586900, 810.379700, 4679.696300, 810.383700, 39121.140600, 810.387600, 52979.617200, 810.391600, 30812.173800, 810.395600, 40648.218800, 810.399600, 98844.078100, 810.403600, 352305.656200, 810.407500, 970060.125000, 810.411500, 1787798.125000, 810.415500, 2295224.500000, 810.419400, 2093907.625000, 810.423400, 1321908.500000, 810.427400, 514400.062500, 810.431400, 73405.148400, 810.435400, 18628.507800, 810.439300, 13153.760700, 810.443300, 6270.501000, 810.447300, 5825.568800, 810.451200, 259.063900, 810.455300, 4645.333500, 810.459200, 1064.302000, 810.463200, 5938.245100, 810.467200, 1532.820100, 810.471100, 1292.436800, 810.475100, 1122.282700, 810.479100, 2703.187000, 810.483100, 321.115100, 810.487100, 1795.361800, 810.491000, 1075.285200, 810.495000, 1707.908700, 810.499000, 572.236500, 810.503000, 1601.414800, 810.507000, 1110.299800, 810.510900, 1176.937300, 810.514900, 443.296700, 810.518900, 1288.253400, 810.522800, 0.000000, 810.526900, 0.000000, 810.530800, 0.000000, 810.534800, 0.000000, 810.538800, 1369.308100, 810.542700, 1914.818100, 810.546700, 497.219900, 810.550700, 0.000000, 810.554700, 0.000000, 810.558700, 0.000000, 810.562600, 0.000000, 810.725800, 0.000000, 810.729700, 0.000000, 810.733700, 0.000000, 810.737700, 0.000000, 810.741600, 760.516800, 810.745700, 1415.572300, 810.749600, 437.060700, 810.753600, 0.000000, 810.757600, 0.000000, 810.761500, 0.000000, 810.765600, 0.000000, 810.777500, 0.000000, 810.781400, 0.000000, 810.785500, 0.000000, 810.789400, 0.000000, 810.793400, 26.770600, 810.797400, 1271.681900, 810.801400, 1457.158200, 810.805400, 543.397400, 810.809300, 1457.991000, 810.813300, 242.238800, 810.817300, 0.000000, 810.821300, 0.000000, 810.825300, 1412.413300, 810.829200, 0.000000, 810.833200, 0.000000, 810.837200, 0.000000, 810.841200, 0.000000, 810.845200, 894.918900, 810.849100, 1961.378900, 810.853100, 408.813300, 810.857100, 2179.574500, 810.861100, 2833.404800, 810.865100, 4970.447300, 810.869000, 3401.553700, 810.873000, 5247.141600, 810.877000, 7574.849600, 810.881000, 3733.999000, 810.884900, 33771.468800, 810.888900, 44082.332000, 810.892900, 17454.869100, 810.896900, 29561.988300, 810.900900, 98749.945300, 810.904800, 344787.750000, 810.908800, 896349.250000, 810.912800, 1596359.625000, 810.916800, 2006171.000000, 810.920800, 1800765.375000, 810.924700, 1118746.375000, 810.928800, 425829.812500, 810.932700, 57181.339800, 810.936700, 15168.465800, 810.940700, 11471.797900, 810.944700, 4399.850100, 810.948700, 6007.852500, 810.952600, 0.000000, 810.956600, 3924.998000, 810.960600, 3405.507300, 810.964600, 5835.790000, 810.968600, 127.287900, 810.972500, 1720.544400, 810.976500, 1492.606200, 810.980500, 1574.352100, 810.984500, 1817.881800, 810.988500, 2664.881100, 810.992400, 164.361000, 810.996500, 0.000000 }; int peakFamilyDetectorFTTestDataSize_ = sizeof(peakFamilyDetectorFTTestData_) / sizeof(double); pwiz/pwiz/analysis/peakdetect/MZRTField.hpp0000664000175100017510000001316112664775614022755 0ustar teamcityteamcity00000000000000// // $Id: MZRTField.hpp 2469 2011-01-18 19:27:57Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _MZRTFIELD_HPP_ #define _MZRTFIELD_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/misc/PeakData.hpp" #include "pwiz/utility/chemistry/MZTolerance.hpp" #include "boost/shared_ptr.hpp" #include "boost/concept/assert.hpp" #include "boost/concept/usage.hpp" #include #include namespace pwiz { namespace analysis { using chemistry::MZTolerance; namespace { /// /// lexicographic ordering, by m/z then retention time /// template struct LessThan_MZRT { typedef boost::shared_ptr TPtr; bool operator()(const T& a, const T& b) const { if (a.mz < b.mz) return true; if (b.mz < a.mz) return false; return (a.retentionTime < b.retentionTime); // rare } bool operator()(const TPtr& a, const TPtr& b) const { return (*this)(*a, *b); } }; /// /// struct for Boost concept checking /// template struct HasMZRT { BOOST_CONCEPT_USAGE(HasMZRT) { T t; // default construction double a = t.mz; // must have member 'mz' a = t.retentionTime; // must have member 'retentionTime' const T& c = t; a = c.retentionTimeMin(); // must have member 'double retentionTimeMin() const' a = c.retentionTimeMax(); // must have member 'double retentionTimeMin() const' } }; } // namespace /// /// MZRTField is a std::set of boost::shared_ptrs, stored as a binary tree /// ordered by LessThan_MZRT /// template struct MZRTField : public std::set< boost::shared_ptr, LessThan_MZRT > { //BOOST_CONCEPT_ASSERT((HasMZRT)); typedef boost::shared_ptr TPtr; /// find all objects with a given m/z, within a given m/z tolerance, /// satisfying the 'matches' predicate template std::vector find(double mz, MZTolerance mzTolerance, RTMatches matches) const; /// remove an object via a shared reference, rather than an iterator into the set void remove(const TPtr& p); }; typedef MZRTField PeakelField; typedef MZRTField FeatureField; PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const PeakelField& peakelField); PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const FeatureField& featureField); /// predicate always returns true template struct RTMatches_Any { bool operator()(const T& t) const {return true;} }; /// predicate returns true iff the object's retention time range contains the specified /// retention time template struct RTMatches_Contains { RTMatches_Contains(double rt, double rtTolerance = 0) : rt_(rt), rtTolerance_(rtTolerance) {} bool operator()(const T& t) const { return rt_>t.retentionTimeMin()-rtTolerance_ && rt_ struct RTMatches_IsContainedIn { RTMatches_IsContainedIn(const T& reference, double rtTolerance = 0) : reference_(reference), rtTolerance_(rtTolerance) {} bool operator()(const T& t) const { return t.retentionTimeMin() > reference_.retentionTimeMin() - rtTolerance_ && t.retentionTimeMax() < reference_.retentionTimeMax() + rtTolerance_; } private: const T& reference_; double rtTolerance_; }; template template std::vector< boost::shared_ptr > MZRTField::find(double mz, MZTolerance mzTolerance, RTMatches matches) const { TPtr target(new T); // use binary search to get a std::set iterator range target->mz = mz - mzTolerance; typename MZRTField::const_iterator begin = this->lower_bound(target); target->mz = mz + mzTolerance; typename MZRTField::const_iterator end = this->upper_bound(target); // linear copy_if within range std::vector result; for (typename MZRTField::const_iterator it=begin; it!=end; ++it) if (matches(**it)) result.push_back(*it); return result; } template void MZRTField::remove(const boost::shared_ptr& p) { std::pair::iterator, typename MZRTField::iterator> range = this->equal_range(p); // uses LessThan_MZRT typename MZRTField::iterator found = std::find(range.first, range.second, p); // uses shared_ptr::operator== if (found == range.second) throw std::runtime_error("[MZRTField::remove()] TPtr not found."); this->erase(found); } } // namespace analysis } // namespace pwiz #endif // _MZRTFIELD_HPP_ pwiz/pwiz/analysis/peakdetect/MZRTField.cpp0000664000175100017510000000375512664775614022760 0ustar teamcityteamcity00000000000000// // $Id: MZRTField.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "MZRTField.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace analysis { using namespace pwiz::minimxml; PWIZ_API_DECL ostream& operator<<(ostream& os, const PeakelField& peakelField) { XMLWriter writer(os); XMLWriter::Attributes attributes; attributes.push_back(make_pair("count", lexical_cast(peakelField.size()))); writer.startElement("peakelField", attributes); for (PeakelField::const_iterator it=peakelField.begin(); it!=peakelField.end(); ++it) (*it)->write(writer); writer.endElement(); return os; } PWIZ_API_DECL ostream& operator<<(ostream& os, const FeatureField& featureField) { XMLWriter writer(os); XMLWriter::Attributes attributes; attributes.push_back(make_pair("count", lexical_cast(featureField.size()))); writer.startElement("featureField", attributes); for (FeatureField::const_iterator it=featureField.begin(); it!=featureField.end(); ++it) (*it)->write(writer); writer.endElement(); return os; } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/peakdetect/FeatureDetectorSimple.hpp0000664000175100017510000000335412664775614025457 0ustar teamcityteamcity00000000000000// // $Id: FeatureDetectorSimple.hpp 1191 2009-08-14 19:33:05Z chambm $ // // // Original author: Kate Hoff // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Cnter, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _FEATUREDETECTORSIMPLE_HPP_ #define _FEATUREDETECTORSIMPLE_HPP_ #include "FeatureDetector.hpp" #include "pwiz/analysis/peakdetect/PeakFamilyDetector.hpp" #include "pwiz/data/misc/PeakData.hpp" namespace pwiz{ namespace analysis{ using namespace pwiz::data::peakdata; /// FeatureDetectorSimple detects 'rectangular' features, ie number of peaks in /// isotope envelope is the same for each scan included in the feature class PWIZ_API_DECL FeatureDetectorSimple : public FeatureDetector { public: FeatureDetectorSimple(boost::shared_ptr _pfd); virtual void detect(const MSData& msd, FeatureField& result) const; private: class Impl; boost::shared_ptr _pimpl; FeatureDetectorSimple(const FeatureDetectorSimple&); FeatureDetectorSimple& operator=(const FeatureDetectorSimple&); }; } // namespace analysis } // namespace pwiz #endif // _FEATUREDETECTORSIMPLE_HPP_ pwiz/pwiz/analysis/peakdetect/PeakFitter.hpp0000664000175100017510000000436612664775614023262 0ustar teamcityteamcity00000000000000// // $Id: PeakFitter.hpp 1191 2009-08-14 19:33:05Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PEAKFITTER_HPP_ #define _PEAKFITTER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/utility/math/OrderedPair.hpp" #include "pwiz/data/misc/PeakData.hpp" #include namespace pwiz { namespace analysis { /// /// interface for fitting peaks in an array of ordered pairs /// class PWIZ_API_DECL PeakFitter { public: typedef pwiz::data::peakdata::Peak Peak; virtual void fitPeak(const math::OrderedPairContainerRef& pairs, size_t index, Peak& result) const = 0; void fitPeaks(const math::OrderedPairContainerRef& pairs, std::vector& indices, std::vector& result) const; virtual ~PeakFitter(){} }; /// /// PeakFitter implementation based on fitting a parabola /// class PWIZ_API_DECL PeakFitter_Parabola : public PeakFitter { public: struct Config { size_t windowRadius; Config(size_t _windowRadius = 1) : windowRadius(_windowRadius) {} }; PeakFitter_Parabola(const Config& config = Config()); virtual void fitPeak(const math::OrderedPairContainerRef& pairs, size_t index, Peak& result) const; private: Config config_; }; } // namespace analysis } // namespace pwiz #endif // _PEAKFITTER_HPP_ pwiz/pwiz/analysis/peakdetect/FeatureDetectorPeakelTest.cpp0000664000175100017510000001172612664775614026264 0ustar teamcityteamcity00000000000000// // $Id: FeatureDetectorPeakelTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "FeatureDetectorPeakel.hpp" #include "pwiz/data/msdata/MSDataFile.hpp" #include "pwiz/utility/misc/unit.hpp" #include "boost/filesystem/path.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::analysis; using namespace pwiz::data; using namespace pwiz::data::peakdata; using namespace pwiz::msdata; namespace bfs = boost::filesystem; ostream* os_ = 0; void verifyBombesinFeatures(const FeatureField& featureField) { const double epsilon = .01; const double mz_bomb2 = 810.415; vector bombesin_2_found = featureField.find(mz_bomb2, epsilon, RTMatches_Contains(1865)); unit_assert(bombesin_2_found.size() == 1); const Feature& bombesin_2 = *bombesin_2_found[0]; unit_assert(bombesin_2.charge == 2); unit_assert(bombesin_2.peakels.size() == 5); unit_assert_equal(bombesin_2.peakels[0]->mz, mz_bomb2, epsilon); unit_assert_equal(bombesin_2.peakels[1]->mz, mz_bomb2+.5, epsilon); unit_assert_equal(bombesin_2.peakels[2]->mz, mz_bomb2+1, epsilon); unit_assert_equal(bombesin_2.peakels[3]->mz, mz_bomb2+1.5, epsilon); unit_assert_equal(bombesin_2.peakels[4]->mz, mz_bomb2+2, epsilon); //TODO: verify feature metadata const double mz_bomb3 = 540.612; vector bombesin_3_found = featureField.find(mz_bomb3, epsilon, RTMatches_Contains(1865)); unit_assert(bombesin_3_found.size() == 1); const Feature& bombesin_3 = *bombesin_3_found[0]; unit_assert(bombesin_3.charge == 3); unit_assert(bombesin_3.peakels.size() == 3); unit_assert_equal(bombesin_3.peakels[0]->mz, mz_bomb3, epsilon); unit_assert_equal(bombesin_3.peakels[1]->mz, mz_bomb3+1./3, epsilon); unit_assert_equal(bombesin_3.peakels[2]->mz, mz_bomb3+2./3, epsilon); //TODO: verify feature metadata } shared_ptr createFeatureDetectorPeakel() { FeatureDetectorPeakel::Config config; // these are just the defaults, to demonstrate usage config.noiseCalculator_2Pass.zValueCutoff = 1; config.peakFinder_SNR.windowRadius = 2; config.peakFinder_SNR.zValueThreshold = 3; config.peakFinder_SNR.preprocessWithLogarithm = true; config.peakFitter_Parabola.windowRadius = 1; config.peakelGrower_Proximity.mzTolerance = .01; config.peakelGrower_Proximity.rtTolerance = 10; config.peakelPicker_Basic.log = 0; // ostream* config.peakelPicker_Basic.minCharge = 2; config.peakelPicker_Basic.maxCharge = 5; config.peakelPicker_Basic.minMonoisotopicPeakelSize = 2; config.peakelPicker_Basic.mzTolerance = MZTolerance(10, MZTolerance::PPM); config.peakelPicker_Basic.rtTolerance = 5; config.peakelPicker_Basic.minPeakelCount = 3; return FeatureDetectorPeakel::create(config); } void testBombesin(const string& filename) { if (os_) *os_ << "testBombesin()" << endl; // open data file and check sanity MSDataFile msd(filename); unit_assert(msd.run.spectrumListPtr.get()); unit_assert(msd.run.spectrumListPtr->size() == 8); // instantiate FeatureDetector shared_ptr featureDetectorPeakel = createFeatureDetectorPeakel(); FeatureField featureField; featureDetectorPeakel->detect(msd, featureField); if (os_) *os_ << "featureField:\n" << featureField << endl; verifyBombesinFeatures(featureField); } void test(const bfs::path& datadir) { testBombesin((datadir / "FeatureDetectorTest_Bombesin.mzML").string()); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { bfs::path datadir = "."; for (int i=1; i // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PEAKEXTRACTOR_HPP_ #define _PEAKEXTRACTOR_HPP_ #include "PeakFinder.hpp" #include "PeakFitter.hpp" #include "pwiz/utility/misc/Export.hpp" #include "pwiz/utility/math/OrderedPair.hpp" #include "pwiz/data/misc/PeakData.hpp" #include "boost/shared_ptr.hpp" #include namespace pwiz { namespace analysis { /// /// Class for extracting Peak objects from an array of ordered pairs; /// in design pattern lingo, this is a "template method" delegating /// peak finding and peak fitting to "strategies". /// class PWIZ_API_DECL PeakExtractor { public: typedef pwiz::data::peakdata::Peak Peak; PeakExtractor(boost::shared_ptr peakFinder, boost::shared_ptr peakFitter); void extractPeaks(const pwiz::math::OrderedPairContainerRef& pairs, std::vector& result) const; private: boost::shared_ptr peakFinder_; boost::shared_ptr peakFitter_; }; } // namespace analysis } // namespace pwiz #endif // _PEAKEXTRACTOR_HPP_ pwiz/pwiz/analysis/peakdetect/PeakFinder.cpp0000664000175100017510000001116712664775614023224 0ustar teamcityteamcity00000000000000// // $Id: PeakFinder.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "PeakFinder.hpp" #include "pwiz/utility/misc/Std.hpp" #include #include namespace pwiz { namespace analysis { using namespace pwiz::math; PeakFinder_SNR::PeakFinder_SNR(shared_ptr noiseCalculator, const Config& config) : noiseCalculator_(noiseCalculator), config_(config) {} namespace { struct ComputeLogarithm { OrderedPair operator()(const OrderedPair& p) { double value = p.y>0 ? std::log(p.y) : 0; return OrderedPair(p.x, value); } }; struct CalculatePValue { double operator()(const OrderedPair& p) {return noise_.pvalue(p.y);} CalculatePValue(const Noise& noise) : noise_(noise) {} const Noise& noise_; }; vector calculateRollingProducts(const vector& in, size_t radius) { vector out; vector::const_iterator begin = in.begin(); vector::const_iterator end = in.end(); for (vector::const_iterator it=begin; it!=end; ++it) { double product = *it; for (int i=1; i<=(int)radius; i++) { // Note that the non-intuitive iterator arithmetic (with result signed int) // is used to appease MSVC's checked iterators. // (it-begin >= i) <-> (it-i >= begin) if (it-begin >= i) product *= *(it-i); if (i < end-it) product *= *(it+i); } out.push_back(product); } return out; } } // namespace void PeakFinder_SNR::findPeaks(const OrderedPairContainerRef& pairs, vector& resultIndices) const { vector preprocessedData; if (config_.preprocessWithLogarithm) transform(pairs.begin(), pairs.end(), back_inserter(preprocessedData), ComputeLogarithm()); const OrderedPairContainerRef& data = config_.preprocessWithLogarithm ? preprocessedData : pairs; Noise noise = noiseCalculator_->calculateNoise(data); // TODO: investigate calculating noise on unprocessed data vector pvalues; transform(data.begin(), data.end(), back_inserter(pvalues), CalculatePValue(noise)); vector rollingProducts = calculateRollingProducts(pvalues, config_.windowRadius); if (rollingProducts.size() != data.size()) throw runtime_error("[PeakFinder_SNR::findPeaks()] This isn't happening"); double thresholdValue = noise.mean + config_.zValueThreshold * noise.standardDeviation; double thresholdPValue = noise.pvalue(thresholdValue); double threshold = ((double(*)(double,int))std::pow)(thresholdPValue, 1+2*config_.windowRadius); // report local minima above the threshold for (size_t i=0; i // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Noise.hpp" #include "pwiz/utility/math/erf.hpp" #include "pwiz/utility/misc/Std.hpp" #include namespace pwiz { namespace analysis { using namespace pwiz::math; // // Noise // Noise::Noise(double m, double sd) : mean(m), variance(sd*sd), standardDeviation(sd) {} namespace { double normalCDF(double x, double mean, double sd) { double inner = (x-mean)/(sd*sqrt(2.)); return .5 * (1 + erf(inner)); } } // namespace double Noise::pvalue(double value) const { return 1-normalCDF(value, mean, standardDeviation); } // // NoiseCalculator_2Pass // NoiseCalculator_2Pass::NoiseCalculator_2Pass(const Config& config) : config_(config) {} Noise NoiseCalculator_2Pass::calculateNoise(const OrderedPairContainerRef& pairs) const { // calculate initial stats double sumIntensity = 0; double sumIntensity2 = 0; for (OrderedPairContainerRef::const_iterator it=pairs.begin(); it!=pairs.end(); ++it) { double value = it->y; sumIntensity += value; sumIntensity2 += value*value; } size_t count = pairs.size(); Noise result; result.mean = sumIntensity/count; result.variance = sumIntensity2/count - result.mean*result.mean; result.standardDeviation = sqrt(result.variance); // recalculate, excluding extreme values sumIntensity = 0; sumIntensity2 = 0; count = 0; for (OrderedPairContainerRef::const_iterator it=pairs.begin(); it!=pairs.end(); ++it) { double value = it->y; if (value > result.mean + result.standardDeviation*config_.zValueCutoff) continue; count++; sumIntensity += value; sumIntensity2 += value*value; } result.mean = sumIntensity/count; result.variance = sumIntensity2/count - result.mean*result.mean; result.standardDeviation = sqrt(result.variance); return result; } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/peakdetect/PeakFamilyDetectorFT.cpp0000664000175100017510000001760312664775614025163 0ustar teamcityteamcity00000000000000// // $Id: PeakFamilyDetectorFT.cpp 6141 2014-05-05 21:03:47Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "PeakFamilyDetectorFT.hpp" #include "pwiz/analysis/frequency/PeakDetectorMatchedFilter.hpp" #include "pwiz/data/misc/FrequencyData.hpp" #include "pwiz/utility/chemistry/IsotopeEnvelopeEstimator.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace analysis { using namespace pwiz::chemistry; using namespace pwiz::data; using namespace pwiz::frequency; // // PeakFamilyDetectorFT::Impl // class PeakFamilyDetectorFT::Impl { public: Impl(const Config& config); void detect(const MZIntensityPair* begin, const MZIntensityPair* end, vector& result); private: Config config_; auto_ptr isotopeEnvelopeEstimator_; auto_ptr pdmf_; auto_ptr createFrequencyData(const MZIntensityPair* begin, const MZIntensityPair* end) const; }; namespace { void readSecretConfigFile(PeakDetectorMatchedFilter::Config& config) { ifstream is("secret_config.txt"); if (!is) return; cout << "Reading secret_config.txt..."; map attributes; while (is) { string name, value; is >> name >> value; if (!is) break; attributes[name] = value; } if (attributes.count("filterMatchRate")) config.filterMatchRate = atoi(attributes["filterMatchRate"].c_str()); if (attributes.count("filterSampleRadius")) config.filterSampleRadius = atoi(attributes["filterSampleRadius"].c_str()); if (attributes.count("peakThresholdFactor")) config.peakThresholdFactor = atof(attributes["peakThresholdFactor"].c_str()); if (attributes.count("peakMaxCorrelationAngle")) config.peakMaxCorrelationAngle = atof(attributes["peakMaxCorrelationAngle"].c_str()); if (attributes.count("isotopeThresholdFactor")) config.isotopeThresholdFactor = atof(attributes["isotopeThresholdFactor"].c_str()); if (attributes.count("monoisotopicPeakThresholdFactor")) config.monoisotopicPeakThresholdFactor = atof(attributes["monoisotopicPeakThresholdFactor"].c_str()); if (attributes.count("isotopeMaxChargeState")) config.isotopeMaxChargeState = atoi(attributes["isotopeMaxChargeState"].c_str()); if (attributes.count("isotopeMaxNeutronCount")) config.isotopeMaxNeutronCount = atoi(attributes["isotopeMaxNeutronCount"].c_str()); if (attributes.count("collapseRadius")) config.collapseRadius = atof(attributes["collapseRadius"].c_str()); cout << "done.\n" << flush; } PeakDetectorMatchedFilter::Config getPeakDetectorConfiguration() { PeakDetectorMatchedFilter::Config config; config.filterMatchRate = 4; config.filterSampleRadius = 2; config.peakThresholdFactor = 4; config.peakMaxCorrelationAngle = 30; config.isotopeThresholdFactor = 4; config.monoisotopicPeakThresholdFactor = 1.5; config.isotopeMaxChargeState = 6; config.isotopeMaxNeutronCount = 5; config.collapseRadius = 15; config.useMagnitudeFilter = true; config.logDetailLevel = 1; readSecretConfigFile(config); return config; } auto_ptr createIsotopeEnvelopeEstimator() { const double abundanceCutoff = .01; const double massPrecision = .1; IsotopeCalculator isotopeCalculator(abundanceCutoff, massPrecision); IsotopeEnvelopeEstimator::Config config; config.isotopeCalculator = &isotopeCalculator; return auto_ptr(new IsotopeEnvelopeEstimator(config)); } } // namespace PeakFamilyDetectorFT::Impl::Impl(const Config& config) : config_(config) { // instantiate IsotopeEnvelopeEstimator isotopeEnvelopeEstimator_ = createIsotopeEnvelopeEstimator(); // fill in PeakDetectorMatchedFilter::Config structure PeakDetectorMatchedFilter::Config pdmfConfig = getPeakDetectorConfiguration(); pdmfConfig.isotopeEnvelopeEstimator = isotopeEnvelopeEstimator_.get(); pdmfConfig.log = config.log; // instantiate PeakDetector pdmf_ = PeakDetectorMatchedFilter::create(pdmfConfig); } void PeakFamilyDetectorFT::Impl::detect(const MZIntensityPair* begin, const MZIntensityPair* end, vector& result) { if (!begin || !end || begin==end) return; // convert mass data to frequency data auto_ptr fd = createFrequencyData(begin, end); if (!fd.get() || fd->data().empty()) throw NoDataException(); // find peaks in the frequency data peakdata::Scan scan; pdmf_->findPeaks(*fd, scan); result = scan.peakFamilies; } auto_ptr PeakFamilyDetectorFT::Impl::createFrequencyData(const MZIntensityPair* begin, const MZIntensityPair* end) const { auto_ptr fd(new FrequencyData); // convert mass/intensity pairs to frequency/intensity pairs for (const MZIntensityPair* it=end-1; it>=begin; --it) fd->data().push_back(FrequencyDatum(config_.cp.frequency(it->mz), it->intensity)); // fill in metadata fd->observationDuration(fd->observationDurationEstimatedFromData()); fd->calibrationParameters(config_.cp); fd->analyze(); // noise floor calculation must account for fact that there may be holes in mass data! fd->noiseFloor(fd->cutoffNoiseFloor()); // log if requested if (config_.log) { *config_.log << setprecision(6) << fixed << "[MassPeakDetector::createFrequencyData()]\n" << "mzLow: " << begin->mz << endl << "mzHigh: " << (end-1)->mz << endl << "A: " << config_.cp.A << endl << "B: " << config_.cp.B << endl << "observationDuration: " << fd->observationDuration() << endl << "noiseFloor: " << fd->noiseFloor() << endl << "" << endl << "# m/z freq intensity\n"; for (const MZIntensityPair* it=end-1; it>=begin; --it) *config_.log << setw(15) << it->mz << setw(15) << config_.cp.frequency(it->mz) << setw(15) << it->intensity << endl; *config_.log << "" << endl << endl; } return fd; } // // PeakFamilyDetectorFT // PWIZ_API_DECL PeakFamilyDetectorFT::PeakFamilyDetectorFT(const Config& config) : impl_(new Impl(config)) {} PWIZ_API_DECL void PeakFamilyDetectorFT::detect(const MZIntensityPair* begin, const MZIntensityPair* end, vector& result) { impl_->detect(begin, end, result); } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/peakdetect/PeakFitter.cpp0000664000175100017510000000557712664775614023262 0ustar teamcityteamcity00000000000000// // $Id: PeakFitter.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "PeakFitter.hpp" #include "pwiz/utility/math/Parabola.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace analysis { using namespace pwiz::math; // // PeakFitter // void PeakFitter::fitPeaks(const OrderedPairContainerRef& pairs, vector& indices, vector& result) const { result.resize(indices.size()); for (size_t i=0; i OrderedPairToPair(const OrderedPair& p) { return make_pair(p.x, p.y); } } // namespace void PeakFitter_Parabola::fitPeak(const OrderedPairContainerRef& pairs, size_t index, Peak& result) const { const OrderedPair* center = &pairs[index]; const OrderedPair* begin = max(center-config_.windowRadius, pairs.begin()); const OrderedPair* end = min(center+config_.windowRadius+1, pairs.end()); if ((end-begin) < 3) throw runtime_error("[PeakFitter_Parabola] Not enough samples."); vector< pair > samples; transform(begin, end, back_inserter(samples), OrderedPairToPair); Parabola p(samples); double totalIntensity = 0; double totalError2 = 0; for (const OrderedPair* it=begin; it!=end; ++it) { totalIntensity += it->y; double error = it->y - p(it->x); totalError2 += error*error; } result.mz = p.center(); result.retentionTime = 0; result.intensity = p(p.center()); result.area = totalIntensity; result.error = sqrt(totalError2/(end-begin)); // rms error const size_t dataRadius = 3; const OrderedPair* dataBegin = max(center-dataRadius, pairs.begin()); const OrderedPair* dataEnd = min(center+dataRadius+1, pairs.end()); result.data.clear(); copy(dataBegin, dataEnd, back_inserter(result.data)); } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/peakdetect/PeakExtractorTest.cpp0000664000175100017510000001365712664775614024636 0ustar teamcityteamcity00000000000000// // $Id: PeakExtractorTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "PeakExtractor.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::math; using namespace pwiz::util; using namespace pwiz::analysis; using namespace pwiz::data::peakdata; ostream* os_ = 0; const double testData_[] = { 807.9820, 0.0000, 807.9860, 0.0000, 807.9899, 0.0000, 807.9939, 0.0000, 808.9221, 0.0000, 808.9261, 0.0000, 808.9300, 0.0000, 808.9340, 0.0000, 808.9379, 46.1869, 808.9419, 68.1574, 808.9459, 74.2945, 808.9498, 67.5736, 808.9538, 55.4186, 808.9577, 0.0000, 808.9617, 0.0000, 808.9656, 0.0000, 808.9696, 0.0000, 810.3800, 0.0000, 810.3840, 0.0000, 810.3880, 0.0000, 810.3919, 0.0000, 810.3959, 0.0000, 810.3999, 72.5160, 810.4038, 450.4998, 810.4078, 1138.1459, 810.4118, 1834.3859, 810.4158, 2075.0105, 810.4197, 1699.1493, 810.4237, 1021.4493, 810.4277, 500.8886, 810.4316, 276.2554, 810.4356, 179.6894, 810.4396, 127.4826, 810.4435, 91.4053, 810.4475, 55.3596, 810.4515, 0.0000, 810.4554, 0.0000, 810.4594, 0.0000, 810.4634, 0.0000, 810.8248, 0.0000, 810.8288, 0.0000, 810.8327, 0.0000, 810.8367, 0.0000, 810.8407, 32.4939, 810.8447, 66.3772, 810.8486, 89.7902, 810.8526, 70.5686, 810.8566, 16.7061, 810.8605, 0.0000, 810.8645, 32.4340, 810.8685, 71.6267, 810.8725, 91.5372, 810.8764, 81.2383, 810.8804, 52.8255, 810.8844, 0.0000, 810.8884, 0.0000, 810.8923, 0.0000, 810.8963, 0.0000, 810.9003, 0.0000, 810.9043, 54.5496, 810.9082, 532.4702, 810.9122, 1171.1777, 810.9162, 1586.9846, 810.9202, 1490.4944, 810.9241, 979.2804, 810.9281, 434.2267, 810.9321, 162.3475, 810.9361, 128.5575, 810.9400, 134.1554, 810.9440, 123.5086, 810.9480, 88.7253, 810.9520, 48.2328, 810.9559, 0.0000, 810.9599, 0.0000, 810.9639, 0.0000, 810.9678, 0.0000, 811.3854, 0.0000, 811.3894, 0.0000, 811.3934, 0.0000, 811.3973, 0.0000, 811.4013, 9.2748, 811.4053, 133.5402, 811.4093, 298.1690, 811.4132, 463.7706, 811.4172, 554.1553, 811.4212, 503.8234, 811.4252, 333.9661, 811.4292, 149.2269, 811.4331, 48.4688, 811.4371, 0.0000, 811.4411, 0.0000, 811.4451, 0.0000, 811.4491, 0.0000, 811.7675, 0.0000, 811.7715, 0.0000, 811.7755, 0.0000, 811.7795, 0.0000, 811.7835, 41.8127, 811.7874, 69.9106, 811.7914, 87.5734, 811.7954, 91.7424, 811.7994, 90.7267, 811.8034, 87.8043, 811.8074, 74.6657, 811.8113, 46.1904, 811.8153, 0.0000, 811.8193, 0.0000, 811.8233, 0.0000, 811.8273, 0.0000, 812.3853, 0.0000, 812.3893, 0.0000, 812.3933, 0.0000, 812.3972, 0.0000, 812.4012, 23.7360, 812.4052, 85.1701, 812.4092, 124.7133, 812.4132, 118.7524, 812.4172, 69.4944, 812.4212, 9.8729, 812.4252, 0.0000, 812.4292, 0.0000, 812.4331, 0.0000, 812.4371, 0.0000 }; const size_t testDataSize_ = sizeof(testData_)/sizeof(double); void test() { if (os_) *os_ << "test()\n"; shared_ptr noiseCalculator(new NoiseCalculator_2Pass); PeakFinder_SNR::Config pfsnrConfig; pfsnrConfig.windowRadius = 2; pfsnrConfig.zValueThreshold = 2; shared_ptr peakFinder(new PeakFinder_SNR(noiseCalculator, pfsnrConfig)); PeakFitter_Parabola::Config pfpConfig; pfpConfig.windowRadius = 1; // (windowRadius != 1) is not good for real data shared_ptr peakFitter(new PeakFitter_Parabola(pfpConfig)); PeakExtractor peakExtractor(peakFinder, peakFitter); OrderedPairContainerRef data(testData_, testData_+testDataSize_); vector peaks; peakExtractor.extractPeaks(data, peaks); if (os_) { *os_ << "peaks: " << peaks.size() << endl; copy(peaks.begin(), peaks.end(), ostream_iterator(*os_, "\n")); } const double epsilon = .01; unit_assert(peaks.size() == 3); unit_assert_equal(peaks[0].mz, 810.41, epsilon); unit_assert_equal(peaks[1].mz, 810.91, epsilon); unit_assert_equal(peaks[2].mz, 811.41, epsilon); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/peakdetect/PeakelGrower.cpp0000664000175100017510000000615212664775614023601 0ustar teamcityteamcity00000000000000// // $Id: PeakelGrower.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "PeakelGrower.hpp" #include #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace analysis { using namespace pwiz::data::peakdata; // // PeakelGrower // void PeakelGrower::sowPeaks(PeakelField& peakelField, const vector& peaks) const { for (vector::const_iterator it=peaks.begin(); it!= peaks.end(); ++it) sowPeak(peakelField, *it); } void PeakelGrower::sowPeaks(PeakelField& peakelField, const vector< vector >& peaks) const { for (vector< vector >::const_iterator it=peaks.begin(); it!= peaks.end(); ++it) sowPeaks(peakelField, *it); } // // PeakelGrower_Proximity // PeakelGrower_Proximity::PeakelGrower_Proximity(const Config& config) : config_(config) {} namespace { //#define PEAKELGROWER_DEBUG void insertNewPeakel(PeakelField& peakelField, const Peak& peak) { PeakelPtr peakel(new Peakel); peakel->mz = peak.mz; peakel->retentionTime = peak.retentionTime; peakel->peaks.push_back(peak); peakelField.insert(peakel); #ifdef PEAKELGROWER_DEBUG cout << "insertNewPeakel():\n " << *peakel << endl; #endif } void updatePeakel(Peakel& peakel, const Peak& peak) { peakel.peaks.push_back(peak); #ifdef PEAKELGROWER_DEBUG cout << "updatePeakel():\n " << peakel << endl; #endif } } // namespace void PeakelGrower_Proximity::sowPeak(PeakelField& peakelField, const Peak& peak) const { vector candidates = peakelField.find(peak.mz, config_.mzTolerance, RTMatches_Contains(peak.retentionTime, config_.rtTolerance)); if (candidates.empty()) insertNewPeakel(peakelField, peak); else if (candidates.size() == 1) updatePeakel(*candidates.front(), peak); else { if (config_.log) { *config_.log << "[PeakelGrower_Proximity::sowPeak()] Warning: multiple candidate peakels.\n" << " peak: " << peak << " candidates: " << candidates.size() << endl; for (vector::const_iterator it=candidates.begin(); it!=candidates.end(); ++it) *config_.log << **it << endl; *config_.log << endl; } } } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/peakdetect/PeakFamilyDetectorFTTest.cpp0000664000175100017510000000456412664775614026025 0ustar teamcityteamcity00000000000000// // $Id: PeakFamilyDetectorFTTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "PeakFamilyDetectorFT.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::analysis; using namespace pwiz::data; using namespace pwiz::data::peakdata; using namespace pwiz; using namespace pwiz::msdata; ostream* os_ = 0; extern double peakFamilyDetectorFTTestData_[]; extern int peakFamilyDetectorFTTestDataSize_; void test() { // instantiate PeakFamilyDetectorFT PeakFamilyDetectorFT::Config config; config.log = os_; config.cp = CalibrationParameters::thermo_FT(); PeakFamilyDetectorFT detector(config); // detect vector result; const MZIntensityPair* begin = reinterpret_cast(&peakFamilyDetectorFTTestData_[0]); const MZIntensityPair* end = begin + peakFamilyDetectorFTTestDataSize_/2; detector.detect(begin, end, result); if (os_) { *os_ << setprecision(10) << "result: " << result.size() << endl; copy(result.begin(), result.end(), ostream_iterator(*os_, "\n")); } unit_assert(result.size() == 1); unit_assert_equal(result[0].mzMonoisotopic, 810.4148, .005); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; if (os_) *os_ << "PeakFamilyDetectorFTTest\n"; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/peakdetect/msextract.cpp0000775000175100017510000003715312664775614023234 0ustar teamcityteamcity00000000000000// // $Id: msextract.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Kate Hoff // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Cnter, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "FeatureDetectorSimple.hpp" #include "FeatureDetectorPeakel.hpp" #include "PeakFamilyDetectorFT.hpp" #include "FeatureModeler.hpp" #include "pwiz/analysis/passive/MSDataCache.hpp" #include "pwiz/analysis/spectrum_processing/SpectrumListFactory.hpp" #include "pwiz/data/msdata/Serializer_mzML.hpp" #include "pwiz/data/msdata/MSDataFile.hpp" #include "pwiz/data/msdata/SpectrumIterator.hpp" #include "pwiz/data/msdata/SpectrumInfo.hpp" #include "pwiz/data/misc/PeakData.hpp" #include "pwiz/utility/minimxml/XMLWriter.hpp" #include "boost/program_options.hpp" #include "boost/filesystem/path.hpp" #include "boost/filesystem/convenience.hpp" #include "boost/iostreams/positioning.hpp" #include "boost/tuple/tuple_comparison.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::cv; using namespace pwiz::analysis; using namespace pwiz::data; using namespace pwiz::data::peakdata; using namespace pwiz::msdata; using namespace pwiz::util; using namespace pwiz::minimxml; namespace bfs = boost::filesystem; struct Config { vector filenames; vector filters; string featureDetectorImplementation; string outputPath; bool writeFeatureFile; bool writeTSV; bool writeLog; bool useFeatureModeler; FeatureDetectorPeakel::Config fdpConfig; int maxChargeState; Config() : featureDetectorImplementation("Simple"), outputPath("."), writeFeatureFile(true), writeTSV(true), writeLog(false), useFeatureModeler(false), maxChargeState(6) {} void write_program_options_config(ostream& os) const; string outputFileName(const string& inputFileName, const string& extension) const; }; void Config::write_program_options_config(ostream& os) const { // write out configuration options in format parseable by program_options os << "featureDetectorImplementation=" << featureDetectorImplementation << endl; os << "useFeatureModeler=" << useFeatureModeler << endl; os << "noiseCalculator_2Pass.zValueCutoff=" << fdpConfig.noiseCalculator_2Pass.zValueCutoff << endl; os << "peakFinder_SNR.windowRadius=" << fdpConfig.peakFinder_SNR.windowRadius << endl; os << "peakFinder_SNR.zValueThreshold=" << fdpConfig.peakFinder_SNR.zValueThreshold << endl; os << "peakFinder_SNR.preprocessWithLogarithm=" << fdpConfig.peakFinder_SNR.preprocessWithLogarithm << endl; os << "peakFitter_Parabola.windowRadius=" << fdpConfig.peakFitter_Parabola.windowRadius << endl; os << "peakelGrower_Proximity.mzTolerance=" << fdpConfig.peakelGrower_Proximity.mzTolerance << endl; os << "peakelGrower_Proximity.rtTolerance=" << fdpConfig.peakelGrower_Proximity.rtTolerance << endl; os << "peakelPicker_Basic.minCharge=" << fdpConfig.peakelPicker_Basic.minCharge << endl; os << "peakelPicker_Basic.maxCharge=" << fdpConfig.peakelPicker_Basic.maxCharge << endl; os << "peakelPicker_Basic.minMonoisotopicPeakelSize=" << fdpConfig.peakelPicker_Basic.minMonoisotopicPeakelSize << endl; os << "peakelPicker_Basic.mzTolerance=" << fdpConfig.peakelPicker_Basic.mzTolerance << endl; os << "peakelPicker_Basic.rtTolerance=" << fdpConfig.peakelPicker_Basic.rtTolerance << endl; os << "peakelPicker_Basic.minPeakelCount=" << fdpConfig.peakelPicker_Basic.minPeakelCount << endl; os << "#maxChargeState=TODO" << endl; // TODO } ostream& operator<<(ostream& os, const Config& config) { config.write_program_options_config(os); os << "filenames:\n "; copy(config.filenames.begin(), config.filenames.end(), ostream_iterator(os, "\n ")); os << endl; os << "filters:\n "; copy(config.filters.begin(), config.filters.end(), ostream_iterator(os,"\n ")); os << endl; return os; } string Config::outputFileName(const string& inputFileName, const string& extension) const { string newFilename = bfs::basename(inputFileName) + extension; bfs::path fullPath = bfs::path(this->outputPath) / newFilename; return fullPath.string(); } Config parseCommandLine(int argc, char* argv[]) { namespace po = boost::program_options; Config config; ostringstream usage; usage << "Usage: msextract [options] [file]\n" << endl; // input file of config parameters string configFilename; bool printDefaultConfig = false; // define command line options po::options_description od_config("Options"); od_config.add_options() ("config,c", po::value(&configFilename), ": specify file of config options, in format optionName=optionValue") ("defaults,d", po::value(&printDefaultConfig)->zero_tokens(), ": print configuration defaults") ("outputPath,o", po::value(&config.outputPath)->default_value(config.outputPath), ": specify output path") ("featureDetectorImplementation,f", po::value(&config.featureDetectorImplementation)->default_value(config.featureDetectorImplementation), ": specify implementation of FeatureDetector to use. Options: Simple, PeakelFarmer") ("useFeatureModeler,m", po::value(&config.useFeatureModeler)->default_value(config.useFeatureModeler)->zero_tokens(), ": post-process with feature modeler") ("writeFeatureFile", po::value(&config.writeFeatureFile)->default_value(config.writeFeatureFile), ": write xml representation of detected features (.features file) ") ("writeTSV", po::value(&config.writeTSV)->default_value(config.writeTSV), ": write tab-separated file") ("writeLog", po::value(&config.writeLog)->default_value(config.writeLog), ": write log file (for debugging)") ("filter", po::value< vector >(&config.filters), (": add a spectrum list filter\n" + SpectrumListFactory::usage()).c_str()) ; po::options_description od_config_peakel("FeatureDetectorPeakel Options"); od_config_peakel.add_options() ("noiseCalculator_2Pass.zValueCutoff", po::value(&config.fdpConfig.noiseCalculator_2Pass.zValueCutoff)->default_value(config.fdpConfig.noiseCalculator_2Pass.zValueCutoff), "") ("peakFinder_SNR.windowRadius", po::value(&config.fdpConfig.peakFinder_SNR.windowRadius)->default_value(config.fdpConfig.peakFinder_SNR.windowRadius), "") ("peakFinder_SNR.zValueThreshold", po::value(&config.fdpConfig.peakFinder_SNR.zValueThreshold)->default_value(config.fdpConfig.peakFinder_SNR.zValueThreshold), "") ("peakFinder_SNR.preprocessWithLogarithm", po::value(&config.fdpConfig.peakFinder_SNR.preprocessWithLogarithm)->default_value(config.fdpConfig.peakFinder_SNR.preprocessWithLogarithm), "") ("peakFitter_Parabola.windowRadius", po::value(&config.fdpConfig.peakFitter_Parabola.windowRadius)->default_value(config.fdpConfig.peakFitter_Parabola.windowRadius), "") ("peakelGrower_Proximity.mzTolerance", po::value(&config.fdpConfig.peakelGrower_Proximity.mzTolerance), "") ("peakelGrower_Proximity.rtTolerance", po::value(&config.fdpConfig.peakelGrower_Proximity.rtTolerance)->default_value(config.fdpConfig.peakelGrower_Proximity.rtTolerance), "") ("peakelPicker_Basic.minCharge", po::value(&config.fdpConfig.peakelPicker_Basic.minCharge)->default_value(config.fdpConfig.peakelPicker_Basic.minCharge), "") ("peakelPicker_Basic.maxCharge", po::value(&config.fdpConfig.peakelPicker_Basic.maxCharge)->default_value(config.fdpConfig.peakelPicker_Basic.maxCharge), "") ("peakelPicker_Basic.minMonoisotopicPeakelSize", po::value(&config.fdpConfig.peakelPicker_Basic.minMonoisotopicPeakelSize)->default_value(config.fdpConfig.peakelPicker_Basic.minMonoisotopicPeakelSize), "") ("peakelPicker_Basic.mzTolerance", po::value(&config.fdpConfig.peakelPicker_Basic.mzTolerance), "") ("peakelPicker_Basic.rtTolerance", po::value(&config.fdpConfig.peakelPicker_Basic.rtTolerance)->default_value(config.fdpConfig.peakelPicker_Basic.rtTolerance), "") ("peakelPicker_Basic.minPeakelCount", po::value(&config.fdpConfig.peakelPicker_Basic.minPeakelCount)->default_value(config.fdpConfig.peakelPicker_Basic.minPeakelCount), "") ; // append options to usage string usage << od_config << endl << od_config_peakel; usage << "\n\nExamples:\n" << "\n" << "# print default configuration parameters to config.txt\n" << "msextract -d > config.txt\n" << "\n" << "# run using parameters in config.txt, output in outputdir\n" << "msextract -c config.txt -o outputdir file1.mzML file2.mzML\n" << "\n" << "# filters: select scan numbers\n" << "msextract file1.mzML --filter \"scanNumber [500,1000]\"\n" << endl << "\n"; // handle positional args const char* label_args = "args"; po::options_description od_args; od_args.add_options()(label_args, po::value< vector >(), ""); po::positional_options_description pod_args; pod_args.add(label_args, -1); po::options_description od_parse; od_parse.add(od_config).add(od_config_peakel).add(od_args); // parse command line po::variables_map vm; po::store(po::command_line_parser(argc, (char**)argv). options(od_parse).positional(pod_args).run(), vm); po::notify(vm); if (configFilename.size() > 0) { ifstream is(configFilename.c_str()); if (is) { cout << "Reading configuration file " << configFilename << "\n\n"; po::store(parse_config_file(is, od_parse), vm); po::notify(vm); } else { cout << "Unable to read configuration file " << configFilename << "\n\n"; } } // get filenames if (vm.count(label_args)) config.filenames = vm[label_args].as< vector >(); // special handling if (printDefaultConfig) { Config defaultConfig; defaultConfig.write_program_options_config(cout); throw runtime_error(""); } if (config.filenames.empty()) throw runtime_error(usage.str()); return config; } shared_ptr createFeatureDetector(const MSData& msd, const Config& config, ostream* log) { if (config.featureDetectorImplementation == "Simple") { PeakFamilyDetectorFT::Config pfd_config; //pfd_config.log = log; // TODO: too much output! // set calibration parameters bool done = false; vector::const_iterator icp_it = msd.instrumentConfigurationPtrs.begin(); while (!done && icp_it != msd.instrumentConfigurationPtrs.end()) { if ((*icp_it)->componentList.analyzer(0).hasCVParam(MS_FT_ICR)) { pfd_config.cp = CalibrationParameters::thermo_FT(); if (log) *log << "thermo_FT params set" << endl; done = true; } else if ((*icp_it)->componentList.analyzer(0).hasCVParam(MS_orbitrap)) { pfd_config.cp = CalibrationParameters::thermo_Orbitrap(); if (log) *log << "thermo_Orbitrap params set" << endl; done = true; } else ++icp_it; } if (!done) throw runtime_error("[FeatureDetectorSimple] Unsupported mass analyzer."); // pfd_config.isotopeMaxChargeState = config.maxChargeState; // TODO: Kate, why is this disabled? shared_ptr detector(new PeakFamilyDetectorFT(pfd_config)); return shared_ptr(new FeatureDetectorSimple(detector)); } else if (config.featureDetectorImplementation == "PeakelFarmer") { FeatureDetectorPeakel::Config temp = config.fdpConfig; temp.log = log; // specific to the file we're processing return FeatureDetectorPeakel::create(temp); } else { throw runtime_error(("[msextract] Unsupported featureDetectorImplementation: " + config.featureDetectorImplementation).c_str()); } } void writeOutputFiles(const FeatureField& features, const string& filename, const Config& config) { if (config.writeFeatureFile) { FeatureFile featureFile; copy(features.begin(), features.end(), back_inserter(featureFile.features)); ofstream ofs(config.outputFileName(filename, ".features").c_str()); XMLWriter writer(ofs); featureFile.write(writer); } if (config.writeTSV) { ofstream ofs(config.outputFileName(filename, ".features.tsv").c_str()); ofs << "# mzMonoisotopic\tretentionTime\tretentionTimeMin\tretentionTimeMax\ttotalIntensity\tscore\terror\n"; for (FeatureField::const_iterator it=features.begin(); it!=features.end(); ++it) ofs << (*it)->mz << "\t" << (*it)->retentionTime << "\t" << (*it)->retentionTimeMin() << "\t" << (*it)->retentionTimeMax() << "\t" << (*it)->totalIntensity << "\t" << (*it)->score << "\t" << (*it)->error << "\n"; } } void processFile(const string& filename, const Config& config) { shared_ptr log; if (config.writeLog) log = shared_ptr(new ofstream(config.outputFileName(filename,".log").c_str())); MSDataFile msd(filename); SpectrumListFactory::wrap(msd, config.filters); shared_ptr fd = createFeatureDetector(msd, config, log.get()); FeatureField features; fd->detect(msd, features); FeatureField* features_to_output = &features; FeatureField features_modeled; if (config.useFeatureModeler) { FeatureModeler_Gaussian fm; fm.fitFeatures(features, features_modeled); features_to_output = &features_modeled; } writeOutputFiles(*features_to_output, filename, config); } void go(Config& config) { bfs::create_directories(config.outputPath); // process each file for (vector::const_iterator it=config.filenames.begin(); it!=config.filenames.end(); ++it) { try { processFile(*it, config); } catch (exception& e) { cout << e.what() << endl; cout << "Error processing file " << *it << endl; } catch (...) { cout << "Unknown error.\n"; cout << "Error processing file " << *it << endl; } } } int main(int argc, char* argv[]) { try { Config config = parseCommandLine(argc, argv); cout << "Config:\n" << config << endl; go(config); return 0; } catch (exception& e) { cout << e.what() << endl; } catch (...) { cout << "[msextract.cpp::main()] Abnormal termination.\n"; } return 1; } pwiz/pwiz/analysis/peakdetect/FeatureDetectorPeakel.hpp0000664000175100017510000000464412664775614025432 0ustar teamcityteamcity00000000000000// // $Id: FeatureDetectorPeakel.hpp 1191 2009-08-14 19:33:05Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _FEATUREDETECTORPEAKEL_HPP_ #define _FEATUREDETECTORPEAKEL_HPP_ #include "FeatureDetector.hpp" #include "PeakExtractor.hpp" #include "PeakelGrower.hpp" #include "PeakelPicker.hpp" namespace pwiz { namespace analysis { /// /// FeatureDetectorPeakel implements a 'template method', delegating to 'strategies' /// encapsulated by the following interfaces: /// PeakExtractor /// PeakelGrower /// PeakelPicker /// class PWIZ_API_DECL FeatureDetectorPeakel : public FeatureDetector { public: typedef pwiz::msdata::MSData MSData; FeatureDetectorPeakel(boost::shared_ptr peakExtractor, boost::shared_ptr peakelGrower, boost::shared_ptr peakelPicker); virtual void detect(const MSData& msd, FeatureField& result) const; /// convenience construction struct Config { std::ostream* log; // propagates to sub-objects during create() NoiseCalculator_2Pass::Config noiseCalculator_2Pass; PeakFinder_SNR::Config peakFinder_SNR; PeakFitter_Parabola::Config peakFitter_Parabola; PeakelGrower_Proximity::Config peakelGrower_Proximity; PeakelPicker_Basic::Config peakelPicker_Basic; Config() : log(0) {} }; static boost::shared_ptr create(Config config); private: boost::shared_ptr peakExtractor_; boost::shared_ptr peakelGrower_; boost::shared_ptr peakelPicker_; }; } // namespace analysis } // namespace pwiz #endif // _FEATUREDETECTORPEAKEL_HPP_ pwiz/pwiz/analysis/peakdetect/FeatureDetectorSimpleTest.cpp0000664000175100017510000001057612664775614026316 0ustar teamcityteamcity00000000000000// // $Id: FeatureDetectorSimpleTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Kate Hoff // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Cnter, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "FeatureDetectorSimple.hpp" #include "PeakFamilyDetectorFT.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/data/msdata/MSDataFile.hpp" #include "pwiz/data/msdata/Serializer_mzML.hpp" #include "boost/iostreams/positioning.hpp" #include "boost/filesystem/path.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::analysis; using namespace pwiz::data; using namespace pwiz::data::peakdata; using namespace pwiz::msdata; namespace bfs = boost::filesystem; ostream* os_ = 0; double mz_epsilon = .005; // tolerance for mz differences double rt_epsilon = 10; // tolerance for rt differences struct mzrtEqual { mzrtEqual(FeaturePtr a_) : a(a_) {} bool operator()(FeaturePtr b) const // should be enough info to uniquely identify a feature { return fabs(a->mz-b->mz) < mz_epsilon && fabs(a->retentionTime - b->retentionTime) < rt_epsilon; } FeaturePtr a; }; void testFeatureDetectorSimple(const bfs::path& datadir) { if (os_) *os_ << "testFeatureDetectorSimple() ... " << endl; // instantiate PeakFamilyDetectorFT // (from PeakFamilyDetectorFTTest.cpp) ostream* os_log_ = 0; // don't log peak family detection PeakFamilyDetectorFT::Config config; config.log = os_log_; config.cp = CalibrationParameters::thermo_FT(); boost::shared_ptr detector(new PeakFamilyDetectorFT(config)); FeatureDetectorSimple fds(detector); // instantiate MSData from test file MSDataFile msd((datadir / "FeatureDetectorTest_Bombesin.mzML").string()); FeatureField output_features; fds.detect(msd, output_features); // instantiate the bombesin +2 feature that we know is correct, with calculated mzMonoisotopic and eyeballed retentionTime FeaturePtr bombesin2_truth(new Feature()); bombesin2_truth->mz = 810.4148; bombesin2_truth->retentionTime = 1866; FeatureField::iterator bombesin2_hopeful = find_if(output_features.begin(), output_features.end(), mzrtEqual(bombesin2_truth)); // assert that it is found, correctly, in the data unit_assert(bombesin2_hopeful != output_features.end()); if (os_) *os_ << "\n[FeatureDetectorSimple] Bombesin detected at charge state +2 ... " << endl << *bombesin2_hopeful << endl; // do the same for the +3 feature FeaturePtr bombesin3_truth(new Feature()); bombesin3_truth->mz = 540.6123; bombesin3_truth->retentionTime = 1866; FeatureField::iterator bombesin3_hopeful = find_if(output_features.begin(), output_features.end(), mzrtEqual(bombesin3_truth)); // assert that it is found, correctly, in the data unit_assert(bombesin3_hopeful != output_features.end()); if (os_) *os_ << "\n[FeatureDetectorSimple] Bombesin detected at charge state +3 ... " << endl << *bombesin3_hopeful << endl; return; } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { bfs::path datadir = "."; for (int i=1; i // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "FeatureDetectorPeakel.hpp" #include "pwiz/analysis/passive/MSDataCache.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace analysis { using namespace pwiz::msdata; shared_ptr FeatureDetectorPeakel::create(FeatureDetectorPeakel::Config config) { // note: config passed by value, allowing us to propagate the log pointers if (config.log) { config.peakFinder_SNR.log = config.log; config.peakelGrower_Proximity.log = config.log; config.peakelPicker_Basic.log = config.log; } shared_ptr noiseCalculator( new NoiseCalculator_2Pass(config.noiseCalculator_2Pass)); shared_ptr peakFinder(new PeakFinder_SNR(noiseCalculator, config.peakFinder_SNR)); shared_ptr peakFitter(new PeakFitter_Parabola(config.peakFitter_Parabola)); shared_ptr peakExtractor(new PeakExtractor(peakFinder, peakFitter)); shared_ptr peakelGrower(new PeakelGrower_Proximity(config.peakelGrower_Proximity)); shared_ptr peakelPicker(new PeakelPicker_Basic(config.peakelPicker_Basic)); return shared_ptr( new FeatureDetectorPeakel(peakExtractor, peakelGrower, peakelPicker)); } FeatureDetectorPeakel::FeatureDetectorPeakel(shared_ptr peakExtractor, shared_ptr peakelGrower, shared_ptr peakelPicker) : peakExtractor_(peakExtractor), peakelGrower_(peakelGrower), peakelPicker_(peakelPicker) { if (!peakExtractor.get() || !peakelGrower.get() || !peakelPicker.get()) throw runtime_error("[FeatureDetectorPeakel] Null pointer"); } namespace { struct SetPeakMetadata { const SpectrumInfo& spectrumInfo; SetPeakMetadata(const SpectrumInfo& _spectrumInfo) : spectrumInfo(_spectrumInfo) {} void operator()(Peak& peak) { peak.id = spectrumInfo.scanNumber; peak.retentionTime = spectrumInfo.retentionTime; } }; vector< vector > extractPeaks(const MSData& msd, const PeakExtractor& peakExtractor) { MSDataCache msdCache; msdCache.open(msd); const size_t spectrumCount = msdCache.size(); vector< vector > result(spectrumCount); for (size_t index=0; index& peaks = result[index]; peakExtractor.extractPeaks(spectrumInfo.data, peaks); for_each(peaks.begin(), peaks.end(), SetPeakMetadata(spectrumInfo)); /* TODO: logging if (os_) { *os_ << "index: " << index << endl; *os_ << "peaks: " << peaks.size() << endl; copy(peaks.begin(), peaks.end(), ostream_iterator(*os_, "\n")); } */ } return result; } } // namespace void FeatureDetectorPeakel::detect(const MSData& msd, FeatureField& result) const { vector< vector > peaks = extractPeaks(msd, *peakExtractor_); PeakelField peakelField; peakelGrower_->sowPeaks(peakelField, peaks); peakelPicker_->pick(peakelField, result); } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/peakdetect/PeakFamilyDetector.cpp0000664000175100017510000000242112664775614024721 0ustar teamcityteamcity00000000000000// // $Id: PeakFamilyDetector.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "PeakFamilyDetector.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace analysis { PWIZ_API_DECL void PeakFamilyDetector::detect(const vector& data, vector& result) { if (data.empty()) return; detect(&data[0], &data[0] + data.size(), result); } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/peakdetect/FeatureModelerTest.cpp0000664000175100017510000000662112664775614024756 0ustar teamcityteamcity00000000000000// // $Id: FeatureModelerTest.cpp 6141 2014-05-05 21:03:47Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "FeatureModeler.hpp" #include "pwiz/utility/misc/unit.hpp" #include "boost/filesystem/path.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::analysis; using namespace pwiz::data::peakdata; namespace bfs = boost::filesystem; ostream* os_ = 0; FeaturePtr getFeature(const string& filename) { std::ifstream is(filename.c_str()); if (!is) throw runtime_error(("Unable to open file " + filename).c_str()); FeaturePtr feature(new Feature); is >> *feature; return feature; } void testGaussian_Bombesin2(const Feature& bombesin2) { if (os_) *os_ << "testGaussian_Bombesin2()\n"; unit_assert(bombesin2.peakels.size() == 5); if (os_) *os_ << "before:\n" << bombesin2; FeatureModeler_Gaussian fm; Feature result; fm.fitFeature(bombesin2, result); if (os_) *os_ << "after:\n" << result << endl; } void testGaussian_Bombesin3(const Feature& bombesin3) { if (os_) *os_ << "testGaussian_Bombesin3()\n"; unit_assert(bombesin3.peakels.size() == 3); if (os_) *os_ << "before:\n" << bombesin3; FeatureModeler_Gaussian fm; Feature result; fm.fitFeature(bombesin3, result); if (os_) *os_ << "after:\n" << result << endl; } void testMulti(const FeatureField& ff) { if (os_) *os_ << "testMulti()\n"; FeatureField result; unit_assert(result.empty()); FeatureModeler_Gaussian fm; fm.fitFeatures(ff, result); if (os_) *os_ << result << endl; unit_assert(result.size() == 2); } void test(const bfs::path& datadir) { FeaturePtr bombesin2 = getFeature((datadir / "Bombesin2.feature").string()); FeaturePtr bombesin3 = getFeature((datadir / "Bombesin3.feature").string()); testGaussian_Bombesin2(*bombesin2); testGaussian_Bombesin3(*bombesin3); FeatureField ff; ff.insert(bombesin2); ff.insert(bombesin3); testMulti(ff); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { bfs::path datadir = "."; for (int i=1; i // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "PeakelPicker.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::analysis; using namespace pwiz::data::peakdata; ostream* os_ = 0; shared_ptr createToyPeakelField() { // // 0 1 2 // |.....:.....|.....:.....| // 10 x x o // 20 x x o x // 30 x x o x // 40 x x o <-- feature z==3, noise Peakel at mono+.5 // 50 // 60 x x // 70 x x x // 80 x x x // 90 x <-- feature z==2 // shared_ptr toy(new PeakelField); PeakelPtr battery(new Peakel(Peak(0,10))); battery->peaks.push_back(Peak(0, 20)); battery->peaks.push_back(Peak(0, 30)); battery->peaks.push_back(Peak(0, 40)); toy->insert(battery); battery.reset(new Peakel(Peak(1./3 + 1e-6, 10))); battery->peaks.push_back(Peak(1./3, 20)); battery->peaks.push_back(Peak(1./3, 30)); battery->peaks.push_back(Peak(1./3, 40)); toy->insert(battery); battery.reset(new Peakel(Peak(.5, 10))); battery->peaks.push_back(Peak(.5, 20)); battery->peaks.push_back(Peak(.5, 30)); battery->peaks.push_back(Peak(.5, 40)); toy->insert(battery); battery.reset(new Peakel(Peak(2./3, 20))); battery->peaks.push_back(Peak(2./3, 30)); toy->insert(battery); battery.reset(new Peakel(Peak(1./3, 60))); battery->peaks.push_back(Peak(1./3, 70)); battery->peaks.push_back(Peak(1./3, 80)); battery->peaks.push_back(Peak(1./3, 90)); toy->insert(battery); battery.reset(new Peakel(Peak(1./3 + .5, 60))); battery->peaks.push_back(Peak(1./3 + .5, 70)); battery->peaks.push_back(Peak(1./3 + .5, 80)); toy->insert(battery); battery.reset(new Peakel(Peak(1./3 + 1, 70))); battery->peaks.push_back(Peak(1./3 + 1, 80)); toy->insert(battery); return toy; } void testToy() { PeakelPicker_Basic::Config config; // TODO: specify parameters? if (os_) { *os_ << "testToy()\n"; config.log = os_; } PeakelPicker_Basic peterPiper(config); shared_ptr peakels = createToyPeakelField(); unit_assert(peakels->size() == 7); FeatureField peck; peterPiper.pick(*peakels, peck); unit_assert(peck.size() == 2); unit_assert(peakels->size() == 1); FeatureField::const_iterator it = peck.begin(); unit_assert((*it)->mz == 0); unit_assert((*it)->charge == 3); unit_assert_equal((*it)->retentionTime, 25, 20); ++it; unit_assert((*it)->mz == 1./3); unit_assert((*it)->charge == 2); unit_assert_equal((*it)->retentionTime, 75, 20); } void test() { testToy(); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/peakdetect/PeakFinderTest.cpp0000664000175100017510000000756612664775614024074 0ustar teamcityteamcity00000000000000// // $Id: PeakFinderTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "PeakFinder.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::math; using namespace pwiz::util; using namespace pwiz::analysis; ostream* os_ = 0; double testNoise_[] = // generated ~ N(10,1) { 0, 10.2134, 1, 9.50442, 2, 11.5754, 3, 8.9408, 4, 11.8393, 5, 11.8858, 6, 10.6047, 7, 9.63402, 8, 9.42174, 9, 9.36562, 10, 11.0297, 11, 10.7241, 12, 9.88493, 13, 10.6358, 14, 6.99061, 15, 9.08698, 16, 13.2407, 17, 9.11359, 18, 12.5566, 19, 9.42665, 20, 10.8823, 21, 11.3452, 22, 12.7695, 23, 9.48237, 24, 10.4651, 25, 9.87172, 26, 8.21869, 27, 10.1641, 28, 10.2608, 29, 9.20198, 30, 10.0615, 31, 10.0762, 32, 9.56936, 33, 10.2306, 34, 11.2333, 35, 9.27828, 36, 10.5381, 37, 8.01883, 38, 11.1455, 39, 9.70199, 40, 9.00168, 41, 8.51621, 42, 10.9232, 43, 10.2107, 44, 10.4026, 45, 9.43944, 46, 11.3842, 47, 9.39058, 48, 9.56328, 49, 9.09075, 50, 10.0799, 51, 8.35904, 52, 9.95105, 53, 8.86625, 54, 9.18384, 55, 10.6562, 56, 9.65414, 57, 9.48778, 58, 10.4029, 59, 10.746, 60, 9.51285, 61, 8.28112, 62, 10.8551, 63, 10.1733, 64, 9.65835, 65, 12.0004, 66, 10.5445, 67, 10.1626, 68, 12.6242, 69, 11.8353, 70, 10.8273, 71, 8.33673, 72, 9.82429, 73, 9.51358, 74, 9.30484, 75, 11.55, 76, 11.1051, 77, 9.64263, 78, 11.4417, 79, 10.317, 80, 9.51919, 81, 10.1948, 82, 9.49461, 83, 10.4654, 84, 10.0316, 85, 9.67727, 86, 10.0763, 87, 9.73844, 88, 10.396, 89, 10.9456, 90, 8.89552, 91, 10.0711, 92, 8.91056, 93, 10.3877, 94, 8.92218, 95, 8.58656, 96, 9.43114, 97, 7.82059, 98, 10.0535, 99, 8.1854 }; // testNoise_ void addSignal(OrderedPair* p) { (p-2)->y += 3; (p-1)->y += 5; p->y += 6; (p+1)->y += 5; (p+2)->y += 3; } vector createTestData() { vector data; copy(testNoise_, testNoise_+sizeof(testNoise_)/sizeof(double), back_inserter(data)); addSignal((OrderedPair*)&data[50]); addSignal((OrderedPair*)&data[100]); addSignal((OrderedPair*)&data[150]); return data; } void test_SNR() { if (os_) *os_ << "test_SNR()\n"; shared_ptr noiseCalculator(new NoiseCalculator_2Pass); PeakFinder_SNR::Config config; config.windowRadius = 2; config.log = os_; PeakFinder_SNR peakFinder(noiseCalculator, config); vector data = createTestData(); vector peakIndices; peakFinder.findPeaks(data, peakIndices); if (os_) { *os_ << "peakIndices: " << peakIndices.size() << endl; copy(peakIndices.begin(), peakIndices.end(), ostream_iterator(*os_, "\n")); } unit_assert(peakIndices.size() == 3); unit_assert(peakIndices[0] == 25); unit_assert(peakIndices[1] == 50); unit_assert(peakIndices[2] == 75); } void test() { test_SNR(); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/peakdetect/Noise.hpp0000664000175100017510000000363512664775614022277 0ustar teamcityteamcity00000000000000// // $Id: Noise.hpp 1191 2009-08-14 19:33:05Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _NOISECALCULATOR_HPP_ #define _NOISECALCULATOR_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/utility/math/OrderedPair.hpp" namespace pwiz { namespace analysis { struct PWIZ_API_DECL Noise { double mean; double variance; double standardDeviation; Noise(double m=0, double sd=0); double pvalue(double value) const; // pvalue for a value, given this noise distribution }; class PWIZ_API_DECL NoiseCalculator { public: virtual Noise calculateNoise(const math::OrderedPairContainerRef& pairs) const = 0; virtual ~NoiseCalculator(){} }; class PWIZ_API_DECL NoiseCalculator_2Pass : public NoiseCalculator { public: struct Config { double zValueCutoff; Config() : zValueCutoff(1) {} }; NoiseCalculator_2Pass(const Config& config = Config()); virtual Noise calculateNoise(const math::OrderedPairContainerRef& pairs) const; private: Config config_; }; } // namespace analysis } // namespace pwiz #endif // _NOISECALCULATOR_HPP_ pwiz/pwiz/analysis/peakdetect/FeatureDetectorTuningTest.cpp0000664000175100017510000002057112664775614026325 0ustar teamcityteamcity00000000000000// // $Id: FeatureDetectorTuningTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "PeakExtractor.hpp" #include "PeakelGrower.hpp" #include "PeakelPicker.hpp" #include "pwiz/data/msdata/MSDataFile.hpp" #include "pwiz/analysis/passive/MSDataCache.hpp" #include "pwiz/utility/misc/unit.hpp" #include "boost/filesystem/path.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::analysis; using namespace pwiz::data; using namespace pwiz::data::peakdata; using namespace pwiz::msdata; namespace bfs = boost::filesystem; ostream* os_ = 0; shared_ptr createPeakExtractor() { shared_ptr noiseCalculator(new NoiseCalculator_2Pass); PeakFinder_SNR::Config pfsnrConfig; pfsnrConfig.windowRadius = 2; pfsnrConfig.zValueThreshold = 3; shared_ptr peakFinder(new PeakFinder_SNR(noiseCalculator, pfsnrConfig)); PeakFitter_Parabola::Config pfpConfig; pfpConfig.windowRadius = 1; // (windowRadius != 1) is not good for real data shared_ptr peakFitter(new PeakFitter_Parabola(pfpConfig)); return shared_ptr(new PeakExtractor(peakFinder, peakFitter)); } struct SetRetentionTime { double rt; SetRetentionTime(double _rt) : rt(_rt) {} void operator()(Peak& peak) {peak.retentionTime = rt;} }; vector< vector > extractPeaks(const MSData& msd, const PeakExtractor& peakExtractor) { MSDataCache msdCache; msdCache.open(msd); const size_t spectrumCount = msdCache.size(); vector< vector > result(spectrumCount); for (size_t index=0; index& peaks = result[index]; peakExtractor.extractPeaks(spectrumInfo.data, peaks); for_each(peaks.begin(), peaks.end(), SetRetentionTime(spectrumInfo.retentionTime)); if (os_) { *os_ << "index: " << index << endl; *os_ << "peaks: " << peaks.size() << endl; copy(peaks.begin(), peaks.end(), ostream_iterator(*os_, "\n")); } } return result; } shared_ptr createPeakelGrower() { PeakelGrower_Proximity::Config config; config.mzTolerance = .01; config.rtTolerance = 10; // seconds return shared_ptr(new PeakelGrower_Proximity(config)); } void print(ostream& os, const string& label, vector v) { os << label << ":\n"; for (vector::const_iterator it=v.begin(); it!=v.end(); ++it) os << **it << endl; } void verifyBombesinPeakels(const PeakelField& peakelField) { // TODO: assert # peaks/peakel, verify metadata // charge state 2 vector bombesin_2_0 = peakelField.find(810.41, .01, RTMatches_Contains(1870)); if (os_) print(*os_, "bombesin_2_0", bombesin_2_0); unit_assert(bombesin_2_0.size() == 1); vector bombesin_2_1 = peakelField.find(810.91, .01, RTMatches_Contains(1870)); if (os_) print(*os_, "bombesin_2_1", bombesin_2_1); unit_assert(bombesin_2_1.size() == 1); vector bombesin_2_2 = peakelField.find(811.41, .01, RTMatches_Contains(1870)); if (os_) print(*os_, "bombesin_2_2", bombesin_2_2); unit_assert(bombesin_2_2.size() == 1); vector bombesin_2_3 = peakelField.find(811.91, .01, RTMatches_Contains(1870,10)); if (os_) print(*os_, "bombesin_2_3", bombesin_2_3); unit_assert(bombesin_2_3.size() == 1); // charge state 3 vector bombesin_3_0 = peakelField.find(540.61, .01, RTMatches_Contains(1870)); if (os_) print(*os_, "bombesin_3_0", bombesin_3_0); unit_assert(bombesin_3_0.size() == 1); vector bombesin_3_1 = peakelField.find(540.61 + 1./3., .02, RTMatches_Contains(1865)); if (os_) print(*os_, "bombesin_3_1", bombesin_3_1); unit_assert(bombesin_3_1.size() == 1); vector bombesin_3_2 = peakelField.find(540.61 + 2./3., .02, RTMatches_Contains(1865,5)); if (os_) print(*os_, "bombesin_3_2", bombesin_3_2); unit_assert(bombesin_3_2.size() == 1); // TODO: verify peaks.size() == 1 } shared_ptr createPeakelPicker() { PeakelPicker_Basic::Config config; //config.log = os_; config.minMonoisotopicPeakelSize = 2; return shared_ptr(new PeakelPicker_Basic(config)); } void verifyBombesinFeatures(const FeatureField& featureField) { const double epsilon = .01; const double mz_bomb2 = 810.415; vector bombesin_2_found = featureField.find(mz_bomb2, epsilon, RTMatches_Contains(1865)); unit_assert(bombesin_2_found.size() == 1); const Feature& bombesin_2 = *bombesin_2_found[0]; unit_assert(bombesin_2.charge == 2); unit_assert(bombesin_2.peakels.size() == 5); unit_assert_equal(bombesin_2.peakels[0]->mz, mz_bomb2, epsilon); unit_assert_equal(bombesin_2.peakels[1]->mz, mz_bomb2+.5, epsilon); unit_assert_equal(bombesin_2.peakels[2]->mz, mz_bomb2+1, epsilon); unit_assert_equal(bombesin_2.peakels[3]->mz, mz_bomb2+1.5, epsilon); unit_assert_equal(bombesin_2.peakels[4]->mz, mz_bomb2+2, epsilon); //TODO: verify feature metadata const double mz_bomb3 = 540.612; vector bombesin_3_found = featureField.find(mz_bomb3, epsilon, RTMatches_Contains(1865)); unit_assert(bombesin_3_found.size() == 1); const Feature& bombesin_3 = *bombesin_3_found[0]; unit_assert(bombesin_3.charge == 3); unit_assert(bombesin_3.peakels.size() == 3); unit_assert_equal(bombesin_3.peakels[0]->mz, mz_bomb3, epsilon); unit_assert_equal(bombesin_3.peakels[1]->mz, mz_bomb3+1./3, epsilon); unit_assert_equal(bombesin_3.peakels[2]->mz, mz_bomb3+2./3, epsilon); //TODO: verify feature metadata } void testBombesin(const string& filename) { if (os_) *os_ << "testBombesin()" << endl; // open data file and check sanity MSDataFile msd(filename); unit_assert(msd.run.spectrumListPtr.get()); unit_assert(msd.run.spectrumListPtr->size() == 8); // instantiate PeakExtractor and extract peaks shared_ptr peakExtractor = createPeakExtractor(); vector< vector > peaks = extractPeaks(msd, *peakExtractor); unit_assert(peaks.size() == 8); // grow peakels shared_ptr peakelGrower = createPeakelGrower(); PeakelField peakelField; peakelGrower->sowPeaks(peakelField, peaks); if (os_) *os_ << "peakelField:\n" << peakelField << endl; verifyBombesinPeakels(peakelField); // pick peakels shared_ptr peakelPicker = createPeakelPicker(); FeatureField featureField; peakelPicker->pick(peakelField, featureField); if (os_) *os_ << "featureField:\n" << featureField << endl; verifyBombesinFeatures(featureField); } void test(const bfs::path& datadir) { testBombesin((datadir / "FeatureDetectorTest_Bombesin.mzML").string()); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { bfs::path datadir = "."; for (int i=1; i // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PEAKELGROWER_HPP_ #define _PEAKELGROWER_HPP_ #include "MZRTField.hpp" #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/misc/PeakData.hpp" #include namespace pwiz { namespace analysis { /// /// interface for growing Peakels /// class PWIZ_API_DECL PeakelGrower { public: typedef pwiz::data::peakdata::Peak Peak; virtual void sowPeak(PeakelField& peakelField, const Peak& peak) const = 0; virtual void sowPeaks(PeakelField& peakelField, const std::vector& peaks) const; virtual void sowPeaks(PeakelField& peakelField, const std::vector< std::vector >& peaks) const; virtual ~PeakelGrower(){} }; /// /// simple PeakelGrower implementation, based on proximity of Peaks /// class PWIZ_API_DECL PeakelGrower_Proximity : public PeakelGrower { public: struct Config { MZTolerance mzTolerance; // m/z units double rtTolerance; // seconds std::ostream* log; Config(double _mzTolerance = .01, double _rtTolerance = 10) : mzTolerance(_mzTolerance), rtTolerance(_rtTolerance), log(0) {} }; PeakelGrower_Proximity(const Config& config = Config()); virtual void sowPeak(PeakelField&, const Peak& peak) const; private: Config config_; }; } // namespace analysis } // namespace pwiz #endif // _PEAKELGROWER_HPP_ pwiz/pwiz/analysis/peakdetect/NoiseTest.cpp0000664000175100017510000001075312664775614023131 0ustar teamcityteamcity00000000000000// // $Id: NoiseTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "Noise.hpp" #include "pwiz/utility/misc/unit.hpp" #include #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::math; using namespace pwiz::analysis; ostream* os_ = 0; void generateNoise() { boost::mt19937 rng; boost::normal_distribution<> normal(10, 1); boost::variate_generator > generator(rng, normal); for (int i=0; i<100; i++) { cout << i << ", " << generator() << ", "; if (i%10 == 9) cout << endl; } } double testNoise_[] = // generated ~ N(10,1) { 0, 10.2134, 1, 9.50442, 2, 11.5754, 3, 8.9408, 4, 11.8393, 5, 11.8858, 6, 10.6047, 7, 9.63402, 8, 9.42174, 9, 9.36562, 10, 11.0297, 11, 10.7241, 12, 9.88493, 13, 10.6358, 14, 6.99061, 15, 9.08698, 16, 13.2407, 17, 9.11359, 18, 12.5566, 19, 9.42665, 20, 10.8823, 21, 11.3452, 22, 12.7695, 23, 9.48237, 24, 10.4651, 25, 9.87172, 26, 8.21869, 27, 10.1641, 28, 10.2608, 29, 9.20198, 30, 10.0615, 31, 10.0762, 32, 9.56936, 33, 10.2306, 34, 11.2333, 35, 9.27828, 36, 10.5381, 37, 8.01883, 38, 11.1455, 39, 9.70199, 40, 9.00168, 41, 8.51621, 42, 10.9232, 43, 10.2107, 44, 10.4026, 45, 9.43944, 46, 11.3842, 47, 9.39058, 48, 9.56328, 49, 9.09075, 50, 10.0799, 51, 8.35904, 52, 9.95105, 53, 8.86625, 54, 9.18384, 55, 10.6562, 56, 9.65414, 57, 9.48778, 58, 10.4029, 59, 10.746, 60, 9.51285, 61, 8.28112, 62, 10.8551, 63, 10.1733, 64, 9.65835, 65, 12.0004, 66, 10.5445, 67, 10.1626, 68, 12.6242, 69, 11.8353, 70, 10.8273, 71, 8.33673, 72, 9.82429, 73, 9.51358, 74, 9.30484, 75, 11.55, 76, 11.1051, 77, 9.64263, 78, 11.4417, 79, 10.317, 80, 9.51919, 81, 10.1948, 82, 9.49461, 83, 10.4654, 84, 10.0316, 85, 9.67727, 86, 10.0763, 87, 9.73844, 88, 10.396, 89, 10.9456, 90, 8.89552, 91, 10.0711, 92, 8.91056, 93, 10.3877, 94, 8.92218, 95, 8.58656, 96, 9.43114, 97, 7.82059, 98, 10.0535, 99, 8.1854 }; // testNoise_ void test_2Pass_NoSignal() { NoiseCalculator_2Pass::Config config; config.zValueCutoff = 10; // high value -> nothing is excluded NoiseCalculator_2Pass noiseCalculator(config); OrderedPairContainerRef data(testNoise_, testNoise_+sizeof(testNoise_)/sizeof(double)); Noise noise = noiseCalculator.calculateNoise(data); if (os_) *os_ << "noise ~ N(" << noise.mean << "," << noise.standardDeviation << ")\n"; const double epsilon = .2; unit_assert_equal(noise.mean, 10, epsilon); unit_assert_equal(noise.standardDeviation, 1, epsilon); } void test_2Pass() { NoiseCalculator_2Pass noiseCalculator; vector data; copy(testNoise_, testNoise_+sizeof(testNoise_)/sizeof(double), back_inserter(data)); // add spikes data[51] += 100; data[101] += 100; data[151] += 100; Noise noise = noiseCalculator.calculateNoise(data); if (os_) *os_ << "noise ~ N(" << noise.mean << "," << noise.standardDeviation << ")\n"; const double epsilon = .2; unit_assert_equal(noise.mean, 10, epsilon); unit_assert_equal(noise.standardDeviation, 1, epsilon); } void test_pvalue() { Noise noise(0,1); const double epsilon = .0005; unit_assert_equal(noise.pvalue(1), .159, epsilon); unit_assert_equal(noise.pvalue(2), .023, epsilon); unit_assert_equal(noise.pvalue(3), .001, epsilon); } void test() { test_2Pass_NoSignal(); test_2Pass(); test_pvalue(); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/peakdetect/FeatureModeler.cpp0000664000175100017510000002125312664775614024114 0ustar teamcityteamcity00000000000000// // $Id: FeatureModeler.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "FeatureModeler.hpp" #include "MZRTField.hpp" #include "pwiz/utility/misc/Export.hpp" #include "pwiz/utility/chemistry/IsotopeEnvelopeEstimator.hpp" #include "pwiz/utility/chemistry/Ion.hpp" #include "boost/math/distributions/normal.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace analysis { using namespace pwiz::data::peakdata; using namespace pwiz::chemistry; using namespace pwiz::math; // // Feature Modeler // void FeatureModeler::fitFeatures(const FeatureField& in, FeatureField& out) const { for (FeatureField::const_iterator it=in.begin(); it!=in.end(); ++it) { try { FeaturePtr temp(new Feature); fitFeature(**it, *temp); out.insert(temp); } catch (exception& e) { cerr << "[FeatureModeler::fitFeatures()] Caught exception: " << e.what() << endl; } catch (...) { cerr << "[FeatureModeler::fitFeatures()] Caught unknown exception.\n"; } } } // // FeatureModeler_Gaussian // namespace { class GaussianModel { public: GaussianModel(double mean_mz, double sd_mz, double mean_rt, double sd_rt, int charge) : normal_mz_(mean_mz, sd_mz), normal_rt_(mean_rt, sd_rt), charge_(charge), neutralMass_(Ion::neutralMass(mean_mz, charge)), intensity_(1) { if (!isotopeEnvelopeEstimator_.get()) createIsotopeEnvelopeEstimator(); envelope_ = isotopeEnvelopeEstimator_->isotopeEnvelope(neutralMass_); if (envelope_.empty()) throw runtime_error("[FeatureModeler::GaussianModel()] Empty envelope."); } double mean_mz() const {return normal_mz_.mean();} double mean_rt() const {return normal_rt_.mean();} double sd_mz() const {return normal_mz_.standard_deviation();} double sd_rt() const {return normal_rt_.standard_deviation();} static void createIsotopeEnvelopeEstimator() { const double abundanceCutoff = .01; const double massPrecision = .1; IsotopeCalculator isotopeCalculator(abundanceCutoff, massPrecision); IsotopeEnvelopeEstimator::Config config; config.isotopeCalculator = &isotopeCalculator; config.normalization = IsotopeCalculator::NormalizeMass; isotopeEnvelopeEstimator_ = shared_ptr(new IsotopeEnvelopeEstimator(config)); } double operator()(double mz, double rt) const { double minMassDifference = numeric_limits::max(); size_t bestIndex = 0; double mass = Ion::neutralMass(mz, charge_); for (size_t i=0; i massDifference) { minMassDifference = massDifference; bestIndex = i; } } double mz_shifted = Ion::mz(mass - envelope_[bestIndex].mass, charge_); double isotopeAbundance = envelope_[bestIndex].abundance; double result = intensity_ * isotopeAbundance * pdf(normal_mz_, mz_shifted) * pdf(normal_rt_, rt); return result; } private: static shared_ptr isotopeEnvelopeEstimator_; boost::math::normal normal_mz_; boost::math::normal normal_rt_; int charge_; double neutralMass_; chemistry::MassDistribution envelope_; double intensity_; friend ostream& operator<<(ostream& os, const GaussianModel& model) { os << "[mz(" << model.mean_mz() << "," << model.sd_mz() << "),rt(" << model.mean_rt() << "," << model.sd_rt() << "),+" << model.charge_ << "]"; return os; } }; shared_ptr GaussianModel::isotopeEnvelopeEstimator_; // static storage GaussianModel estimateParameters(const Feature& feature) { // for now, simple estimation based on calculation of mean/variance of m/z and retention time // from cached peak data if (feature.peakels.empty()) throw runtime_error("[FeatureModeler::estimateParameters()] Empty feature."); const Peakel& peakel = *feature.peakels[0]; double peakelSumIntensity = 0; double peakelSumIntensityMZ = 0; double peakelSumIntensityMZ2 = 0; double peakelSumIntensityRT = 0; double peakelSumIntensityRT2 = 0; for (vector::const_iterator peak=peakel.peaks.begin(); peak!=peakel.peaks.end(); ++peak) { double peakSumIntensity = 0; double peakSumIntensityMZ = 0; double peakSumIntensityMZ2 = 0; for (vector::const_iterator it=peak->data.begin(); it!=peak->data.end(); ++it) { peakSumIntensity += it->y; peakSumIntensityMZ += (it->x * it->y); peakSumIntensityMZ2 += (it->x * it->x * it->y); } peakelSumIntensity += peakSumIntensity; peakelSumIntensityMZ += peakSumIntensityMZ; peakelSumIntensityMZ2 += peakSumIntensityMZ2; peakelSumIntensityRT += peakSumIntensity * peak->retentionTime; peakelSumIntensityRT2 += peakSumIntensity * peak->retentionTime * peak->retentionTime; } double peakelMeanMZ = peakelSumIntensityMZ/peakelSumIntensity; double peakelMeanMZ2 = peakelSumIntensityMZ2/peakelSumIntensity; double peakelVarianceMZ = peakelMeanMZ2 - peakelMeanMZ*peakelMeanMZ; double peakelStandardDeviationMZ = sqrt(peakelVarianceMZ); double peakelMeanRT = peakelSumIntensityRT/peakelSumIntensity; double peakelMeanRT2 = peakelSumIntensityRT2/peakelSumIntensity; double peakelVarianceRT = peakelMeanRT2 - peakelMeanRT*peakelMeanRT; double peakelStandardDeviationRT = sqrt(peakelVarianceRT); return GaussianModel(peakelMeanMZ, peakelStandardDeviationMZ, peakelMeanRT, peakelStandardDeviationRT, feature.charge); } void calculateFit(const GaussianModel& model, const Feature& in, Feature& out) { double sumModelData = 0; // dot product double sumModel2 = 0; // normalization double sumData2 = 0; // normalization size_t count = 0; // number of terms in the sums for (vector::const_iterator peakel=in.peakels.begin(); peakel!=in.peakels.end(); ++peakel) { for (vector::const_iterator peak=(*peakel)->peaks.begin(); peak!=(*peakel)->peaks.end(); ++peak) { double rt = peak->retentionTime; for (vector::const_iterator it=peak->data.begin(); it!=peak->data.end(); ++it) { double mz = it->x; double value_data = it->y; double value_model = model(mz, rt); sumModelData += value_model * value_data; sumModel2 += value_model * value_model; sumData2 += value_data * value_data; count++; } } } double scale = sumModelData/sumModel2; // scaling factor for model, from projection of data double cosine = sumModelData/sqrt(sumData2)/sqrt(sumModel2); // cosine of angle between model and data double sumSquaredDifferences = sumData2 - 2*scale*sumModelData + scale*scale*sumModel2; // total squared error between data and scaled model double rms = sqrt(sumSquaredDifferences/count); // root mean squared error between model and data out = in; // shallow copy out.mz = model.mean_mz(); out.retentionTime = model.mean_rt(); out.totalIntensity = scale; // TODO: revisit out.rtVariance = model.sd_rt() * model.sd_rt(); out.score = cosine; out.error = rms; } } // namespace void FeatureModeler_Gaussian::fitFeature(const Feature& in, Feature& out) const { GaussianModel model = estimateParameters(in); calculateFit(model, in, out); } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/peakdetect/PeakelPicker.hpp0000664000175100017510000000455712664775614023565 0ustar teamcityteamcity00000000000000// // $Id: PeakelPicker.hpp 1191 2009-08-14 19:33:05Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PEAKELPICKER_HPP_ #define _PEAKELPICKER_HPP_ #include "PeakelPicker.hpp" #include "MZRTField.hpp" #include "pwiz/utility/misc/Export.hpp" namespace pwiz { namespace analysis { /// /// interface for picking Peakels and arranging into Features; /// note: Peakels are actually removed from the PeakelField /// class PWIZ_API_DECL PeakelPicker { public: virtual void pick(PeakelField& peakels, FeatureField& features) const = 0; virtual ~PeakelPicker(){} }; /// /// basic implementation /// class PWIZ_API_DECL PeakelPicker_Basic : public PeakelPicker { public: struct Config { std::ostream* log; size_t minCharge; size_t maxCharge; size_t minMonoisotopicPeakelSize; MZTolerance mzTolerance; double rtTolerance; size_t minPeakelCount; //double intensityThreshold; // ? // some kind of tolerance to match isotope envelope //double relativeIntensityTolerance; Config() : log(0), minCharge(2), maxCharge(5), minMonoisotopicPeakelSize(3), mzTolerance(10, MZTolerance::PPM), rtTolerance(5), // seconds minPeakelCount(3) {} }; PeakelPicker_Basic(const Config& config = Config()) : config_(config) {} virtual void pick(PeakelField& peakels, FeatureField& features) const; private: Config config_; }; } // namespace analysis } // namespace pwiz #endif // _PEAKELPICKER_HPP_ pwiz/pwiz/analysis/peakdetect/PeakFitterTest.cpp0000664000175100017510000000710112664775614024103 0ustar teamcityteamcity00000000000000// // $Id: PeakFitterTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "PeakFitter.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::math; using namespace pwiz::util; using namespace pwiz::analysis; using namespace pwiz::data::peakdata; ostream* os_ = 0; void testParabola() { if (os_) *os_ << "testParabola()\n"; const double center = 2.1; const double height = 5; vector pairs; for (double i=0; i<5; i++) pairs.push_back(OrderedPair(i, height-(i-center)*(i-center))); // sampled parabola PeakFitter_Parabola::Config config; config.windowRadius = 1; PeakFitter_Parabola fitter(config); Peak peak; fitter.fitPeak(pairs, 2, peak); if (os_) { *os_ << peak; copy(peak.data.begin(), peak.data.end(), ostream_iterator(*os_, " ")); *os_ << endl; } const double epsilon = 1e-6; unit_assert_equal(peak.mz, center, epsilon); unit_assert_equal(peak.intensity, 5, epsilon); unit_assert_equal(peak.area, 12.97, epsilon); unit_assert_equal(peak.error, 0, epsilon); unit_assert_equal(peak.intensity, 5, epsilon); unit_assert(!peak.data.empty()); } void testMultiplePeaks() { if (os_) *os_ << "testMultiplePeaks()\n"; const double center = 2.1; const double height = 5; vector pairs; for (double i=0; i<5; i++) pairs.push_back(OrderedPair(i, height-(i-center)*(i-center))); // sampled parabola for (double i=0; i<5; i++) pairs.push_back(OrderedPair(i+5, height-(i-center)*(i-center))); // sampled parabola for (double i=0; i<5; i++) pairs.push_back(OrderedPair(i+10, height-(i-center)*(i-center))); // sampled parabola vector indices; indices.push_back(2); indices.push_back(7); indices.push_back(12); PeakFitter_Parabola fitter; vector peaks; fitter.fitPeaks(pairs, indices, peaks); if (os_) { for (vector::const_iterator it=peaks.begin(); it!=peaks.end(); ++it) { *os_ << *it; copy(it->data.begin(), it->data.end(), ostream_iterator(*os_, " ")); *os_ << endl; } } const double epsilon = 1e-6; unit_assert(peaks.size() == 3); unit_assert_equal(peaks[0].mz, center, epsilon); unit_assert_equal(peaks[1].mz, center+5, epsilon); unit_assert_equal(peaks[2].mz, center+10, epsilon); } void test() { testParabola(); testMultiplePeaks(); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/peakdetect/PeakFamilyDetector.hpp0000664000175100017510000000365512664775614024740 0ustar teamcityteamcity00000000000000// // $Id: PeakFamilyDetector.hpp 1191 2009-08-14 19:33:05Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PEAKFAMILYDETECTOR_HPP_ #define _PEAKFAMILYDETECTOR_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/MSData.hpp" #include "pwiz/data/misc/PeakData.hpp" namespace pwiz { namespace analysis { /// /// interface for peak family (isotope envelope) detection /// class PWIZ_API_DECL PeakFamilyDetector { public: typedef pwiz::msdata::MZIntensityPair MZIntensityPair; typedef pwiz::data::peakdata::PeakFamily PeakFamily; /// find peak families in a specified array of MZIntensityPair virtual void detect(const MZIntensityPair* begin, const MZIntensityPair* end, std::vector& result) = 0; /// convenience function -- equivalent to: /// detect(&data[0], &data[0]+data.size(), result) virtual void detect(const std::vector& data, std::vector& result); virtual ~PeakFamilyDetector() {} }; } // namespace analysis } // namespace pwiz #endif // _PEAKFAMILYDETECTOR_HPP_ pwiz/pwiz/analysis/peakdetect/PeakelGrowerTest.cpp0000664000175100017510000000644012664775614024441 0ustar teamcityteamcity00000000000000// // $Id: PeakelGrowerTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "PeakelGrower.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::analysis; using namespace pwiz::data::peakdata; ostream* os_ = 0; vector< vector > createToyPeaks() { // rt\mz 1000 1001 1002 // 0 x x // 1 x x x // 2 x x // 3 x x x // 4 x x vector< vector > peaks(5); Peak peak; peak.retentionTime = 0; peak.mz = 1000; peaks[0].push_back(peak); peak.mz = 1002; peaks[0].push_back(peak); peak.retentionTime = 1; peak.mz = 1000.01; peaks[1].push_back(peak); peak.mz = 1001; peaks[1].push_back(peak); peak.mz = 1002.01; peaks[1].push_back(peak); peak.retentionTime = 2; peak.mz = 1001.01; peaks[2].push_back(peak); peak.mz = 1002-.01; peaks[2].push_back(peak); peak.retentionTime = 3; peak.mz = 1000; peaks[3].push_back(peak); peak.mz = 1001-.01; peaks[3].push_back(peak); peak.mz = 1002.02; peaks[3].push_back(peak); peak.retentionTime = 4; peak.mz = 1000.01; peaks[4].push_back(peak); peak.mz = 1002-.02; peaks[4].push_back(peak); return peaks; } void testToyExample() { vector< vector > peaks = createToyPeaks(); PeakelGrower_Proximity::Config config; config.mzTolerance = .1; config.rtTolerance = 1.5; PeakelGrower_Proximity peakelGrower(config); PeakelField field; peakelGrower.sowPeaks(field, peaks); const double epsilon = .1; unit_assert(field.size() == 4); PeakelField::const_iterator it = field.begin(); unit_assert_equal((*it)->mz, 1000, epsilon); unit_assert_equal((*it)->retentionTime, 0, epsilon); ++it; unit_assert_equal((*it)->mz, 1000, epsilon); unit_assert_equal((*it)->retentionTime, 3, epsilon); ++it; unit_assert_equal((*it)->mz, 1001, epsilon); unit_assert_equal((*it)->retentionTime, 1, epsilon); ++it; unit_assert_equal((*it)->mz, 1002, epsilon); unit_assert_equal((*it)->retentionTime, 0, epsilon); } void test() { testToyExample(); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/peakdetect/FeatureDetector.hpp0000664000175100017510000000273612664775614024310 0ustar teamcityteamcity00000000000000// // $Id: FeatureDetector.hpp 1191 2009-08-14 19:33:05Z chambm $ // // // Original author: Kate Hoff // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Cnter, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _FEATUREDETECTOR_HPP_ #define _FEATUREDETECTOR_HPP_ #include "MZRTField.hpp" #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/MSData.hpp" #include "pwiz/data/misc/PeakData.hpp" namespace pwiz { namespace analysis { using namespace pwiz::data::peakdata; class PWIZ_API_DECL FeatureDetector { public: typedef msdata::MSData MSData; typedef data::peakdata::Feature Feature; virtual void detect(const MSData& msd, FeatureField& result) const = 0; virtual ~FeatureDetector(){} }; } // namespace analysis } // namespace pwiz #endif pwiz/pwiz/analysis/peakdetect/MZRTFieldTest.cpp0000664000175100017510000001563312664775614023616 0ustar teamcityteamcity00000000000000// // $Id: MZRTFieldTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "MZRTField.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::analysis; using namespace pwiz::chemistry; using namespace pwiz::data::peakdata; ostream* os_ = 0; void testPredicate() { if (os_) *os_ << "testPredicate()\n"; PeakelPtr a(new Peakel(Peak(1.0, 1.0))); PeakelPtr b(new Peakel(Peak(2.0, 1.0))); PeakelPtr c(new Peakel(Peak(1.0, 2.0))); LessThan_MZRT lt; // a < c < b unit_assert(lt(*a,*b)); unit_assert(lt(a,b)); unit_assert(!lt(b,a)); unit_assert(lt(a,c)); unit_assert(!lt(c,a)); unit_assert(lt(c,b)); unit_assert(!lt(b,c)); unit_assert(!lt(a,a)); } void testPredicate_Feature() { Feature a,b; a.mz = 1; b.mz = 2; LessThan_MZRT lt; unit_assert(lt(a,b)); unit_assert(!lt(b,a)); unit_assert(!lt(a,a)); } struct Goober { // minimum requirements to instantiate MZRTField<>; // removing any of these will produce compiler error via Boost concept checking // with the struct HasMZRT double mz; double retentionTime; double retentionTimeMin() const; double retentionTimeMax() const; }; void testConceptChecking() { MZRTField gooberField; } struct Simple { double mz; double retentionTime; double rtMin; double rtMax; double retentionTimeMin() const {return rtMin;} double retentionTimeMax() const {return rtMax;} Simple(double _mz = 0, double _rtMin = 0, double _rtMax = 0) : mz(_mz), retentionTime((_rtMin+_rtMax)/2), rtMin(_rtMin), rtMax(_rtMax) {} }; typedef shared_ptr SimplePtr; void testFind() { // rt\mz 400 410 420 430 440 // 660 a c // 661 a c // 662 c // 663 // 664 b // 665 b d // 666 b d // 667 b d // 668 b // 669 SimplePtr a(new Simple(400, 660, 661)); SimplePtr b(new Simple(400, 664, 668)); SimplePtr c(new Simple(420, 660, 662)); SimplePtr d(new Simple(420, 665, 667)); MZRTField simpleField; simpleField.insert(a); simpleField.insert(b); simpleField.insert(c); simpleField.insert(d); vector result = simpleField.find(420, 1, RTMatches_Any()); unit_assert(result.size()==2 && result[0]==c && result[1]==d); result = simpleField.find(410, 11, RTMatches_Contains(666,0)); unit_assert(result.size()==2 && result[0]==b && result[1]==d); result = simpleField.find(420, 1, RTMatches_IsContainedIn(*b)); unit_assert(result.size()==1 && result[0]==d); result = simpleField.find(400, 1, RTMatches_IsContainedIn(*d, 1.5)); unit_assert(result.size()==1 && result[0]==b); } void testPeakelField() { if (os_) *os_ << "testPeakelField()\n"; PeakelPtr a(new Peakel(Peak(1.0, 1.0))); PeakelPtr b(new Peakel(Peak(2.0, 1.0))); PeakelPtr c(new Peakel(Peak(1.0, 2.0))); PeakelField pf; pf.insert(a); pf.insert(b); pf.insert(c); if (os_) *os_ << pf << endl; unit_assert(pf.size() == 3); PeakelField::const_iterator it = pf.begin(); unit_assert(*it == a); // note that std::set allows only const access // however, we can modify **it (*it)->peaks.push_back(Peak()); (*it)->peaks.clear(); ++it; unit_assert(*it == c); ++it; unit_assert(*it == b); // find() if (os_) *os_ << "testPeakelField(): find()\n"; vector v = pf.find(1.5, .6, RTMatches_Contains(1, .5)); if (os_) { *os_ << "find(): " << v.size() << endl; for (vector::const_iterator it=v.begin(); it!=v.end(); ++it) *os_ << **it << endl; } unit_assert(v.size()==2 && v[0]==a && v[1]==b); v = pf.find(1.5, .4, RTMatches_Contains(1, .5)); unit_assert(v.empty()); v = pf.find(2, .1, RTMatches_Contains(1, .1)); unit_assert(v.size()==1 && v[0]==b); MZTolerance fiveppm(5, MZTolerance::PPM); v = pf.find(1.000001, fiveppm, RTMatches_Contains(1, 10)); unit_assert(v.size()==2 && v[0]==a && v[1]==c); v = pf.find(1.000006, fiveppm, RTMatches_Contains(1, 10)); unit_assert(v.empty()); // remove() if (os_) *os_ << "testPeakelField(): remove()\n"; pf.remove(a); unit_assert(pf.size() == 2); it = pf.begin(); unit_assert(*it == c); ++it; unit_assert(*it == b); bool caught = false; try { pf.remove(a); } catch (exception& e) { if (os_) *os_ << "Caught exception correctly: " << e.what() << endl; caught = true; } unit_assert(caught); pf.remove(b); unit_assert(pf.size() == 1); it = pf.begin(); unit_assert(*it == c); pf.remove(c); unit_assert(pf.empty()); if (os_) *os_ << endl; } struct MyPred { void operator()(double mz) { cout << "MyPred: " << mz << endl; } }; void testFeatureField() { if (os_) *os_ << "testFeatureField()\n"; FeatureField ff; FeaturePtr a(new Feature); a->mz=1; a->retentionTime=1; FeaturePtr b(new Feature); b->mz=2; b->retentionTime=1; FeaturePtr c(new Feature); c->mz=1; c->retentionTime=2; ff.insert(a); ff.insert(b); ff.insert(c); if (os_) *os_ << ff << endl; MZTolerance fiveppm(5, MZTolerance::PPM); vector v = ff.find(1.000001, fiveppm, RTMatches_Contains(1, 10)); unit_assert(v.size()==2 && v[0]==a && v[1]==c); v = ff.find(1.000006, fiveppm, RTMatches_Contains(1, 10)); unit_assert(v.empty()); } void test() { testPredicate(); testPredicate_Feature(); testConceptChecking(); testFind(); testPeakelField(); testFeatureField(); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/peakdetect/FeatureModeler.hpp0000664000175100017510000000325412664775614024122 0ustar teamcityteamcity00000000000000// // $Id: FeatureModeler.hpp 1342 2009-09-17 22:40:11Z dkessner $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _FEATUREMODELER_HPP_ #define _FEATUREMODELER_HPP_ #include "MZRTField.hpp" #include "pwiz/utility/misc/Export.hpp" namespace pwiz { namespace analysis { /// /// interface for fitting and scoring Feature data to a model /// class PWIZ_API_DECL FeatureModeler { public: typedef pwiz::data::peakdata::Feature Feature; virtual void fitFeature(const Feature& in, Feature& out) const = 0; virtual void fitFeatures(const FeatureField& in, FeatureField& out) const; virtual ~FeatureModeler(){} }; /// /// Gaussian implementation /// class PWIZ_API_DECL FeatureModeler_Gaussian : public FeatureModeler { public: virtual void fitFeature(const Feature& in, Feature& out) const; }; } // namespace analysis } // namespace pwiz #endif // _FEATUREMODELER_HPP_ pwiz/pwiz/analysis/peakdetect/PeakExtractor.cpp0000664000175100017510000000334012664775614023762 0ustar teamcityteamcity00000000000000// // $Id: PeakExtractor.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "PeakExtractor.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace analysis { using namespace pwiz::math; PeakExtractor::PeakExtractor(shared_ptr peakFinder, shared_ptr peakFitter) : peakFinder_(peakFinder), peakFitter_(peakFitter) { if (!peakFinder.get()) throw runtime_error("[PeakExtractor] Null PeakFinder."); if (!peakFitter.get()) throw runtime_error("[PeakExtractor] Null PeakFitter."); } void PeakExtractor::extractPeaks(const OrderedPairContainerRef& pairs, vector& result) const { result.clear(); vector peakIndices; peakFinder_->findPeaks(pairs, peakIndices); peakFitter_->fitPeaks(pairs, peakIndices, result); } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/peakdetect/FeatureDetectorSimple.cpp0000664000175100017510000002664212664775614025457 0ustar teamcityteamcity00000000000000// // $Id: FeatureDetectorSimple.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Kate Hoff // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Cnter, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "FeatureDetectorSimple.hpp" #include "pwiz/data/msdata/Serializer_mzML.hpp" #include "boost/iostreams/positioning.hpp" #include "pwiz/data/msdata/SpectrumIterator.hpp" #include "pwiz/data/msdata/SpectrumInfo.hpp" #include "pwiz/analysis/passive/MSDataCache.hpp" #include "boost/tuple/tuple_comparison.hpp" #include "pwiz/utility/misc/Std.hpp" namespace{ using namespace pwiz::analysis; using namespace pwiz::data; using namespace pwiz::data::peakdata; using namespace pwiz::msdata; // helper function to fill in Peak id attribute (currently from scan number) struct SetID { SetID(int id) : _id(id) {} void operator()(Peak& peak) { peak.id = _id; } int _id; }; // helper function to fill in Peak retentionTime attribute struct SetRT { SetRT(double rt) : _rt(rt) {} void operator()(Peak& peak) { peak.retentionTime = _rt; } private: double _rt; }; // define keys for matching a PeakFamily to a Feature. FeatureKey captures all the attributes of a PeakFamily necessary to match it to an existing Feature, provided that the Feature and PeakFamily are contiguous in the retention time dimension. FeatureKey is a tuple of the (mzMonoisotopic, charge, peaks.size()) attributes of a PeakFamily. typedef boost::tuple FeatureKey; bool operator==(const FeatureKey& a, const FeatureKey& b) { return (fabs(a.get<0>() - b.get<0>())) < .001 && // accurate to 10e-3 a.get<1>() == b.get<1>() && a.get<2>() == b.get<2>(); } } // anonymous namespace using namespace pwiz::analysis; using namespace pwiz::data; using namespace pwiz::data::peakdata; using namespace pwiz::msdata; class FeatureDetectorSimple::Impl { public: Impl(shared_ptr pfd) : _pfd(pfd) {} typedef string FeatureID; void detect(const MSData& msd, FeatureField& result) const; FeaturePtr makeFeature(const PeakFamily& pf, FeatureID& id) const; void updatePeakel(const Peak& peak, Peakel& peakel) const; void updateFeature(const PeakFamily& pf, FeaturePtr feature) const; void getMetadata(FeatureField& result) const; private: shared_ptr _pfd; }; FeatureDetectorSimple::FeatureDetectorSimple(shared_ptr pfd) : _pimpl(new Impl(pfd)){} void FeatureDetectorSimple::detect(const MSData& msd, FeatureField& result) const { _pimpl->detect(msd,result); } FeaturePtr FeatureDetectorSimple::Impl::makeFeature(const PeakFamily& pf, FeatureID& id) const { FeaturePtr result(new Feature()); result->id = id; result->charge = pf.charge; result->charge = pf.charge; for(vector::const_iterator peak_it = pf.peaks.begin(); peak_it != pf.peaks.end(); ++peak_it) { // initialize peakels, one for each peak in the PeakFamily PeakelPtr peakel(new Peakel); updatePeakel(*peak_it, *peakel); result->peakels.push_back(peakel); } return result; } void FeatureDetectorSimple::Impl::updatePeakel(const Peak& peak, Peakel& peakel) const { peakel.peaks.push_back(peak); return; } void FeatureDetectorSimple::Impl::updateFeature(const PeakFamily& pf, FeaturePtr feature) const { // iterate through peakels, adding new peaks and updating attributes vector::iterator peakel_it = feature->peakels.begin(); vector::const_iterator peak_it = pf.peaks.begin(); for(; peak_it != pf.peaks.end(); ++peakel_it, ++peak_it) { // update appropriate peakel updatePeakel(*peak_it, **peakel_it); } return; } void FeatureDetectorSimple::Impl::getMetadata(FeatureField& detected) const { FeatureField::iterator feat_it = detected.begin(); for(; feat_it != detected.end(); ++feat_it) { (*feat_it)->calculateMetadata(); } return; } // TODO Make this interpretable to a normal human // FeatureDetectorSimple::Impl::detect uses two maps to find // features. The first is rewritten with every scan, // and is keyed by FeatureKeys mapping to FeatureIDs. These // FeatureIDs correspond to features that // will be eligible to be updated by PeakFamilys found in the next // scan. The second map stores all detected features, keyed by these // FeatureIDs, regardless of eligibility for update. The first map is // rolled over the scan set, updating the second as it goes. void FeatureDetectorSimple::Impl::detect(const MSData& msd, FeatureField& detected) const { // initialize buffer maps map grandparentBuffer; map parentBuffer; map featureMap; size_t featureCount = 0; MSDataCache cache; cache.open(msd); for(size_t spectrum_index = 0; spectrum_index < cache.size(); spectrum_index ++) { map buffer; const SpectrumInfo info = cache.spectrumInfo(spectrum_index, true); //getBinaryData ? // if info.PrecursorInfo ? // call peak family detector on each scan vector mzIntensityPairs = info.data; vector result; if (info.massAnalyzerType != MS_FT_ICR && info.massAnalyzerType != MS_orbitrap) { cerr << "Skipping non-FT scan number " << info.scanNumber << endl; continue; } _pfd->detect(mzIntensityPairs,result); // iterate thru peak families vector::iterator result_it = result.begin(); double rt = info.retentionTime; int id = info.scanNumber; for(; result_it != result.end(); ++result_it) { // set ID attribute for_each(result_it->peaks.begin(), result_it->peaks.end(), SetID(id)); // set RT attribute for_each(result_it->peaks.begin(), result_it->peaks.end(), SetRT(rt)); // make keys for search FeatureKey featureKey(floor(result_it->mzMonoisotopic*100)/100, result_it->charge, result_it->peaks.size()); // no digits past 10e-3 map::iterator grandparentLocation = grandparentBuffer.find(featureKey); map::iterator parentLocation = parentBuffer.find(featureKey); if ( parentLocation == parentBuffer.end() && grandparentLocation == grandparentBuffer.end()) { // feature doesn't exist, make new feature FeatureID featureID = boost::lexical_cast(++featureCount); FeaturePtr feature(makeFeature(*result_it,featureID)); featureMap.insert(pair(featureID, feature)); buffer.insert(pair(featureKey, featureID)); } else { // if parent location update from parent FeatureID foundID; if ( parentLocation != parentBuffer.end() ) foundID = parentLocation->second; else foundID = grandparentLocation->second; // update existing feature updateFeature(*result_it, featureMap[foundID]); buffer.insert(pair(featureKey,foundID)); } } // old buffer map := new buffer map // bufferMap.swap(updatedBufferMap); grandparentBuffer.swap(parentBuffer); parentBuffer.swap(buffer); } // write output vector map::iterator the_it = featureMap.begin(); for(; the_it != featureMap.end(); ++the_it) { if(the_it->second->peakels.front()->peaks.size()>1) // for now only write features lasting > 1 scan { the_it->second->calculateMetadata(); detected.insert(the_it->second); } } return; } /* // // output files and plotting tools // commented out for now, to be implemented in FeatureExporter // map::iterator the_it = featureMap.begin(); for(; the_it != featureMap.end(); ++the_it) { // .features file ofstream ofs_all((msd.id+".features").c_str(), ios::app); // files for plotting ofstream ofs_peak("peak_plot.txt", ios::app); ofstream ofs_pkl("peakel_plot.txt", ios::app); ofstream ofs_feat("feature_plot.txt", ios::app); if(the_it->second.peakels.begin()->peaks.size()>1) // for now only write stuff found in > 1 scan { detected.push_back(the_it->second); // write features to .features file ofs_all << the_it->second; ///////////////////////////////////////////////////////////// // write files suitable for gnuplot // factor this out into a separate program that will read in a .features file and export a gnuplot file? ///////////////////////////////////////////////////////////// // write to files for plotting: // write all the feature data out ofs_feat << the_it->second.mzMonoisotopic << "\t" << the_it->second.retentionTime << "\n"; // write all the peakel peak data out vector::iterator peakel_it = the_it->second.peakels.begin(); for(; peakel_it != the_it->second.peakels.end(); ++peakel_it) { vector::iterator peak_it = peakel_it->peaks.begin(); for(; peak_it!= peakel_it->peaks.end(); ++peak_it) { ofs_peak << peak_it->mz << "\t" << peak_it->retentionTime << "\n"; ofs_pkl << peak_it->mz << "\t" << peak_it->retentionTime << "\n"; } ofs_pkl << "\n\n"; } } } return; } */ pwiz/pwiz/analysis/peakdetect/PeakFinder.hpp0000664000175100017510000000473512664775614023234 0ustar teamcityteamcity00000000000000// // $Id: PeakFinder.hpp 1318 2009-09-15 17:48:07Z dkessner $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PEAKFINDER_HPP_ #define _PEAKFINDER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/analysis/peakdetect/Noise.hpp" #include "boost/shared_ptr.hpp" namespace pwiz { namespace analysis { /// /// interface for finding peaks in an array of ordered pairs /// class PWIZ_API_DECL PeakFinder { public: virtual void findPeaks(const math::OrderedPairContainerRef& pairs, std::vector& resultIndices) const = 0; virtual ~PeakFinder(){} }; /// /// PeakFinder implementation based on signal-to-noise ratio /// class PWIZ_API_DECL PeakFinder_SNR : public PeakFinder { public: struct Config { size_t windowRadius; double zValueThreshold; bool preprocessWithLogarithm; std::ostream* log; Config(size_t _windowRadius = 2, double _zValueThreshold = 3, bool _preprocessWithLogarithm = true, std::ostream* _log = 0) : windowRadius(_windowRadius), zValueThreshold(_zValueThreshold), preprocessWithLogarithm(_preprocessWithLogarithm), log(_log) {} }; PeakFinder_SNR(boost::shared_ptr noiseCalculator, const Config& config = Config()); virtual void findPeaks(const math::OrderedPairContainerRef& pairs, std::vector& resultIndices) const; private: boost::shared_ptr noiseCalculator_; Config config_; }; } // namespace analysis } // namespace pwiz #endif // _PEAKFINDER_HPP_ pwiz/pwiz/data/vendor_readers/Bruker/SpectrumList_Bruker.hpp0000664000175100017510000000610412664775620026372 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_Bruker.hpp 6979 2014-12-09 16:15:35Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_BRUKER_HPP_ #define _SPECTRUMLIST_BRUKER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/SpectrumListBase.hpp" #include "pwiz/utility/misc/IntegerSet.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Container.hpp" #include "pwiz/utility/misc/String.hpp" #include "pwiz/utility/misc/Stream.hpp" #include "Reader_Bruker_Detail.hpp" #include namespace pwiz { namespace msdata { namespace detail { using boost::shared_ptr; // // SpectrumList_Bruker // class PWIZ_API_DECL SpectrumList_Bruker : public SpectrumListBase { public: virtual size_t size() const; virtual const SpectrumIdentity& spectrumIdentity(size_t index) const; virtual size_t find(const string& id) const; virtual SpectrumPtr spectrum(size_t index, bool getBinaryData) const; virtual SpectrumPtr spectrum(size_t index, DetailLevel detailLevel) const; virtual SpectrumPtr spectrum(size_t index, bool getBinaryData, const pwiz::util::IntegerSet& msLevelsToCentroid) const; virtual SpectrumPtr spectrum(size_t index, DetailLevel detailLevel, const pwiz::util::IntegerSet& msLevelsToCentroid) const; #ifdef PWIZ_READER_BRUKER SpectrumList_Bruker(MSData& msd, const string& rootpath, Bruker::Reader_Bruker_Format format, CompassDataPtr compassDataPtr); MSSpectrumPtr getMSSpectrumPtr(size_t index, vendor_api::Bruker::DetailLevel detailLevel) const; private: MSData& msd_; bfs::path rootpath_; Bruker::Reader_Bruker_Format format_; mutable CompassDataPtr compassDataPtr_; size_t size_; vector sourcePaths_; struct IndexEntry : public SpectrumIdentity { int source; int collection; // -1 for an MS spectrum int scan; }; vector index_; // idToIndexMap_["scan=<#>" or "file="] == index boost::container::flat_map idToIndexMap_; void fillSourceList(); void createIndex(); //string findPrecursorID(int precursorMsLevel, size_t index) const; #endif // PWIZ_READER_BRUKER }; } // detail } // msdata } // pwiz #endif // _SPECTRUMLIST_BRUKER_HPP_ pwiz/pwiz/data/vendor_readers/Bruker/Reader_Bruker_Test.cpp0000664000175100017510000000324112664775620026127 0ustar teamcityteamcity00000000000000// // $Id: Reader_Bruker_Test.cpp 7155 2015-02-03 22:38:32Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/unit.hpp" #include "Reader_Bruker.hpp" #include "pwiz/utility/misc/VendorReaderTestHarness.hpp" #include "pwiz/utility/misc/Filesystem.hpp" struct IsDirectory : public pwiz::util::TestPathPredicate { bool operator() (const string& rawpath) const { return bfs::is_directory(rawpath); } }; int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) #ifdef PWIZ_READER_BRUKER const bool testAcceptOnly = false; #else const bool testAcceptOnly = true; #endif try { bool requireUnicodeSupport = false; pwiz::util::testReader(pwiz::msdata::Reader_Bruker(), testArgs, testAcceptOnly, requireUnicodeSupport, IsDirectory()); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/vendor_readers/Bruker/Reader_Bruker.cpp0000664000175100017510000002125112664775620025131 0ustar teamcityteamcity00000000000000// // $Id: Reader_Bruker.cpp 6979 2014-12-09 16:15:35Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE // CompassXtractMS DLL usage is msvc only - mingw doesn't provide com support #if (!defined(_MSC_VER) && defined(PWIZ_READER_BRUKER)) #undef PWIZ_READER_BRUKER #endif #include "Reader_Bruker.hpp" #include "Reader_Bruker_Detail.hpp" #include "pwiz/utility/misc/String.hpp" #include "pwiz/utility/misc/DateTime.hpp" #include "pwiz/data/msdata/Version.hpp" #include // A Bruker Analysis source (representing a "run") is actually a directory // It contains several files related to a single acquisition, e.g.: // fid, acqu, acqus, Analysis.FAMethod, AnalysisParameter.xml, sptype PWIZ_API_DECL std::string pwiz::msdata::Reader_Bruker::identify(const std::string& filename, const std::string& head) const { using namespace pwiz::msdata::detail::Bruker; switch (pwiz::msdata::detail::Bruker::format(filename)) { case Reader_Bruker_Format_FID: return "Bruker FID"; case Reader_Bruker_Format_YEP: return "Bruker YEP"; case Reader_Bruker_Format_BAF: return "Bruker BAF"; case Reader_Bruker_Format_U2: return "Bruker U2"; case Reader_Bruker_Format_BAF_and_U2: return "Bruker BAF/U2"; case Reader_Bruker_Format_Unknown: default: return ""; } } #ifdef PWIZ_READER_BRUKER #include "pwiz/utility/misc/SHA1Calculator.hpp" #include "SpectrumList_Bruker.hpp" #include "ChromatogramList_Bruker.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace msdata { using namespace pwiz::util; using namespace pwiz::msdata::detail; using namespace pwiz::msdata::detail::Bruker; using namespace pwiz::vendor_api::Bruker; // // Reader_Bruker // namespace { void initializeInstrumentConfigurationPtrs(MSData& msd, CompassDataPtr rawfile, const SoftwarePtr& instrumentSoftware) { CVID cvidSeries = translateAsInstrumentSeries(rawfile); // set common instrument parameters ParamGroupPtr commonInstrumentParams(new ParamGroup); commonInstrumentParams->id = "CommonInstrumentParams"; msd.paramGroupPtrs.push_back(commonInstrumentParams); if (!rawfile->getInstrumentDescription().empty()) commonInstrumentParams->userParams.push_back(UserParam("instrument model", rawfile->getInstrumentDescription())); commonInstrumentParams->set(cvidSeries); // create instrument configuration templates based on the instrument model vector configurations = createInstrumentConfigurations(rawfile); if (configurations.empty()) configurations.resize(1); // provide at least one configuration for (size_t i = 0; i < configurations.size(); ++i) { InstrumentConfigurationPtr ic = InstrumentConfigurationPtr(new InstrumentConfiguration(configurations[i])); ic->id = (boost::format("IC%d") % (i + 1)).str(); ic->paramGroupPtrs.push_back(commonInstrumentParams); ic->softwarePtr = instrumentSoftware; msd.instrumentConfigurationPtrs.push_back(ic); } } void fillInMetadata(const bfs::path& rootpath, MSData& msd, Reader_Bruker_Format format, CompassDataPtr compassDataPtr) { msd.cvs = defaultCVList(); msd.id = bfs::basename(rootpath); SoftwarePtr software(new Software); software->id = "CompassXtract"; software->set(MS_CompassXtract); software->version = "3.1.7"; msd.softwarePtrs.push_back(software); SoftwarePtr acquisitionSoftware(new Software); CVID acquisitionSoftwareCvid = translateAsAcquisitionSoftware(compassDataPtr); acquisitionSoftware->id = cvTermInfo(acquisitionSoftwareCvid).shortName(); acquisitionSoftware->set(acquisitionSoftwareCvid); acquisitionSoftware->version = compassDataPtr->getAcquisitionSoftwareVersion(); msd.softwarePtrs.push_back(acquisitionSoftware); SoftwarePtr softwarePwiz(new Software); softwarePwiz->id = "pwiz_Reader_Bruker"; softwarePwiz->set(MS_pwiz); softwarePwiz->version = pwiz::msdata::Version::str(); msd.softwarePtrs.push_back(softwarePwiz); DataProcessingPtr dpPwiz(new DataProcessing); dpPwiz->id = "pwiz_Reader_Bruker_conversion"; dpPwiz->processingMethods.push_back(ProcessingMethod()); dpPwiz->processingMethods.back().softwarePtr = softwarePwiz; dpPwiz->processingMethods.back().set(MS_Conversion_to_mzML); // give ownership of dpPwiz to the SpectrumList (and ChromatogramList) SpectrumList_Bruker* sl = dynamic_cast(msd.run.spectrumListPtr.get()); ChromatogramList_Bruker* cl = dynamic_cast(msd.run.chromatogramListPtr.get()); if (sl) sl->setDataProcessingPtr(dpPwiz); if (cl) cl->setDataProcessingPtr(dpPwiz); bool hasMS1 = false; bool hasMSn = false; size_t scan=1, end=compassDataPtr->getMSSpectrumCount(); if (format == Reader_Bruker_Format_FID) --scan, --end; for (; scan <= end && (!hasMS1 || !hasMSn); ++scan) { int msLevel = sl->getMSSpectrumPtr(scan, vendor_api::Bruker::DetailLevel_InstantMetadata)->getMSMSStage(); if (!hasMS1 && msLevel == 1) { hasMS1 = true; msd.fileDescription.fileContent.set(MS_MS1_spectrum); } else if (!hasMSn && msLevel > 1) { hasMSn = true; msd.fileDescription.fileContent.set(MS_MSn_spectrum); } } initializeInstrumentConfigurationPtrs(msd, compassDataPtr, acquisitionSoftware); if (!msd.instrumentConfigurationPtrs.empty()) msd.run.defaultInstrumentConfigurationPtr = msd.instrumentConfigurationPtrs[0]; msd.run.id = msd.id; msd.run.startTimeStamp = encode_xml_datetime(compassDataPtr->getAnalysisDateTime()); } } // namespace PWIZ_API_DECL void Reader_Bruker::read(const string& filename, const string& head, MSData& result, int runIndex, const Config& config) const { if (runIndex != 0) throw ReaderFail("[Reader_Bruker::read] multiple runs not supported"); Reader_Bruker_Format format = Bruker::format(filename); if (format == Reader_Bruker_Format_Unknown) throw ReaderFail("[Reader_Bruker::read] Path given is not a recognized Bruker format"); // trim filename from end of source path if necessary (it's not valid to pass to CompassXtract) bfs::path rootpath = filename; if (bfs::is_regular_file(rootpath)) rootpath = rootpath.branch_path(); CompassDataPtr compassDataPtr(CompassData::create(rootpath.string(), format)); SpectrumList_Bruker* sl = new SpectrumList_Bruker(result, rootpath.string(), format, compassDataPtr); ChromatogramList_Bruker* cl = new ChromatogramList_Bruker(result, rootpath.string(), format, compassDataPtr); result.run.spectrumListPtr = SpectrumListPtr(sl); result.run.chromatogramListPtr = ChromatogramListPtr(cl); fillInMetadata(rootpath, result, format, compassDataPtr); } } // namespace msdata } // namespace pwiz #else // PWIZ_READER_BRUKER // // non-MSVC implementation // namespace pwiz { namespace msdata { PWIZ_API_DECL void Reader_Bruker::read(const string& filename, const string& head, MSData& result, int sampleIndex /* = 0 */, const Config& config) const { throw ReaderFail("[Reader_Bruker::read()] Bruker Analysis reader not implemented: " #ifdef _MSC_VER // should be possible, apparently somebody decided to skip it "support was explicitly disabled when program was built" #elif defined(WIN32) // wrong compiler "program was built without COM support and cannot access CompassXtract DLLs - try building with MSVC instead of GCC" #else // wrong platform "requires CompassXtract which only works on Windows" #endif ); } } // namespace msdata } // namespace pwiz #endif // PWIZ_READER_BRUKER pwiz/pwiz/data/vendor_readers/Bruker/Reader_Bruker_Detail.hpp0000664000175100017510000000437512664775620026430 0ustar teamcityteamcity00000000000000// // $Id: Reader_Bruker_Detail.hpp 6478 2014-07-08 20:01:38Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _READER_BRUKER_DETAIL_HPP_ #define _READER_BRUKER_DETAIL_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/MSData.hpp" #include #include namespace pwiz { namespace vendor_api { namespace Bruker { struct CompassData; typedef boost::shared_ptr CompassDataPtr; } } } namespace pwiz { namespace msdata { namespace detail { namespace Bruker { PWIZ_API_DECL enum Reader_Bruker_Format { Reader_Bruker_Format_Unknown, Reader_Bruker_Format_FID, Reader_Bruker_Format_YEP, Reader_Bruker_Format_BAF, Reader_Bruker_Format_U2, Reader_Bruker_Format_BAF_and_U2 }; /// returns Bruker format of 'path' if it is a Bruker directory; /// otherwise returns empty string PWIZ_API_DECL Reader_Bruker_Format format(const std::string& path); PWIZ_API_DECL std::vector createInstrumentConfigurations(pwiz::vendor_api::Bruker::CompassDataPtr rawfile); PWIZ_API_DECL cv::CVID translateAsInstrumentSeries(pwiz::vendor_api::Bruker::CompassDataPtr rawfile); PWIZ_API_DECL cv::CVID translateAsAcquisitionSoftware(pwiz::vendor_api::Bruker::CompassDataPtr rawfile); } // namespace Bruker } // namespace detail } // namespace msdata } // namespace pwiz #ifdef PWIZ_READER_BRUKER #include "pwiz_aux/msrc/utility/vendor_api/Bruker/CompassData.hpp" using namespace pwiz::vendor_api::Bruker; #endif #endif // _READER_BRUKER_DETAIL_HPP_ pwiz/pwiz/data/vendor_readers/Bruker/Reader_Bruker_Detail.cpp0000664000175100017510000003367512664775620026430 0ustar teamcityteamcity00000000000000// // $Id: Reader_Bruker_Detail.cpp 8990 2015-10-14 14:08:24Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "Reader_Bruker_Detail.hpp" #include "pwiz/utility/misc/String.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include "boost/filesystem/convenience.hpp" #include "pwiz/data/msdata/Reader.hpp" using namespace pwiz::vendor_api::Bruker; namespace pwiz { namespace msdata { namespace detail { namespace Bruker { using namespace pwiz::util; Reader_Bruker_Format format(const string& path) { bfs::path sourcePath(path); // Make sure target "path" is actually a directory since // all Bruker formats are directory-based if (!bfs::is_directory(sourcePath)) { // Special cases for identifying direct paths to fid/Analysis.yep/Analysis.baf/.U2 // Note that direct paths to baf or u2 will fail to find a baf/u2 hybrid source std::string leaf = BFS_STRING(sourcePath.leaf()); bal::to_lower(leaf); if (leaf == "fid" && !bfs::exists(sourcePath.branch_path() / "analysis.baf")) return Reader_Bruker_Format_FID; else if(extension(sourcePath) == ".u2") return Reader_Bruker_Format_U2; else if(leaf == "analysis.yep") return Reader_Bruker_Format_YEP; else if(leaf == "analysis.baf") return Reader_Bruker_Format_BAF; else return Reader_Bruker_Format_Unknown; } // TODO: 1SRef is not the only possible substring below, get more examples! // Check for fid-based data; // Every directory within the queried directory should have a "1/1SRef" // subdirectory with a fid file in it, but we check only the first non-dotted // directory for efficiency. This can fail, but those failures are acceptable. // Alternatively, a directory closer to the fid file can be identified. // Caveat: BAF files may be accompanied by a fid, skip these cases! (?) const static bfs::directory_iterator endItr; bfs::directory_iterator itr(sourcePath); for (; itr != endItr; ++itr) if (bfs::is_directory(itr->status())) { if (BFS_STRING(itr->path().leaf())[0] == '.') // HACK: skip ".svn" continue; else if (bfs::exists(itr->path() / "1/1SRef/fid") || bfs::exists(itr->path() / "1SRef/fid") || bfs::exists(itr->path() / "1/1SLin/fid") || bfs::exists(itr->path() / "1SLin/fid") || bfs::exists(itr->path() / "1/1Ref/fid") || bfs::exists(itr->path() / "1Ref/fid") || bfs::exists(itr->path() / "1/1Lin/fid") || bfs::exists(itr->path() / "1Lin/fid") || (bfs::exists(itr->path() / "fid") && !bfs::exists(itr->path() / "Analysis.baf") && !bfs::exists(itr->path() / "analysis.baf")) || (bfs::exists(sourcePath / "fid") && !bfs::exists(sourcePath / "Analysis.baf") && !bfs::exists(sourcePath / "analysis.baf"))) return Reader_Bruker_Format_FID; else break; } // Check for yep-based data; // The directory should have a file named "Analysis.yep" if (bfs::exists(sourcePath / "Analysis.yep") || bfs::exists(sourcePath / "analysis.yep")) return Reader_Bruker_Format_YEP; bfs::path sourceDirectory = *(--sourcePath.end()); // Check for baf-based data; // The directory should have a file named "Analysis.baf" if (bfs::exists(sourcePath / "Analysis.baf") || bfs::exists(sourcePath / "analysis.baf")) { // Check for baf/u2 hybrid data if (bfs::exists(sourcePath / sourceDirectory.replace_extension(".u2"))) return Reader_Bruker_Format_BAF_and_U2; else return Reader_Bruker_Format_BAF; } // Check for u2-based data; // The directory should have a file named ".u2" if (bfs::exists(sourcePath / sourceDirectory.replace_extension(".u2"))) return Reader_Bruker_Format_U2; return Reader_Bruker_Format_Unknown; } #ifdef PWIZ_READER_BRUKER std::vector createInstrumentConfigurations(CompassDataPtr rawfile) { vector configurations; MSSpectrumPtr firstSpectrum = rawfile->getMSSpectrum(1); MSSpectrumParameterListPtr parametersPtr = firstSpectrum->parameters(); const MSSpectrumParameterList& parameters = *parametersPtr; map parameterMap; BOOST_FOREACH(const MSSpectrumParameter& p, parameters) parameterMap[p.name] = p.value; switch (rawfile->getInstrumentSource()) { case InstrumentSource_AP_MALDI: configurations.push_back(InstrumentConfiguration()); configurations.back().componentList.push_back(Component(MS_AP_MALDI, 1)); break; case InstrumentSource_MALDI: configurations.push_back(InstrumentConfiguration()); configurations.back().componentList.push_back(Component(MS_MALDI, 1)); break; case InstrumentSource_ESI: case InstrumentSource_MULTI_MODE: case InstrumentSource_Ultraspray: configurations.push_back(InstrumentConfiguration()); configurations.back().componentList.push_back(Component(MS_ESI, 1)); configurations.back().componentList.back().set(MS_electrospray_inlet); break; case InstrumentSource_NANO_ESI_OFFLINE: case InstrumentSource_NANO_ESI_ONLINE: case InstrumentSource_NANO_FLOW_ESI: case InstrumentSource_CaptiveSpray: configurations.push_back(InstrumentConfiguration()); configurations.back().componentList.push_back(Component(MS_nanoelectrospray, 1)); configurations.back().componentList.back().set(MS_nanospray_inlet); break; case InstrumentSource_APCI: case InstrumentSource_GC_APCI: configurations.push_back(InstrumentConfiguration()); configurations.back().componentList.push_back(Component(MS_atmospheric_pressure_chemical_ionization, 1)); break; case InstrumentSource_APPI: configurations.push_back(InstrumentConfiguration()); configurations.back().componentList.push_back(Component(MS_atmospheric_pressure_photoionization, 1)); break; case InstrumentSource_EI: configurations.push_back(InstrumentConfiguration()); configurations.back().componentList.push_back(Component(MS_electron_ionization, 1)); break; case InstrumentSource_AlsoUnknown: case InstrumentSource_Unknown: { switch (rawfile->getInstrumentFamily()) { case InstrumentFamily_Trap: case InstrumentFamily_OTOF: case InstrumentFamily_OTOFQ: case InstrumentFamily_maXis: configurations.push_back(InstrumentConfiguration()); configurations.back().componentList.push_back(Component(MS_ESI, 1)); configurations.back().componentList.back().set(MS_electrospray_inlet); break; case InstrumentFamily_MaldiTOF: case InstrumentFamily_BioTOF: case InstrumentFamily_BioTOFQ: configurations.push_back(InstrumentConfiguration()); configurations.back().componentList.push_back(Component(MS_MALDI, 1)); break; case InstrumentFamily_FTMS: case InstrumentFamily_solariX: configurations.push_back(InstrumentConfiguration()); if (parameterMap["Mobile Hexapole Position"] == "MALDI") // HACK: I haven't seen enough data to know whether this is robust. configurations.back().componentList.push_back(Component(MS_MALDI, 1)); else { configurations.back().componentList.push_back(Component(MS_ESI, 1)); configurations.back().componentList.back().set(MS_electrospray_inlet); } break; case InstrumentFamily_Unknown: break; // unknown configuration default: throw runtime_error("[Reader_Bruker::createInstrumentConfigurations] no case for InstrumentFamily " + lexical_cast(rawfile->getInstrumentFamily())); } break; } // InstrumentSource_Unknown default: throw runtime_error("[Reader_Bruker::createInstrumentConfigurations] no case for InstrumentSource " + lexical_cast(rawfile->getInstrumentSource())); } switch (rawfile->getInstrumentFamily()) { case InstrumentFamily_Trap: configurations.back().componentList.push_back(Component(MS_radial_ejection_linear_ion_trap, 2)); configurations.back().componentList.push_back(Component(MS_electron_multiplier, 3)); break; case InstrumentFamily_OTOF: case InstrumentFamily_MaldiTOF: configurations.back().componentList.push_back(Component(MS_time_of_flight, 2)); configurations.back().componentList.push_back(Component(MS_multichannel_plate, 3)); configurations.back().componentList.push_back(Component(MS_photomultiplier, 4)); break; case InstrumentFamily_OTOFQ: case InstrumentFamily_BioTOFQ: case InstrumentFamily_maXis: configurations.back().componentList.push_back(Component(MS_quadrupole, 2)); configurations.back().componentList.push_back(Component(MS_quadrupole, 3)); configurations.back().componentList.push_back(Component(MS_time_of_flight, 4)); configurations.back().componentList.push_back(Component(MS_multichannel_plate, 5)); configurations.back().componentList.push_back(Component(MS_photomultiplier, 6)); break; case InstrumentFamily_FTMS: case InstrumentFamily_solariX: configurations.back().componentList.push_back(Component(MS_FT_ICR, 2)); configurations.back().componentList.push_back(Component(MS_inductive_detector, 3)); break; default: case InstrumentFamily_Unknown: break; // unknown configuration } return configurations; } PWIZ_API_DECL cv::CVID translateAsInstrumentSeries(CompassDataPtr rawfile) { switch (rawfile->getInstrumentFamily()) { case InstrumentFamily_Trap: return MS_Bruker_Daltonics_HCT_Series; // or amazon case InstrumentFamily_OTOF: return MS_Bruker_Daltonics_micrOTOF_series; case InstrumentFamily_OTOFQ: return MS_Bruker_Daltonics_micrOTOF_series; // or ultroTOF case InstrumentFamily_BioTOF: return MS_Bruker_Daltonics_BioTOF_series; case InstrumentFamily_BioTOFQ: return MS_Bruker_Daltonics_BioTOF_series; case InstrumentFamily_MaldiTOF: return MS_Bruker_Daltonics_flex_series; case InstrumentFamily_FTMS: return MS_Bruker_Daltonics_apex_series; // or solarix case InstrumentFamily_maXis: return MS_Bruker_Daltonics_maXis_series; default: case InstrumentFamily_Unknown: return MS_Bruker_Daltonics_instrument_model; } } PWIZ_API_DECL cv::CVID translateAsAcquisitionSoftware(CompassDataPtr rawfile) { string name = rawfile->getAcquisitionSoftware(); if (name.empty()) // fall back on instrument family switch (rawfile->getInstrumentFamily()) { case InstrumentFamily_Trap: return MS_HCTcontrol; case InstrumentFamily_OTOF: return MS_micrOTOFcontrol; case InstrumentFamily_OTOFQ: return MS_micrOTOFcontrol; case InstrumentFamily_BioTOF: return MS_Compass; case InstrumentFamily_BioTOFQ: return MS_Compass; case InstrumentFamily_MaldiTOF: return MS_FlexControl; case InstrumentFamily_FTMS: return MS_apexControl; case InstrumentFamily_maXis: return MS_Compass; default: case InstrumentFamily_Unknown: return MS_Compass; } if (bal::icontains(name, "HCT")) return MS_HCTcontrol; if (bal::icontains(name, "oTOFcontrol")) return MS_micrOTOFcontrol; if (bal::icontains(name, "Compass")) return MS_Compass; if (bal::icontains(name, "Apex")) return MS_apexControl; if (bal::icontains(name, "Flex")) return MS_FlexControl; return MS_Compass; // default to Compass } #else PWIZ_API_DECL std::vector createInstrumentConfigurations(CompassDataPtr rawfile) { throw runtime_error("Reader_Bruker not implemented"); } PWIZ_API_DECL cv::CVID translateAsInstrumentSeries(CompassDataPtr rawfile) { throw runtime_error("Reader_Bruker not implemented"); } PWIZ_API_DECL cv::CVID translateAsAcquisitionSoftware(CompassDataPtr rawfile) { throw runtime_error("Reader_Bruker not implemented"); } #endif } // namespace Bruker } // namespace detail } // namespace msdata } // namespace pwiz pwiz/pwiz/data/vendor_readers/Bruker/ChromatogramList_Bruker.hpp0000664000175100017510000000452212664775620027215 0ustar teamcityteamcity00000000000000// // $Id: ChromatogramList_Bruker.hpp 6478 2014-07-08 20:01:38Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/ChromatogramListBase.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Container.hpp" #include "pwiz/utility/misc/String.hpp" #include "pwiz/utility/misc/Stream.hpp" #include "Reader_Bruker_Detail.hpp" using boost::shared_ptr; namespace pwiz { namespace msdata { namespace detail { // // ChromatogramList_Bruker // class PWIZ_API_DECL ChromatogramList_Bruker : public ChromatogramListBase { public: virtual size_t size() const; virtual const ChromatogramIdentity& chromatogramIdentity(size_t index) const; virtual size_t find(const string& id) const; virtual ChromatogramPtr chromatogram(size_t index, bool getBinaryData) const; #ifdef PWIZ_READER_BRUKER ChromatogramList_Bruker(MSData& msd, const string& rootpath, Bruker::Reader_Bruker_Format format, CompassDataPtr compassDataPtr); private: MSData& msd_; bfs::path rootpath_; Bruker::Reader_Bruker_Format format_; CompassDataPtr compassDataPtr_; size_t size_; struct IndexEntry : public ChromatogramIdentity { CVID chromatogramType; size_t declaration; long trace; }; vector index_; // idToIndexMap_["scan=<#>" or "file="] == index map idToIndexMap_; void createIndex(); #endif // PWIZ_READER_BRUKER }; } // detail } // msdata } // pwiz pwiz/pwiz/data/vendor_readers/Bruker/ChromatogramList_Bruker.cpp0000664000175100017510000001364412664775620027215 0ustar teamcityteamcity00000000000000// // $Id: ChromatogramList_Bruker.cpp 6478 2014-07-08 20:01:38Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "ChromatogramList_Bruker.hpp" #ifdef PWIZ_READER_BRUKER #include "pwiz/data/msdata/MSData.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/IntegerSet.hpp" #include "pwiz/utility/misc/SHA1Calculator.hpp" #include "pwiz/utility/misc/automation_vector.h" using namespace pwiz::util; using namespace pwiz::vendor_api::Bruker; namespace pwiz { namespace msdata { namespace detail { using namespace Bruker; PWIZ_API_DECL ChromatogramList_Bruker::ChromatogramList_Bruker(MSData& msd, const string& rootpath, Reader_Bruker_Format format, CompassDataPtr compassDataPtr) : msd_(msd), rootpath_(rootpath), format_(format), compassDataPtr_(compassDataPtr), size_(0) { switch (format_) { case Reader_Bruker_Format_U2: //size_ = compassXtractWrapperPtr->traceDeclarations_.size(); break; } createIndex(); } PWIZ_API_DECL size_t ChromatogramList_Bruker::size() const { return size_; } PWIZ_API_DECL const ChromatogramIdentity& ChromatogramList_Bruker::chromatogramIdentity(size_t index) const { if (index > size_) throw runtime_error(("[ChromatogramList_Bruker::chromatogramIdentity()] Bad index: " + lexical_cast(index)).c_str()); return index_[index]; } PWIZ_API_DECL size_t ChromatogramList_Bruker::find(const string& id) const { map::const_iterator scanItr = idToIndexMap_.find(id); if (scanItr == idToIndexMap_.end()) return size_; return scanItr->second; } PWIZ_API_DECL ChromatogramPtr ChromatogramList_Bruker::chromatogram(size_t index, bool getBinaryData) const { if (index > size_) throw runtime_error(("[ChromatogramList_Bruker::chromatogram()] Bad index: " + lexical_cast(index)).c_str()); // allocate a new Spectrum ChromatogramPtr result(new Chromatogram); if (!result.get()) throw runtime_error("[ChromatogramList_Bruker::chromatogram()] Allocation error."); const IndexEntry& ci = index_[index]; result->index = ci.index; result->id = ci.id; result->set(ci.chromatogramType); /*try { automation_vector xArray(*trace->GetTimes(), automation_vector::MOVE); if (getBinaryData) { result->setTimeIntensityArrays(vector(), vector(), UO_second, MS_number_of_detector_counts); result->getTimeArray()->data.assign(xArray.begin(), xArray.end()); automation_vector yArray(*trace->GetValues(), automation_vector::MOVE); result->getIntensityArray()->data.assign(yArray.begin(), yArray.end()); } else result->defaultArrayLength = xArray.size(); } catch (_com_error& e) // not caught by either std::exception or '...' { throw runtime_error(string("[ChromatogramList_Bruker::chromatogram()] COM error: ") + (const char*)e.Description()); }*/ return result; } PWIZ_API_DECL void ChromatogramList_Bruker::createIndex() { /*if (format_ == Reader_Bruker_Format_U2) { CompassXtractWrapper::LC_TraceDeclarationList& tdList = compassXtractWrapperPtr_->traceDeclarations_; CompassXtractWrapper::LC_AnalysisPtr& analysis = compassXtractWrapperPtr_->lcAnalysis_; for (size_t i=0; i < tdList.size(); ++i) { long tId = tdList[i]->GetTraceId(); CompassXtractWrapper::LC_TraceDeclarationPtr& td = compassXtractWrapperPtr_->traceDeclarations_[i]; if (td->GetTraceUnit() == BDal_CXt_Lc_Interfaces::Unit_Intensity) { index_.push_back(IndexEntry()); IndexEntry& ci = index_.back(); ci.declaration = i; ci.trace = tId; ci.index = index_.size()-1; ci.id = "declaration=" + lexical_cast(i) + " trace=" + lexical_cast(tId); ci.chromatogramType = MS_TIC_chromatogram; idToIndexMap_[ci.id] = ci.index; } //else // throw runtime_error("[ChromatogramList_Bruker::chromatogram()] unexpected TraceUnit"); } }*/ } } // detail } // msdata } // pwiz #else // PWIZ_READER_BRUKER // // non-MSVC implementation // namespace pwiz { namespace msdata { namespace detail { namespace {const ChromatogramIdentity emptyIdentity;} size_t ChromatogramList_Bruker::size() const {return 0;} const ChromatogramIdentity& ChromatogramList_Bruker::chromatogramIdentity(size_t index) const {return emptyIdentity;} size_t ChromatogramList_Bruker::find(const string& id) const {return 0;} ChromatogramPtr ChromatogramList_Bruker::chromatogram(size_t index, bool getBinaryData) const {return ChromatogramPtr();} } // detail } // msdata } // pwiz #endif // PWIZ_READER_BRUKER pwiz/pwiz/data/vendor_readers/Bruker/Reader_Bruker.hpp0000664000175100017510000000360612664775620025142 0ustar teamcityteamcity00000000000000// // $Id: Reader_Bruker.hpp 3808 2012-07-24 20:31:10Z donmarsh $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _READER_BRUKER_HPP_ #define _READER_BRUKER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/Reader.hpp" namespace pwiz { namespace msdata { class PWIZ_API_DECL Reader_Bruker : public Reader { public: virtual std::string identify(const std::string& filename, const std::string& head) const; virtual void read(const std::string& filename, const std::string& head, MSData& result, int runIndex = 0, const Config& config = Config()) const; virtual void read(const std::string& filename, const std::string& head, std::vector& results, const Config& config = Config()) const { results.push_back(MSDataPtr(new MSData)); read(filename, head, *results.back(), 0, config); } virtual const char * getType() const {return "Bruker Analysis";} }; } // namespace msdata } // namespace pwiz #endif // _READER_BRUKER_HPP_ pwiz/pwiz/data/vendor_readers/Bruker/SpectrumList_Bruker.cpp0000664000175100017510000005634012664775620026374 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_Bruker.cpp 7127 2015-01-27 18:41:39Z pcbrefugee $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_Bruker.hpp" #ifdef PWIZ_READER_BRUKER #include "pwiz/data/msdata/MSData.hpp" #include "pwiz/utility/misc/automation_vector.h" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/IntegerSet.hpp" #include "pwiz/utility/misc/SHA1Calculator.hpp" #include "pwiz/utility/minimxml/XMLWriter.hpp" #include using namespace pwiz::util; using namespace pwiz::minimxml; using namespace pwiz::vendor_api::Bruker; namespace pwiz { namespace msdata { namespace detail { using namespace Bruker; PWIZ_API_DECL SpectrumList_Bruker::SpectrumList_Bruker(MSData& msd, const string& rootpath, Reader_Bruker_Format format, CompassDataPtr compassDataPtr) : msd_(msd), rootpath_(rootpath), format_(format), compassDataPtr_(compassDataPtr), size_(0) { fillSourceList(); createIndex(); } PWIZ_API_DECL size_t SpectrumList_Bruker::size() const { return size_; } PWIZ_API_DECL const SpectrumIdentity& SpectrumList_Bruker::spectrumIdentity(size_t index) const { if (index >= size_) throw runtime_error(("[SpectrumList_Bruker::spectrumIdentity()] Bad index: " + lexical_cast(index)).c_str()); return index_[index]; } PWIZ_API_DECL size_t SpectrumList_Bruker::find(const string& id) const { boost::container::flat_map::const_iterator scanItr = idToIndexMap_.find(id); if (scanItr == idToIndexMap_.end()) return size_; return scanItr->second; } MSSpectrumPtr SpectrumList_Bruker::getMSSpectrumPtr(size_t scan, vendor_api::Bruker::DetailLevel detailLevel) const { if (format_ == Reader_Bruker_Format_FID) { compassDataPtr_ = CompassData::create(sourcePaths_[scan].string()); return compassDataPtr_->getMSSpectrum(1, detailLevel); } return compassDataPtr_->getMSSpectrum(scan, detailLevel); } PWIZ_API_DECL SpectrumPtr SpectrumList_Bruker::spectrum(size_t index, bool getBinaryData) const { return spectrum(index, getBinaryData, MSLevelsNone); } PWIZ_API_DECL SpectrumPtr SpectrumList_Bruker::spectrum(size_t index, DetailLevel detailLevel) const { return spectrum(index, detailLevel, MSLevelsNone); } PWIZ_API_DECL SpectrumPtr SpectrumList_Bruker::spectrum(size_t index, bool getBinaryData, const pwiz::util::IntegerSet& msLevelsToCentroid) const { return spectrum(index, getBinaryData ? DetailLevel_FullData : DetailLevel_FullMetadata, msLevelsToCentroid); } PWIZ_API_DECL SpectrumPtr SpectrumList_Bruker::spectrum(size_t index, DetailLevel detailLevel, const pwiz::util::IntegerSet& msLevelsToCentroid) const { if (index >= size_) throw runtime_error(("[SpectrumList_Bruker::spectrum()] Bad index: " + lexical_cast(index)).c_str()); // allocate a new Spectrum SpectrumPtr result(new Spectrum); if (!result.get()) throw runtime_error("[SpectrumList_Bruker::spectrum()] Allocation error."); vendor_api::Bruker::DetailLevel brukerDetailLevel; switch (detailLevel) { case DetailLevel_InstantMetadata: case DetailLevel_FastMetadata: brukerDetailLevel = vendor_api::Bruker::DetailLevel_InstantMetadata; break; case DetailLevel_FullMetadata: brukerDetailLevel = vendor_api::Bruker::DetailLevel_FullMetadata; break; default: case DetailLevel_FullData: brukerDetailLevel = vendor_api::Bruker::DetailLevel_FullData; break; } const IndexEntry& si = index_[index]; result->index = si.index; result->id = si.id; // the scan element may be empty for MALDI spectra, but it's required for a valid file result->scanList.set(MS_no_combination); result->scanList.scans.push_back(Scan()); Scan& scan = result->scanList.scans[0]; scan.instrumentConfigurationPtr = msd_.run.defaultInstrumentConfigurationPtr; //try //{ // is this spectrum from the LC interface? if (si.collection > -1) { // fill the spectrum from the LC interface LCSpectrumSourcePtr source = compassDataPtr_->getLCSource(si.source); LCSpectrumPtr spectrum = compassDataPtr_->getLCSpectrum(si.source, si.scan); if (source->getXAxisUnit() == LCUnit_NanoMeter) result->set(MS_EMR_spectrum); else throw runtime_error("[SpectrumList_Bruker::spectrum()] unexpected XAxisUnit"); double scanTime = spectrum->getTime(); if (scanTime > 0) scan.set(MS_scan_start_time, scanTime, UO_minute); result->set(MS_profile_spectrum); vector lcX; source->getXAxis(lcX); if (detailLevel == DetailLevel_FullData) { result->setMZIntensityArrays(vector(), vector(), MS_number_of_detector_counts); result->defaultArrayLength = lcX.size(); BinaryDataArrayPtr mzArray = result->getMZArray(); vector::iterator itr = boost::range::find_if(mzArray->cvParams, CVParamIs(MS_m_z_array)); *itr = CVParam(MS_wavelength_array); swap(mzArray->data, lcX); vector lcY; spectrum->getData(lcY); swap(result->getIntensityArray()->data, lcY); } else result->defaultArrayLength = lcX.size(); return result; } // get the spectrum from MS interface; for FID formats scan is 0-based, else it's 1-based MSSpectrumPtr spectrum = getMSSpectrumPtr(si.scan, brukerDetailLevel); int msLevel = spectrum->getMSMSStage(); result->set(MS_ms_level, msLevel); if (msLevel == 1) result->set(MS_MS1_spectrum); else result->set(MS_MSn_spectrum); double scanTime = spectrum->getRetentionTime(); if (scanTime > 0) scan.set(MS_scan_start_time, scanTime, UO_second); IonPolarity polarity = spectrum->getPolarity(); switch (polarity) { case IonPolarity_Negative: result->set(MS_negative_scan); break; case IonPolarity_Positive: result->set(MS_positive_scan); break; default: break; } // Enumerating the parameter list is not instant. if (detailLevel == DetailLevel_InstantMetadata) return result; //sd.set(MS_base_peak_m_z, pScanStats_->BPM); if (spectrum->getTIC() > 0) { result->set(MS_base_peak_intensity, spectrum->getBPI()); result->set(MS_total_ion_current, spectrum->getTIC()); } //sd.set(MS_lowest_observed_m_z, minObservedMz); //sd.set(MS_highest_observed_m_z, maxObservedMz); pair scanRange = spectrum->getScanRange(); if (scanRange.first > 0 && scanRange.second > 0) scan.scanWindows.push_back(ScanWindow(scanRange.first, scanRange.second, MS_m_z)); if (msLevel > 1) { Precursor precursor; vector fragMZs, isolMZs; vector fragModes; vector isolModes; spectrum->getFragmentationData(fragMZs, fragModes); if (!fragMZs.empty()) { spectrum->getIsolationData(isolMZs, isolModes); for (size_t i=0; i < fragMZs.size(); ++i) { if (fragMZs[i] > 0) { SelectedIon selectedIon(fragMZs[i]); int charge = spectrum->getChargeState(); if (charge > 0) selectedIon.set(MS_charge_state, charge); switch (fragModes[i]) { case FragmentationMode_CID: precursor.activation.set(MS_CID); break; case FragmentationMode_ETD: precursor.activation.set(MS_ETD); break; case FragmentationMode_CIDETD_CID: precursor.activation.set(MS_CID); precursor.activation.set(MS_ETD); break; case FragmentationMode_CIDETD_ETD: precursor.activation.set(MS_CID); precursor.activation.set(MS_ETD); break; case FragmentationMode_ISCID: precursor.activation.set(MS_in_source_collision_induced_dissociation); break; case FragmentationMode_ECD: precursor.activation.set(MS_ECD); break; case FragmentationMode_IRMPD: precursor.activation.set(MS_IRMPD); break; case FragmentationMode_PTR: break; } //precursor.activation.set(MS_collision_energy, pExScanStats_->CollisionEnergy); precursor.selectedIons.push_back(selectedIon); } if (isolMZs[i] > 0) { precursor.isolationWindow.set(MS_isolation_window_target_m_z, isolMZs[i], MS_m_z); double isolationWidth = spectrum->getIsolationWidth(); if (isolationWidth > 0) { precursor.isolationWindow.set(MS_isolation_window_lower_offset, isolationWidth / 2, MS_m_z); precursor.isolationWindow.set(MS_isolation_window_upper_offset, isolationWidth / 2, MS_m_z); } } } } if (precursor.selectedIons.size() > 0 || !precursor.isolationWindow.empty()) result->precursors.push_back(precursor); } if (detailLevel == DetailLevel_FullData) { bool getLineData = msLevelsToCentroid.contains(msLevel); result->setMZIntensityArrays(vector(), vector(), MS_number_of_detector_counts); automation_vector mzArray, intensityArray; if (!getLineData) { spectrum->getProfileData(mzArray, intensityArray); if (mzArray.size() == 0) getLineData = true; // We preferred profile, but there isn't any - try centroided else result->set(MS_profile_spectrum); } if (getLineData) { result->set(MS_centroid_spectrum); // Declare this as centroided data even if scan is empty spectrum->getLineData(mzArray, intensityArray); if (mzArray.size() > 0) { result->set(MS_profile_spectrum); // let SpectrumList_PeakPicker know this was probably also a profile spectrum, but doesn't need conversion (actually checking for profile data is crazy slow) } } result->getMZArray()->data.assign(mzArray.begin(), mzArray.end()); result->getIntensityArray()->data.assign(intensityArray.begin(), intensityArray.end()); result->defaultArrayLength = mzArray.size(); } else if (detailLevel == DetailLevel_FullMetadata) { // N.B.: just getting the data size from the Bruker API is quite expensive. if (msLevelsToCentroid.contains(msLevel) || ((result->defaultArrayLength = spectrum->getProfileDataSize())==0)) { result->defaultArrayLength = spectrum->getLineDataSize(); result->set(MS_centroid_spectrum); } else { result->set(MS_profile_spectrum); } } /*} catch (_com_error& e) // not caught by either std::exception or '...' { throw runtime_error(string("[SpectrumList_Bruker::spectrum()] COM error: ") + (const char*)e.Description()); }*/ return result; } namespace { void recursivelyEnumerateFIDs(vector& fidPaths, const bfs::path& rootpath) { const static bfs::directory_iterator endItr = bfs::directory_iterator(); if (rootpath.leaf() == "fid") fidPaths.push_back(rootpath.branch_path()); else if (bfs::is_directory(rootpath)) { for (bfs::directory_iterator itr(rootpath); itr != endItr; ++itr) recursivelyEnumerateFIDs(fidPaths, itr->path()); } } void addSource(MSData& msd, const bfs::path& sourcePath, const bfs::path& rootPath) { SourceFilePtr sourceFile(new SourceFile); sourceFile->id = sourcePath.string(); sourceFile->name = BFS_STRING(sourcePath.leaf()); // sourcePath: \Analysis.yep|\Analysis.baf|\fid // rootPath: c:\path\to\[\Analysis.yep|Analysis.baf|fid] bfs::path location = rootPath.has_branch_path() ? BFS_COMPLETE(rootPath.branch_path() / sourcePath) : BFS_COMPLETE(sourcePath); // uses initial path sourceFile->location = "file://" + location.branch_path().string(); msd.fileDescription.sourceFilePtrs.push_back(sourceFile); } } // namespace #if BOOST_FILESYSTEM_VERSION == 2 # define NATIVE_PATH_SLASH "/" #else # define NATIVE_PATH_SLASH "\\" #endif PWIZ_API_DECL void SpectrumList_Bruker::fillSourceList() { switch (format_) { case Reader_Bruker_Format_FID: recursivelyEnumerateFIDs(sourcePaths_, rootpath_); // each fid's source path is a directory but the source file is the fid for (size_t i=0; i < sourcePaths_.size(); ++i) { // in "/foo/bar/1/1SRef/fid", replace "/foo/bar/" with "" so relativePath is "1/1SRef/fid" bfs::path relativePath = sourcePaths_[i] / "fid"; if (rootpath_.has_branch_path()) relativePath = bal::replace_first_copy(relativePath.string(), rootpath_.branch_path().string() + NATIVE_PATH_SLASH, ""); relativePath = bal::replace_all_copy(relativePath.string(), NATIVE_PATH_SLASH, "/"); addSource(msd_, relativePath, rootpath_); msd_.fileDescription.sourceFilePtrs.back()->set(MS_Bruker_FID_nativeID_format); msd_.fileDescription.sourceFilePtrs.back()->set(MS_Bruker_FID_format); } break; // a YEP's source path is the same as the source file case Reader_Bruker_Format_YEP: { sourcePaths_.push_back(rootpath_ / "Analysis.yep"); // strip parent path to get "bar.d/Analysis.yep" bfs::path relativePath = bfs::path(rootpath_.filename()) / "Analysis.yep"; addSource(msd_, relativePath, rootpath_); msd_.fileDescription.sourceFilePtrs.back()->set(MS_Bruker_Agilent_YEP_nativeID_format); msd_.fileDescription.sourceFilePtrs.back()->set(MS_Bruker_Agilent_YEP_format); msd_.run.defaultSourceFilePtr = msd_.fileDescription.sourceFilePtrs.back(); } break; // a BAF's source path is the same as the source file case Reader_Bruker_Format_BAF: { sourcePaths_.push_back(rootpath_ / "Analysis.baf"); // strip parent path to get "bar.d/Analysis.baf" bfs::path relativePath = bfs::path(rootpath_.filename()) / "Analysis.baf"; addSource(msd_, relativePath, rootpath_); msd_.fileDescription.sourceFilePtrs.back()->set(MS_Bruker_BAF_nativeID_format); msd_.fileDescription.sourceFilePtrs.back()->set(MS_Bruker_BAF_format); msd_.run.defaultSourceFilePtr = msd_.fileDescription.sourceFilePtrs.back(); } break; // a BAF/U2 combo has two sources, with different nativeID formats case Reader_Bruker_Format_BAF_and_U2: { sourcePaths_.push_back(rootpath_ / "Analysis.baf"); // strip parent path to get "bar.d/Analysis.baf" bfs::path relativePath = bfs::path(rootpath_.filename()) / "Analysis.baf"; addSource(msd_, relativePath, rootpath_); msd_.fileDescription.sourceFilePtrs.back()->set(MS_Bruker_BAF_nativeID_format); msd_.fileDescription.sourceFilePtrs.back()->set(MS_Bruker_BAF_format); msd_.run.defaultSourceFilePtr = msd_.fileDescription.sourceFilePtrs.back(); } { sourcePaths_.push_back(bfs::change_extension(rootpath_, ".u2")); // in "/foo/bar.d/bar.u2", replace "/foo/" with "" so relativePath is "bar.d/bar.u2" bfs::path relativePath = sourcePaths_.back(); if (rootpath_.has_branch_path()) relativePath = bal::replace_first_copy(relativePath.string(), rootpath_.branch_path().string() + NATIVE_PATH_SLASH, ""); relativePath = bal::replace_all_copy(relativePath.string(), NATIVE_PATH_SLASH, "/"); addSource(msd_, relativePath, rootpath_); msd_.fileDescription.sourceFilePtrs.back()->set(MS_Bruker_U2_nativeID_format); msd_.fileDescription.sourceFilePtrs.back()->set(MS_Bruker_U2_format); } break; case Reader_Bruker_Format_U2: { sourcePaths_.push_back(bfs::change_extension(rootpath_, ".u2")); // in "/foo/bar.d/bar.u2", replace "/foo/" with "" so relativePath is "bar.d/bar.u2" bfs::path relativePath = sourcePaths_.back(); if (rootpath_.has_branch_path()) relativePath = bal::replace_first_copy(relativePath.string(), rootpath_.branch_path().string() + NATIVE_PATH_SLASH, ""); relativePath = bal::replace_all_copy(relativePath.string(), NATIVE_PATH_SLASH, "/"); addSource(msd_, relativePath, rootpath_); msd_.fileDescription.sourceFilePtrs.back()->set(MS_Bruker_U2_nativeID_format); msd_.fileDescription.sourceFilePtrs.back()->set(MS_Bruker_U2_format); msd_.run.defaultSourceFilePtr = msd_.fileDescription.sourceFilePtrs.back(); } break; } } PWIZ_API_DECL void SpectrumList_Bruker::createIndex() { map idToIndexTempMap; if (format_ == Reader_Bruker_Format_U2 || format_ == Reader_Bruker_Format_BAF_and_U2) { msd_.fileDescription.fileContent.set(MS_EMR_spectrum); for (size_t i=0, end=compassDataPtr_->getLCSourceCount(); i < end; ++i) { LCSpectrumSourcePtr source = compassDataPtr_->getLCSource(i); for (size_t scan=0, end=compassDataPtr_->getLCSpectrumCount(i); scan < end; ++scan) { index_.push_back(IndexEntry()); IndexEntry& si = index_.back(); si.source = i; si.collection = source->getCollectionId(); si.scan = scan; si.index = index_.size()-1; si.id = "collection=" + lexical_cast(si.collection) + " scan=" + lexical_cast(si.scan); idToIndexTempMap[si.id] = si.index; } } } if (format_ == Reader_Bruker_Format_FID) { int scan = -1; BOOST_FOREACH(const SourceFilePtr& sf, msd_.fileDescription.sourceFilePtrs) { index_.push_back(IndexEntry()); IndexEntry& si = index_.back(); si.source = si.collection = -1; si.index = index_.size()-1; si.scan = ++scan; si.id = "file=" + encode_xml_id_copy(sf->id); idToIndexTempMap[si.id] = si.index; } } else if (format_ != Reader_Bruker_Format_U2) { for (size_t scan=1, end=compassDataPtr_->getMSSpectrumCount(); scan <= end; ++scan) { index_.push_back(IndexEntry()); IndexEntry& si = index_.back(); si.source = si.collection = -1; si.index = index_.size()-1; si.scan = scan; si.id = "scan=" + lexical_cast(si.scan); idToIndexTempMap[si.id] = si.index; } } idToIndexMap_.reserve(idToIndexTempMap.size()); idToIndexMap_.insert(boost::container::ordered_unique_range, idToIndexTempMap.begin(), idToIndexTempMap.end()); size_ = index_.size(); } } // detail } // msdata } // pwiz #else // PWIZ_READER_BRUKER // // non-MSVC implementation // namespace pwiz { namespace msdata { namespace detail { namespace {const SpectrumIdentity emptyIdentity;} size_t SpectrumList_Bruker::size() const {return 0;} const SpectrumIdentity& SpectrumList_Bruker::spectrumIdentity(size_t index) const {return emptyIdentity;} size_t SpectrumList_Bruker::find(const std::string& id) const {return 0;} SpectrumPtr SpectrumList_Bruker::spectrum(size_t index, bool getBinaryData) const {return SpectrumPtr();} SpectrumPtr SpectrumList_Bruker::spectrum(size_t index, DetailLevel detailLevel) const {return SpectrumPtr();} SpectrumPtr SpectrumList_Bruker::spectrum(size_t index, bool getBinaryData, const pwiz::util::IntegerSet& msLevelsToCentroid) const {return SpectrumPtr();} SpectrumPtr SpectrumList_Bruker::spectrum(size_t index, DetailLevel detailLevel, const pwiz::util::IntegerSet& msLevelsToCentroid) const {return SpectrumPtr();} } // detail } // msdata } // pwiz #endif // PWIZ_READER_BRUKER pwiz/pwiz/data/vendor_readers/ExtendedReaderList.hpp0000775000175100017510000000246312664775617024724 0ustar teamcityteamcity00000000000000// // $Id: ExtendedReaderList.hpp 1195 2009-08-14 22:12:04Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _EXTENDEDREADERLIST_HPP_ #define _EXTENDEDREADERLIST_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/DefaultReaderList.hpp" namespace pwiz { namespace msdata { /// default ReaderList, extended to include vendor readers class PWIZ_API_DECL ExtendedReaderList : public DefaultReaderList { public: ExtendedReaderList(); }; } // namespace msdata } // namespace pwiz #endif// _EXTENDEDREADERLIST_HPP_ pwiz/pwiz/data/vendor_readers/ExtendedReaderList.cpp0000775000175100017510000000335312664775617024716 0ustar teamcityteamcity00000000000000// // $Id: ExtendedReaderList.cpp 6770 2014-10-09 20:35:21Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "ExtendedReaderList.hpp" #include "ABI/Reader_ABI.hpp" #include "ABI/T2D/Reader_ABI_T2D.hpp" #include "Agilent/Reader_Agilent.hpp" #include "Bruker/Reader_Bruker.hpp" #include "Shimadzu/Reader_Shimadzu.hpp" #include "Thermo/Reader_Thermo.hpp" #include "UIMF/Reader_UIMF.hpp" #include "Waters/Reader_Waters.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace msdata { PWIZ_API_DECL ExtendedReaderList::ExtendedReaderList() { push_back(ReaderPtr(new Reader_ABI)); push_back(ReaderPtr(new Reader_ABI_T2D)); push_back(ReaderPtr(new Reader_Agilent)); push_back(ReaderPtr(new Reader_Bruker)); push_back(ReaderPtr(new Reader_Shimadzu)); push_back(ReaderPtr(new Reader_Thermo)); push_back(ReaderPtr(new Reader_UIMF)); push_back(ReaderPtr(new Reader_Waters)); } } // namespace msdata } // namespace pwiz pwiz/pwiz/analysis/peptideid/PeptideID.hpp0000775000175100017510000001007312664775613022663 0ustar teamcityteamcity00000000000000// // $Id: PeptideID.hpp 3095 2011-11-01 21:12:23Z broter $ // // // Original author: Darren Kessner // Modifying author: Robert Burke // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PEPTIDEID_HPP_ #define _PEPTIDEID_HPP_ #include "pwiz/utility/misc/Export.hpp" #include #include #include #include #include namespace pwiz { namespace peptideid { /// This is an interface for classes that allow access to data sources /// of identified peptides. class PWIZ_API_DECL PeptideID { public: struct PWIZ_API_DECL Location { std::string nativeID; double mz; double retentionTimeSec; Location(){} Location(std::string nativeID, double retentionTimeSec, double mz) : nativeID(nativeID), mz(mz), retentionTimeSec(retentionTimeSec) {} }; struct PWIZ_API_DECL Record { std::string nativeID; std::string sequence; std::string protein_descr; double mz; double retentionTimeSec; double normalizedScore; // in [0,1] Record() : normalizedScore(0) {} Record(const Record& record) : nativeID(record.nativeID), sequence(record.sequence), protein_descr(record.protein_descr), mz(record.mz), retentionTimeSec(record.retentionTimeSec), normalizedScore(record.normalizedScore) { } }; /** * Interface for */ struct IteratorInternal { virtual void increment() = 0; virtual bool equal(const boost::shared_ptr& li) const = 0; virtual const PeptideID::Record& dereference() const = 0; }; /** * Iterator for */ class Iterator : public boost::iterator_facade { public: Iterator() {} Iterator(const Iterator& it) : pimpl(it.pimpl) {} Iterator(boost::shared_ptr pimpl) : pimpl(pimpl) {} protected: friend class boost::iterator_core_access; void increment() { pimpl->increment(); } bool equal(const PeptideID::Iterator& li) const { return pimpl->equal(li.pimpl); } const PeptideID::Record& dereference() const { return pimpl->dereference(); } boost::shared_ptr pimpl; }; virtual Record record(const Location& location) const = 0; virtual ~PeptideID() {} virtual Iterator begin() const = 0; virtual Iterator end() const = 0; }; struct nativeID_less { bool operator()(const PeptideID::Record& a, const PeptideID::Record& b) const { return atof(a.nativeID.c_str()) < atof(b.nativeID.c_str()); } }; class location_less { public: bool operator()(const PeptideID::Location& a, const PeptideID::Location& b) const { return a.nativeID.compare(b.nativeID) < 0 && a.mz < b.mz && a.retentionTimeSec < b.retentionTimeSec; } }; } // namespace peptideid } // namespace pwiz #endif // _PEPTIDEID_HPP_ pwiz/pwiz/analysis/peptideid/PeptideID_pepXMLTest.cpp0000664000175100017510000000543412664775613024745 0ustar teamcityteamcity00000000000000// // $Id: PeptideID_pepXMLTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Robert Burke // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/Std.hpp" #include #include "PeptideID_pepXML.hpp" #include "pwiz/utility/minimxml/SAXParser.hpp" #include "pwiz/utility/misc/unit.hpp" using namespace pwiz::util; using namespace pwiz::peptideid; using namespace pwiz::minimxml::SAXParser; ostream* os_; const char* samplePepXML = "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n"; void testIStream() { istringstream xml (samplePepXML); PeptideID_pepXml ppXml(&xml); PeptideID::Location loc("1", 1.0, 0.); PeptideID::Record bf = ppXml.record(loc); unit_assert(bf.nativeID == "1"); unit_assert(bf.sequence == "ABC"); unit_assert_equal(bf.normalizedScore, 0.9, 1e-15); } void testFilename() { ifstream xml ("test.pep.xml"); PeptideID_pepXml ppXml(&xml); PeptideID::Location loc("1", 1.0, 0.); PeptideID::Record bf = ppXml.record(loc); unit_assert(bf.nativeID == "1"); unit_assert(bf.sequence == "ABC"); unit_assert_equal(bf.normalizedScore, 0.9, 1e-15); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; testIStream(); //testFilename(); //testDone(); //testBadXML(); //testNested(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/peptideid/PeptideID_pepXML.cpp0000664000175100017510000002036612664775613024106 0ustar teamcityteamcity00000000000000// // $Id: PeptideID_pepXML.cpp 3095 2011-11-01 21:12:23Z broter $ // // // Original author: Robert Burke // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "pwiz/utility/misc/Std.hpp" #include "PeptideID_pepXML.hpp" #include "pwiz/utility/minimxml/SAXParser.hpp" namespace { using namespace pwiz::peptideid; ostream& operator<<(ostream& os, const PeptideID::Record& rec) { os << "\tscan: " << rec.nativeID << endl; os << "\tsequence: " << rec.sequence << endl; os << "\tprotein_descr: " << rec.protein_descr << endl; return os; } struct local_iterator : public pwiz::peptideid::PeptideID::IteratorInternal { local_iterator(map::const_iterator it) : it(it) {} void increment() { it++; } bool equal(const shared_ptr& impl) const { local_iterator* li = dynamic_cast(impl.get()); if (li) return it == li->it; return false; } const PeptideID::Record& dereference() const { return it->second; } map::const_iterator it; }; typedef boost::shared_ptr plocal_iterator; } namespace pwiz { namespace peptideid { using namespace pwiz::minimxml::SAXParser; typedef map record_map; typedef multimap, std::less > double_multimap; //////////////////////////////////////////////////////////////////////////// // PeptideID_pepXml::Impl class PeptideID_pepXml::Impl { public: string filename; istream* in; enum Source {Source_file, Source_stream}; Source source; record_map recordMap; double_multimap rtMap; Impl(const string& filename) { source = Source_file; this->filename = filename; in = NULL; } Impl(const char* filename) { source = Source_file; this->filename = filename; in = NULL; } Impl(istream* in) { source = Source_stream; filename.empty(); this->in = in; } PeptideID::Record record(const Location& location) { record_map::iterator rec = recordMap.find(location.nativeID); if (rec == recordMap.end()) throw new range_error(location.nativeID.c_str()); return (*rec).second; } double_multimap::const_iterator record(double retention_time_sec) { double_multimap::const_iterator recs = rtMap.find(retention_time_sec); if (recs == rtMap.end()) { ostringstream error; error << "No records found for " << retention_time_sec; throw new range_error(error.str()); } return recs; } }; //////////////////////////////////////////////////////////////////////////// // class PepXMLHandler class PepXMLHandler : public pwiz::minimxml::SAXParser::Handler { public: static const char* spectrum_query_tag; static const char* search_hit_tag; static const char* peptide_attr; static const char* protein_descr_attr; static const char* peptideprophet_result_tag; static const char* start_scan_attr; static const char* retention_time_sec_attr; static const char* end_scan_attr; static const char* probability_attr; PepXMLHandler(record_map* recordMap, double_multimap* rtMap) { if (recordMap == NULL) throw new runtime_error("null pointer"); if (rtMap == NULL) throw new runtime_error("null pointer"); this->recordMap = recordMap; this->rtMap = rtMap; } virtual Handler::Status startElement(const string& name, const Attributes& attributes, stream_offset position); virtual Handler::Status endElement(const string& name, stream_offset position); // isntance variables record_map* recordMap; double_multimap* rtMap; string current; }; // Tags and attributes we look for const char* PepXMLHandler::spectrum_query_tag = "spectrum_query"; const char* PepXMLHandler::search_hit_tag = "search_hit"; const char* PepXMLHandler::peptide_attr = "peptide"; const char* PepXMLHandler::protein_descr_attr = "protein_descr"; const char* PepXMLHandler::peptideprophet_result_tag = "peptideprophet_result"; const char* PepXMLHandler::start_scan_attr = "start_scan"; const char* PepXMLHandler::retention_time_sec_attr = "retention_time_sec"; const char* PepXMLHandler::end_scan_attr = "end_scan"; const char* PepXMLHandler::probability_attr = "probability"; Handler::Status PepXMLHandler::startElement(const std::string& name, const Attributes& attributes, stream_offset position) { if (name == spectrum_query_tag) { getAttribute(attributes, start_scan_attr, current); (*recordMap)[current].nativeID = current; (*recordMap)[current].sequence = ""; (*recordMap)[current].normalizedScore = 0.; getAttribute(attributes, retention_time_sec_attr, (*recordMap)[current].retentionTimeSec); } else if (name == search_hit_tag) { (*recordMap)[current].sequence = ""; (*recordMap)[current].protein_descr = ""; getAttribute(attributes, peptide_attr, (*recordMap)[current].sequence); getAttribute(attributes, protein_descr_attr, (*recordMap)[current].protein_descr); } else if (name == peptideprophet_result_tag) { getAttribute(attributes, probability_attr, (*recordMap)[current].normalizedScore); } return Handler::Status::Ok; } Handler::Status PepXMLHandler::endElement(const std::string& name, stream_offset position) { return Handler::Status::Ok; } //////////////////////////////////////////////////////////////////////////// // class PeptideID_pepXML PWIZ_API_DECL PeptideID_pepXml::PeptideID_pepXml(const char* filename) : pimpl(new Impl(filename)) { ifstream in(filename); if (in.bad()) { ostringstream oss; oss << "Unable to open file " << filename; throw std::ios_base::failure(oss.str()); } PepXMLHandler pxh(&(pimpl->recordMap), &(pimpl->rtMap)); parse(in, pxh); } PWIZ_API_DECL PeptideID_pepXml::PeptideID_pepXml(const string& filename) : pimpl(new Impl(filename)) { ifstream in(filename.c_str()); if (in.bad()) { ostringstream oss; oss << "Unable to open file " << filename; throw std::ios_base::failure(oss.str()); } PepXMLHandler pxh(&(pimpl->recordMap), &(pimpl->rtMap)); parse(in, pxh); } PWIZ_API_DECL PeptideID_pepXml::PeptideID_pepXml(istream* in) : pimpl(new Impl(in)) { if (in == NULL) throw runtime_error("null pointer"); else if (in->bad()) throw std::ios_base::failure("Unable to open input stream"); PepXMLHandler pxh(&(pimpl->recordMap), &(pimpl->rtMap)); parse(*in, pxh); } PWIZ_API_DECL PeptideID::Record PeptideID_pepXml::record(const Location& location) const { return pimpl->record(location); } double_multimap::const_iterator PeptideID_pepXml::record(double retention_time_sec) const { return pimpl->record(retention_time_sec); } PeptideID::Iterator PeptideID_pepXml::begin() const { return PeptideID::Iterator(plocal_iterator(new local_iterator(pimpl->recordMap.begin()))); } PeptideID::Iterator PeptideID_pepXml::end() const { return PeptideID::Iterator(plocal_iterator(new local_iterator(pimpl->recordMap.end()))); } } // namespace peptideid } // namespace pwiz pwiz/pwiz/analysis/peptideid/PeptideID_flat.hpp0000664000175100017510000000635712664775613023700 0ustar teamcityteamcity00000000000000// // $Id: PeptideID_flat.hpp 3095 2011-11-01 21:12:23Z broter $ // // // Original author: Robert Burke // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PEPTIDEID_FLAT_HPP_ #define _PEPTIDEID_FLAT_HPP_ #include #include #include #include #include #include "pwiz/utility/misc/Export.hpp" #include "PeptideID.hpp" namespace pwiz { namespace peptideid { class PWIZ_API_DECL FlatRecordBuilder { public: virtual ~FlatRecordBuilder() {} virtual PeptideID::Record build(const std::vector& fields) const; virtual bool header() const; virtual double epsilon() const; virtual bool operator()(const PeptideID::Record& a, const PeptideID::Record& b) const; virtual bool operator()(const PeptideID::Record& a, const PeptideID::Location& ) const; }; class PWIZ_API_DECL MSInspectRecordBuilder : public FlatRecordBuilder { public: virtual ~MSInspectRecordBuilder() {} virtual PeptideID::Record build(const std::vector& fields) const; virtual bool header() const; virtual double epsilon() const; virtual bool operator()(const PeptideID::Record& a, const PeptideID::Record& b) const; virtual bool operator()(const PeptideID::Record& a, const PeptideID::Location& ) const; }; /// This class allows access to peptides listed in a flat tab /// delimited text file /// A PeptideID_flat object is contructed with either the path to a /// tab delimited file (*.txt/*.tab), or an std::istream open to /// the beginning of a tab delimited file. class PWIZ_API_DECL PeptideID_flat : public PeptideID { public: /// Constructor taking path to input file in std::string. PeptideID_flat(const std::string& filename, boost::shared_ptr builder = boost::shared_ptr(new FlatRecordBuilder())); /// Constructor taking std::istream as input. PeptideID_flat(std::istream* in, boost::shared_ptr builder = boost::shared_ptr(new FlatRecordBuilder())); /// Destructor. virtual ~PeptideID_flat() {} /// Returns the Record object associated with the given nativeID. /// A range_error is thrown if the nativeID isn't associated with /// a Record. virtual Record record(const Location& location) const; virtual Iterator begin() const; virtual Iterator end() const; private: class Impl; boost::shared_ptr pimpl; }; } // namespace peptideid } // namespace pwiz #endif // _PEPTIDEID_FLAT_HPP_ pwiz/pwiz/analysis/peptideid/PeptideID_pepXML.hpp0000664000175100017510000000440712664775613024111 0ustar teamcityteamcity00000000000000// // $Id: PeptideID_pepXML.hpp 3095 2011-11-01 21:12:23Z broter $ // // // Original author: Robert Burke // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PEPTIDEID_PEPXML_HPP_ #define _PEPTIDEID_PEPXML_HPP_ #include "pwiz/utility/misc/Export.hpp" #include #include #include "PeptideID.hpp" namespace pwiz { namespace peptideid { /// This class allows access to identified proteins in PeptideProphet files. /// A PeptideID_pepXML object is contructed with either the path to a /// PeptideProphet format file (*.pep.xml), or an std::istream open to /// the beginning of a pep.xml file. class PWIZ_API_DECL PeptideID_pepXml : public PeptideID { public: /// Constructor taking path to input file in std::string. PeptideID_pepXml(const std::string& filename); /// Constructor taking path to input file from const char*. PeptideID_pepXml(const char* filename); /// Constructor taking std::istream as input. PeptideID_pepXml(std::istream* in); /// Destructor. virtual ~PeptideID_pepXml() {} /// Returns the Record object associated with the given nativeID. /// A range_error is thrown if the nativeID isn't associated with /// a Record. virtual Record record(const Location& location) const; virtual std::multimap >::const_iterator record(double retention_time_sec) const; virtual Iterator begin() const; virtual Iterator end() const; private: class Impl; boost::shared_ptr pimpl; }; } // namespace peptideid } // namespace pwiz #endif // _PEPTIDEID_PEPXML_HPP_ pwiz/pwiz/analysis/peptideid/PeptideIDMap.hpp0000775000175100017510000000272412664775613023325 0ustar teamcityteamcity00000000000000// // $Id: PeptideIDMap.hpp 3095 2011-11-01 21:12:23Z broter $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PEPTIDEIDMAP_HPP_ #define _PEPTIDEIDMAP_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "PeptideID.hpp" #include namespace pwiz { namespace peptideid { class PWIZ_API_DECL PeptideIDMap : public PeptideID, public std::map { public: virtual Record record(const pwiz::peptideid::PeptideID::Location& location) const; virtual PeptideID::Iterator begin() const; virtual PeptideID::Iterator end() const; }; } // namespace peptideid } // namespace pwiz #endif // _PEPTIDEIDMAP_HPP_ pwiz/pwiz/analysis/peptideid/PeptideIDMap.cpp0000775000175100017510000000464312664775613023322 0ustar teamcityteamcity00000000000000// // $Id: PeptideIDMap.cpp 3095 2011-11-01 21:12:23Z broter $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "PeptideIDMap.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::peptideid; namespace { struct local_iterator : public PeptideID::IteratorInternal { local_iterator(map::const_iterator it) : it(it) {} private: friend class boost::iterator_core_access; virtual void increment() { it++; } virtual bool equal(const boost::shared_ptr& li) const { local_iterator* lip = dynamic_cast(li.get()); if (lip) return it == lip->it; return false; } virtual const PeptideID::Record& dereference() const { return it->second; } map::const_iterator it; }; typedef boost::shared_ptr plocal_iterator; } namespace pwiz { namespace peptideid { PWIZ_API_DECL PeptideID::Record PeptideIDMap::record(const Location& location) const { map::const_iterator it = this->find(location.nativeID); if (it != map::end()) return it->second; return PeptideID::Record(); } PWIZ_API_DECL PeptideID::Iterator PeptideIDMap::begin() const { return PeptideID::Iterator(plocal_iterator(new local_iterator(map::begin()))); } PWIZ_API_DECL PeptideID::Iterator PeptideIDMap::end() const { return PeptideID::Iterator(plocal_iterator(new local_iterator(map::end()))); } } // namespace peptideid } // namespace pwiz pwiz/pwiz/analysis/peptideid/PeptideID_flatTest.cpp0000664000175100017510000000631712664775613024527 0ustar teamcityteamcity00000000000000// // $Id: PeptideID_flatTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Robert Burke // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/Std.hpp" #include #include "PeptideID_flat.hpp" #include "pwiz/utility/minimxml/SAXParser.hpp" #include "pwiz/utility/misc/unit.hpp" using namespace pwiz::util; using namespace pwiz::peptideid; using namespace pwiz::minimxml::SAXParser; ostream* os_; const char* sampleFlat = "1\t1000.0\t1000.0\t0.9\tABC\n" "2\t2000\t500.0\t0.7\tDEF\n"; const char* sampleMSI = "scan time mz mass intensity charge chargeStates kl background median peaks scanFirst scanLast scanCount\n" "1 2.248 878.889 1755.7633 61.847733 2 1 0.05977635 0.9152653 1.0536207 5 693 721 1\n" "1 2.248 752.86017 1503.7076 41.52021 2 1 0.10636939 1.6415321 0.8086928 5 693 715 1\n" "1 2.248 933.4445 932.4372 33.840942 1 1 0.2521489 5.717129 2.8336976 2 695 707 1\n" "4 7.116 801.4013 800.3538 18.389582 1 1 0.6249515 1.6089915 1.3883085 3 698 713 1\n"; void testIStream() { istringstream data (sampleFlat); PeptideID_flat ppFlat(&data, shared_ptr(new FlatRecordBuilder)); PeptideID::Location loc("1", 1000., 0); PeptideID::Record bf = ppFlat.record(loc); unit_assert(bf.nativeID == "1"); unit_assert(bf.sequence == "ABC"); unit_assert_equal(bf.normalizedScore, 0.9, 1e-14); } void testMSInspectIStream() { istringstream data (sampleMSI); PeptideID_flat ppFlat(&data, shared_ptr(new MSInspectRecordBuilder())); PeptideID::Location loc("1", 2.248, 878.889); PeptideID::Record bf = ppFlat.record(loc); unit_assert(bf.nativeID == "1"); unit_assert(bf.sequence == ""); unit_assert_equal(bf.normalizedScore, 0.05977635, 1e-14); } //void testFilename() //{ // ifstream data ("test.txt"); // // PeptideID_flat<> ppFlat(&data); // // // PeptideID::Location loc("1", 0, 0.9); // PeptideID::Record bf = ppFlat.record(loc); // // unit_assert(bf.nativeID == "1"); // unit_assert(bf.sequence == "ABC"); // unit_assert_equal(bf.normalizedScore, 0.9, 1e-14); //} int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; testIStream(); testMSInspectIStream(); //testFilename(); //testDone(); //testBadXML(); //testNested(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/peptideid/PeptideIDMapTest.cpp0000775000175100017510000000431012664775613024151 0ustar teamcityteamcity00000000000000// // $Id: PeptideIDMapTest.cpp 6141 2014-05-05 21:03:47Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "PeptideIDMap.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::peptideid; void test() { PeptideIDMap peptideIDMap; PeptideID::Record* record = &peptideIDMap["1"]; record->nativeID = "1"; record->sequence = "DARREN"; record->normalizedScore = .5; record = &peptideIDMap["2"]; record->nativeID = "2"; record->sequence = "KESSNER"; record->normalizedScore = .6; PeptideID::Record result = peptideIDMap.record(PeptideID::Location("goober", 0, 0)); unit_assert(result.nativeID.empty()); unit_assert(result.sequence.empty()); unit_assert_equal(result.normalizedScore, 0, 1e-15); result = peptideIDMap.record(PeptideID::Location("1", 0, 0)); unit_assert(result.nativeID == "1"); unit_assert(result.sequence == "DARREN"); unit_assert_equal(result.normalizedScore, .5, 1e-15); result = peptideIDMap.record(PeptideID::Location("2", 0, 0)); unit_assert(result.nativeID == "2"); unit_assert(result.sequence == "KESSNER"); unit_assert_equal(result.normalizedScore, .6, 1e-15); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/peptideid/PeptideID_flat.cpp0000664000175100017510000002214312664775613023662 0ustar teamcityteamcity00000000000000// // $Id: PeptideID_flat.cpp 6141 2014-05-05 21:03:47Z chambm $ // // // Original author: Robert Burke // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "pwiz/utility/misc/Std.hpp" #include #include #include "PeptideID_flat.hpp" namespace pwiz { namespace peptideid { using boost::tokenizer; using boost::char_separator; using boost::shared_ptr; namespace { typedef multimap nativeID_map; struct redirect { boost::shared_ptr builder; redirect(const redirect& rd) : builder(rd.builder) {} redirect(boost::shared_ptr builder) : builder(builder) {} bool operator()(const PeptideID::Record& a, const PeptideID::Record& b) const { return (*builder)(a, b); } }; struct local_iterator : public pwiz::peptideid::PeptideID::IteratorInternal { public: local_iterator(vector::const_iterator it) : it(it) {} void increment() { it++; } bool equal(const boost::shared_ptr& impl) const { local_iterator* li = dynamic_cast(impl.get()); if (li) return it == li->it; return false; } const PeptideID::Record& dereference() const { return *it; } private: vector::const_iterator it; }; typedef boost::shared_ptr plocal_iterator; } //////////////////////////////////////////////////////////////////////////// // PeptideID_flat::Impl class PeptideID_flat::Impl { public: string filename; istream* in; enum Source {Source_file, Source_stream}; Source source; boost::shared_ptr builder; vector records; nativeID_map nativeIDMap; Impl(const string& filename, boost::shared_ptr builder) { source = Source_file; this->filename = filename; this->builder = builder; in = NULL; } Impl(istream* in, boost::shared_ptr builder) { source = Source_stream; filename.empty(); this->in = in; this->builder = builder; } PeptideID::Record record(const Location& location) { //PeptideID::Record loc; //loc.nativeID = location.nativeID; //loc.mz = location.mz; //loc.retentionTimeSec = location.retentionTimeSec; PeptideID::Record result; // if there's only one record w/ given nativeID, check and // return if match nativeID_map::iterator nid_it = nativeIDMap.find(location.nativeID); // There should never be a key w/ count 0. But we'll check for // complete error checking. if (nid_it == nativeIDMap.end() || nativeIDMap.count((*nid_it).first) == 0) throw range_error(location.nativeID.c_str()); bool found = false; do { if ((*builder)(*(*nid_it).second, location)) { result = *(*nid_it).second; found = true; } nid_it++; } while (!found && nid_it != nativeIDMap.upper_bound(location.nativeID)); if (!found) throw range_error(location.nativeID.c_str()); return result; } bool parse() { bool success = true; if(source == Source_file) in = new ifstream(filename.c_str()); string line; bool first=true; while (getline(*in, line)) { if (first) { first = false; if (builder->header()) continue; } vector fields; char_separator sep(" \t"); tokenizer< char_separator > tok(line, sep); for (tokenizer >::iterator i=tok.begin(); i!=tok.end(); i++) fields.push_back(*i); try { PeptideID::Record record = builder->build(fields); records.push_back(record); Location loc(record.nativeID, record.mz, record.retentionTimeSec); } catch(invalid_argument ia) { success = false; } } redirect rd(builder); sort(records.begin(), records.end(), rd); // Map the records to the nativeID's for (vector::iterator i=records.begin(); i!=records.end(); i++) nativeIDMap.insert(pair((*i).nativeID, &(*i))); return success; } size_t size() const { return records.size(); } Record record(size_t index) const { return records.at(index); } }; //////////////////////////////////////////////////////////////////////////// // PeptideID_flat PeptideID_flat::PeptideID_flat(const std::string& filename, boost::shared_ptr builder) : pimpl(new Impl(filename, builder)) { pimpl->parse(); } PeptideID_flat::PeptideID_flat(std::istream* in, boost::shared_ptr builder) : pimpl(new Impl(in, builder)) { pimpl->parse(); } PeptideID::Record PeptideID_flat::record(const Location& location) const { return pimpl->record(location); } PeptideID::Iterator PeptideID_flat::begin() const { return PeptideID::Iterator(plocal_iterator(new local_iterator(pimpl->records.begin()))); } PeptideID::Iterator PeptideID_flat::end() const { return PeptideID::Iterator(plocal_iterator(new local_iterator(pimpl->records.end()))); } //////////////////////////////////////////////////////////////////////////// // class FlatRecordBuilder PeptideID::Record FlatRecordBuilder::build(const vector& fields) const { PeptideID::Record record; if (fields.size() == 0) throw invalid_argument("zero length fields vector."); if (fields.size() >= 1) record.nativeID = fields.at(0); if (fields.size() >= 2) record.retentionTimeSec = atof(fields.at(1).c_str()); if (fields.size() >= 3) record.mz = atof(fields.at(2).c_str()); if (fields.size() >= 4) record.normalizedScore = atof(fields.at(3).c_str()); if (fields.size() >= 5) record.sequence = fields.at(4); return record; } bool FlatRecordBuilder::header() const { return false; } bool FlatRecordBuilder::operator()(const PeptideID::Record& a, const PeptideID::Record& b) const { bool result = false; result = a.nativeID.compare(b.nativeID) < 0; return result; } bool FlatRecordBuilder::operator()(const PeptideID::Record& a, const PeptideID::Location& b) const { bool result = false; result = a.nativeID.compare(b.nativeID) == 0; return result; } double FlatRecordBuilder::epsilon() const { return 1e-14; } //////////////////////////////////////////////////////////////////////////// // class MSInspectRecordBuilder PeptideID::Record MSInspectRecordBuilder::build(const vector& fields) const { PeptideID::Record record; if (fields.size() == 0) throw invalid_argument("zero length fields vector."); if (fields.size() >= 1) record.nativeID = fields.at(0); if (fields.size() >= 2) record.retentionTimeSec = atof(fields.at(1).c_str()); if (fields.size() >= 3) record.mz = atof(fields.at(2).c_str()); if (fields.size() >= 8) record.normalizedScore = atof(fields.at(7).c_str()); if (fields.size() >= 15) record.sequence = fields.at(14); return record; } bool MSInspectRecordBuilder::header() const { return true; } bool MSInspectRecordBuilder::operator()(const PeptideID::Record& a, const PeptideID::Record& b) const { bool result = false; result = a.retentionTimeSec < b.retentionTimeSec && a.mz < b.mz; return result; } bool MSInspectRecordBuilder::operator()(const PeptideID::Record& a, const PeptideID::Location& b) const { bool result = false; result = fabs(a.retentionTimeSec - b.retentionTimeSec) < epsilon() && fabs(a.mz - b.mz) < epsilon(); return result; } double MSInspectRecordBuilder::epsilon() const { return 1e-14; } } // namespace peptideid } // namespace pwiz pwiz/pwiz/data/proteome/DefaultReaderList.cpp0000664000175100017510000000267012664775621023363 0ustar teamcityteamcity00000000000000// // $Id: DefaultReaderList.cpp 1688 2010-01-13 20:01:21Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/String.hpp" #include "pwiz/utility/misc/Stream.hpp" #include "DefaultReaderList.hpp" #include "Reader_FASTA.hpp" #include "pwiz/data/proteome/Version.hpp" #include "pwiz/utility/misc/random_access_compressed_ifstream.hpp" namespace pwiz { namespace proteome { /// default Reader list PWIZ_API_DECL DefaultReaderList::DefaultReaderList(bool indexed /*= false*/) { Reader_FASTA::Config fastaConfig; fastaConfig.indexed = indexed; push_back(ReaderPtr(new Reader_FASTA(fastaConfig))); } } // namespace proteome } // namespace pwiz pwiz/pwiz/data/proteome/Version.hpp0000664000175100017510000000237512664775621021454 0ustar teamcityteamcity00000000000000// // $Id: Version.hpp 1586 2009-12-03 00:47:33Z chambm $ // // // Original author: Matt Chambers // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PWIZ_PROTEOME_VERSION_HPP_ #define _PWIZ_PROTEOME_VERSION_HPP_ #include namespace pwiz { namespace proteome { struct Version { static int Major(); static int Minor(); static int Revision(); static std::string str(); static std::string LastModified(); }; } // namespace proteome } // namespace pwiz #endif // _PWIZ_PROTEOME_VERSION_HPP_ pwiz/pwiz/data/proteome/Diff.cpp0000664000175100017510000001116212664775621020664 0ustar teamcityteamcity00000000000000// // $Id: Diff.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Diff.hpp" #include "TextWriter.hpp" #include "pwiz/data/common/diff_std.hpp" #include "pwiz/utility/misc/Std.hpp" #include namespace pwiz { namespace data { namespace diff_impl { using namespace pwiz::proteome; PWIZ_API_DECL void diff(const Protein& a, const Protein& b, Protein& a_b, Protein& b_a, const DiffConfig& config) { a_b = Protein("", 0, "", ""); b_a = Protein("", 0, "", ""); // important scan metadata diff_integral(a.index, b.index, a_b.index, b_a.index, config); diff(a.id, b.id, a_b.id, b_a.id, config); if (!config.ignoreMetadata) { diff(a.description, b.description, a_b.description, b_a.description, config); } string sequenceA_B, sequenceB_A; diff(a.sequence(), b.sequence(), sequenceA_B, sequenceB_A, config); // provide context if (!a_b.empty() || !b_a.empty() || !sequenceA_B.empty() || !sequenceB_A.empty()) { a_b = Protein(a.id, a.index, a_b.description, sequenceA_B); b_a = Protein(b.id, b.index, b_a.description, sequenceB_A); } } PWIZ_API_DECL void diff(const ProteinList& a, const ProteinList& b, ProteinListSimple& a_b, ProteinListSimple& b_a, const DiffConfig& config) { a_b.proteins.clear(); b_a.proteins.clear(); if (a.size() != b.size()) { ProteinPtr dummy(new Protein("dummy", 0, "ProteinList sizes differ", "")); a_b.proteins.push_back(dummy); return; } for (size_t i=0; i < a.size(); ++i) { ProteinPtr temp_a_b(new Protein("", 0, "", "")); ProteinPtr temp_b_a(new Protein("", 0, "", "")); diff(*a.protein(i, true), *b.protein(i, true), *temp_a_b, *temp_b_a, config); if (!temp_a_b->empty() || !temp_b_a->empty()) { a_b.proteins.push_back(temp_a_b); b_a.proteins.push_back(temp_b_a); } } } PWIZ_API_DECL void diff(const ProteomeData& a, const ProteomeData& b, ProteomeData& a_b, ProteomeData& b_a, const DiffConfig& config) { if (!config.ignoreMetadata) { diff(a.id, b.id, a_b.id, b_a.id, config); } // special handling for ProteinList diff shared_ptr temp_a_b(new ProteinListSimple); shared_ptr temp_b_a(new ProteinListSimple); a_b.proteinListPtr = temp_a_b; b_a.proteinListPtr = temp_b_a; ProteinListPtr temp_a = a.proteinListPtr.get() ? a.proteinListPtr : ProteinListPtr(new ProteinListSimple); ProteinListPtr temp_b = b.proteinListPtr.get() ? b.proteinListPtr : ProteinListPtr(new ProteinListSimple); diff(*temp_a, *temp_b, *temp_a_b, *temp_b_a, config); // provide context if (!a_b.empty() || !b_a.empty()) { a_b.id = a.id; b_a.id = b.id; } } } // namespace diff_impl } // namespace data namespace proteome { std::ostream& os_write_proteins(std::ostream& os, const ProteinListPtr a_b, const ProteinListPtr b_a) { TextWriter write(os, 1); if(a_b->size()!=b_a->size()) { os<<"in ProteinList diff: ProteinList sizes differ"<size(); ++index) { os<<"+\n"; write(*(a_b->protein(index))); os<<"-\n"; write(*(b_a->protein(index))); } return os; } PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const data::Diff& diff) { TextWriter write(os, 1); if(!diff.a_b.empty()|| !diff.b_a.empty()) { os<<"+\n"; write(diff.a_b,true); os<<"-\n"; write(diff.b_a,true); os_write_proteins(os, diff.a_b.proteinListPtr, diff.b_a.proteinListPtr); } return os; } } // namespace proteome } // namespace pwiz pwiz/pwiz/data/proteome/ProteinListCacheTest.cpp0000664000175100017510000002203512664775621024055 0ustar teamcityteamcity00000000000000// // $Id: ProteinListCacheTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "ProteinListCache.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include "Serializer_FASTA.hpp" using namespace pwiz::util; using namespace pwiz::proteome; ostream* os_ = 0; namespace std { ostream& operator<< (ostream& os, const ProteinListCache::CacheType& cache) { os << "Protein cache indices (from MRU to LRU):"; for (ProteinListCache::CacheType::const_iterator itr = cache.begin(); itr != cache.end(); ++itr) os << " " << itr->second->index; return os; } } // namespace std void testModeOff() { // initialize list ProteomeData pd; shared_ptr sl(new ProteinListSimple); sl->proteins.push_back(ProteinPtr(new Protein("P1", 0, "0", "ABC"))); sl->proteins.push_back(ProteinPtr(new Protein("P2", 1, "1", "DEF"))); sl->proteins.push_back(ProteinPtr(new Protein("P3", 2, "2", "GHI"))); sl->proteins.push_back(ProteinPtr(new Protein("P4", 3, "3", "JKL"))); pd.proteinListPtr = sl; // ProteinListSimple returns the same shared_ptrs regardless of caching; // serializing to FASTA and back will produce different shared_ptrs boost::shared_ptr ss(new stringstream); Serializer_FASTA serializer; serializer.write(*ss, pd, 0); serializer.read(ss, pd); // access a series of proteins and make sure the cache behaves appropriately: // in off mode, the cache should always be empty ProteinPtr s; ProteinListCache slc(pd.proteinListPtr, ProteinListCacheMode_Off, 2); const ProteinListCache::CacheType& cache = slc.cache(); unit_assert(cache.empty()); s = slc.protein(0, false); s = slc.protein(1, true); unit_assert_operator_equal("1", s->description); unit_assert_operator_equal("DEF", s->sequence()); s = slc.protein(2, false); s = slc.protein(3, true); if (os_) *os_ << cache << endl; unit_assert(cache.empty()); } void testModeMetaDataOnly() { // initialize list ProteomeData pd; shared_ptr sl(new ProteinListSimple); sl->proteins.push_back(ProteinPtr(new Protein("P1", 0, "0", "ABC"))); sl->proteins.push_back(ProteinPtr(new Protein("P2", 1, "1", "DEF"))); sl->proteins.push_back(ProteinPtr(new Protein("P3", 2, "2", "GHI"))); sl->proteins.push_back(ProteinPtr(new Protein("P4", 3, "3", "JKL"))); pd.proteinListPtr = sl; // ProteinListSimple returns the same shared_ptrs regardless of caching; // serializing to FASTA and back will produce different shared_ptrs boost::shared_ptr ss(new stringstream); Serializer_FASTA serializer; serializer.write(*ss, pd, 0); serializer.read(ss, pd); // access a series of proteins and make sure the cache behaves appropriately: // in metadata-only mode, entries in the cache should: // - always have metadata // - never have sequences ProteinPtr s; ProteinListCache slc(pd.proteinListPtr, ProteinListCacheMode_MetaDataOnly, 2); const ProteinListCache::CacheType& cache = slc.cache(); unit_assert(cache.empty()); unit_assert_operator_equal(2, cache.max_size()); s = slc.protein(0, false); // pointers should be equal unit_assert_operator_equal(slc.protein(0, false), s); if (os_) *os_ << cache << endl; unit_assert(!cache.empty()); unit_assert_operator_equal(1, cache.size()); unit_assert_operator_equal(0, cache.mru().second->index); unit_assert_operator_equal("0", cache.mru().second->description); unit_assert_operator_equal("", cache.mru().second->sequence()); // with-sequence access should return the sequence, but only cache the metadata s = slc.protein(1, true); unit_assert_operator_equal("DEF", s->sequence()); if (os_) *os_ << cache << endl; unit_assert_operator_equal(2, cache.size()); unit_assert_operator_equal(1, cache.mru().second->index); unit_assert_operator_equal("", cache.mru().second->sequence()); unit_assert_operator_equal(0, cache.lru().second->index); s = slc.protein(2, false); // pointers should be equal unit_assert_operator_equal(slc.protein(2, false), s); if (os_) *os_ << cache << endl; unit_assert_operator_equal(2, cache.size()); unit_assert_operator_equal(2, cache.mru().second->index); unit_assert_operator_equal("", cache.mru().second->sequence()); unit_assert_operator_equal(1, cache.lru().second->index); s = slc.protein(3, true); unit_assert_operator_equal("JKL", s->sequence()); if (os_) *os_ << cache << endl; unit_assert_operator_equal(2, cache.size()); unit_assert_operator_equal(3, cache.mru().second->index); unit_assert_operator_equal("", cache.mru().second->sequence()); unit_assert_operator_equal(2, cache.lru().second->index); s = slc.protein(2, true); unit_assert_operator_equal("GHI", s->sequence()); if (os_) *os_ << cache << endl; unit_assert_operator_equal(2, cache.size()); unit_assert_operator_equal(2, cache.mru().second->index); unit_assert_operator_equal("", cache.mru().second->sequence()); unit_assert_operator_equal(3, cache.lru().second->index); } void testModeMetaDataAndSequence() { // initialize list ProteomeData pd; shared_ptr sl(new ProteinListSimple); sl->proteins.push_back(ProteinPtr(new Protein("P1", 0, "0", "ABC"))); sl->proteins.push_back(ProteinPtr(new Protein("P2", 1, "1", "DEF"))); sl->proteins.push_back(ProteinPtr(new Protein("P3", 2, "2", "GHI"))); sl->proteins.push_back(ProteinPtr(new Protein("P4", 3, "3", "JKL"))); pd.proteinListPtr = sl; // ProteinListSimple returns the same shared_ptrs regardless of caching; // serializing to FASTA and back will produce different shared_ptrs boost::shared_ptr ss(new stringstream); Serializer_FASTA serializer; serializer.write(*ss, pd, 0); serializer.read(ss, pd); // access a series of proteins and make sure the cache behaves appropriately: // in metadata-and-sequence mode, entries in the cache should: // - always have metadata // - always have sequences ProteinPtr s; ProteinListCache slc(pd.proteinListPtr, ProteinListCacheMode_MetaDataAndSequence, 2); const ProteinListCache::CacheType& cache = slc.cache(); unit_assert(cache.empty()); unit_assert_operator_equal(2, cache.max_size()); // metadata-only access should not affect the cache s = slc.protein(0, false); if (os_) *os_ << cache << endl; unit_assert(cache.empty()); unit_assert_operator_equal(0, cache.size()); s = slc.protein(1, true); // pointers should be equal unit_assert_operator_equal(slc.protein(1, true), s); if (os_) *os_ << cache << endl; unit_assert_operator_equal(1, cache.size()); unit_assert_operator_equal(1, cache.mru().second->index); unit_assert_operator_equal("1", cache.mru().second->description); unit_assert_operator_equal("DEF", cache.mru().second->sequence()); // metadata-only access should not affect the cache s = slc.protein(2, false); if (os_) *os_ << cache << endl; unit_assert_operator_equal(1, cache.size()); unit_assert_operator_equal(1, cache.mru().second->index); unit_assert_operator_equal("DEF", cache.mru().second->sequence()); s = slc.protein(3, true); // pointers should be equal unit_assert_operator_equal(slc.protein(3, true), s); if (os_) *os_ << cache << endl; unit_assert_operator_equal(2, cache.size()); unit_assert_operator_equal(3, cache.mru().second->index); unit_assert_operator_equal("JKL", cache.mru().second->sequence()); unit_assert_operator_equal(1, cache.lru().second->index); s = slc.protein(2, true); if (os_) *os_ << cache << endl; unit_assert_operator_equal(2, cache.size()); unit_assert_operator_equal(2, cache.mru().second->index); unit_assert_operator_equal("GHI", cache.mru().second->sequence()); unit_assert_operator_equal(3, cache.lru().second->index); } void test() { testModeOff(); testModeMetaDataOnly(); testModeMetaDataAndSequence(); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/proteome/DefaultReaderList.hpp0000664000175100017510000000243112664775621023363 0ustar teamcityteamcity00000000000000// // $Id: DefaultReaderList.hpp 1688 2010-01-13 20:01:21Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PROTEOME_DEFAULTREADERLIST_HPP_ #define _PROTEOME_DEFAULTREADERLIST_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "Reader.hpp" namespace pwiz { namespace proteome { /// default Reader list class PWIZ_API_DECL DefaultReaderList : public ReaderList { public: DefaultReaderList(bool indexed = false); }; } // namespace proteome } // namespace pwiz #endif // _PROTEOME_DEFAULTREADERLIST_HPP_ pwiz/pwiz/data/proteome/AminoAcid.cpp0000664000175100017510000001227712664775621021650 0ustar teamcityteamcity00000000000000// // $Id: AminoAcid.cpp 3317 2012-02-27 16:36:06Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "AminoAcid.hpp" #include "pwiz/utility/misc/Std.hpp" #include #include "pwiz/utility/misc/CharIndexedVector.hpp" #include "pwiz/utility/misc/Singleton.hpp" using namespace pwiz::util; namespace pwiz { namespace proteome { namespace AminoAcid { namespace Info { class RecordData : public boost::singleton { public: RecordData(boost::restricted) { initializeRecords(); } inline const Record& record(Type type) {return records_[type];} inline const Record* record(char symbol) {return (size_t) symbol >= recordsSymbolIndex_.size() ? NULL : recordsSymbolIndex_[symbol];} private: void initializeRecords(); vector records_; CharIndexedVector recordsSymbolIndex_; }; namespace { Record createRecord(const std::string& name, const std::string& abbreviation, char symbol, const std::string& formula, double abundance) { Record result; result.name = name; result.abbreviation = abbreviation; result.symbol = symbol; result.residueFormula = chemistry::Formula(formula); result.formula = result.residueFormula + chemistry::Formula("H2O1"); result.abundance = abundance; return result; } } // namespace void RecordData::initializeRecords() { using namespace chemistry; records_.resize(Unknown+1); records_[Alanine] = createRecord("Alanine", "Ala", 'A', "C3 H5 N1 O1 S0", .078); records_[Cysteine] = createRecord("Cysteine", "Cys", 'C', "C3 H5 N1 O1 S1", .019); records_[AsparticAcid] = createRecord("Aspartic Acid", "Asp", 'D', "C4 H5 N1 O3 S0", .053); records_[GlutamicAcid] = createRecord("Glutamic Acid", "Glu", 'E', "C5 H7 N1 O3 S0", .063); records_[Phenylalanine] = createRecord("Phenylalanine", "Phe", 'F', "C9 H9 N1 O1 S0", .039); records_[Glycine] = createRecord("Glycine", "Gly", 'G', "C2 H3 N1 O1 S0", .072); records_[Histidine] = createRecord("Histidine", "His", 'H', "C6 H7 N3 O1 S0", .023); records_[Isoleucine] = createRecord("Isoleucine", "Ile", 'I', "C6 H11 N1 O1 S0", .053); records_[Lysine] = createRecord("Lysine", "Lys", 'K', "C6 H12 N2 O1 S0", .059); records_[Leucine] = createRecord("Leucine", "Leu", 'L', "C6 H11 N1 O1 S0", .091); records_[Methionine] = createRecord("Methionine", "Met", 'M', "C5 H9 N1 O1 S1", .023); records_[Asparagine] = createRecord("Asparagine", "Asn", 'N', "C4 H6 N2 O2 S0", .043); records_[Proline] = createRecord("Proline", "Pro", 'P', "C5 H7 N1 O1 S0", .052); records_[Glutamine] = createRecord("Glutamine", "Gln", 'Q', "C5 H8 N2 O2 S0", .042); records_[Arginine] = createRecord("Arginine", "Arg", 'R', "C6 H12 N4 O1 S0", .051); records_[Serine] = createRecord("Serine", "Ser", 'S', "C3 H5 N1 O2 S0", .068); records_[Threonine] = createRecord("Threonine", "Thr", 'T', "C4 H7 N1 O2 S0", .059); records_[Valine] = createRecord("Valine", "Val", 'V', "C5 H9 N1 O1 S0", .066); records_[Tryptophan] = createRecord("Tryptophan", "Trp", 'W', "C11 H10 N2 O1 S0", .014); records_[Tyrosine] = createRecord("Tyrosine", "Tyr", 'Y', "C9 H9 N1 O2 S0", .032); records_[Selenocysteine] = createRecord("Selenocysteine", "Sec", 'U', "C3 H5 N1 O1 Se1", .00); records_[AspX] = createRecord("AspX", "Asx", 'B', "C4 H6 N2 O2 S0", .00); records_[GlutX] = createRecord("GlutX", "Glx", 'Z', "C5 H8 N2 O2 S0", .00); records_[Unknown] = createRecord("Unknown", "Unk", 'X', "C5 H6 N1 O1 S0", .00); // records_[Unknown] = createRecord("Unknown", "Unk", 'X', "C4.9384 H7.7583 N1.357701 O1.4773 S0.0417", .00); //Averagine is really C4.9384H7.7583N1.3577O1.4773S0.0417 // create the symbol index for the records for (vector::iterator it=records_.begin(); it!=records_.end(); ++it) recordsSymbolIndex_[it->symbol] = &*it; } PWIZ_API_DECL const Record& record(Type type) {return RecordData::instance->record(type);} PWIZ_API_DECL const Record& record(char symbol) { const Record* record = RecordData::instance->record(symbol); if (!record) throw runtime_error(string("[AminoAcid::Info] Invalid amino acid symbol: ") + symbol); return *record; } } // namespace Info } // namespace AminoAcid } // namespace proteome } // namespace pwiz pwiz/pwiz/data/proteome/ProteinListWrapperTest.cpp0000664000175100017510000000577612664775621024507 0ustar teamcityteamcity00000000000000// // $Id: ProteinListWrapperTest.cpp 6141 2014-05-05 21:03:47Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "ProteinListWrapper.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::proteome; using namespace pwiz::util; class MyWrapper : public ProteinListWrapper { public: MyWrapper(const ProteinListPtr& inner) : ProteinListWrapper(inner) {} void verifySize(size_t size) { // verify that we can see inner_ unit_assert(size == inner_->size()); } }; class FilterWrapper : public ProteinListWrapper { // a simple filter that returns only even indices public: FilterWrapper(const ProteinListPtr& inner) : ProteinListWrapper(inner) {} virtual size_t size() const {return inner_->size()/2;} virtual ProteinPtr protein(size_t index, bool getSequence = true) const {return inner_->protein(index*2, getSequence);} }; void test() { typedef shared_ptr ProteinListSimplePtr; ProteinListSimplePtr simple(new ProteinListSimple); const size_t proteinCount = 10; for (size_t i=0; iproteins.push_back(ProteinPtr(new Protein("PWIZ:" + lexical_cast(i), i, "", ""))); // check MyWrapper shared_ptr wrapper(new MyWrapper(simple)); wrapper->verifySize(10); unit_assert(wrapper->size() == 10); for (size_t i=0; i(i); unit_assert(wrapper->find(id) == i); ProteinPtr s = wrapper->protein(i); unit_assert(s->id == id); } // check FilterWrapper shared_ptr filterWrapper(new FilterWrapper(simple)); unit_assert(filterWrapper->size() == 5); for (size_t i=0; isize(); i++) { string id = "PWIZ:" + lexical_cast(i*2); unit_assert(filterWrapper->find(id) == i); ProteinPtr s = filterWrapper->protein(i); unit_assert(s->id == id); } } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/proteome/AminoAcid.hpp0000664000175100017510000000434512664775621021652 0ustar teamcityteamcity00000000000000// // $Id: AminoAcid.hpp 1808 2010-02-12 21:01:48Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _AMINOACID_HPP_ #define _AMINOACID_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/utility/chemistry/Chemistry.hpp" #include #include namespace pwiz { namespace proteome { /// scope for types related to amino acids namespace AminoAcid { /// enumeration of the amino acids enum PWIZ_API_DECL Type { Alanine, Cysteine, AsparticAcid, GlutamicAcid, Phenylalanine, Glycine, Histidine, Isoleucine, Lysine, Leucine, Methionine, Asparagine, Proline, Glutamine, Arginine, Serine, Threonine, Valine, Tryptophan, Tyrosine, Selenocysteine, AspX, GlutX, Unknown }; /// class for accessing information about the amino acids namespace Info { /// struct for holding data for a single amino acid struct PWIZ_API_DECL Record { std::string name; std::string abbreviation; char symbol; chemistry::Formula residueFormula; chemistry::Formula formula; double abundance; }; /// returns the amino acid's Record by type PWIZ_API_DECL const Record& record(Type type); /// returns the amino acid's Record by symbol (may throw) PWIZ_API_DECL const Record& record(char symbol); } // namespace Info } // namespace AminoAcid } // namespace proteome } // namespace pwiz #endif // _AMINOACID_HPP_ pwiz/pwiz/data/proteome/ProteomeData.cpp0000664000175100017510000000563312664775621022406 0ustar teamcityteamcity00000000000000// // $Id: ProteomeData.cpp 2908 2011-08-05 16:41:41Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "ProteomeData.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace proteome { // // Protein // PWIZ_API_DECL Protein::Protein(const std::string& id, size_t index, const std::string& description, const std::string& sequence) : Peptide(sequence), id(id), index(index), description(description) {} PWIZ_API_DECL bool Protein::empty() const { return id.empty() && description.empty() && sequence().empty(); } // // ProteinList (default implementations) // PWIZ_API_DECL bool ProteinList::empty() const { return size() == 0; } PWIZ_API_DECL size_t ProteinList::find(const string& id) const { for (size_t index = 0, end = size(); index < end; ++index) if (protein(index, false)->id == id) return index; return size(); } PWIZ_API_DECL IndexList ProteinList::findKeyword(const string& keyword, bool caseSensitive /*= true*/) const { IndexList indexList; if (caseSensitive) { for (size_t index = 0, end = size(); index < end; ++index) if (protein(index, false)->description.find(keyword) != string::npos) indexList.push_back(index); } else { string lcKeyword = keyword; for (size_t index = 0, end = size(); index < end; ++index) { string lcDescription = protein(index, false)->description; bal::to_lower(lcDescription); if (lcDescription.find(lcKeyword) != string::npos) indexList.push_back(index); } } return indexList; } // // ProteinListSimple // PWIZ_API_DECL ProteinPtr ProteinListSimple::protein(size_t index, bool getSequence) const { // validate index if (index >= size()) throw runtime_error("[ProteinListSimple::protein()] Invalid index."); // validate Protein* if (!proteins[index].get()) throw runtime_error("[ProteinListSimple::protein()] Null ProteinPtr."); return proteins[index]; } // // ProteomeData // PWIZ_API_DECL bool ProteomeData::empty() const { return proteinListPtr->empty(); } } // namespace proteome } // namespace pwiz pwiz/pwiz/data/proteome/Modification.cpp0000664000175100017510000003015412664775621022423 0ustar teamcityteamcity00000000000000// // $Id: Modification.cpp 2454 2011-01-07 21:34:45Z chambm $ // // // Original author: Matt Chambers // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Modification.hpp" #include #include "pwiz/utility/misc/Exception.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace proteome { using namespace chemistry; using namespace pwiz::util; class Modification::Impl { public: Impl(const chemistry::Formula& formula) : formula_(new Formula(formula)), monoDeltaMass(formula_->monoisotopicMass()), avgDeltaMass(formula_->molecularWeight()) { } Impl(double monoisotopicDeltaMass, double averageDeltaMass) : monoDeltaMass(monoisotopicDeltaMass), avgDeltaMass(averageDeltaMass) { } Impl(const Impl& mod) : formula_(mod.hasFormula() ? new Formula(*mod.formula_) : NULL), monoDeltaMass(mod.monoDeltaMass), avgDeltaMass(mod.avgDeltaMass) { } inline bool hasFormula() const { return formula_.get() != NULL; } inline const chemistry::Formula& formula() const { if (!formula_.get()) throw runtime_error("[Modification::formula()] this mod was constructed with mass info only"); return *formula_; } inline double monoisotopicDeltaMass() const { return monoDeltaMass; } inline double averageDeltaMass() const { return avgDeltaMass; } private: auto_ptr formula_; double monoDeltaMass; double avgDeltaMass; }; PWIZ_API_DECL Modification::Modification() : impl_(new Impl(0, 0)) { } PWIZ_API_DECL Modification::Modification(const chemistry::Formula& formula) : impl_(new Impl(formula)) { } PWIZ_API_DECL Modification::Modification(double monoisotopicDeltaMass, double averageDeltaMass) : impl_(new Impl(monoisotopicDeltaMass, averageDeltaMass)) { } PWIZ_API_DECL Modification::Modification(const Modification& mod) : impl_(new Impl(*mod.impl_)) { } PWIZ_API_DECL Modification& Modification::operator=(const Modification& rhs) { impl_.reset(new Impl(*rhs.impl_)); return *this; } PWIZ_API_DECL Modification::~Modification() {} PWIZ_API_DECL bool Modification::hasFormula() const {return impl_->hasFormula();} PWIZ_API_DECL const Formula& Modification::formula() const {return impl_->formula();} PWIZ_API_DECL double Modification::monoisotopicDeltaMass() const {return impl_->monoisotopicDeltaMass();} PWIZ_API_DECL double Modification::averageDeltaMass() const {return impl_->averageDeltaMass();} PWIZ_API_DECL bool Modification::operator==(const Modification& rhs) const { return monoisotopicDeltaMass() == rhs.monoisotopicDeltaMass() && averageDeltaMass() == rhs.averageDeltaMass(); } PWIZ_API_DECL bool Modification::operator<(const Modification& rhs) const { return monoisotopicDeltaMass() < rhs.monoisotopicDeltaMass(); } PWIZ_API_DECL ModificationList::ModificationList() { } PWIZ_API_DECL ModificationList::ModificationList(const Modification& mod) : vector(1, mod) { } PWIZ_API_DECL ModificationList::ModificationList(const std::vector& mods) : vector(mods.begin(), mods.end()) { } PWIZ_API_DECL double ModificationList::monoisotopicDeltaMass() const { double mass = 0; for (const_iterator itr = begin(); itr != end(); ++itr) mass += itr->monoisotopicDeltaMass(); return mass; } PWIZ_API_DECL double ModificationList::averageDeltaMass() const { double mass = 0; for (const_iterator itr = begin(); itr != end(); ++itr) mass += itr->averageDeltaMass(); return mass; } PWIZ_API_DECL bool ModificationList::operator==(const ModificationList& rhs) const { if (size() != rhs.size()) return false; ModificationList::const_iterator itr, rhsItr; for (itr = begin(), rhsItr = rhs.begin(); itr != end() && rhsItr != rhs.end(); ++itr, ++rhsItr) { if (!(*itr == *rhsItr)) return false; } return true; // lists are equal } PWIZ_API_DECL bool ModificationList::operator<(const ModificationList& rhs) const { if (size() == rhs.size()) { ModificationList::const_iterator itr, rhsItr; for (itr = begin(), rhsItr = rhs.begin(); itr != end() && rhsItr != rhs.end(); ++itr, ++rhsItr) { if (!(*itr == *rhsItr)) return *itr < *rhsItr; } return false; // lists are equal } return size() < rhs.size(); } int ModificationMap::NTerminus() {return INT_MIN;} int ModificationMap::CTerminus() {return INT_MAX;} class ModificationMap::Impl { public: Impl(ModificationMap* mods) : dirty_(false), monoDeltaMass_(0), avgDeltaMass_(0), mods_(mods) { } Impl(ModificationMap* mods, const Impl& other) : dirty_(other.dirty_), monoDeltaMass_(other.monoDeltaMass_), avgDeltaMass_(other.avgDeltaMass_), mods_(mods) { mods_->virtual_map::insert(other.mods_->begin(), other.mods_->end()); } inline double monoDeltaMass() const { calculateMasses(); return monoDeltaMass_; } inline double avgDeltaMass() const { calculateMasses(); return avgDeltaMass_; } mutable bool dirty_; mutable double monoDeltaMass_; mutable double avgDeltaMass_; private: ModificationMap* mods_; inline void calculateMasses() const { if (dirty_) { dirty_ = false; monoDeltaMass_ = avgDeltaMass_ = 0; for (ModificationMap::const_iterator itr = mods_->begin(); itr != mods_->end(); ++itr) { const ModificationList& modList = itr->second; monoDeltaMass_ += modList.monoisotopicDeltaMass(); avgDeltaMass_ += modList.averageDeltaMass(); } } } }; PWIZ_API_DECL ModificationMap::~ModificationMap() { } PWIZ_API_DECL ModificationMap::ModificationMap() : impl_(new Impl(this)) { } PWIZ_API_DECL ModificationMap::ModificationMap(const ModificationMap& other) : impl_(new Impl(this, *other.impl_)) { } PWIZ_API_DECL double ModificationMap::monoisotopicDeltaMass() const { return impl_->monoDeltaMass(); } PWIZ_API_DECL double ModificationMap::averageDeltaMass() const { return impl_->avgDeltaMass(); } PWIZ_API_DECL ModificationMap::iterator ModificationMap::begin() { impl_->dirty_ = true; return virtual_map::begin(); } PWIZ_API_DECL ModificationMap::iterator ModificationMap::end() { impl_->dirty_ = true; return virtual_map::end(); } PWIZ_API_DECL ModificationMap::reverse_iterator ModificationMap::rbegin() { impl_->dirty_ = true; return virtual_map::rbegin(); } PWIZ_API_DECL ModificationMap::reverse_iterator ModificationMap::rend() { impl_->dirty_ = true; return virtual_map::rend(); } PWIZ_API_DECL ModificationMap::mapped_type& ModificationMap::operator[](const ModificationMap::key_type& x) { impl_->dirty_ = true; return virtual_map::operator[](x); } PWIZ_API_DECL std::pair ModificationMap::equal_range(const ModificationMap::key_type& x) { impl_->dirty_ = true; return virtual_map::equal_range(x); } PWIZ_API_DECL ModificationMap::iterator ModificationMap::find(const ModificationMap::key_type& x) { impl_->dirty_ = true; return virtual_map::find(x); } PWIZ_API_DECL ModificationMap::iterator ModificationMap::lower_bound(const ModificationMap::key_type& x) { impl_->dirty_ = true; return virtual_map::lower_bound(x); } PWIZ_API_DECL ModificationMap::iterator ModificationMap::upper_bound(const ModificationMap::key_type& x) { impl_->dirty_ = true; return virtual_map::upper_bound(x); } PWIZ_API_DECL void ModificationMap::clear() { impl_->monoDeltaMass_ = impl_->avgDeltaMass_ = 0; virtual_map::clear(); } PWIZ_API_DECL void ModificationMap::erase(ModificationMap::iterator position) { const ModificationList& modList = position->second; impl_->monoDeltaMass_ -= modList.monoisotopicDeltaMass(); impl_->avgDeltaMass_ -= modList.averageDeltaMass(); virtual_map::erase(position); } PWIZ_API_DECL void ModificationMap::erase(ModificationMap::iterator start, ModificationMap::iterator finish) { for (; start != finish; ++start) { const ModificationList& modList = start->second; impl_->monoDeltaMass_ -= modList.monoisotopicDeltaMass(); impl_->avgDeltaMass_ -= modList.averageDeltaMass(); } virtual_map::erase(start, finish); } PWIZ_API_DECL ModificationMap::size_type ModificationMap::erase(const key_type& x) { iterator itr = find(x); if (itr != end()) { erase(itr); return 1; } return 0; } PWIZ_API_DECL std::pair ModificationMap::insert(const value_type& x) { std::pair insertResult = virtual_map::insert(x); if (insertResult.second) { const ModificationList& modList = x.second; impl_->monoDeltaMass_ += modList.monoisotopicDeltaMass(); impl_->avgDeltaMass_ += modList.averageDeltaMass(); } return insertResult; } PWIZ_API_DECL ModificationMap::iterator ModificationMap::insert(ModificationMap::iterator position, const value_type& x) { // ignore hint because that base function won't tell us if the insert happened or not return insert(x).first; } PWIZ_API_DECL void ModificationMap::swap(ModificationMap& other) { throw runtime_error("[ModificationMap::swap()] should not be called"); } PWIZ_API_DECL bool ModificationMap::operator==(const ModificationMap& rhs) const { if (size() != rhs.size()) return false; ModificationMap::const_iterator itr, rhsItr; for (itr = begin(), rhsItr = rhs.begin(); itr != end() && rhsItr != rhs.end(); ++itr, ++rhsItr) { // compare positions and modification lists if (itr->first != rhsItr->first || !(itr->second == rhsItr->second)) return false; } return true; } PWIZ_API_DECL bool ModificationMap::operator<(const ModificationMap& rhs) const { if (size() < rhs.size()) { ModificationMap::const_iterator itr, rhsItr; for (itr = begin(), rhsItr = rhs.begin(); itr != end() && rhsItr != rhs.end(); ++itr, ++rhsItr) { // compare positions if (itr->first == rhsItr->first) { // compare modification lists return itr->second < rhsItr->second; } else return itr->first < rhsItr->first; } return false; } return size() < rhs.size(); } } // namespace proteome } // namespace pwiz pwiz/pwiz/data/proteome/Peptide.hpp0000664000175100017510000001531712664775621021421 0ustar teamcityteamcity00000000000000// // $Id: Peptide.hpp 2453 2011-01-07 21:29:27Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PEPTIDE_HPP_ #define _PEPTIDE_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/utility/chemistry/Chemistry.hpp" #include namespace pwiz { namespace proteome { class ModificationMap; class Fragmentation; /// settings to enable parsing of inline modifications in peptide sequences enum PWIZ_API_DECL ModificationParsing { ModificationParsing_Off, /// any non-AA characters will cause an exception ModificationParsing_ByFormula, /// oxidized P in peptide: PEP(O)TIDE ModificationParsing_ByMass, /// PEP(15.94)TIDE or PEP(15.94,15.99)TIDE ModificationParsing_Auto /// either by formula or by mass }; /// the delimiter expected to signify an inline modification enum PWIZ_API_DECL ModificationDelimiter { ModificationDelimiter_Parentheses, /// '(' and ')' ModificationDelimiter_Brackets, /// '[' and ']' ModificationDelimiter_Braces /// '{' and '}' }; #define MODIFICATION_PARSING_ARGUMENTS \ ModificationParsing mp = ModificationParsing_Off, \ ModificationDelimiter md = ModificationDelimiter_Parentheses /// represents a peptide or polypeptide (a sequence of amino acids) class PWIZ_API_DECL Peptide { public: Peptide(const std::string& sequence = "", MODIFICATION_PARSING_ARGUMENTS); Peptide(const char* sequence, MODIFICATION_PARSING_ARGUMENTS); Peptide(std::string::const_iterator begin, std::string::const_iterator end, MODIFICATION_PARSING_ARGUMENTS); Peptide(const char* begin, const char* end, MODIFICATION_PARSING_ARGUMENTS); Peptide(const Peptide&); Peptide& operator=(const Peptide&); virtual ~Peptide(); /// returns the sequence of amino acids making up the peptide const std::string& sequence() const; /// if modified = false: returns the composition formula of sequence()+water /// if modified = true: returns the composition formula of sequence()+modifications()+water /// throws an exception if modified = true and any modification has only mass information chemistry::Formula formula(bool modified = false) const; /// if charge = 0: returns neutral mass /// if charge > 0: returns charged m/z /// if modified = false: returns the monoisotopic mass of sequence()+water /// if modified = true: returns the monoisotopic mass of sequence()+modifications()+water double monoisotopicMass(int charge = 0, bool modified = true) const; /// if charge = 0: returns neutral mass /// if charge > 0: returns charged m/z /// if modified = false: returns the molecular weight of sequence()+water /// if modified = true: returns the molecular weight of sequence()+modifications()+water double molecularWeight(int charge = 0, bool modified = true) const; /// the map of sequence offsets (0-based) to modifications; /// modifications can be added or removed from the peptide with this map ModificationMap& modifications(); /// the map of sequence offsets (0-based) to modifications const ModificationMap& modifications() const; /// returns a fragmentation model for the peptide; /// fragment masses can calculated as mono/avg and as modified/unmodified Fragmentation fragmentation(bool monoisotopic = true, bool modified = true) const; /// returns true iff peptide sequences and modifications are equal bool operator==(const Peptide& rhs) const; /// returns true iff this peptide has a lesser sequence length, sequence, /// modifications length, or modifications bool operator<(const Peptide& rhs) const; private: friend class ModificationMap; // allow ModificationMap to befriend Peptide::Impl friend class Fragmentation; class Impl; boost::shared_ptr impl_; }; /// provides fragment ion masses for a peptide class PWIZ_API_DECL Fragmentation { public: Fragmentation(const Peptide& peptide, bool monoisotopic, bool modified); Fragmentation(const Fragmentation&); ~Fragmentation(); /// returns the a ion of length ; /// example: a(1) returns the a1 ion /// if = 0: returns neutral mass /// if > 0: returns charged m/z double a(size_t length, size_t charge = 0) const; /// returns the b ion of length /// example: b(1) returns the b1 ion /// if = 0: returns neutral mass /// if > 0: returns charged m/z double b(size_t length, size_t charge = 0) const; /// returns the c ion of length /// example: c(1) returns the c1 ion /// if = 0: returns neutral mass /// if > 0: returns charged m/z double c(size_t length, size_t charge = 0) const; /// returns the x ion of length /// example: x(1) returns the x1 ion /// if = 0: returns neutral mass /// if > 0: returns charged m/z double x(size_t length, size_t charge = 0) const; /// returns the y ion of length /// example: y(1) returns the y1 ion /// if = 0: returns neutral mass /// if > 0: returns charged m/z double y(size_t length, size_t charge = 0) const; /// returns the z ion of length /// example: z(1) returns the z1 ion /// if = 0: returns neutral mass /// if > 0: returns charged m/z double z(size_t length, size_t charge = 0) const; /// returns the z radical ion of length /// example: zRadical(1) returns the z1* ion /// if = 0: returns neutral mass /// if > 0: returns charged m/z double zRadical(size_t length, size_t charge = 0) const; private: class Impl; boost::shared_ptr impl_; }; } // namespace proteome } // namespace pwiz // include here for user convenience #include "Modification.hpp" #endif // _PEPTIDE_HPP_ pwiz/pwiz/data/proteome/Version.cpp0000664000175100017510000000266612664776103021446 0ustar teamcityteamcity00000000000000// This file was generated by the "svnrev" utility // You should not modify it manually, as it may be re-generated. // // $Revision: 9198 $ // $Date: 2015-12-4 $ // // Licensed under the Apache License, Version 2.0 (the License); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an AS IS BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "Version.hpp" #include #ifdef PWIZ_USER_VERSION_INFO_H // in case you need to add any info version of your own #include PWIZ_USER_VERSION_INFO_H // must define PWIZ_USER_VERSION_INFO_H_STR for use below #endif namespace pwiz { namespace proteome { int Version::Major() {return 3;} int Version::Minor() {return 0;} int Version::Revision() {return 9198;} std::string Version::LastModified() {return "2015-12-4";} std::string Version::str() { std::ostringstream v; v << Major() << '.' << Minor() << '.' << Revision(); #ifdef PWIZ_USER_VERSION_INFO_H v << " (" << PWIZ_USER_VERSION_INFO_H_STR << ")"; #endif return v.str(); } } // namespace proteome } // namespace pwiz pwiz/pwiz/data/proteome/Digestion.hpp0000664000175100017510000002266512664775621021760 0ustar teamcityteamcity00000000000000// // $Id: Digestion.hpp 6909 2014-11-19 17:18:29Z chambm $ // // // Original author: Matt Chambers // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _DIGESTION_HPP_ #define _DIGESTION_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/common/cv.hpp" #include "pwiz/utility/chemistry/Chemistry.hpp" #include "Peptide.hpp" #include "boost/shared_ptr.hpp" #include #include #include namespace pwiz { namespace proteome { using namespace pwiz::cv; /// peptide subclass that contains extra metadata provided by digestion class PWIZ_API_DECL DigestedPeptide : public Peptide { public: DigestedPeptide(const std::string& sequence); DigestedPeptide(const char* sequence); DigestedPeptide(std::string::const_iterator begin, std::string::const_iterator end, size_t offset, size_t missedCleavages, bool NTerminusIsSpecific, bool CTerminusIsSpecific, std::string NTerminusPrefix = "", std::string CTerminusSuffix = ""); DigestedPeptide(const Peptide& peptide, size_t offset, size_t missedCleavages, bool NTerminusIsSpecific, bool CTerminusIsSpecific, std::string NTerminusPrefix = "", std::string CTerminusSuffix = ""); DigestedPeptide(const DigestedPeptide&); DigestedPeptide& operator=(const DigestedPeptide&); virtual ~DigestedPeptide(); /// returns the zero-based offset of the N terminus of the peptide /// in the polypeptide from which it was digested size_t offset() const; /// returns the number of missed cleavage sites in the peptide size_t missedCleavages() const; /// returns the number of termini that matched to the digestion rules size_t specificTermini() const; /// returns true iff the N terminus matched the digestion rules bool NTerminusIsSpecific() const; /// returns true iff the C terminus matched the digestion rules bool CTerminusIsSpecific() const; /// returns residue preceding digestion site std::string NTerminusPrefix() const; /// returns residue following digestion site std::string CTerminusSuffix() const; /// returns true iff peptide sequences, masses, and all digestion metadata are equal bool operator==(const DigestedPeptide& rhs) const; private: size_t offset_; size_t missedCleavages_; bool NTerminusIsSpecific_; bool CTerminusIsSpecific_; std::string NTerminusPrefix_; std::string CTerminusSuffix_; }; /// enumerates the peptides from proteolytic digestion of a polypeptide or protein; class PWIZ_API_DECL Digestion { public: /// sets the number of peptide termini that must match to a digestion motif /// note: castable to int; i.e. non=0, semi=1, fully=2 enum PWIZ_API_DECL Specificity { NonSpecific = 0, /// neither termini must match digestion motif(s) SemiSpecific = 1, /// either or both termini must match digestion motif(s) FullySpecific = 2 /// both termini must match digestion motif(s) }; /// sets constraints for valid peptides produced by iterating the digestion struct PWIZ_API_DECL Config { int maximumMissedCleavages; //double minimumMass; //double maximumMass; int minimumLength; int maximumLength; Specificity minimumSpecificity; bool clipNTerminalMethionine; Config(int maximumMissedCleavages = 100000, //double minimumMass = 0, //double maximumMass = 100000, int minimumLength = 0, int maximumLength = 100000, Specificity minimumSpecificity = FullySpecific, bool clipNTerminalMethionine = true); }; /// returns the set of predefined cleavage agents defined in the PSI-MS CV static const std::set& getCleavageAgents(); /// returns the names of the set of predefined cleavage agents defined in the PSI-MS CV static const std::vector& getCleavageAgentNames(); /// returns the cvid of the specified cleavage agent using a case-insensitive search, /// or CVID_Unknown if the agent is not found static CVID getCleavageAgentByName(const std::string& agentName); /// returns the cvid of the specified cleavage agent looking it up by the Perl regular expression, /// or CVID_Unknown if the agent is not found (the regex pattern must match exactly) static CVID getCleavageAgentByRegex(const std::string& agentRegex); /// returns the official PSI Perl regular expression defining the places in a /// polypeptide or protein that the agent will cut. static const std::string& getCleavageAgentRegex(CVID agentCvid); /// returns a modified version of a cleavage agent regex where any ambiguous AA symbols (BJXZ) /// are augmented with their unambiguous counterparts (e.g. B -> [BND]) static std::string disambiguateCleavageAgentRegex(const std::string& cleavageAgentRegex); /// specifies digestion occurs by a commonly used cleavage agent Digestion(const Peptide& polypeptide, CVID cleavageAgent, const Config& config = Config()); /// specifies digestion occurs by a combination of commonly used cleavage agents Digestion(const Peptide& polypeptide, const std::vector& cleavageAgents, const Config& config = Config()); /// specifies digestion occurs by a user-specified, zero-width Perl regular expression /// example: "(?<=K)" means "cleaves after K" /// example: "((?<=D))|((?=D))" means "cleaves before or after D" /// example: "(?=[DE])" means "cleaves before D or E" /// example: "(?<=[FYWLKR])(?!P)" means "cleaves after any single residue from FYWLKR except when it is followed by P" Digestion(const Peptide& polypeptide, const std::string& cleavageAgentRegex, const Config& config = Config()); /// specifies digestion occurs by a combination of user-specified, zero-width Perl regular expressions /// example: "(?<=K)" means "cleaves after K" /// example: "((?<=D))|((?=D))" means "cleaves before or after D" /// example: "(?=[DE])" means "cleaves before D or E" /// example: "(?<=[FYWLKR])(?!P)" means "cleaves after any single residue from FYWLKR except when it is followed by P" Digestion(const Peptide& polypeptide, const std::vector& cleavageAgentRegexes, const Config& config = Config()); /// returns all instances of the given peptide in the polypeptide under digestion; /// note: the filters set in Digestion::Config are respected! std::vector find_all(const Peptide& peptide) const; /// returns the first instance of the given peptide in the polypeptide under digestion; /// if offsetHint is provided, the search will begin at that offset; /// throws runtime_error if no instance of the peptide is found; /// note: the filters set in Digestion::Config are respected! DigestedPeptide find_first(const Peptide& peptide, size_t offsetHint = 0) const; ~Digestion(); private: class Impl; // forward-declared for const_iterator public: /// provides forward-only, read-only iteration to enumerate peptides class PWIZ_API_DECL const_iterator { public: const_iterator(const const_iterator& rhs); ~const_iterator(); const DigestedPeptide& operator*() const; const DigestedPeptide* operator->() const; const_iterator& operator++(); const_iterator operator++(int); bool operator!=(const const_iterator& that) const; bool operator==(const const_iterator& that) const; typedef std::forward_iterator_tag iterator_category; typedef DigestedPeptide value_type; typedef size_t difference_type; typedef value_type* pointer; typedef value_type& reference; private: const_iterator(); const_iterator(const Digestion& digestion); friend class Digestion; friend class Digestion::Impl; class Impl; boost::shared_ptr impl_; }; const_iterator begin() const; const_iterator end() const; private: friend class const_iterator; friend class const_iterator::Impl; boost::shared_ptr impl_; }; } // namespace proteome } // namespace pwiz #endif // _DIGESTION_HPP_ pwiz/pwiz/data/proteome/ProteomeDataFileTest.cpp0000664000175100017510000001322312664775621024040 0ustar teamcityteamcity00000000000000// // $Id: ProteomeDataFileTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "ProteomeDataFile.hpp" #include "Diff.hpp" #include "examples.hpp" #include "Reader_FASTA.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include #include #include #include using namespace pwiz::util; using namespace pwiz::proteome; using namespace pwiz::data; using boost::shared_ptr; ostream* os_ = 0; string filenameBase_ = "temp.ProteomeDataFileTest"; void validateWriteRead(const ProteomeDataFile::WriteConfig& writeConfig, const DiffConfig diffConfig) { if (os_) *os_ << "validateWriteRead()\n " << writeConfig << endl; string filename1 = filenameBase_ + "1.fasta"; string filename2 = filenameBase_ + "2.fasta"; { // create ProteomeData object in memory ProteomeData tiny; examples::initializeTiny(tiny); // write to file #1 (static) ProteomeDataFile::write(tiny, filename1, writeConfig); shared_ptr reader; if (writeConfig.format == ProteomeDataFile::Format_FASTA) { // Reader_FASTA creates the index in the read() call Reader_FASTA::Config config; config.indexed = writeConfig.indexed; reader.reset(new Reader_FASTA(config)); } // read back into an ProteomeDataFile object ProteomeDataFile pd1(filename1, *reader); // compare Diff diff(tiny, pd1, diffConfig); if (diff && os_) *os_ << diff << endl; unit_assert(!diff); // write to file #2 (member) pd1.write(filename2, writeConfig); // read back into another ProteomeDataFile object ProteomeDataFile pd2(filename2, *reader); // compare diff(tiny, pd2); if (diff && os_) *os_ << diff << endl; unit_assert(!diff); // now give the gzip read a workout bio::filtering_istream tinyGZ(bio::gzip_compressor() | bio::file_descriptor_source(filename1)); bio::copy(tinyGZ, bio::file_descriptor_sink(filename1+".gz", ios::out|ios::binary)); ProteomeDataFile pd3(filename1+".gz", *reader); // compare diff(tiny, pd3); if (diff && os_) *os_ << diff << endl; unit_assert(!diff); } // remove temp files bfs::remove(filename1); bfs::remove(filename2); bfs::remove(filename1 + ".gz"); bool index1Exists = bfs::exists(filename1 + ".index"); bool index2Exists = bfs::exists(filename2 + ".index"); bool index3Exists = bfs::exists(filename1 + ".gz.index"); bool indexShouldExist = writeConfig.indexed; unit_assert(!indexShouldExist || index1Exists); unit_assert(!indexShouldExist || index2Exists); unit_assert(!indexShouldExist || index3Exists); if (index1Exists) bfs::remove(filename1 + ".index"); if (index2Exists) bfs::remove(filename2 + ".index"); if (index3Exists) bfs::remove(filename1 + ".gz.index"); } void test() { ProteomeDataFile::WriteConfig writeConfig; DiffConfig diffConfig; // test FASTA with binary stream index validateWriteRead(writeConfig, diffConfig); // test FASTA with memory index writeConfig.indexed = false; validateWriteRead(writeConfig, diffConfig); } class TestReader : public Reader { public: TestReader() : count(0) {} virtual std::string identify(const std::string& uri, shared_ptr uriStreamPtr) const { ++count; if (!bal::iends_with(uri, ".fasta")) return ""; string buf; getline(*uriStreamPtr, buf); if (buf[0] != '>') return ""; return getType(); } virtual void read(const std::string& uri, shared_ptr uriStreamPtr, ProteomeData& pd) const { ++count; } const char *getType() const {return "testReader";} // satisfy inheritance mutable int count; }; void testReader() { // create a file string filename = filenameBase_ + ".fAsTa"; ofstream os(filename.c_str()); os << ">Id Description\nSEQUENCE\n"; os.close(); // open the file with our Reader TestReader reader; ProteomeDataFile pd(filename, reader); // verify that our reader got called properly unit_assert(reader.count == 2); // remove temp file boost::filesystem::remove(filename); if (os_) *os_ << endl; } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); testReader(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/proteome/PeptideTest.cpp0000664000175100017510000007002112664775621022245 0ustar teamcityteamcity00000000000000// // $Id: PeptideTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/unit.hpp" #include "Peptide.hpp" #include "pwiz/utility/misc/Std.hpp" #include "boost/thread/thread.hpp" #include "boost/thread/barrier.hpp" using namespace pwiz::util; using namespace pwiz::proteome; using namespace pwiz::chemistry; ostream* os_ = 0; void test() { Peptide angiotensin("DRVYIHPF"); if (os_) *os_ << "angiotensin: " << angiotensin.sequence() << " " << angiotensin.formula() << endl; Peptide alpha16("WHWLQL"); if (os_) *os_ << "alpha16: " << alpha16.sequence() << " " << alpha16.formula() << endl; } const char* sequences[] = { "CLPMILDNK", "AVSNPFQQR", "CELLFFFK", "AGASIVGVNCR", "QPTPPFFGR", "AVFHMQSVK", "TRUCKER" }; struct TestPeptide { const char* sequence; double monoMassNeutral, monoMassPlus1, monoMassPlus2; double avgMassNeutral, avgMassPlus1, avgMassPlus2; }; TestPeptide testPeptides[] = { { "ELK", 388.2322, 389.24005, 195.12396, 388.45918, 389.4665, 195.2369 }, { "DEERLICKER", 1289.6398, 1290.6477, 645.8278, 1290.44644, 1291.4537, 646.2305 }, { "ELVISLIVES", 1100.6329, 1101.6408, 551.3243, 1101.29052, 1102.2978, 551.6525 }, { "THEQUICKRWNFUMPSVERTHELAYDG", 3348.3249, 3349.3328, 1675.17035, 3348.44626, 3349.45416, 1675.23103 }, { "No?PepTidE...", 0, 0, 0, 0, 0, 0 } }; const size_t testPeptidesSize = sizeof(testPeptides)/sizeof(TestPeptide); void peptideTest() { for (size_t i=0; i < testPeptidesSize; ++i) { const TestPeptide& p = testPeptides[i]; double BIG_EPSILON = 0.001; Peptide peptide(p.sequence); if (os_) *os_ << peptide.sequence() << ": " << peptide.formula() << " " << peptide.monoisotopicMass() << " " << peptide.molecularWeight() << endl; unit_assert_equal(peptide.formula().monoisotopicMass(), p.monoMassNeutral, BIG_EPSILON); unit_assert_equal(peptide.formula().molecularWeight(), p.avgMassNeutral, BIG_EPSILON); unit_assert_equal(peptide.monoisotopicMass(), p.monoMassNeutral, BIG_EPSILON); unit_assert_equal(peptide.molecularWeight(), p.avgMassNeutral, BIG_EPSILON); unit_assert_equal(peptide.monoisotopicMass(1, true), p.monoMassPlus1, BIG_EPSILON); unit_assert_equal(peptide.molecularWeight(1, true), p.avgMassPlus1, BIG_EPSILON); unit_assert_equal(peptide.monoisotopicMass(2, true), p.monoMassPlus2, BIG_EPSILON); unit_assert_equal(peptide.molecularWeight(2, true), p.avgMassPlus2, BIG_EPSILON); peptide = p.sequence; // test assignment if (os_) *os_ << peptide.sequence() << ": " << peptide.formula() << " " << peptide.monoisotopicMass() << " " << peptide.molecularWeight() << endl; unit_assert_equal(peptide.formula().monoisotopicMass(), p.monoMassNeutral, BIG_EPSILON); unit_assert_equal(peptide.formula().molecularWeight(), p.avgMassNeutral, BIG_EPSILON); unit_assert_equal(peptide.monoisotopicMass(), p.monoMassNeutral, BIG_EPSILON); unit_assert_equal(peptide.molecularWeight(), p.avgMassNeutral, BIG_EPSILON); } } struct TestModification { const char* motif; const char* formula; double deltaMonoMass; double deltaAvgMass; bool isDynamic; }; TestModification testModifications[] = { { "M", "O1", 15.9949, 15.9994, true }, // Oxidation of M { "C", "C2H3N1O1", 57.02146, 57.052, false }, // Carboxyamidomethylation of C { "(Q", "N-1H-3", -17.02655, -17.0306, false }, // Pyroglutamic acid from Q at the N terminus { "(E", "N-1H-3", -17.02655, -17.0306, true }, // Pyroglutamic acid from E at the N terminus { "N!G", "N-1H-3", -17.02655, -17.0306, true }, // Succinimide from N when N terminal to G //{ "[NQ]", "O1N-1H-2", 0.98402, 0.9847, true }, // Deamidation of N or Q { "[STY]!{STY}", "H1P1O3", 79.96633, 79.9799, true }, // Phosphorylation of S, T, or Y when not N terminal to S, T, or Y { "(", "C2H2O1", 42.010565, 42.0367, true }, // N-terminal acetylation { "[ED)]", "C2H5N1", 43.042199, 43.0678, true }, // Carboxyl modification with ethanolamine }; struct TestModifiedPeptide { const char* sequence; const char* mods; // index pairs bool modsHaveFormulas; ModificationParsing mp; ModificationDelimiter md; double monoMass; double avgMass; int exception; // if non-zero, test should cause this exception }; TestModifiedPeptide testModifiedPeptides[] = { // M+16 { "MEERKAT", "0 0", false, ModificationParsing_Off, ModificationDelimiter_Brackets, 879.41205, 879.97844, 0 }, // M+16 { "M[O1]EERKAT", "0 0", true, ModificationParsing_ByFormula, ModificationDelimiter_Brackets, 879.41205, 879.97844, 0 }, // M+16 { "M[O1]EERKAT", "0 0", true, ModificationParsing_Auto, ModificationDelimiter_Brackets, 879.41205, 879.97844, 0 }, // M+16 { "M(15.9949,15.9994)EERKAT", "0 0", false, ModificationParsing_ByFormula, ModificationDelimiter_Parentheses, 879.41205, 879.97844, 1 //"[Peptide::Impl::parse()] Expected a chemical formula for all modifications in sequence " }, // M+16 { "M[15.9949,15.9994]EERKAT", "0 0", false, ModificationParsing_ByMass, ModificationDelimiter_Brackets, 879.41205, 879.97844, 0 }, // M+16 { "M(15.9949,15.9994)EERKAT", "0 0", false, ModificationParsing_Auto, ModificationDelimiter_Parentheses, 879.41205, 879.97844, 0 }, // M+16 { "M[O1)EERKAT", "0 0", true, ModificationParsing_ByFormula, ModificationDelimiter_Brackets, 879.41205, 879.97844, 1 //"[Peptide::Impl::parse()] Modification started but not ended in sequence " }, // C+57 { "THEQICKRWNFMPSVERTHELAYDG", "1 5", false, ModificationParsing_Off, ModificationDelimiter_Brackets, 3103.43929, 3105.4218, 0 }, // C+57, M+16 { "THEQICKRWNFMPSVERTHELAYDG", "0 11 1 5", false, ModificationParsing_Off, ModificationDelimiter_Brackets, 3119.43419, 3121.4212, 0 }, // C+57, M+16 { "THEQIC{C2H3N1O1}KRWNFM{O1}PSVERTHELAYDG", "0 11 1 5", true, ModificationParsing_ByFormula, ModificationDelimiter_Braces, 3119.43419, 3121.4212, 0 }, // C+57, M+16 { "THEQIC{C2H3N1O1}KRWNFM{15.9949,15.9994}PSVERTHELAYDG", "0 11 1 5", false, ModificationParsing_Auto, ModificationDelimiter_Braces, 3119.43419, 3121.4212, 0 }, // C+57, Q-17 { "QICKRWNFMPSVERTHELAYDG", "2 0 1 2", false, ModificationParsing_Off, ModificationDelimiter_Brackets, 2719.26356, 2721.0341, 0 }, // no mods { "ELVISLIVES", 0, false, ModificationParsing_Off, ModificationDelimiter_Brackets, 1100.63293, 1101.29052, 0 }, // E-17 { "ELVISLIVES", "3 0", false, ModificationParsing_Off, ModificationDelimiter_Brackets, 1083.60638, 1084.26, 0 }, // E-17 { "E(N-1H-3)LVISLIVES", "3 0", true, ModificationParsing_ByFormula, ModificationDelimiter_Parentheses, 1083.60638, 1084.26, 0 }, // E-17 { "E(N-1H-3)LVISLIVES", "3 0", true, ModificationParsing_ByMass, ModificationDelimiter_Parentheses, 1083.60638, 1084.26, 1 //"[Peptide::Impl::parse()] Expected one or two comma-separated numbers in sequence " }, // E-17 { "E(N-1H-3)LVISLIVES", "3 0", true, ModificationParsing_Auto, ModificationDelimiter_Parentheses, 1083.60638, 1084.26, 0 }, // E-17 { "E(-17.02655,-17.0306)LVISLIVES", "3 0", false, ModificationParsing_ByMass, ModificationDelimiter_Parentheses, 1083.60638, 1084.26, 0 }, // E-17 { "E(-17.02655,-17.0306)LVISLIVES", "3 0", false, ModificationParsing_Auto, ModificationDelimiter_Parentheses, 1083.60638, 1084.26, 0 }, // no mods { "PINGPNG", 0, false, ModificationParsing_Off, ModificationDelimiter_Brackets, 667.32898, 667.7112, 0 }, // N-17 { "PINGPNG", "4 2", false, ModificationParsing_Off, ModificationDelimiter_Brackets, 650.30243, 650.6807, 0 }, // no mods { "MISSISSIPPI", 0, false, ModificationParsing_Off, ModificationDelimiter_Brackets, 1143.62099, 1144.3815, 0 }, // no mods { "MISSISSIPPI", 0, false, ModificationParsing_Auto, ModificationDelimiter_Brackets, 1143.62099, 1144.3815, 0 }, // S+80, S+80 { "MISSISSIPPI", "5 3 5 5", true, ModificationParsing_Off, ModificationDelimiter_Brackets, 1303.55365, 1304.3413, 0 }, // N-terminal +42 { "PINGPNG", "6 n", true, ModificationParsing_Off, ModificationDelimiter_Brackets, 709.339545, 709.7479, 0 }, // C-terminal +43 { "PINGPNG", "7 c", true, ModificationParsing_Off, ModificationDelimiter_Brackets, 710.371179, 710.779, 0 } }; const size_t testModificationsSize = sizeof(testModifications)/sizeof(TestModification); const size_t testModifiedPeptidesSize = sizeof(testModifiedPeptides)/sizeof(TestModifiedPeptide); void modificationTest() { for (size_t i=0; i < testModifiedPeptidesSize; ++i) { TestModifiedPeptide& p = testModifiedPeptides[i]; try { Peptide peptide; double monoDeltaMass = 0; double avgDeltaMass = 0; double BIG_EPSILON = 0.001; if (p.exception != 0) { //unit_assert_throws_what(Peptide(p.sequence, p.mp, p.md), exception, string(p.exception)+p.sequence); continue; } if (p.mp == ModificationParsing_Off || p.mods == NULL) { peptide = Peptide(p.sequence); if (p.mods != NULL) { ModificationMap& modMap = peptide.modifications(); vector tokens; boost::split(tokens, p.mods, boost::is_space()); for (size_t i=0; i < tokens.size(); i+=2) { TestModification& mod = testModifications[lexical_cast(tokens[i])]; int modOffset; if (tokens[i+1] == "n") modOffset = ModificationMap::NTerminus(); else if (tokens[i+1] == "c") modOffset = ModificationMap::CTerminus(); else modOffset = lexical_cast(tokens[i+1]); if (p.modsHaveFormulas) modMap[modOffset].push_back(Modification(mod.formula)); else modMap[modOffset].push_back(Modification(mod.deltaMonoMass, mod.deltaAvgMass)); monoDeltaMass += mod.deltaMonoMass; avgDeltaMass += mod.deltaAvgMass; } } } else { peptide = Peptide(p.sequence, p.mp, p.md); ModificationMap& modMap = peptide.modifications(); vector tokens; boost::split(tokens, p.mods, boost::is_space()); for (size_t i=0; i < tokens.size(); i+=2) { TestModification& mod = testModifications[lexical_cast(tokens[i])]; int modOffset; if (tokens[i+1] == "n") modOffset = ModificationMap::NTerminus(); else if (tokens[i+1] == "c") modOffset = ModificationMap::CTerminus(); else modOffset = lexical_cast(tokens[i+1]); ModificationMap::const_iterator itr = modMap.find(modOffset); unit_assert(itr != modMap.end()); const ModificationList& modList = itr->second; if (p.modsHaveFormulas) { unit_assert(modList[0].hasFormula()); unit_assert(modList[0].formula() == mod.formula); } unit_assert_equal(modList[0].monoisotopicDeltaMass(), mod.deltaMonoMass, BIG_EPSILON); unit_assert_equal(modList[0].averageDeltaMass(), mod.deltaAvgMass, BIG_EPSILON); monoDeltaMass += mod.deltaMonoMass; avgDeltaMass += mod.deltaAvgMass; } } if (os_) *os_ << peptide.sequence() << ": " << peptide.monoisotopicMass() << " " << peptide.molecularWeight() << endl; if (p.modsHaveFormulas) { unit_assert_equal(peptide.formula(true).monoisotopicMass(), p.monoMass, BIG_EPSILON); unit_assert_equal(peptide.formula(true).molecularWeight(), p.avgMass, BIG_EPSILON); } else if (p.mods != NULL) unit_assert_throws_what(peptide.formula(true), runtime_error, "[Peptide::formula()] peptide formula cannot be generated when any modifications have no formula info"); unit_assert_equal(peptide.formula(false).monoisotopicMass(), p.monoMass-monoDeltaMass, BIG_EPSILON); unit_assert_equal(peptide.formula(false).molecularWeight(), p.avgMass-avgDeltaMass, BIG_EPSILON); unit_assert_equal(peptide.monoisotopicMass(0, true), p.monoMass, BIG_EPSILON); unit_assert_equal(peptide.molecularWeight(0, true), p.avgMass, BIG_EPSILON); unit_assert_equal(peptide.monoisotopicMass(0, false), p.monoMass-monoDeltaMass, BIG_EPSILON); unit_assert_equal(peptide.molecularWeight(0, false), p.avgMass-avgDeltaMass, BIG_EPSILON); } catch (exception& e) { cout << "Unit test " << lexical_cast(i+1) << " on modified peptide \"" << p.sequence << "\" failed:\n" << e.what() << endl; } } } struct TestOperator { const char* lhsPeptide; const char* rhsPeptide; int compare; // 0:lhs==rhs -1:lhsrhs }; const TestOperator testOperators[] = { {"PEPTIDE", "PEPTIDE", 0}, {"PEPTIDE", "PEPTIDEK", -1}, {"PEPTIDEK", "PEPTIDE", 1}, {"(42)PEPTIDE", "(42)PEPTIDE", 0}, {"PEP(42)TIDE", "PEP(42)TIDE", 0}, {"PEPTIDE(42)", "PEPTIDE(42)", 0}, {"PEPTIDE", "(42)PEPTIDE", -1}, {"(42)PEPTIDE", "PEPTIDE", 1}, {"PEPTIDE(41)", "PEPTIDE(42)", -1}, {"PEPTIDE(42)", "PEPTIDE(41)", 1}, {"(42)PEPTIDE(42)", "(42)PEPTIDE(42)", 0}, {"(42)PEPTIDE(41)", "(42)PEPTIDE(42)", -1}, {"(42)PEPTIDE(42)", "(42)PEPTIDE(41)", 1}, {"(42)PEPTIDE", "(42)PEPTIDE(42)", -1}, {"(42)PEPTIDE(42)", "PEPTIDE(42)", 1}, {"P(42)EPTIDE(42)", "PEPTIDE(42)", 1}, {"(42)PEPTIDE", "P(42)EPTIDE", -1}, {"P(42)EPTIDE", "(42)PEPTIDE", 1}, }; const size_t testOperatorsSize = sizeof(testOperators)/sizeof(TestOperator); void operatorTest() { for (size_t i=0; i < testOperatorsSize; ++i) { const TestOperator& p = testOperators[i]; try { Peptide lhs(p.lhsPeptide); Peptide rhs(p.rhsPeptide); switch(p.compare) { case 0: unit_assert(lhs == rhs); unit_assert(!(lhs < rhs)); unit_assert(lhs.modifications() == rhs.modifications()); unit_assert(!(lhs.modifications() < rhs.modifications())); break; case -1: unit_assert(lhs < rhs); unit_assert(!(lhs == rhs)); if (!lhs.modifications().empty() || !rhs.modifications().empty()) { unit_assert(lhs.modifications() < rhs.modifications()); unit_assert(!(lhs.modifications() == rhs.modifications())); } break; case 1: unit_assert(!(lhs == rhs)); unit_assert(!(lhs < rhs)); if (!lhs.modifications().empty() || !rhs.modifications().empty()) { unit_assert(!(lhs.modifications() == rhs.modifications())); unit_assert(!(lhs.modifications() < rhs.modifications())); } break; } } catch (exception& e) { cout << "Unit test " << lexical_cast(i+1) << " comparing \"" << p.lhsPeptide << "\" and \"" << p.rhsPeptide << "\" failed:\n" << e.what() << endl; } } } struct TestFragmentation { const char* sequence; double a1, aN, a1Plus2, aNPlus2; double b1, bN, b1Plus2, bNPlus2; double c1, cN, c1Plus2, cNPlus2; double x1, xN, x1Plus2, xNPlus2; double y1, yN, y1Plus2, yNPlus2; double z1, zN, z1Plus2, zNPlus2; }; // test masses calculated at: // $Id: PeptideTest.cpp 4129 2012-11-20 00:05:37Z chambm $tml const TestFragmentation testFragmentations[] = { { "MEERKAT", 104.05344, 818.41949, 52.53066, 409.71368, 132.04836, 846.41441, 66.52811, 423.71114, 149.07490, 762.39328, 75.04139, 381.70057, 146.04538, 759.36375, 73.52662, 380.18581, 120.06611, 864.42497, 60.53699, 432.71642, 103.03956, 847.39842, 52.02372, 424.20315 }, { "THEQICKRWNFMPSVERTHELAYDG", 74.06063, 3001.42018, 37.53425, 1501.21402, 102.05555, 3029.41509, 51.53171, 1515.21148, 119.08210, 2989.42018, 60.04498, 1495.21402, 102.01916, 2972.35724, 51.51352, 1486.68256, 76.03990, 3047.42566, 38.52388, 1524.21676, 59.01335, 3030.39911, 30.01061, 1515.70349 }, }; const size_t testFragmentationsSize = sizeof(testFragmentations)/sizeof(TestFragmentation); void writeFragmentation(const Peptide& p, const Fragmentation& f, ostream& os) { size_t length = p.sequence().length(); os << "a:"; for (size_t i=1; i <= length; ++i) os << " " << f.a(i); os << endl; os << "b:"; for (size_t i=1; i <= length; ++i) os << " " << f.b(i); os << endl; os << "c:"; for (size_t i=1; i < length; ++i) os << " " << f.c(i); os << endl; os << "x:"; for (size_t i=1; i < length; ++i) os << " " << f.x(i); os << endl; os << "y:"; for (size_t i=1; i <= length; ++i) os << " " << f.y(i); os << endl; os << "z:"; for (size_t i=1; i <= length; ++i) os << " " << f.z(i); os << endl; } void fragmentTest() { const double EPSILON = 0.005; for (size_t i=0; i < testFragmentationsSize; ++i) { const TestFragmentation& tf = testFragmentations[i]; size_t length = string(tf.sequence).length(); Peptide peptide(tf.sequence); if (os_) *os_ << peptide.sequence() << ": " << peptide.monoisotopicMass() << endl; Fragmentation f = peptide.fragmentation(); if (os_) writeFragmentation(peptide, f, *os_); unit_assert_equal(tf.a1 - Proton, f.a(1), EPSILON); unit_assert_equal(tf.b1 - Proton, f.b(1), EPSILON); unit_assert_equal(tf.c1 - Proton, f.c(1), EPSILON); unit_assert_equal(tf.x1 - Proton, f.x(1), EPSILON); unit_assert_equal(tf.y1 - Proton, f.y(1), EPSILON); unit_assert_equal(tf.z1 - Proton, f.z(1), EPSILON); unit_assert_equal(tf.aN - Proton, f.a(length), EPSILON); unit_assert_equal(tf.bN - Proton, f.b(length), EPSILON); unit_assert_equal(tf.cN - Proton, f.c(length-1), EPSILON); unit_assert_equal(tf.xN - Proton, f.x(length-1), EPSILON); unit_assert_equal(tf.yN - Proton, f.y(length), EPSILON); unit_assert_equal(tf.zN - Proton, f.z(length), EPSILON); unit_assert_equal(tf.a1, f.a(1, 1), EPSILON); unit_assert_equal(tf.b1, f.b(1, 1), EPSILON); unit_assert_equal(tf.c1, f.c(1, 1), EPSILON); unit_assert_equal(tf.x1, f.x(1, 1), EPSILON); unit_assert_equal(tf.y1, f.y(1, 1), EPSILON); unit_assert_equal(tf.z1, f.z(1, 1), EPSILON); unit_assert_equal(tf.aN, f.a(length, 1), EPSILON); unit_assert_equal(tf.bN, f.b(length, 1), EPSILON); unit_assert_equal(tf.cN, f.c(length-1, 1), EPSILON); unit_assert_equal(tf.xN, f.x(length-1, 1), EPSILON); unit_assert_equal(tf.yN, f.y(length, 1), EPSILON); unit_assert_equal(tf.zN, f.z(length, 1), EPSILON); unit_assert_equal(tf.a1Plus2, f.a(1, 2), EPSILON); unit_assert_equal(tf.b1Plus2, f.b(1, 2), EPSILON); unit_assert_equal(tf.c1Plus2, f.c(1, 2), EPSILON); unit_assert_equal(tf.x1Plus2, f.x(1, 2), EPSILON); unit_assert_equal(tf.y1Plus2, f.y(1, 2), EPSILON); unit_assert_equal(tf.z1Plus2, f.z(1, 2), EPSILON); unit_assert_equal(tf.aNPlus2, f.a(length, 2), EPSILON); unit_assert_equal(tf.bNPlus2, f.b(length, 2), EPSILON); unit_assert_equal(tf.cNPlus2, f.c(length-1, 2), EPSILON); unit_assert_equal(tf.xNPlus2, f.x(length-1, 2), EPSILON); unit_assert_equal(tf.yNPlus2, f.y(length, 2), EPSILON); unit_assert_equal(tf.zNPlus2, f.z(length, 2), EPSILON); } // test fragmentation with mods { Peptide p("THEQICKRWNFMPSVERTHELAYDG"); Modification C57("C2H3N1O1"), M16("O1"); (p.modifications())[5].push_back(C57); (p.modifications())[11].push_back(M16); Fragmentation f = p.fragmentation(true, false); Fragmentation fWithMods = p.fragmentation(true, true); if (os_) writeFragmentation(p, f, *os_); if (os_) writeFragmentation(p, fWithMods, *os_); double EPSILON = 0.00000001; for (size_t i=1; i <= 5; ++i) { unit_assert_equal(f.a(i), fWithMods.a(i), EPSILON); unit_assert_equal(f.b(i), fWithMods.b(i), EPSILON); unit_assert_equal(f.c(i), fWithMods.c(i), EPSILON); } for (size_t i=6; i <= 11; ++i) { double deltaMass = C57.monoisotopicDeltaMass(); unit_assert_equal(f.a(i)+deltaMass, fWithMods.a(i), EPSILON); unit_assert_equal(f.b(i)+deltaMass, fWithMods.b(i), EPSILON); unit_assert_equal(f.c(i)+deltaMass, fWithMods.c(i), EPSILON); } for (size_t i=12; i <= p.sequence().length(); ++i) { double deltaMass = C57.monoisotopicDeltaMass() + M16.monoisotopicDeltaMass(); unit_assert_equal(f.a(i)+deltaMass, fWithMods.a(i), EPSILON); unit_assert_equal(f.b(i)+deltaMass, fWithMods.b(i), EPSILON); if (i < p.sequence().length()) unit_assert_equal(f.c(i)+deltaMass, fWithMods.c(i), EPSILON); } for (size_t i=1; i <= 13; ++i) { unit_assert_equal(f.x(i), fWithMods.x(i), EPSILON); unit_assert_equal(f.y(i), fWithMods.y(i), EPSILON); unit_assert_equal(f.z(i), fWithMods.z(i), EPSILON); } for (size_t i=14; i <= 19; ++i) { double deltaMass = M16.monoisotopicDeltaMass(); unit_assert_equal(f.x(i)+deltaMass, fWithMods.x(i), EPSILON); unit_assert_equal(f.y(i)+deltaMass, fWithMods.y(i), EPSILON); unit_assert_equal(f.z(i)+deltaMass, fWithMods.z(i), EPSILON); } for (size_t i=20; i <= p.sequence().length(); ++i) { double deltaMass = C57.monoisotopicDeltaMass() + M16.monoisotopicDeltaMass(); if (i < p.sequence().length()) unit_assert_equal(f.x(i)+deltaMass, fWithMods.x(i), EPSILON); unit_assert_equal(f.y(i)+deltaMass, fWithMods.y(i), EPSILON); unit_assert_equal(f.z(i)+deltaMass, fWithMods.z(i), EPSILON); } } { Peptide p("QICKRWNFMPSVERTHELAYDG"); Modification Q17("N-1H-3"), S80("H1P1O3"); (p.modifications())[ModificationMap::NTerminus()].push_back(Q17); // close enough (p.modifications())[10].push_back(S80); Fragmentation f = p.fragmentation(true, false); Fragmentation fWithMods = p.fragmentation(true, true); if (os_) writeFragmentation(p, f, *os_); if (os_) writeFragmentation(p, fWithMods, *os_); double EPSILON = 0.00000001; for (size_t i=0; i <= 10; ++i) { double deltaMass = Q17.monoisotopicDeltaMass(); unit_assert_equal(f.a(i)+deltaMass, fWithMods.a(i), EPSILON); unit_assert_equal(f.b(i)+deltaMass, fWithMods.b(i), EPSILON); unit_assert_equal(f.c(i)+deltaMass, fWithMods.c(i), EPSILON); } for (size_t i=11; i <= p.sequence().length(); ++i) { double deltaMass = Q17.monoisotopicDeltaMass() + S80.monoisotopicDeltaMass(); unit_assert_equal(f.a(i)+deltaMass, fWithMods.a(i), EPSILON); unit_assert_equal(f.b(i)+deltaMass, fWithMods.b(i), EPSILON); if (i < p.sequence().length()) unit_assert_equal(f.c(i)+deltaMass, fWithMods.c(i), EPSILON); } for (size_t i=1; i <= 11; ++i) { unit_assert_equal(f.x(i), fWithMods.x(i), EPSILON); unit_assert_equal(f.y(i), fWithMods.y(i), EPSILON); unit_assert_equal(f.z(i), fWithMods.z(i), EPSILON); } for (size_t i=12; i <= p.sequence().length(); ++i) { double deltaMass = S80.monoisotopicDeltaMass(); if (i < p.sequence().length()) unit_assert_equal(f.x(i)+deltaMass, fWithMods.x(i), EPSILON); unit_assert_equal(f.y(i)+deltaMass, fWithMods.y(i), EPSILON); unit_assert_equal(f.z(i)+deltaMass, fWithMods.z(i), EPSILON); } } } void testThreadSafetyWorker(boost::barrier* testBarrier) { testBarrier->wait(); // wait until all threads have started try { peptideTest(); modificationTest(); operatorTest(); fragmentTest(); } catch (exception& e) { cerr << "Exception in worker thread: " << e.what() << endl; } catch (...) { cerr << "Unhandled exception in worker thread." << endl; } } void testThreadSafety(const int& testThreadCount) { boost::barrier testBarrier(testThreadCount); boost::thread_group testThreadGroup; for (int i=0; i < testThreadCount; ++i) testThreadGroup.add_thread(new boost::thread(&testThreadSafetyWorker, &testBarrier)); testThreadGroup.join_all(); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; if (os_) *os_ << "PeptideTest\n"; //test(); //isotopeTest(); //testThreadSafety(1); // does not test thread-safety of singleton initialization testThreadSafety(2); testThreadSafety(4); testThreadSafety(8); testThreadSafety(16); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/proteome/DiffTest.cpp0000664000175100017510000001130712664775621021525 0ustar teamcityteamcity00000000000000// // $Id: DiffTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "Diff.hpp" //#include "examples.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::proteome; using namespace pwiz::data; ostream* os_ = 0; // BUG: Protein doesn't have a default ctor, should it? /*void testProtein() { if (os_) *os_ << "testProtein()\n"; Protein a("420", 0, "", ""), b("420", 0, "", ""); Diff diff(a, b); if (diff) cout << diff; unit_assert(!diff); b.id = "421"; unit_assert(diff); }*/ void testProteinList() { if (os_) *os_ << "testProteinList()\n"; ProteinListSimple aSimple, bSimple; ProteinPtr protein1a = ProteinPtr(new Protein("420", 0, "", "")); ProteinPtr protein1b = ProteinPtr(new Protein("420", 0, "", "")); aSimple.proteins.push_back(protein1a); bSimple.proteins.push_back(protein1b); ProteinList& a = aSimple; ProteinList& b = bSimple; Diff diff(a, b); DiffConfig config_ignore; config_ignore.ignoreMetadata = true; Diff diffIgnore(a, b, config_ignore); unit_assert(!diff); unit_assert(!diffIgnore); // check: different ProteinList::size() ProteinPtr protein2 = ProteinPtr(new Protein("421", 0, "", "")); aSimple.proteins.push_back(protein2); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.proteins.size() == 1); diffIgnore(a, b); if (os_) *os_ << diffIgnore << endl; unit_assert(diffIgnore); unit_assert(diffIgnore.a_b.proteins.size() == 1); // check: same ProteinList::size(), different last id ProteinPtr protein3 = ProteinPtr(new Protein("422", 0, "", "")); bSimple.proteins.push_back(protein3); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.proteins.size() == 1); unit_assert(diff.a_b.proteins[0]->id == "421"); unit_assert(diff.b_a.proteins.size() == 1); unit_assert(diff.b_a.proteins[0]->id == "422"); // id is not ignored diffIgnore(a, b); unit_assert(diffIgnore); // check: ids match, different description bSimple.proteins.back() = ProteinPtr(new Protein("421", 0, "different metadata", "")); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.proteins.size() == 1); unit_assert(diff.a_b.proteins[0]->description == ""); unit_assert(diff.b_a.proteins.size() == 1); unit_assert(diff.b_a.proteins[0]->description == "different metadata"); diffIgnore(a, b); unit_assert(!diffIgnore); // check: same metadata, different sequences bSimple.proteins.back() = ProteinPtr(new Protein("421", 0, "", "ELVISLIVES")); diff(a, b); unit_assert(diff); diffIgnore(a, b); unit_assert(diffIgnore); } void testProteomeData() { if (os_) *os_ << "testProteomeData()\n"; ProteomeData a, b; a.id = "goober"; b.id = "goober"; Diff diff(a, b); unit_assert(!diff); b.id = "raisinet"; shared_ptr proteinList1(new ProteinListSimple); proteinList1->proteins.push_back(ProteinPtr(new Protein("p1", 0, "", ""))); b.proteinListPtr = proteinList1; diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.proteinListPtr.get()); unit_assert(diff.a_b.proteinListPtr->size() == 1); } void test() { //testProtein(); testProteinList(); testProteomeData(); } int main(int argc, char* argv[]) { TEST_PROLOG_EX(argc, argv, "_ProteomeData") try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/proteome/TextWriter.hpp0000664000175100017510000000607212664775621022146 0ustar teamcityteamcity00000000000000// // $Id: TextWriter.hpp 1623 2009-12-17 20:58:35Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PROTEOME_TEXTWRITER_HPP_ #define _PROTEOME_TEXTWRITER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "ProteomeData.hpp" #include "boost/lexical_cast.hpp" #include #include #include namespace pwiz { namespace proteome { class PWIZ_API_DECL TextWriter { public: TextWriter(std::ostream& os, int depth = 0) : os_(os), depth_(depth), indent_(depth*2, ' ') {} TextWriter child() {return TextWriter(os_, depth_+1);} TextWriter& operator()(const std::string& text) { os_ << indent_ << text << std::endl; return *this; } template TextWriter& operator()(const std::string& label, const std::vector& v) { (*this)(label); for_each(v.begin(), v.end(), child()); return *this; } TextWriter& operator()(const ProteomeData& pd, bool metadata_only=false) { (*this)("ProteomeData:"); child() ("id: " + pd.id); if (pd.proteinListPtr.get()) child()(*pd.proteinListPtr, metadata_only); return *this; } TextWriter& operator()(const Protein& p) { (*this)("protein:"); child() ("id: " + p.id) ("index: " + p.index) ("description: " + p.description) ("sequence: " + p.sequence().substr(0, 10)); return *this; } TextWriter& operator()(const ProteinList& proteinList, bool metadata_only=false) { std::string text("proteinList (" + boost::lexical_cast(proteinList.size()) + " proteins)"); if (!metadata_only) text += ":"; (*this)(text); if (!metadata_only) for (size_t index = 0; index < proteinList.size(); ++index) child() (*proteinList.protein(index, true)); return *this; } // if no other overload matches, assume the object is a shared_ptr of a valid overloaded type template TextWriter& operator()(const boost::shared_ptr& p) { return p.get() ? (*this)(*p) : *this; } private: std::ostream& os_; int depth_; std::string indent_; }; } // namespace proteome } // namespace pwiz #endif // _PROTEOME_TEXTWRITER_HPP_ pwiz/pwiz/data/proteome/ProteomeDataFile.hpp0000664000175100017510000000553312664775621023212 0ustar teamcityteamcity00000000000000// // $Id: ProteomeDataFile.hpp 1688 2010-01-13 20:01:21Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PROTEOMEDATAFILE_HPP_ #define _PROTEOMEDATAFILE_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "ProteomeData.hpp" #include "Reader.hpp" #include "pwiz/utility/misc/IterationListener.hpp" namespace pwiz { namespace proteome { /// ProteomeData object plus file I/O struct PWIZ_API_DECL ProteomeDataFile : public ProteomeData { /// constructs ProteomeData object backed by file; /// indexed==true -> uses DefaultReaderList with indexing ProteomeDataFile(const std::string& uri, bool indexed = false); /// constructs ProteomeData object backed by file using the specified reader ProteomeDataFile(const std::string& uri, const Reader& reader); /// data format for write() enum PWIZ_API_DECL Format {Format_FASTA, Format_Text}; /// configuration for write() struct PWIZ_API_DECL WriteConfig { Format format; bool indexed; bool gzipped; // if true, file is written as .gz WriteConfig(Format _format = Format_FASTA, bool _gzipped = false) : format(_format), indexed(true), gzipped(_gzipped) {} }; /// static write function for any ProteomeData object; /// iterationListenerRegistry may be used for progress updates static void write(const ProteomeData& pd, const std::string& uri, const WriteConfig& config = WriteConfig(), const pwiz::util::IterationListenerRegistry* iterationListenerRegistry = 0); /// member write function void write(const std::string& uri, const WriteConfig& config = WriteConfig(), const pwiz::util::IterationListenerRegistry* iterationListenerRegistry = 0); }; PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, ProteomeDataFile::Format format); PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const ProteomeDataFile::WriteConfig& config); } // namespace proteome } // namespace pwiz #endif // _PROTEOMEDATAFILE_HPP_ pwiz/pwiz/data/proteome/Reader.hpp0000664000175100017510000001231612664775621021225 0ustar teamcityteamcity00000000000000// // $Id: Reader.hpp 1623 2009-12-17 20:58:35Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PROTEOME_READER_HPP_ #define _PROTEOME_READER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "ProteomeData.hpp" #include #include namespace pwiz { namespace proteome { /// interface for file readers class PWIZ_API_DECL Reader { public: /// return true iff Reader recognizes the file as one it should handle /// that's not to say one it CAN handle, necessarily, as in Thermo on linux, /// see comment for identify() below bool accept(const std::string& uri, boost::shared_ptr uriStreamPtr) const { return (identify(uri, uriStreamPtr).length() != 0); } /// return file type iff Reader recognizes the file, else empty; /// note: for formats requiring a 3rd party DLL identify() should /// return non-empty if it recognized the format, even though reading /// may fail if the 3rd party DLL isn't actually present /// Reader may filter based on URI and/or contents of the file virtual std::string identify(const std::string& uri, boost::shared_ptr uriStreamPtr) const = 0; /// fill in the ProteomeData structure from a new URI stream virtual void read(const std::string& uri, ProteomeData& result) const; /// fill in the ProteomeData structure from a shared URI stream virtual void read(const std::string& uri, boost::shared_ptr uriStreamPtr, ProteomeData& result) const = 0; virtual const char *getType() const = 0; // what kind of reader are you? virtual ~Reader(){} }; class PWIZ_API_DECL ReaderFail : public std::runtime_error // reader failure exception { public: ReaderFail(const std::string& error) : std::runtime_error(("[ReaderFail] " + error).c_str()), error_(error) {} virtual const std::string& error() const {return error_;} virtual ~ReaderFail() throw() {} private: std::string error_; }; typedef boost::shared_ptr ReaderPtr; /// /// Reader container (composite pattern). /// /// The template get() gives access to child Readers by type, to facilitate /// Reader-specific configuration at runtime. /// class PWIZ_API_DECL ReaderList : public Reader, public std::vector { public: /// returns child name iff some child identifies, else empty string virtual std::string identify(const std::string& uri) const; /// returns child name iff some child identifies, else empty string virtual std::string identify(const std::string& uri, boost::shared_ptr uriStreamPtr) const; /// delegates to first child that identifies virtual void read(const std::string& uri, ProteomeData& result) const; /// delegates to first child that identifies virtual void read(const std::string& uri, boost::shared_ptr uriStreamPtr, ProteomeData& result) const; /// appends all of the rhs operand's Readers to the list ReaderList& operator +=(const ReaderList& rhs); /// appends the rhs Reader to the list ReaderList& operator +=(const ReaderPtr& rhs); /// returns a concatenated list of all the Readers from the lhs and rhs operands ReaderList operator +(const ReaderList& rhs) const; /// returns a concatenated list of all the Readers from the lhs and rhs operands ReaderList operator +(const ReaderPtr& rhs) const; /// returns pointer to Reader of the specified type template reader_type* get() { for (iterator it=begin(); it!=end(); ++it) { reader_type* p = dynamic_cast(it->get()); if (p) return p; } return 0; } /// returns const pointer to Reader of the specified type template const reader_type* get() const { return const_cast(this)->get(); } virtual const char *getType() const {return "ReaderList";} // satisfy inheritance }; /// returns a list containing the lhs and rhs as readers PWIZ_API_DECL ReaderList operator +(const ReaderPtr& lhs, const ReaderPtr& rhs); } // namespace proteome } // namespace pwiz #endif // _PROTEOME_READER_HPP_ pwiz/pwiz/data/proteome/ProteinListCache.cpp0000664000175100017510000001134412664775621023216 0ustar teamcityteamcity00000000000000// // $Id: ProteinListCache.cpp 2071 2010-06-21 21:00:31Z chambm $ // // // Original author: Matt Chambers // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "ProteinListCache.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace proteome { PWIZ_API_DECL ProteinListCache::ProteinListCache(const ProteinListPtr& inner, ProteinListCacheMode cacheMode, size_t cacheSize) : ProteinListWrapper(inner), mode_(cacheMode), cache_(cacheSize) { } namespace { void clearProteinMetadata(Protein& protein) { Protein fresh(protein.id, protein.index, "", ""); swap(protein, fresh); } struct modifyCachedProteinPtr { modifyCachedProteinPtr(const ProteinPtr& newProteinPtr) : newProteinPtr_(newProteinPtr) {} void operator() (ProteinListCache::CacheType::value_type& indexProteinPtrPair) { indexProteinPtrPair.second = newProteinPtr_; } private: ProteinPtr newProteinPtr_; }; } // namespace // There are two kinds of protein requests: metadata and metadata+sequence; // the cache's behavior changes depending on the cache mode and the request. // // For metadata requests: // - If cache off: return protein directly // - If cache metadata: if protein not cached, cache it; return cached protein // - If cache sequence: return protein directly // - If cache all: return protein directly // // For metadata+sequence requests: // - If cache off: return protein directly // - If cache metadata: get protein, make a copy, remove sequence, then cache the copy and return original // - If cache sequence: if protein cached, get protein without sequence, add cached sequence to it and return it; otherwise get full protein, make a copy, remove metadata, cache it, then return original protein // - If cache all: if protein not cached, cache it; return cached protein PWIZ_API_DECL ProteinPtr ProteinListCache::protein(size_t index, bool getSequence) const { ProteinPtr original, copy; if (getSequence) { switch (mode_) { default: case ProteinListCacheMode_Off: return inner_->protein(index, true); case ProteinListCacheMode_MetaDataAndSequence: // if insert returns true, protein was not in cache if (cache_.insert(make_pair(index, ProteinPtr()))) cache_.modify(cache_.begin(), modifyCachedProteinPtr(inner_->protein(index, true))); return cache_.mru().second; case ProteinListCacheMode_MetaDataOnly: original = inner_->protein(index, true); // if insert returns true, protein was not in cache if (cache_.insert(make_pair(index, ProteinPtr()))) { copy.reset(new Protein(original->id, original->index, original->description, "")); cache_.modify(cache_.begin(), modifyCachedProteinPtr(copy)); } return original; } } else // !getSequence { switch (mode_) { default: case ProteinListCacheMode_Off: case ProteinListCacheMode_MetaDataAndSequence: return inner_->protein(index, false); case ProteinListCacheMode_MetaDataOnly: // if insert returns true, protein was not in cache if (cache_.insert(make_pair(index, ProteinPtr()))) cache_.modify(cache_.begin(), modifyCachedProteinPtr(inner_->protein(index, false))); return cache_.mru().second; } } } PWIZ_API_DECL size_t ProteinListCache::find(const std::string& id) const { return inner_->find(id); } PWIZ_API_DECL void ProteinListCache::setMode(ProteinListCacheMode mode) { if (mode != mode_) cache_.clear(); mode_ = mode; } PWIZ_API_DECL ProteinListCacheMode ProteinListCache::mode() const {return mode_;} } // namespace proteome } // namespace pwiz pwiz/pwiz/data/proteome/ProteinListWrapper.hpp0000664000175100017510000000315512664775621023641 0ustar teamcityteamcity00000000000000// // $Id: ProteinListWrapper.hpp 2069 2010-06-21 16:56:35Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PROTEINLISTWRAPPER_HPP_ #define _PROTEINLISTWRAPPER_HPP_ #include "pwiz/data/proteome/ProteomeData.hpp" #include namespace pwiz { namespace proteome { /// Inheritable pass-through implementation for wrapping a ProteinList class ProteinListWrapper : public ProteinList { public: ProteinListWrapper(const ProteinListPtr& inner) : inner_(inner) { if (!inner.get()) throw std::runtime_error("[ProteinListWrapper] Null ProteinListPtr."); } virtual size_t size() const {return inner_->size();} virtual ProteinPtr protein(size_t index, bool getSequence = true) const {return inner_->protein(index, getSequence);} protected: ProteinListPtr inner_; }; } // namespace proteome } // namespace pwiz #endif // _PROTEINLISTWRAPPER_HPP_ pwiz/pwiz/data/proteome/Diff.hpp0000664000175100017510000000405412664775621020673 0ustar teamcityteamcity00000000000000// // $Id: Diff.hpp 1656 2009-12-30 20:54:17Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PROTEOME_DIFF_HPP_ #define _PROTEOME_DIFF_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "ProteomeData.hpp" namespace pwiz { namespace proteome { struct DiffConfig; } } namespace pwiz { namespace data { using namespace proteome; namespace diff_impl { PWIZ_API_DECL void diff(const ProteinList& a, const ProteinList& b, ProteinListSimple& a_b, ProteinListSimple& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const ProteomeData& a, const ProteomeData& b, ProteomeData& a_b, ProteomeData& b_a, const DiffConfig& config); } // namespace diff_impl } // namespace data } // namespace pwiz // this include must come after the above declarations or GCC won't see them #include "pwiz/data/common/diff_std.hpp" namespace pwiz { namespace proteome { /// configuration struct for diffs struct PWIZ_API_DECL DiffConfig : public pwiz::data::BaseDiffConfig { bool ignoreMetadata; DiffConfig() : BaseDiffConfig(1e-6), ignoreMetadata(false) {} }; PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const data::Diff& diff); } // namespace proteome } // namespace pwiz #endif // _PROTEOME_DIFF_HPP_ pwiz/pwiz/data/proteome/Serializer_FASTA.cpp0000664000175100017510000002026012664775621023042 0ustar teamcityteamcity00000000000000// // $Id: Serializer_FASTA.cpp 6979 2014-12-09 16:15:35Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Serializer_FASTA.hpp" #include "pwiz/data/common/Index.hpp" #include "pwiz/utility/misc/Std.hpp" #include #include #include using namespace pwiz::data; using namespace pwiz::util; namespace bxp = boost::xpressive; namespace pwiz { namespace proteome { namespace { class ProteinList_FASTA : public ProteinList { shared_ptr fsPtr_; string fsSHA1_; size_t size_; IndexPtr indexPtr_; vector idAndDescriptionRegexes_; mutable boost::mutex io_mutex; void createIndex() { fsPtr_->clear(); fsPtr_->seekg(0); string buf; // find offsets for all entries in the FASTA stream deque index; set idSet; Index::stream_offset indexOffset = 0; while (getline(*fsPtr_, buf)) { size_t bufLength = buf.length() + 1; // include newline indexOffset += bufLength; if (buf.empty()) continue; if (buf[0] == '>') // signifies a new protein record in a FASTA file { index.push_back(Index::Entry()); Index::Entry& ie = index.back(); bal::trim_right_if(buf, bal::is_any_of(" \r")); BOOST_FOREACH(bxp::sregex& idAndDescriptionRegex, idAndDescriptionRegexes_) { bxp::smatch match; if (bxp::regex_match(buf, match, idAndDescriptionRegex)) { ie.id = match[1].str(); break; } } if (ie.id.empty()) throw runtime_error("[ProteinList_FASTA::createIndex] could not parse id from entry \"" + buf + "\""); // note: We could silently skip the duplicates, but that would only be // reasonable after checking that the sequences are equal. if (!idSet.insert(ie.id).second) throw runtime_error("[ProteinList_FASTA::createIndex] duplicate protein id \"" + ie.id + "\""); ie.index = index.size()-1; ie.offset = indexOffset - bufLength; } } idSet.clear(); vector tmp(index.begin(), index.end()); indexPtr_->create(tmp); } public: ProteinList_FASTA(shared_ptr fsPtr, IndexPtr indexPtr, const vector& idAndDescriptionRegexes) : fsPtr_(fsPtr), indexPtr_(indexPtr) { BOOST_FOREACH(const string& regexString, idAndDescriptionRegexes) { bxp::sregex idAndDescriptionRegex = bxp::sregex::compile(regexString); if (idAndDescriptionRegex.mark_count() == 1) { // TODO: log warning about only capturing id } else if (idAndDescriptionRegex.mark_count() != 2) throw runtime_error("[ProteinList_FASTA::ctor] regular expressions for capturing id and description must contain 1 or 2 capture groups; \"" + regexString + "\" has " + lexical_cast(idAndDescriptionRegex.mark_count())); idAndDescriptionRegexes_.push_back(idAndDescriptionRegex); } if (indexPtr->size() == 0) createIndex(); } virtual size_t find(const string& id) const { Index::EntryPtr entryPtr = indexPtr_->find(id); return entryPtr.get() ? entryPtr->index : indexPtr_->size(); } virtual size_t size() const {return indexPtr_->size();} virtual ProteinPtr protein(size_t index, bool getSequence /*= true*/) const { if (index >= size()) throw out_of_range("[ProteinList_FASTA::protein] Index out of range"); Index::EntryPtr entryPtr = indexPtr_->find(index); if (!entryPtr.get()) throw out_of_range("[ProteinList_FASTA::protein] Index out of range"); boost::mutex::scoped_lock io_lock(io_mutex); fsPtr_->clear(); fsPtr_->seekg(entryPtr->offset); string buf; getline(*fsPtr_, buf); // test that the index offset is valid if (buf.empty() || buf[0] != '>') { // TODO: log notice about stale index // recreate the index const_cast(*this).createIndex(); entryPtr = indexPtr_->find(index); if (!entryPtr.get()) throw out_of_range("[ProteinList_FASTA::protein] Index out of range"); fsPtr_->clear(); fsPtr_->seekg(entryPtr->offset); string buf; getline(*fsPtr_, buf); // if the offset is still invalid, throw if (buf.empty() || buf[0] != '>') throw runtime_error("[ProteinList_FASTA::protein] Invalid index offset"); } // trim whitespace and carriage returns from the end of the line bal::trim_right_if(buf, bal::is_any_of(" \r")); string description; BOOST_FOREACH(const bxp::sregex& idAndDescriptionRegex, idAndDescriptionRegexes_) { if (idAndDescriptionRegex.mark_count() == 2) { bxp::smatch match; if (bxp::regex_match(buf, match, idAndDescriptionRegex)) { description = match[2].str(); break; } //else // TODO: exception is too harsh, log warning if none of the regexes match } } string sequence; if (getSequence) while (getline(*fsPtr_, buf)) { if (buf.empty() || buf[0] == '\r') // skip blank lines continue; if (buf[0] == '>') // signifies the next protein record in a FASTA file break; size_t lineEnd = std::min(buf.length(), buf.find_first_of("\r\n")); sequence.append(buf.begin(), buf.begin()+lineEnd); } return ProteinPtr(new Protein(entryPtr->id, index, description, sequence)); } }; } // namespace PWIZ_API_DECL Serializer_FASTA::Serializer_FASTA(const Config& config) : config_(config) {} PWIZ_API_DECL void Serializer_FASTA::write(ostream& os, const ProteomeData& pd, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry) const { if (!pd.proteinListPtr.get()) throw runtime_error("[Serializer_FASTA::write()] Null protein list."); const ProteinList& pl = *pd.proteinListPtr; for (size_t i=0, end=pl.size(); i < end; ++i) { ProteinPtr proteinPtr = pl.protein(i, true); os << '>' << proteinPtr->id << ' ' << proteinPtr->description << '\n' << proteinPtr->sequence() << '\n'; if (iterationListenerRegistry) iterationListenerRegistry->broadcastUpdateMessage(IterationListener::UpdateMessage(i+1, end)); } } PWIZ_API_DECL void Serializer_FASTA::read(shared_ptr is, ProteomeData& pd) const { if (!is.get() || !*is) throw runtime_error("[Serializer_FASTA::read()] Bad istream."); // TODO: make these regexes user-configurable vector idAndDescriptionRegexes; idAndDescriptionRegexes.push_back(">\\s*(\\S*?IPI\\d+?\\.\\d+?)(?:\\s|\\|)(.*)"); idAndDescriptionRegexes.push_back(">\\s*(\\S+)\\s?(.*)"); pd.proteinListPtr.reset(new ProteinList_FASTA(is, config_.indexPtr, idAndDescriptionRegexes)); } } // namespace proteome } // namespace pwiz pwiz/pwiz/data/proteome/Reader.cpp0000664000175100017510000000614212664775621021220 0ustar teamcityteamcity00000000000000// // $Id: Reader.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Reader.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace proteome { using namespace pwiz::util; using boost::shared_ptr; PWIZ_API_DECL void Reader::read(const string& uri, ProteomeData& result) const { shared_ptr uriStreamPtr(new ifstream(uri.c_str())); read(uri, uriStreamPtr, result); } PWIZ_API_DECL std::string ReaderList::identify(const string& uri) const { shared_ptr uriStreamPtr(new ifstream(uri.c_str())); return identify(uri, uriStreamPtr); } PWIZ_API_DECL std::string ReaderList::identify(const string& uri, shared_ptr uriStreamPtr) const { std::string result; for (const_iterator it=begin(); it!=end(); ++it) { result = (*it)->identify(uri, uriStreamPtr); if (result.length()) { break; } } return result; } PWIZ_API_DECL void ReaderList::read(const string& uri, ProteomeData& result) const { shared_ptr uriStreamPtr(new ifstream(uri.c_str())); read(uri, uriStreamPtr, result); } PWIZ_API_DECL void ReaderList::read(const string& uri, shared_ptr uriStreamPtr, ProteomeData& result) const { for (const_iterator it=begin(); it!=end(); ++it) if ((*it)->accept(uri, uriStreamPtr)) { (*it)->read(uri, uriStreamPtr, result); return; } throw ReaderFail(" don't know how to read " + uri); } PWIZ_API_DECL ReaderList& ReaderList::operator +=(const ReaderList& rhs) { insert(end(), rhs.begin(), rhs.end()); return *this; } PWIZ_API_DECL ReaderList& ReaderList::operator +=(const ReaderPtr& rhs) { push_back(rhs); return *this; } PWIZ_API_DECL ReaderList ReaderList::operator +(const ReaderList& rhs) const { ReaderList readerList(*this); readerList += rhs; return readerList; } PWIZ_API_DECL ReaderList ReaderList::operator +(const ReaderPtr& rhs) const { ReaderList readerList(*this); readerList += rhs; return readerList; } PWIZ_API_DECL ReaderList operator +(const ReaderPtr& lhs, const ReaderPtr& rhs) { ReaderList readerList; readerList.push_back(lhs); readerList.push_back(rhs); return readerList; } } // namespace proteome } // namespace pwiz pwiz/pwiz/data/proteome/AminoAcidTest.cpp0000664000175100017510000001777112664775621022514 0ustar teamcityteamcity00000000000000// // $Id: AminoAcidTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/unit.hpp" #include "AminoAcid.hpp" #include #include "pwiz/utility/misc/Std.hpp" #include "boost/thread/thread.hpp" #include "boost/thread/barrier.hpp" using namespace pwiz::util; using namespace pwiz::proteome; using namespace pwiz::chemistry; using namespace pwiz::chemistry::Element; using namespace pwiz::proteome::AminoAcid; ostream* os_ = 0; bool hasLowerMass(const AminoAcid::Info::Record& a, const AminoAcid::Info::Record& b) { return a.formula.monoisotopicMass() < b.formula.monoisotopicMass(); } void printRecord(ostream* os, const AminoAcid::Info::Record& record) { if (!os) return; *os << record.symbol << ": " << setw(14) << record.name << " " << setw(11) << record.formula << " " << setprecision(3) << setw(5) << record.abundance << " " << fixed << setprecision(6) << setw(10) << record.formula.monoisotopicMass() << " " << setw(10) << record.formula.molecularWeight() << " " << setw(10) << record.residueFormula.monoisotopicMass() << " " << setw(10) << record.residueFormula.molecularWeight() << endl; } struct TestAminoAcid { double monoMass; double avgMass; char symbol; }; // masses copied from http://www.unimod.org/xml/unimod.xml TestAminoAcid testAminoAcids[] = { { 71.0371140, 71.07790, 'A' }, // Alanine { 156.101111, 156.1857, 'R' }, // Arginine { 114.042927, 114.1026, 'N' }, // Asparagine { 115.026943, 115.0874, 'D' }, // Aspartic acid { 103.009185, 103.1429, 'C' }, // Cysteine { 129.042593, 129.1140, 'E' }, // Glutamic acid { 128.058578, 128.1292, 'Q' }, // Glutamine { 57.0214640, 57.05130, 'G' }, // Glycine { 137.058912, 137.1393, 'H' }, // Histidine { 113.084064, 113.1576, 'I' }, // Isoleucine { 113.084064, 113.1576, 'L' }, // Leucine { 128.094963, 128.1723, 'K' }, // Lysine { 131.040485, 131.1961, 'M' }, // Methionine { 147.068414, 147.1739, 'F' }, // Phenylalanine { 97.0527640, 97.11520, 'P' }, // Proline { 87.0320280, 87.07730, 'S' }, // Serine { 150.953636, 150.0379, 'U' }, // Selenocysteine { 101.047679, 101.1039, 'T' }, // Threonine { 186.079313, 186.2099, 'W' }, // Tryptophan { 163.063329, 163.1733, 'Y' }, // Tyrosine { 99.0684140, 99.13110, 'V' }, // Valine { 114.042927, 114.1026, 'B' }, // AspX { 128.058578, 128.1292, 'Z' }, // GlutX { 114.091900, 114.1674, 'X' } // Unknown (Averagine) }; void test() { // get a copy of all the records vector records; for (char symbol='A'; symbol<='Z'; symbol++) { try { const AminoAcid::Info::Record& record = AminoAcid::Info::record(symbol); records.push_back(record); } catch (exception&) {} } for (vector::iterator it=records.begin(); it!=records.end(); ++it) printRecord(os_, *it); unit_assert(AminoAcid::Info::record(Alanine).residueFormula[C] == 3); unit_assert(AminoAcid::Info::record(Alanine).residueFormula[H] == 5); unit_assert(AminoAcid::Info::record(Alanine).residueFormula[N] == 1); unit_assert(AminoAcid::Info::record(Alanine).residueFormula[O] == 1); unit_assert(AminoAcid::Info::record(Alanine).residueFormula[S] == 0); unit_assert(AminoAcid::Info::record(Alanine).formula[C] == 3); unit_assert(AminoAcid::Info::record(Alanine).formula[H] == 7); unit_assert(AminoAcid::Info::record(Alanine).formula[N] == 1); unit_assert(AminoAcid::Info::record(Alanine).formula[O] == 2); unit_assert(AminoAcid::Info::record(Alanine).formula[S] == 0); unit_assert(AminoAcid::Info::record(Selenocysteine).formula[Se] == 1); // test single amino acids for (int i=0; i < 22; ++i) // skip X for now { TestAminoAcid& aa = testAminoAcids[i]; Formula residueFormula = AminoAcid::Info::record(aa.symbol).residueFormula; unit_assert_equal(residueFormula.monoisotopicMass(), aa.monoMass, 0.00001); unit_assert_equal(residueFormula.molecularWeight(), aa.avgMass, 0.0001); //set mmNames = mm2n.getNames(aa.monoMass, EPSILON); //set amNames = am2n.getNames(aa.avgMass, EPSILON); //unit_assert(mmNames.count(aa.symbol) > 0); //unit_assert(amNames.count(aa.symbol) > 0); } // compute some averages double averageMonoisotopicMass = 0; double averageC = 0; double averageH = 0; double averageN = 0; double averageO = 0; double averageS = 0; for (vector::iterator it=records.begin(); it!=records.end(); ++it) { const AminoAcid::Info::Record& record = *it; Formula residueFormula = record.residueFormula; averageMonoisotopicMass += residueFormula.monoisotopicMass() * record.abundance; averageC += residueFormula[C] * record.abundance; averageH += residueFormula[H] * record.abundance; averageN += residueFormula[N] * record.abundance; averageO += residueFormula[O] * record.abundance; averageS += residueFormula[S] * record.abundance; } if (os_) *os_ << setprecision(8) << endl; if (os_) *os_ << "average residue C: " << averageC << endl; if (os_) *os_ << "average residue H: " << averageH << endl; if (os_) *os_ << "average residue N: " << averageN << endl; if (os_) *os_ << "average residue O: " << averageO << endl; if (os_) *os_ << "average residue S: " << averageS << endl; if (os_) *os_ << endl; if (os_) *os_ << "average monoisotopic mass: " << averageMonoisotopicMass << endl; double averageResidueMass = averageMonoisotopicMass; if (os_) *os_ << "average residue mass: " << averageResidueMass << endl << endl; // sort by monoisotopic mass and print again sort(records.begin(), records.end(), hasLowerMass); for (vector::iterator it=records.begin(); it!=records.end(); ++it) printRecord(os_, *it); } void testThreadSafetyWorker(boost::barrier* testBarrier) { testBarrier->wait(); // wait until all threads have started try { test(); } catch (exception& e) { cerr << "Exception in worker thread: " << e.what() << endl; } catch (...) { cerr << "Unhandled exception in worker thread." << endl; } } void testThreadSafety(const int& testThreadCount) { boost::barrier testBarrier(testThreadCount); boost::thread_group testThreadGroup; for (int i=0; i < testThreadCount; ++i) testThreadGroup.add_thread(new boost::thread(&testThreadSafetyWorker, &testBarrier)); testThreadGroup.join_all(); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; if (os_) *os_ << "AminoAcidTest\n"; try { //testThreadSafety(1); // does not test thread-safety of singleton initialization testThreadSafety(2); testThreadSafety(4); testThreadSafety(8); testThreadSafety(16); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/proteome/ProteinListCache.hpp0000664000175100017510000000525012664775621023222 0ustar teamcityteamcity00000000000000// // $Id: ProteinListCache.hpp 2691 2011-05-13 15:56:52Z chambm $ // // // Original author: Matt Chambers // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PROTEINLISTCACHE_HPP_ #define _PROTEINLISTCACHE_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "ProteomeData.hpp" #include "ProteinListWrapper.hpp" #include "pwiz/utility/misc/mru_list.hpp" namespace pwiz { namespace proteome { enum PWIZ_API_DECL ProteinListCacheMode { ProteinListCacheMode_Off, ProteinListCacheMode_MetaDataOnly, ProteinListCacheMode_MetaDataAndSequence }; /// adds a level of flexible MRU caching to a ProteinList processor chain class PWIZ_API_DECL ProteinListCache : public ProteinListWrapper { public: /// a cache mapping spectrum indices to ProteinPtrs typedef std::pair KeyValuePair; BOOST_STATIC_CONSTANT(unsigned, first_offset = offsetof(KeyValuePair, first)); typedef pwiz::util::mru_list > CacheType; ProteinListCache(const ProteinListPtr& inner, ProteinListCacheMode cacheMode, size_t cacheSize); /// returns the requested spectrum which may or may not be cached depending on /// the current cache mode virtual ProteinPtr protein(size_t index, bool getSequence = true) const; virtual size_t find(const std::string& id) const; /// set the caching mode /// note: if the new mode is different than the current mode, the cache will be cleared void setMode(ProteinListCacheMode mode); /// get the current caching mode ProteinListCacheMode mode() const; /// get a const-reference to the cache const CacheType& cache() const {return cache_;} private: ProteinListCache(ProteinListCache&); ProteinListCache& operator=(ProteinListCache&); mutable CacheType cache_; ProteinListCacheMode mode_; }; } // namespace msdata } // namespace pwiz #endif // _PROTEINLISTCACHE_HPP_ pwiz/pwiz/data/proteome/Serializer_FASTA_Test.cpp0000664000175100017510000001066512664775621024051 0ustar teamcityteamcity00000000000000// // $Id: Serializer_FASTA_Test.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "Serializer_FASTA.hpp" #include "Diff.hpp" #include "examples.hpp" #include "pwiz/data/common/BinaryIndexStream.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include "boost/thread/thread.hpp" #include "boost/thread/barrier.hpp" using namespace pwiz::util; using namespace pwiz::proteome; using namespace pwiz::data; ostream* os_ = 0; void testWriteRead(const Serializer_FASTA::Config& config) { ProteomeData pd; examples::initializeTiny(pd); Serializer_FASTA serializer(config); ostringstream oss; serializer.write(oss, pd, NULL); if (os_) *os_ << "oss:\n" << oss.str() << endl; shared_ptr iss(new istringstream(oss.str())); ProteomeData pd2; serializer.read(iss, pd2); Diff diff(pd, pd2); if (os_ && diff) *os_ << diff << endl; unit_assert(!diff); } void testWriteRead() { if (os_) *os_ << "testWriteRead() MemoryIndex" << endl; Serializer_FASTA::Config config; testWriteRead(config); if (os_) *os_ << "testWriteRead() BinaryIndexStream" << endl; shared_ptr indexStringStream(new stringstream); config.indexPtr.reset(new BinaryIndexStream(indexStringStream)); testWriteRead(config); } void testThreadSafetyWorker(pair* args) { args->first->wait(); // wait until all threads have started try { testWriteRead(); for (int i=0; i < 3; ++i) { for (size_t j=0; j < args->second->proteinListPtr->size(); ++j) unit_assert(args->second->proteinListPtr->protein(j)->index == j); } } catch (exception& e) { cerr << "Exception in worker thread: " << e.what() << endl; } catch (...) { cerr << "Unhandled exception in worker thread." << endl; } } void testThreadSafety(const int& testThreadCount) { ProteomeData pd; examples::initializeTiny(pd); boost::barrier testBarrier(testThreadCount); boost::thread_group testThreadGroup; for (int i=0; i < testThreadCount; ++i) testThreadGroup.add_thread(new boost::thread(&testThreadSafetyWorker, new pair(&testBarrier, &pd))); testThreadGroup.join_all(); } void testDuplicateId() { ProteomeData pd; pd.id = "tiny"; shared_ptr proteinListPtr(new ProteinListSimple); pd.proteinListPtr = proteinListPtr; proteinListPtr->proteins.push_back(ProteinPtr(new Protein("ABC123", 0, "One two three.", "ELVISLIVES"))); proteinListPtr->proteins.push_back(ProteinPtr(new Protein("ZEBRA", 1, "Has stripes:", "BLACKANDWHITE"))); proteinListPtr->proteins.push_back(ProteinPtr(new Protein("DEFCON42", 2, "", "DNTPANIC"))); proteinListPtr->proteins.push_back(ProteinPtr(new Protein("ZEBRA", 1, "Black and white", "STRIPES"))); Serializer_FASTA serializer; ostringstream oss; serializer.write(oss, pd, NULL); if (os_) *os_ << "oss:\n" << oss.str() << endl; shared_ptr iss(new istringstream(oss.str())); ProteomeData pd2; unit_assert_throws_what(serializer.read(iss, pd2), runtime_error, "[ProteinList_FASTA::createIndex] duplicate protein id \"ZEBRA\""); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; testWriteRead(); testThreadSafety(2); testThreadSafety(4); testThreadSafety(8); testDuplicateId(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/proteome/Reader_FASTA.cpp0000664000175100017510000001131012664775621022127 0ustar teamcityteamcity00000000000000// // $Id: Reader_FASTA.cpp 4077 2012-11-06 23:02:48Z pcbrefugee $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Reader_FASTA.hpp" #include "Serializer_FASTA.hpp" #include "pwiz/data/common/BinaryIndexStream.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; namespace pwiz { namespace proteome { // // Reader_FASTA // PWIZ_API_DECL Reader_FASTA::Reader_FASTA(const Config& config) : config_(config) {} PWIZ_API_DECL string Reader_FASTA::identify(const string& uri, shared_ptr uriStreamPtr) const { // formerly this checked to see if uri contained .fasta, which meant .fa, .tfa etc failed boost::ignore_unused_variable_warning(uri); if (!uriStreamPtr.get()) throw runtime_error("[Reader_FASTA::identify] Must have a valid stream to identify"); uriStreamPtr->clear(); uriStreamPtr->seekg(0); // first non-blank line in the stream should begin with '>' #define TESTBUFSIZE 16 char buf[TESTBUFSIZE+1]; string result(""); while (uriStreamPtr->good()) { uriStreamPtr->getline(buf,TESTBUFSIZE); if (buf[0] && buf[0] != '\r') // skip blank lines { if (buf[0] == '>') { result = getType(); } break; } } uriStreamPtr->clear(); uriStreamPtr->seekg(0); return result; } PWIZ_API_DECL void Reader_FASTA::read(const std::string& uri, shared_ptr uriStreamPtr, ProteomeData& result) const { result.id = uri; Serializer_FASTA::Config config; if (config_.indexed) // override default MemoryIndex with a BinaryIndexStream { {ofstream((uri + ".index").c_str(), ios::app);} // make sure the file exists shared_ptr isPtr(new fstream((uri + ".index").c_str(), ios::in | ios::out | ios::binary)); // indexes smaller than 200mb are loaded entirely into memory boost::uintmax_t indexSize = bfs::file_size(uri + ".index"); if (indexSize > 0 && indexSize < 200000000) { stringstream* indexFileStream = new stringstream(); bio::copy(*isPtr, *indexFileStream); isPtr.reset(indexFileStream); } if (!*isPtr) // stream is unavailable or read only { isPtr.reset(new fstream((uri + ".index").c_str(), ios::in | ios::binary)); bool canOpenReadOnly = !!*isPtr; if (canOpenReadOnly) { // check that the index is up to date; // if it isn't, a read only index is worthless config.indexPtr.reset(new data::BinaryIndexStream(isPtr)); Serializer_FASTA serializer(config); serializer.read(uriStreamPtr, result); if (result.proteinListPtr->size() > 0) try { result.proteinListPtr->protein(0); return; } catch (exception&) { // TODO: log warning about stale read only index canOpenReadOnly = false; } } // TODO: try opening an index in other locations, e.g.: // * current working directory (may be read only) // * executing directory (may be read only) // * temp directory (pretty much guaranteed to be writable) if (!canOpenReadOnly) { // fall back to in-memory index config.indexPtr.reset(new data::MemoryIndex); } } else // stream is ready and writable config.indexPtr.reset(new data::BinaryIndexStream(isPtr)); } Serializer_FASTA serializer(config); serializer.read(uriStreamPtr, result); } PWIZ_API_DECL ostream& operator<<(ostream& os, const Reader_FASTA::Config& config) { return os; } } // namespace proteome } // namespace pwiz pwiz/pwiz/data/proteome/examples.hpp0000664000175100017510000000223712664775621021642 0ustar teamcityteamcity00000000000000// // $Id: examples.hpp 1623 2009-12-17 20:58:35Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PROTEOME_EXAMPLES_HPP_ #define _PROTEOME_EXAMPLES_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "ProteomeData.hpp" namespace pwiz { namespace proteome { namespace examples { PWIZ_API_DECL void initializeTiny(ProteomeData& pd); //PWIZ_API_DECL void addMIAPEExampleMetadata(TraData& pd); } // namespace examples } // namespace proteome } // namespace pwiz #endif // _PROTEOME_EXAMPLES_HPP_ pwiz/pwiz/data/proteome/ProteomeDataTest.cpp0000664000175100017510000000564112664775621023245 0ustar teamcityteamcity00000000000000// // $Id: ProteomeDataTest.cpp 6141 2014-05-05 21:03:47Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "ProteomeData.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::proteome; void testProteinListSimple() { // fill in ProteinListSimple shared_ptr proteinListSimple(new ProteinListSimple); unit_assert(proteinListSimple->empty()); Protein emptyProtein("", 0, "", ""); unit_assert(emptyProtein.empty()); ProteinPtr protein0(new Protein("IPI-1701", 0, "The final frontier!", "")); ProteinPtr protein1(new Protein("SPROT|42", 1, "Life, the universe, and everything.", "")); unit_assert(!protein0->empty()); proteinListSimple->proteins.push_back(protein0); proteinListSimple->proteins.push_back(protein1); // let a ProteomeData object hold onto it as a ProteinListPtr ProteomeData data; data.proteinListPtr = proteinListSimple; // test ProteinList interface // verify index() const ProteinList& proteinList = *data.proteinListPtr; unit_assert(proteinList.size() == 2); unit_assert(proteinList.find("IPI-1701") == 0); unit_assert(proteinList.find("SPROT|42") == 1); // verify findKeyword IndexList result = proteinList.findKeyword("final"); unit_assert(result.size()==1 && result[0]==0); result = proteinList.findKeyword("the", false); unit_assert(result.size()==2 && result[0]==0 && result[1]==1); result = proteinList.findKeyword("the"); unit_assert(result.size()==1 && result[0]==1); result = proteinList.findKeyword("42"); unit_assert(result.empty()); // verify protein 0 ProteinPtr protein = proteinList.protein(0); unit_assert(protein->index == protein0->index); unit_assert(protein->id == protein0->id); // verify spectrum 1 protein = proteinList.protein(1); unit_assert(protein->index == protein1->index); unit_assert(protein->id == protein1->id); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { testProteinListSimple(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/proteome/Serializer_FASTA.hpp0000664000175100017510000000361312664775621023052 0ustar teamcityteamcity00000000000000// // $Id: Serializer_FASTA.hpp 1623 2009-12-17 20:58:35Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SERIALIZER_FASTA_HPP_ #define _SERIALIZER_FASTA_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "ProteomeData.hpp" #include "pwiz/data/common/MemoryIndex.hpp" #include "pwiz/utility/misc/IterationListener.hpp" namespace pwiz { namespace proteome { /// ProteomeData <-> FASTA stream serialization class PWIZ_API_DECL Serializer_FASTA { public: /// Serializer_FASTA configuration struct PWIZ_API_DECL Config { data::IndexPtr indexPtr; Config() : indexPtr(new data::MemoryIndex) {} }; Serializer_FASTA(const Config& config = Config()); /// write ProteomeData object to ostream as FASTA void write(std::ostream& os, const ProteomeData& pd, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry) const; /// read in ProteomeData object from a FASTA istream void read(boost::shared_ptr is, ProteomeData& pd) const; private: Config config_; Serializer_FASTA(Serializer_FASTA&); Serializer_FASTA& operator=(Serializer_FASTA&); }; } // namespace proteome } // namespace pwiz #endif // _SERIALIZER_FASTA_HPP_ pwiz/pwiz/data/proteome/Modification.hpp0000664000175100017510000001765712664775621022445 0ustar teamcityteamcity00000000000000// // $Id: Modification.hpp 2453 2011-01-07 21:29:27Z chambm $ // // // Original author: Matt Chambers // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _MODIFICATION_HPP_ #define _MODIFICATION_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "Peptide.hpp" #include #include "pwiz/utility/misc/virtual_map.hpp" #include namespace pwiz { namespace proteome { /// represents a post-translational modification (PTM) /// modification formula or masses must be provided at instantiation class PWIZ_API_DECL Modification { public: /// constructs a zero-mass modification (provided for MSVC compatibility) Modification(); Modification(const chemistry::Formula& formula); Modification(double monoisotopicDeltaMass, double averageDeltaMass); Modification(const Modification&); Modification& operator=(const Modification&); ~Modification(); /// returns true iff the mod was constructed with formula bool hasFormula() const; /// returns the difference formula; /// throws runtime_error if hasFormula() = false const chemistry::Formula& formula() const; double monoisotopicDeltaMass() const; double averageDeltaMass() const; /// returns true iff delta masses are equal bool operator==(const Modification& rhs) const; /// returns true iff this mod has smaller delta masses bool operator<(const Modification& rhs) const; private: class Impl; boost::shared_ptr impl_; }; /// represents a list of modifications on a single amino acid class PWIZ_API_DECL ModificationList : public std::vector // TODO: make virtual wrapper { public: ModificationList(); ModificationList(const Modification& mod); ModificationList(const std::vector& mods); /// returns the sum of the monoisotopic delta masses of all modifications in the list double monoisotopicDeltaMass() const; /// returns the sum of the average delta masses of all modifications in the list double averageDeltaMass() const; /// returns true iff the list has equal modifications bool operator==(const ModificationList& rhs) const; /// returns true iff the list has fewer modifications or one that's lesser than in the rhs list bool operator<(const ModificationList& rhs) const; }; /// maps peptide/protein sequence indexes (0-based) to a modification list /// * ModificationMap::NTerminus() returns the index for specifying N terminal mods /// * ModificationMap::CTerminus() returns the index for specifying C terminal mods class PWIZ_API_DECL ModificationMap : public pwiz::util::virtual_map { public: ~ModificationMap(); // bring the const overloads into scope using pwiz::util::virtual_map::begin; using pwiz::util::virtual_map::end; using pwiz::util::virtual_map::rbegin; using pwiz::util::virtual_map::rend; using pwiz::util::virtual_map::operator[]; using pwiz::util::virtual_map::equal_range; using pwiz::util::virtual_map::find; using pwiz::util::virtual_map::lower_bound; using pwiz::util::virtual_map::upper_bound; static int NTerminus(); static int CTerminus(); /// returns the sum of the monoisotopic delta masses of all modifications in the map double monoisotopicDeltaMass() const; /// returns the sum of the average delta masses of all modifications in the map double averageDeltaMass() const; /// Returns an iterator pointing to the first element stored in the map. First is defined by the map's comparison operator, Compare. virtual iterator begin(); /// Returns an iterator pointing to the last element stored in the map; in other words, to the off-the-end value. virtual iterator end(); /// Returns a reverse_iterator pointing to the first element stored in the map. First is defined by the map's comparison operator, Compare. virtual reverse_iterator rbegin(); /// Returns a reverse_iterator pointing to the last element stored in the map; in other words, to the off-the-end value). virtual reverse_iterator rend(); /// If an element with the key x exists in the map, then a reference to its associated value is returned. Otherwise the pair x,T() is inserted into the map and a reference to the default object T() is returned. virtual mapped_type& operator[](const key_type& x); /// Returns the pair (lower_bound(x), upper_bound(x)). virtual std::pair equal_range(const key_type& x); /// Searches the map for a pair with the key value x and returns an iterator to that pair if it is found. If such a pair is not found the value end() is returned. virtual iterator find(const key_type& x); /// Returns a reference to the first entry with a key greater than or equal to x. virtual iterator lower_bound(const key_type& x); /// Returns an iterator for the first entry with a key greater than x. virtual iterator upper_bound(const key_type& x); /// Erases all elements from the self. virtual void clear(); /// Deletes the map element pointed to by the iterator position. virtual void erase(iterator position); /// If the iterators start and finish point to the same map and last is reachable from first, all elements in the range [start, finish) are deleted from the map. virtual void erase(iterator start, iterator finish); /// Deletes the element with the key value x from the map, if one exists. Returns 1 if x existed in the map, 0 otherwise. virtual size_type erase(const key_type& x); /// If a value_type with the same key as x is not present in the map, then x is inserted into the map. Otherwise, the pair is not inserted. virtual std::pair insert(const value_type& x); /// If a value_type with the same key as x is not present in the map, then x is inserted into the map. Otherwise, the pair is not inserted. A position may be supplied as a hint regarding where to do the insertion. If the insertion is done right after position, then it takes amortized constant time. Otherwise it takes O(log N) time. virtual iterator insert(iterator position, const value_type& x); /// returns true iff the map has the same modifications virtual bool operator==(const ModificationMap& rhs) const; /// returns true iff the map has fewer modified positions or one of the positions is less than in the rhs map virtual bool operator<(const ModificationMap& rhs) const; private: ModificationMap(); ModificationMap(const ModificationMap& other); ModificationMap& operator=(const ModificationMap&); class Impl; boost::shared_ptr impl_; virtual void swap(ModificationMap&); friend class Peptide::Impl; // allow only Peptide::Impl to construct a ModificationMap }; } // namespace proteome } // namespace pwiz #endif // _MODIFICATION_HPP_ pwiz/pwiz/data/proteome/Digestion.cpp0000664000175100017510000011746412664775621021755 0ustar teamcityteamcity00000000000000// // $Id: Digestion.cpp 9198 2015-12-04 23:48:50Z chambm $ // // // Original author: Matt Chambers // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Digestion.hpp" #include "Peptide.hpp" #include "AminoAcid.hpp" #include "pwiz/utility/misc/CharIndexedVector.hpp" #include "pwiz/utility/misc/Exception.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/Singleton.hpp" #include namespace pwiz { namespace proteome { using namespace pwiz::cv; using namespace pwiz::util; using boost::shared_ptr; namespace bxp = boost::xpressive; #undef SECURE_SCL PWIZ_API_DECL DigestedPeptide::DigestedPeptide(const string& sequence) : Peptide(sequence) { } PWIZ_API_DECL DigestedPeptide::DigestedPeptide(const char* sequence) : Peptide(sequence) { } PWIZ_API_DECL DigestedPeptide::DigestedPeptide(std::string::const_iterator begin, std::string::const_iterator end, size_t offset, size_t missedCleavages, bool NTerminusIsSpecific, bool CTerminusIsSpecific, std::string NTerminusPrefix, std::string CTerminusSuffix) : Peptide(begin, end), offset_(offset), missedCleavages_(missedCleavages), NTerminusIsSpecific_(NTerminusIsSpecific), CTerminusIsSpecific_(CTerminusIsSpecific), NTerminusPrefix_(NTerminusPrefix), CTerminusSuffix_(CTerminusSuffix) { } PWIZ_API_DECL DigestedPeptide::DigestedPeptide(const Peptide& peptide, size_t offset, size_t missedCleavages, bool NTerminusIsSpecific, bool CTerminusIsSpecific, std::string NTerminusPrefix, std::string CTerminusSuffix) : Peptide(peptide), offset_(offset), missedCleavages_(missedCleavages), NTerminusIsSpecific_(NTerminusIsSpecific), CTerminusIsSpecific_(CTerminusIsSpecific), NTerminusPrefix_(NTerminusPrefix), CTerminusSuffix_(CTerminusSuffix) { } PWIZ_API_DECL DigestedPeptide::DigestedPeptide(const DigestedPeptide& other) : Peptide(other), offset_(other.offset_), missedCleavages_(other.missedCleavages_), NTerminusIsSpecific_(other.NTerminusIsSpecific_), CTerminusIsSpecific_(other.CTerminusIsSpecific_), NTerminusPrefix_(other.NTerminusPrefix_), CTerminusSuffix_(other.CTerminusSuffix_) { } PWIZ_API_DECL DigestedPeptide& DigestedPeptide::operator=(const DigestedPeptide& rhs) { Peptide::operator=(rhs); offset_ = rhs.offset_; missedCleavages_ = rhs.missedCleavages_; NTerminusIsSpecific_ = rhs.NTerminusIsSpecific_; CTerminusIsSpecific_ = rhs.CTerminusIsSpecific_; NTerminusPrefix_ = rhs.NTerminusPrefix_; CTerminusSuffix_ = rhs.CTerminusSuffix_; return *this; } PWIZ_API_DECL DigestedPeptide::~DigestedPeptide() { } PWIZ_API_DECL size_t DigestedPeptide::offset() const { return offset_; } PWIZ_API_DECL size_t DigestedPeptide::missedCleavages() const { return missedCleavages_; } PWIZ_API_DECL size_t DigestedPeptide::specificTermini() const { return (size_t) NTerminusIsSpecific_ + (size_t) CTerminusIsSpecific_; } PWIZ_API_DECL bool DigestedPeptide::NTerminusIsSpecific() const { return NTerminusIsSpecific_; } PWIZ_API_DECL bool DigestedPeptide::CTerminusIsSpecific() const { return CTerminusIsSpecific_; } PWIZ_API_DECL std::string DigestedPeptide::NTerminusPrefix() const { return NTerminusPrefix_; } PWIZ_API_DECL std::string DigestedPeptide::CTerminusSuffix() const { return CTerminusSuffix_; } PWIZ_API_DECL bool DigestedPeptide::operator==(const DigestedPeptide& rhs) const { return this->Peptide::operator==(rhs) && offset() == rhs.offset() && missedCleavages() == rhs.missedCleavages() && NTerminusIsSpecific() == rhs.NTerminusIsSpecific() && CTerminusIsSpecific() == rhs.CTerminusIsSpecific() && NTerminusPrefix() == rhs.NTerminusPrefix() && CTerminusSuffix() == rhs.CTerminusSuffix(); } PWIZ_API_DECL Digestion::Config::Config(int maximumMissedCleavages, //double minimumMass, //double maximumMass, int minimumLength, int maximumLength, Specificity minimumSpecificity, bool clipNTerminalMethionine) : maximumMissedCleavages(maximumMissedCleavages), //minimumMass(minimumMass), maximumMass(maximumMass), minimumLength(minimumLength), maximumLength(maximumLength), minimumSpecificity(minimumSpecificity), clipNTerminalMethionine(clipNTerminalMethionine) { } namespace { class CleavageAgentInfo : public boost::singleton { public: CleavageAgentInfo(boost::restricted) { const vector& cvids = pwiz::cv::cvids(); for (vector::const_iterator itr = cvids.begin(); itr != cvids.end(); ++itr) { if (!cvIsA(*itr, MS_cleavage_agent_name)) continue; const CVTermInfo& cvTermInfo = pwiz::cv::cvTermInfo(*itr); multimap::const_iterator regexRelationItr = cvTermInfo.otherRelations.find("has_regexp"); if (regexRelationItr != cvTermInfo.otherRelations.end()) { cleavageAgents_.insert(*itr); cleavageAgentNames_.push_back(cvTermInfo.name); cleavageAgentNameToCvidMap_[bal::to_lower_copy(cvTermInfo.name)] = *itr; BOOST_FOREACH(const string& synonym, cvTermInfo.exactSynonyms) cleavageAgentNameToCvidMap_[bal::to_lower_copy(synonym)] = *itr; const CVTermInfo& cleavageAgentRegexTerm = pwiz::cv::cvTermInfo(regexRelationItr->second); cleavageAgentRegexToCvidMap_[cleavageAgentRegexTerm.name] = *itr; cleavageAgentToRegexMap_[*itr] = &cleavageAgentRegexTerm; } else if (*itr == MS_unspecific_cleavage || *itr == MS_no_cleavage) { cleavageAgents_.insert(*itr); cleavageAgentNames_.push_back(cvTermInfo.name); cleavageAgentNameToCvidMap_[bal::to_lower_copy(cvTermInfo.name)] = *itr; } } } const set& cleavageAgents() const {return cleavageAgents_;} const vector& cleavageAgentNames() const {return cleavageAgentNames_;} CVID getCleavageAgentByName(const string& agentName) const { string name = bal::to_lower_copy(agentName); map::const_iterator agentTermItr = cleavageAgentNameToCvidMap_.find(name); if (agentTermItr == cleavageAgentNameToCvidMap_.end()) return CVID_Unknown; return agentTermItr->second; } CVID getCleavageAgentByRegex(const string& agentRegex) const { map::const_iterator agentTermItr = cleavageAgentRegexToCvidMap_.find(agentRegex); if (agentTermItr == cleavageAgentRegexToCvidMap_.end()) return CVID_Unknown; return agentTermItr->second; } const std::string& getCleavageAgentRegex(CVID agentCvid) const { if (!pwiz::cv::cvIsA(agentCvid, MS_cleavage_agent_name)) throw invalid_argument("[getCleavageAgentRegex] CVID is not a cleavage agent."); map::const_iterator regexTermItr = cleavageAgentToRegexMap_.find(agentCvid); if (regexTermItr == cleavageAgentToRegexMap_.end()) throw runtime_error("[getCleavageAgentRegex] No regex relation for cleavage agent " + cvTermInfo(agentCvid).name); return regexTermItr->second->name; } private: set cleavageAgents_; vector cleavageAgentNames_; map cleavageAgentNameToCvidMap_; map cleavageAgentRegexToCvidMap_; map cleavageAgentToRegexMap_; }; } // namespace const set& Digestion::getCleavageAgents() { return CleavageAgentInfo::instance->cleavageAgents(); } const vector& Digestion::getCleavageAgentNames() { return CleavageAgentInfo::instance->cleavageAgentNames(); } CVID Digestion::getCleavageAgentByName(const string& agentName) { return CleavageAgentInfo::instance->getCleavageAgentByName(agentName); } CVID Digestion::getCleavageAgentByRegex(const string& agentRegex) { return CleavageAgentInfo::instance->getCleavageAgentByRegex(agentRegex); } const string& Digestion::getCleavageAgentRegex(CVID agentCvid) { return CleavageAgentInfo::instance->getCleavageAgentRegex(agentCvid); } namespace { // match zero or one regex term like (?<=[KR]) or (?<=K) or (?[ND], Z->[EQ], J->[IL], X->[A-Z] bxp::smatch what; bxp::regex_match(cleavageAgentRegex, what, cutNoCutRegex); bool hasLookbehind = what[1].matched && what[2].matched; bool hasLookahead = what[3].matched && what[4].matched; bool lookbehindIsPositive = hasLookbehind && what[1] == "="; bool lookaheadIsPositive = hasLookahead && what[3] == "="; string lookbehindResidues = hasLookbehind ? bal::trim_copy_if(what[2].str(), bal::is_any_of("[]")) : string(); string lookaheadResidues = hasLookahead ? bal::trim_copy_if(what[4].str(), bal::is_any_of("[]")) : string(); // if both looks are empty, throw an exception if (!hasLookbehind && !hasLookahead) throw runtime_error("[Digestion::disambiguateCleavageAgentRegex()] No lookbehind or lookahead expressions found in \"" + cleavageAgentRegex + "\""); // add the ambiguous choices to each B/Z/J; // ambiguous choices might be listed twice ([BD] becomes [BNDD]), but that's not a problem bal::replace_all(lookbehindResidues, "B", "BND"); bal::replace_all(lookbehindResidues, "Z", "ZEQ"); bal::replace_all(lookbehindResidues, "J", "JIL"); bal::replace_all(lookbehindResidues, "X", "A-Z"); bal::replace_all(lookaheadResidues, "B", "BND"); bal::replace_all(lookaheadResidues, "Z", "ZEQ"); bal::replace_all(lookaheadResidues, "J", "JIL"); bal::replace_all(lookaheadResidues, "X", "A-Z"); string& lb = lookbehindResidues; string& la = lookaheadResidues; return (lb.empty() ? "" : string("(?<") + (lookbehindIsPositive ? "=" : "!") + (lb.length() > 1 ? "[" : "") + lb + (lb.length() > 1 ? "])" : ")")) + (la.empty() ? "" : string("(?") + (lookaheadIsPositive ? "=" : "!") + (la.length() > 1 ? "[" : "") + la + (la.length() > 1 ? "])" : ")")); } class Digestion::Impl { public: Impl(const Peptide& peptide, const std::vector& cleavageAgents, const Config& config) : peptide_(peptide), config_(config) { if (cleavageAgents.size() == 1) { cleavageAgent_ = cleavageAgents[0]; if (cleavageAgent_ == MS_unspecific_cleavage) config_.minimumSpecificity = Digestion::NonSpecific; else if (cleavageAgent_ != MS_no_cleavage) cleavageAgentRegex_ = bxp::sregex::compile(disambiguateCleavageAgentRegex(getCleavageAgentRegex(cleavageAgent_))); return; } cleavageAgent_ = CVID_Unknown; // Avoid testing uninitialized value in digest() string mergedRegex = "((" + disambiguateCleavageAgentRegex(getCleavageAgentRegex(cleavageAgents[0])); for (size_t i=1; i < cleavageAgents.size(); ++i) mergedRegex += ")|(" + disambiguateCleavageAgentRegex(getCleavageAgentRegex(cleavageAgents[i])); mergedRegex += "))"; cleavageAgentRegex_ = bxp::sregex::compile(mergedRegex); } Impl(const Peptide& peptide, const vector& cleavageAgentRegexes, const Config& config) : peptide_(peptide), config_(config) { cleavageAgent_ = CVID_Unknown; // Avoid testing uninitialized value in digest() if (cleavageAgentRegexes.size() == 1) { cleavageAgentRegex_ = bxp::sregex::compile(cleavageAgentRegexes[0]); //disambiguateCleavageAgentRegex(cleavageAgentRegexes[0].str()); return; } string mergedRegex = "((" + disambiguateCleavageAgentRegex(cleavageAgentRegexes[0]); for (size_t i=1; i < cleavageAgentRegexes.size(); ++i) mergedRegex += ")|(" + disambiguateCleavageAgentRegex(cleavageAgentRegexes[i]); mergedRegex += "))"; cleavageAgentRegex_ = bxp::sregex::compile(mergedRegex); } inline void digest() const { if (sites_.empty()) { try { const string& sequence = peptide_.sequence(); if (cleavageAgent_ == MS_unspecific_cleavage) { for (int i=-1, end=(int) sequence.size()-1; i < end; ++i) sites_.push_back(i); sitesSet_.insert(sites_.begin(), sites_.end()); return; } else if (cleavageAgent_ == MS_no_cleavage) { sites_.push_back(-1); sites_.push_back(sequence.length()-1); sitesSet_.insert(sites_.begin(), sites_.end()); return; } //if (cleavageAgentRegex_.empty()) // throw runtime_error("empty cleavage regex"); std::string::const_iterator start = sequence.begin(); std::string::const_iterator end = sequence.end(); bxp::smatch what; bxp::regex_constants::match_flag_type flags = bxp::regex_constants::match_default; while (bxp::regex_search(start, end, what, cleavageAgentRegex_, flags)) { sites_.push_back(int(what[0].first-sequence.begin()-1)); // update search position and flags start = max(what[0].second, start+1); flags = flags | bxp::regex_constants::match_prev_avail | bxp::regex_constants::match_not_bol; } // if regex didn't match n-terminus, insert it if (sites_.empty() || sites_.front() > -1) sites_.insert(sites_.begin(), -1); // if regex didn't match c-terminus, insert it if (sites_.back() < (int)sequence.length()-1) sites_.push_back(sequence.length()-1); if (sites_.size() > 2 && sites_[1] != 0 && !sequence.empty() && config_.clipNTerminalMethionine && sequence[0] == 'M') sites_.insert(sites_.begin()+1, 0); sitesSet_.insert(sites_.begin(), sites_.end()); } catch (exception& e) { throw runtime_error(string("[Digestion::Impl::digest()] ") + e.what()); } } } inline vector find_all(const Peptide& peptide) { typedef boost::iterator_range const_string_iterator_range; digest(); // populate sites_ member if necessary const string& sequence_ = peptide_.sequence(); vector result; if ((int) peptide.sequence().length() > config_.maximumLength || (int) peptide.sequence().length() < config_.minimumLength) return result; vector instances; bal::find_all(instances, sequence_, peptide.sequence()); BOOST_FOREACH(const_string_iterator_range& range, instances) { size_t beginOffset = range.begin() - sequence_.begin(); size_t endOffset = beginOffset + peptide.sequence().length() - 1; bool NTerminusIsSpecific = sitesSet_.count(int(beginOffset) - 1) > 0; bool CTerminusIsSpecific = sitesSet_.count(int(endOffset)) > 0; if (((size_t) NTerminusIsSpecific + (size_t) CTerminusIsSpecific) < (size_t) config_.minimumSpecificity) continue; size_t missedCleavages = 0; if (cleavageAgent_ != MS_unspecific_cleavage && cleavageAgent_ != MS_no_cleavage) for (size_t i = beginOffset; i < endOffset; ++i) if (sitesSet_.count((int) i) > 0) ++missedCleavages; if (missedCleavages > (size_t) config_.maximumMissedCleavages) continue; string NTerminusPrefix, CTerminusSuffix; if (beginOffset > 0) NTerminusPrefix = sequence_.substr(beginOffset-1, 1); if (endOffset+1 < sequence_.length()) CTerminusSuffix = sequence_.substr(endOffset+1, 1); result.push_back(DigestedPeptide(peptide, beginOffset, missedCleavages, NTerminusIsSpecific, CTerminusIsSpecific, NTerminusPrefix, CTerminusSuffix)); } return result; } inline DigestedPeptide find_first(const Peptide& peptide, int offsetHint) { digest(); // populate sites_ member if necessary const string& sequence_ = peptide_.sequence(); if ((int) peptide.sequence().length() > config_.maximumLength || (int) peptide.sequence().length() < config_.minimumLength) throw runtime_error("[Digestion::find_first()] Peptide \"" + peptide.sequence() + "\" not found in \"" + sequence_ + "\""); if(offsetHint + peptide.sequence().length() > sequence_.length()) offsetHint = 0; size_t beginOffset = sequence_.find(peptide.sequence(), offsetHint); if (beginOffset == string::npos) beginOffset = sequence_.find(peptide.sequence(), 0); if (beginOffset == string::npos) throw runtime_error("[Digestion::find_first()] Peptide \"" + peptide.sequence() + "\" not found in \"" + sequence_ + "\""); size_t endOffset = beginOffset + peptide.sequence().length() - 1; size_t missedCleavages = 0; if (cleavageAgent_ != MS_unspecific_cleavage && cleavageAgent_ != MS_no_cleavage) for (size_t i = beginOffset; i < endOffset; ++i) if (sitesSet_.count((int) i) > 0) ++missedCleavages; if (missedCleavages > (size_t) config_.maximumMissedCleavages) throw runtime_error("[Digestion::find_first()] Peptide \"" + peptide.sequence() + "\" not found in \"" + sequence_ + "\""); bool NTerminusIsSpecific, CTerminusIsSpecific; do { endOffset = beginOffset + peptide.sequence().length() - 1; NTerminusIsSpecific = sitesSet_.count(int(beginOffset)-1) > 0; CTerminusIsSpecific = sitesSet_.count(int(endOffset)) > 0; if (((size_t) NTerminusIsSpecific + (size_t) CTerminusIsSpecific) >= (size_t) config_.minimumSpecificity) break; beginOffset = sequence_.find(peptide.sequence(), beginOffset + 1); } while (beginOffset != string::npos); if (beginOffset == string::npos || ((size_t) NTerminusIsSpecific + (size_t) CTerminusIsSpecific) < (size_t) config_.minimumSpecificity) throw runtime_error("[Digestion::find_first()] Peptide \"" + peptide.sequence() + "\" not found in \"" + sequence_ + "\""); string NTerminusPrefix, CTerminusSuffix; if (beginOffset > 0) NTerminusPrefix = sequence_.substr(beginOffset-1, 1); if (endOffset+1 < sequence_.length()) CTerminusSuffix = sequence_.substr(endOffset+1, 1); return DigestedPeptide(peptide, beginOffset, missedCleavages, NTerminusIsSpecific, CTerminusIsSpecific, NTerminusPrefix, CTerminusSuffix); } private: Peptide peptide_; Config config_; CVID cleavageAgent_; bxp::sregex cleavageAgentRegex_; friend class Digestion::const_iterator::Impl; // precalculated offsets to digestion sites in order of occurence; // the sites are between offset and offset+1; // -1 is the N terminus digestion site // peptide_.sequence().length()-1 is the C terminus digestion site mutable vector sites_; mutable set sitesSet_; }; PWIZ_API_DECL Digestion::Digestion(const Peptide& peptide, CVID cleavageAgent, const Config& config) : impl_(new Impl(peptide, vector(1, cleavageAgent), config)) { } PWIZ_API_DECL Digestion::Digestion(const Peptide& peptide, const vector& cleavageAgents, const Config& config) : impl_(new Impl(peptide, cleavageAgents, config)) { } PWIZ_API_DECL Digestion::Digestion(const Peptide& peptide, const string& cleavageAgentRegex, const Config& config) : impl_(new Impl(peptide, vector(1, cleavageAgentRegex), config)) { } PWIZ_API_DECL Digestion::Digestion(const Peptide& peptide, const vector& cleavageAgentRegexes, const Config& config) : impl_(new Impl(peptide, cleavageAgentRegexes, config)) { } PWIZ_API_DECL Digestion::~Digestion() { } PWIZ_API_DECL vector Digestion::find_all(const Peptide& peptide) const { return impl_->find_all(peptide); } PWIZ_API_DECL DigestedPeptide Digestion::find_first(const Peptide& peptide, size_t offsetHint) const { return impl_->find_first(peptide, offsetHint); } PWIZ_API_DECL Digestion::const_iterator Digestion::begin() const { return const_iterator(*this); } PWIZ_API_DECL Digestion::const_iterator Digestion::end() const { return const_iterator(); } class Digestion::const_iterator::Impl { public: Impl(const Digestion& digestion) : digestionImpl_(*digestion.impl_), config_(digestionImpl_.config_), sequence_(digestionImpl_.peptide_.sequence()), sites_(digestionImpl_.sites_) { digestionImpl_.digest(); try { switch (config_.minimumSpecificity) { default: case FullySpecific: initFullySpecific(); break; case SemiSpecific: // TODO: optimize semi-specific case NonSpecific: initNonSpecific(); break; } } catch (exception& e) { throw runtime_error(string("[Digestion::const_iterator::Impl::Impl()] ") + e.what()); } } inline void initFullySpecific() { begin_ = end_ = sites_.end(); beginNonSpecific_ = endNonSpecific_ = -1; // So debuggers don't complain about uninit values // iteration requires at least 2 digestion sites if (sites_.size() < 2) return; // try each possible pair of digestion sites; // initialize begin_ and end_ to the first pair that meet // config's filtering criteria for (size_t i=0; i < sites_.size(); ++i) { int testBegin = sites_[i]; for (size_t j=1; j < sites_.size(); ++j) { int testEnd = sites_[j]; int curMissedCleavages = digestionImpl_.cleavageAgent_ == MS_unspecific_cleavage ? 0 : int(end_ - begin_)-1; if (curMissedCleavages > 0 && config_.clipNTerminalMethionine && begin_ != sites_.end() && *begin_ < 0 && sequence_[0] == 'M') --curMissedCleavages; if (curMissedCleavages > config_.maximumMissedCleavages) break; int curLength = testEnd - testBegin; if (curLength > config_.maximumLength) break; if (curLength < config_.minimumLength) continue; begin_ = sites_.begin()+i; end_ = sites_.begin()+j; break; } if (begin_ != sites_.end()) break; } } inline void initNonSpecific() { begin_ = end_ = sites_.begin(); beginNonSpecific_ = endNonSpecific_ = sequence_.length(); int maxLength = (int) sequence_.length(); // try each possible pair of digestion sites; // initialize beginNonSpecific_ and beginNonSpecific_ to the first pair that meet // config's filtering criteria bool passesFilter = false; for (int testBegin = -1; testBegin < maxLength && !passesFilter; ++testBegin) { for (int testEnd = testBegin+config_.minimumLength; testEnd < maxLength; ++testEnd) { // end offset is too far, start again with a new begin offset int curLength = testEnd - testBegin; if (curLength > config_.maximumLength) break; beginNonSpecific_ = testBegin; endNonSpecific_ = testEnd; while (begin_ != sites_.end() && *begin_ <= beginNonSpecific_) ++begin_; if (begin_ != sites_.end()) { end_ = begin_--; while (end_ != sites_.end() && *end_ < endNonSpecific_) ++end_; } // end offset is too far, start again with a new begin offset int curMissedCleavages = digestionImpl_.cleavageAgent_ == MS_unspecific_cleavage ? 0 : int(end_ - begin_)-1; if (curMissedCleavages > 0 && config_.clipNTerminalMethionine && begin_ != sites_.end() && *begin_ < 0 && sequence_[0] == 'M') --curMissedCleavages; if (curMissedCleavages > config_.maximumMissedCleavages) break; if (beginNonSpecific_ != maxLength) { passesFilter = true; break; } } } } const DigestedPeptide& peptide() const { try { string prefix = ""; string suffix = ""; int missedCleavages = int(end_ - begin_)-1; if (missedCleavages > 0 && config_.clipNTerminalMethionine && begin_ != sites_.end() && *begin_ < 0 && sequence_[0] == 'M') --missedCleavages; if (!peptide_.get()) { switch (config_.minimumSpecificity) { default: case FullySpecific: if(*begin_ >= 0 && *begin_ < (int) sequence_.length()) prefix = sequence_.substr(*begin_, 1); //this could be changed to be something other than 1 by a config option later if(*end_ != (int) sequence_.length()) suffix = sequence_.substr(*end_+1, 1); peptide_.reset( new DigestedPeptide(sequence_.begin()+(*begin_+1), sequence_.begin()+(*end_+1), *begin_+1, missedCleavages, true, true, prefix, suffix )); break; case SemiSpecific: case NonSpecific: if(beginNonSpecific_ >= 0 && beginNonSpecific_ < (int) sequence_.length()) prefix = sequence_.substr(beginNonSpecific_, 1); //this could be changed to be something other than 1 by a config option later if(endNonSpecific_ != (int) sequence_.length()) suffix = sequence_.substr(endNonSpecific_+1, 1); peptide_.reset( new DigestedPeptide(sequence_.begin()+(beginNonSpecific_+1), sequence_.begin()+(endNonSpecific_+1), beginNonSpecific_+1, missedCleavages, begin_ != sites_.end() && *begin_ == beginNonSpecific_, end_ != sites_.end() && *end_ == endNonSpecific_, prefix, suffix )); break; } } return *peptide_; } catch (exception& e) { throw runtime_error(string("[Digestion::const_iterator::Impl::peptide()] ") + e.what()); } } inline void nextFullySpecific() { bool newBegin = (end_ == sites_.end()); if (!newBegin) { // advance end_ to the next digestion site bool foundNextValidSitePair = false; for (++end_; end_ != sites_.end(); ++end_) { int curMissedCleavages = int(end_ - begin_)-1; if (curMissedCleavages > 0 && config_.clipNTerminalMethionine && begin_ != sites_.end() && *begin_ < 0 && sequence_[0] == 'M') --curMissedCleavages; if (curMissedCleavages > config_.maximumMissedCleavages) break; int curLength = *end_ - *begin_; if (curLength > config_.maximumLength) break; if (curLength < config_.minimumLength) continue; foundNextValidSitePair = true; break; } // there may not be another site that makes a valid site pair newBegin = !foundNextValidSitePair; } if (newBegin) { // advance to the next valid digestion site pair bool foundNextValidSitePair = false; for (++begin_; begin_ != sites_.end(); ++begin_) { for (end_ = begin_+1; end_ != sites_.end(); ++end_) { int curMissedCleavages = int(end_ - begin_)-1; if (curMissedCleavages > config_.maximumMissedCleavages) break; int curLength = *end_ - *begin_; if (curLength > config_.maximumLength) break; if (curLength < config_.minimumLength) continue; foundNextValidSitePair = true; break; } if (foundNextValidSitePair) break; } } } inline void nextNonSpecific() { int maxLength = (int) sequence_.length(); bool newBegin = (endNonSpecific_ == maxLength); if (!newBegin) { // advance endNonSpecific_ to the next digestion site bool foundNextValidSitePair = false; end_ = begin_; for (++endNonSpecific_; endNonSpecific_ < maxLength; ++endNonSpecific_) { while (end_ != sites_.end() && *end_ < endNonSpecific_) ++end_; int curMissedCleavages = digestionImpl_.cleavageAgent_ == MS_unspecific_cleavage ? 0 : int(end_ - begin_)-1; if (curMissedCleavages > 0 && config_.clipNTerminalMethionine && begin_ != sites_.end() && *begin_ < 0 && sequence_[0] == 'M') --curMissedCleavages; if (curMissedCleavages > config_.maximumMissedCleavages) break; int curLength = endNonSpecific_ - beginNonSpecific_; if (curLength > config_.maximumLength) break; if (curLength < config_.minimumLength) continue; foundNextValidSitePair = true; break; } // there may not be another site that makes a valid site pair newBegin = !foundNextValidSitePair; } if (newBegin) { // advance to the next valid digestion site pair bool foundNextValidSitePair = false; for (++beginNonSpecific_; beginNonSpecific_ < maxLength; ++beginNonSpecific_) { while (begin_ != sites_.end() && *begin_ <= beginNonSpecific_) ++begin_; end_ = begin_--; for (endNonSpecific_ = beginNonSpecific_+config_.minimumLength; endNonSpecific_ < maxLength; ++endNonSpecific_) { while (end_ != sites_.end() && *end_ < endNonSpecific_) ++end_; int curMissedCleavages = digestionImpl_.cleavageAgent_ == MS_unspecific_cleavage ? 0 : int(end_ - begin_)-1; if (curMissedCleavages > 0 && config_.clipNTerminalMethionine && begin_ != sites_.end() && *begin_ < 0 && sequence_[0] == 'M') --curMissedCleavages; if (curMissedCleavages > config_.maximumMissedCleavages) break; int curLength = endNonSpecific_ - beginNonSpecific_; if (curLength > config_.maximumLength) break; if (curLength < config_.minimumLength) continue; foundNextValidSitePair = true; break; } if (foundNextValidSitePair) break; } } } inline Impl& operator++() { try { peptide_.reset(); switch (config_.minimumSpecificity) { default: case FullySpecific: nextFullySpecific(); break; case SemiSpecific: while (beginNonSpecific_ < (int) sequence_.length()) { nextNonSpecific(); if ((begin_ != sites_.end() && *begin_ == beginNonSpecific_) || (end_ != sites_.end() && *end_ == endNonSpecific_)) break; } break; case NonSpecific: nextNonSpecific(); break; } } catch (exception& e) { throw runtime_error(string("[Digestion::Impl::operator++()] ") + e.what()); } return *this; } inline Impl operator++(int) { Impl tmp(*this); ++*this; return tmp; } inline bool atEnd() { switch (config_.minimumSpecificity) { case SemiSpecific: // TODO: optimize semi-specific case NonSpecific: return beginNonSpecific_ == (int) sequence_.length(); case FullySpecific: default: return begin_ == sites_.end(); } } private: const Digestion::Impl& digestionImpl_; const Config& config_; const string& sequence_; const vector& sites_; // used for all digests // fully specific: iterator to the current peptide's N terminal offset-1 // semi- and non-specific: iterator to the previous valid digestion site before or at beginNonSpecific_ vector::const_iterator begin_; // fully specific: iterator to the current peptide's C terminal offset // semi- and non-specific: iterator to the next valid digestion site at or after endNonSpecific_ vector::const_iterator end_; // used for semi- and non-specific digest int beginNonSpecific_; int endNonSpecific_; mutable shared_ptr peptide_; friend class Digestion::const_iterator; }; PWIZ_API_DECL Digestion::const_iterator::const_iterator() { } PWIZ_API_DECL Digestion::const_iterator::const_iterator(const Digestion& digestion) : impl_(new Impl(digestion)) { } PWIZ_API_DECL Digestion::const_iterator::const_iterator(const const_iterator& rhs) : impl_(rhs.impl_.get() ? new Impl(*rhs.impl_) : 0) { } PWIZ_API_DECL Digestion::const_iterator::~const_iterator() { } PWIZ_API_DECL const DigestedPeptide& Digestion::const_iterator::operator*() const { return impl_->peptide(); } PWIZ_API_DECL const DigestedPeptide* Digestion::const_iterator::operator->() const { return &(impl_->peptide()); } PWIZ_API_DECL Digestion::const_iterator& Digestion::const_iterator::operator++() { ++(*impl_); return *this; } PWIZ_API_DECL Digestion::const_iterator Digestion::const_iterator::operator++(int) { const_iterator tmp(*this); ++(*impl_); return tmp; } PWIZ_API_DECL bool Digestion::const_iterator::operator!=(const Digestion::const_iterator& that) const { return !(*this == that); } PWIZ_API_DECL bool Digestion::const_iterator::operator==(const Digestion::const_iterator& that) const { bool gotThis = this->impl_.get() != NULL; bool gotThat = that.impl_.get() != NULL; if (gotThis && gotThat) return this->impl_->begin_ == that.impl_->begin_ && this->impl_->end_ == that.impl_->end_; else if (!gotThis && !gotThat) // end() == end() return true; else if (gotThis) return this->impl_->atEnd(); else // gotThat return that.impl_->atEnd(); } } // namespace proteome } // namespace pwiz pwiz/pwiz/data/proteome/examples.cpp0000664000175100017510000000310612664775621021631 0ustar teamcityteamcity00000000000000// // $Id: examples.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "examples.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace proteome { namespace examples { PWIZ_API_DECL void initializeTiny(ProteomeData& pd) { pd.id = "tiny"; shared_ptr proteinListPtr(new ProteinListSimple); pd.proteinListPtr = proteinListPtr; proteinListPtr->proteins.push_back(ProteinPtr(new Protein("ABC123", 0, "One two three.", "ELVISLIVES"))); proteinListPtr->proteins.push_back(ProteinPtr(new Protein("ZEBRA", 1, "Has stripes:", "BLACKANDWHITE"))); proteinListPtr->proteins.push_back(ProteinPtr(new Protein("DEFCON42", 2, "", "DNTPANIC"))); } // initializeTiny() //PWIZ_API_DECL void addMIAPEExampleMetadata(ProteomeData& pd) {} // addMIAPEExampleMetadata() } // namespace examples } // namespace tdata } // namespace pwiz pwiz/pwiz/data/proteome/DigestionTest.cpp0000664000175100017510000010605412664775621022606 0ustar teamcityteamcity00000000000000// // $Id: DigestionTest.cpp 9198 2015-12-04 23:48:50Z chambm $ // // // Original author: Matt Chambers // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/unit.hpp" #include "Peptide.hpp" #include "Digestion.hpp" #include "pwiz/utility/misc/Std.hpp" #include "boost/thread/thread.hpp" #include "boost/thread/barrier.hpp" #include "boost/exception/all.hpp" #include "boost/foreach_field.hpp" using namespace pwiz::cv; using namespace pwiz::util; using namespace pwiz::proteome; ostream* os_ = 0; void testCleavageAgents() { const set& cleavageAgents = Digestion::getCleavageAgents(); const vector& cleavageAgentNames = Digestion::getCleavageAgentNames(); if (os_) { *os_ << "Cleavage agents:" << endl; BOOST_FOREACH(CVID agentCvid, cleavageAgents) { *os_ << cvTermInfo(agentCvid).name << " (" << Digestion::getCleavageAgentRegex(agentCvid) << ")" << endl; } *os_ << "\nCleavage agent names" << endl; BOOST_FOREACH(string agentName, cleavageAgentNames) { *os_ << agentName << endl; } } unit_assert(cleavageAgents.size() >= 14); unit_assert_operator_equal(MS_Trypsin, *cleavageAgents.begin()); unit_assert(!cleavageAgents.count(MS_NoEnzyme_OBSOLETE)); unit_assert(cleavageAgents.count(MS_no_cleavage)); unit_assert(cleavageAgents.count(MS_unspecific_cleavage)); unit_assert_operator_equal(MS_Trypsin, Digestion::getCleavageAgentByName("TRYPSIN")); unit_assert_operator_equal(MS_Trypsin, Digestion::getCleavageAgentByName("trypsin")); unit_assert_operator_equal(MS_Trypsin_P, Digestion::getCleavageAgentByName("TRYPSIN/P")); unit_assert_operator_equal(MS_Trypsin_P, Digestion::getCleavageAgentByName("trypsin/p")); unit_assert_operator_equal(MS_glutamyl_endopeptidase, Digestion::getCleavageAgentByName("glutamyl endopeptidase")); unit_assert_operator_equal(MS_Glu_C, Digestion::getCleavageAgentByName("Glu-C")); // test exact synonyms unit_assert_operator_equal(CVID_Unknown, Digestion::getCleavageAgentByName("ion trap")); unit_assert_operator_equal(CVID_Unknown, Digestion::getCleavageAgentByName("!@#$%^&*")); unit_assert_operator_equal(MS_Trypsin, Digestion::getCleavageAgentByRegex("(?<=[KR])(?!P)")); unit_assert_operator_equal(MS_Trypsin_P, Digestion::getCleavageAgentByRegex("(?<=[KR])")); unit_assert_operator_equal(MS_Lys_C_P, Digestion::getCleavageAgentByRegex("(?<=K)")); unit_assert_operator_equal(CVID_Unknown, Digestion::getCleavageAgentByRegex("!@#$%^&*")); unit_assert_operator_equal(MS_Trypsin, Digestion::getCleavageAgentByName(cleavageAgentNames[0])); unit_assert_operator_equal(MS_Arg_C, Digestion::getCleavageAgentByName(cleavageAgentNames[1])); unit_assert_operator_equal(MS_Asp_N, Digestion::getCleavageAgentByName(cleavageAgentNames[2])); unit_assert_operator_equal(MS_Asp_N_ambic, Digestion::getCleavageAgentByName(cleavageAgentNames[3])); unit_assert_operator_equal(MS_Chymotrypsin, Digestion::getCleavageAgentByName(cleavageAgentNames[4])); unit_assert_operator_equal(MS_CNBr, Digestion::getCleavageAgentByName(cleavageAgentNames[5])); unit_assert_operator_equal(MS_Formic_acid, Digestion::getCleavageAgentByName(cleavageAgentNames[6])); unit_assert_operator_equal(MS_Lys_C, Digestion::getCleavageAgentByName(cleavageAgentNames[7])); unit_assert_operator_equal(MS_Lys_C_P, Digestion::getCleavageAgentByName(cleavageAgentNames[8])); unit_assert_operator_equal(MS_PepsinA, Digestion::getCleavageAgentByName(cleavageAgentNames[9])); unit_assert_operator_equal(MS_TrypChymo, Digestion::getCleavageAgentByName(cleavageAgentNames[10])); unit_assert_operator_equal(MS_Trypsin_P, Digestion::getCleavageAgentByName(cleavageAgentNames[11])); unit_assert_operator_equal(MS_V8_DE, Digestion::getCleavageAgentByName(cleavageAgentNames[12])); unit_assert_operator_equal(MS_V8_E, Digestion::getCleavageAgentByName(cleavageAgentNames[13])); unit_assert_operator_equal("(?<=[KR])(?!P)", Digestion::getCleavageAgentRegex(MS_Trypsin)); unit_assert_operator_equal("(?<=[EZ])(?!P)", Digestion::getCleavageAgentRegex(MS_V8_E)); unit_assert_throws(Digestion::getCleavageAgentRegex(MS_ion_trap), std::invalid_argument); unit_assert_operator_equal("(?=[BD])", Digestion::getCleavageAgentRegex(MS_Asp_N)); unit_assert_operator_equal("(?=[BNDD])", Digestion::disambiguateCleavageAgentRegex(Digestion::getCleavageAgentRegex(MS_Asp_N))); unit_assert_operator_equal("(?=[A-Z])", Digestion::disambiguateCleavageAgentRegex("(?=X)")); unit_assert_operator_equal("(?=[A-Z])", Digestion::disambiguateCleavageAgentRegex("(?=[X])")); unit_assert_operator_equal("(?![BND])", Digestion::disambiguateCleavageAgentRegex("(?!B)")); unit_assert_operator_equal("(? trypticPeptides(trypticDigestion.begin(), trypticDigestion.end()); set trypticPeptideSet(trypticPeptides.begin(), trypticPeptides.end()); if (os_) { BOOST_FOREACH(const DigestedPeptide& peptide, trypticPeptides) { *os_ << peptide.offset() << "\t" << peptide.missedCleavages() << "\t" << peptide.specificTermini() << "\t" << peptide.sequence().length() << "\t" << peptide.sequence() << "\n"; } } // test count unit_assert(trypticPeptides.size() > 4); // test order of enumeration and metadata: sequence, Off, NMC, NTT, Pre, Suf unit_assert(testDigestionMetadata(trypticPeptides[0], "MKWVTFISLLLLFSSAYSR", 0, 1, 2, "", "G")); unit_assert(testDigestionMetadata(trypticPeptides[1], "MKWVTFISLLLLFSSAYSRGVFR", 0, 2, 2, "", "R")); unit_assert(testDigestionMetadata(trypticPeptides[2], "MKWVTFISLLLLFSSAYSRGVFRR", 0, 3, 2, "", "D")); unit_assert(testDigestionMetadata(trypticPeptides[3], "KWVTFISLLLLFSSAYSR", 1, 1, 2, "M", "G")); // test for non-tryptic peptides unit_assert(!trypticPeptideSet.count("MKWVTFISLLLL")); unit_assert(!trypticPeptideSet.count("STQTALA")); // test some middle peptides unit_assert(trypticPeptideSet.count("RDTHKSEIAHRFK")); unit_assert(trypticPeptideSet.count("DTHKSEIAHRFK")); // test trypticPeptides at the C terminus unit_assert(trypticPeptideSet.count("EACFAVEGPKLVVSTQTALA")); unit_assert(trypticPeptides.back().sequence() == "LVVSTQTALA"); // test maximum missed cleavages unit_assert(!trypticPeptideSet.count("MKWVTFISLLLLFSSAYSRGVFRRDTHK")); unit_assert(!trypticPeptideSet.count("LKPDPNTLCDEFKADEKKFWGKYLYEIARR")); // test minimum peptide length unit_assert(!trypticPeptideSet.count("LR")); unit_assert(!trypticPeptideSet.count("QRLR")); unit_assert(trypticPeptideSet.count("VLASSARQRLR")); // test maximum peptide length unit_assert(!trypticPeptideSet.count("MKWVTFISLLLLFSSAYSRGVFRRDTHKSEIAHRFKDLGEEHFK")); // test methionine clipping at the N-terminus unit_assert(trypticPeptideSet.count("KWVTFISLLLLFSSAYSR")); } void testSemitrypticBSA(const Digestion& semitrypticDigestion) { if (os_) *os_ << "Semi-specific BSA digest (offset, missed cleavages, specific termini, length, sequence)" << endl; set::const_iterator peptideItr; vector semitrypticPeptides(semitrypticDigestion.begin(), semitrypticDigestion.end()); set semitrypticPeptideSet(semitrypticPeptides.begin(), semitrypticPeptides.end()); if (os_) { BOOST_FOREACH(DigestedPeptide peptide, semitrypticPeptides) { *os_ << peptide.offset() << "\t" << peptide.missedCleavages() << "\t" << peptide.specificTermini() << "\t" << peptide.sequence().length() << "\t" << peptide.sequence() << "\n"; } } // test count unit_assert(semitrypticPeptides.size() > 3); // test order of enumeration and peptides at the N terminus unit_assert_operator_equal("MKWVT", semitrypticPeptides[0].sequence()); unit_assert_operator_equal("MKWVTF", semitrypticPeptides[1].sequence()); unit_assert_operator_equal("MKWVTFI", semitrypticPeptides[2].sequence()); // test order of enumeration and peptides at the C terminus unit_assert_operator_equal("QTALA", semitrypticPeptides.rbegin()->sequence()); unit_assert_operator_equal("TQTALA", (semitrypticPeptides.rbegin()+1)->sequence()); unit_assert_operator_equal("STQTALA", (semitrypticPeptides.rbegin()+2)->sequence()); unit_assert_operator_equal("LVVSTQTALA", (semitrypticPeptides.rbegin()+5)->sequence()); unit_assert_operator_equal("LVVSTQTAL", (semitrypticPeptides.rbegin()+6)->sequence()); unit_assert_operator_equal("LVVST", (semitrypticPeptides.rbegin()+10)->sequence()); // test digestion metadata unit_assert_operator_equal(0, semitrypticPeptides[0].offset()); unit_assert_operator_equal(1, semitrypticPeptides[0].missedCleavages()); unit_assert_operator_equal(1, semitrypticPeptides[0].specificTermini()); unit_assert(semitrypticPeptides[0].NTerminusIsSpecific() && !semitrypticPeptides[0].CTerminusIsSpecific()); peptideItr = semitrypticPeptideSet.find("MKWVTFISLLLLFSSAYSR"); unit_assert(peptideItr != semitrypticPeptideSet.end()); unit_assert_operator_equal(0, peptideItr->offset()); unit_assert_operator_equal(1, peptideItr->missedCleavages()); unit_assert_operator_equal(2, peptideItr->specificTermini()); unit_assert(peptideItr->NTerminusIsSpecific() && peptideItr->CTerminusIsSpecific()); peptideItr = semitrypticPeptideSet.find("KWVTFISLLLLFSSAYSR"); unit_assert(peptideItr != semitrypticPeptideSet.end()); unit_assert_operator_equal(1, peptideItr->offset()); unit_assert_operator_equal(1, peptideItr->missedCleavages()); unit_assert_operator_equal(2, peptideItr->specificTermini()); unit_assert(peptideItr->NTerminusIsSpecific() && peptideItr->CTerminusIsSpecific()); peptideItr = semitrypticPeptideSet.find("KWVTFISLLLLFSSAYSRG"); // 2 missed cleavages unit_assert(peptideItr == semitrypticPeptideSet.end()); peptideItr = semitrypticPeptideSet.find("WVTFISLLLLFSSAYSR"); unit_assert(peptideItr != semitrypticPeptideSet.end()); unit_assert_operator_equal(2, peptideItr->offset()); unit_assert_operator_equal(0, peptideItr->missedCleavages()); unit_assert_operator_equal(2, peptideItr->specificTermini()); unit_assert(peptideItr->NTerminusIsSpecific() && peptideItr->CTerminusIsSpecific()); peptideItr = semitrypticPeptideSet.find("WVTFISLLLLFSSAYSRG"); unit_assert(peptideItr != semitrypticPeptideSet.end()); unit_assert_operator_equal(2, peptideItr->offset()); unit_assert_operator_equal(1, peptideItr->missedCleavages()); unit_assert_operator_equal(1, peptideItr->specificTermini()); unit_assert(peptideItr->NTerminusIsSpecific() && !peptideItr->CTerminusIsSpecific()); peptideItr = semitrypticPeptideSet.find("VTFISLLLLFSSAYSRG"); // non-tryptic unit_assert(peptideItr == semitrypticPeptideSet.end()); // test for non-specific peptides unit_assert(semitrypticPeptideSet.count("WVTFISLLLLFSSAYSR")); // tryptic unit_assert(semitrypticPeptideSet.count("VTFISLLLLFSSAYSR")); // semi-tryptic unit_assert(!semitrypticPeptideSet.count("VTFISLLLLFSSAYS")); // non-tryptic // test semi-specific peptides at the C terminus unit_assert(semitrypticPeptideSet.count("FAVEGPKLVVSTQTALA")); // semi-tryptic unit_assert(!semitrypticPeptideSet.count("FAVEGPKLVVSTQTAL")); // non-tryptic } void testNontrypticBSA(const Digestion& nontrypticDigestion) { if (os_) *os_ << "Non-specific BSA digest (offset, missed cleavages, specific termini, length, sequence)" << endl; set::const_iterator peptideItr; vector nontrypticPeptides(nontrypticDigestion.begin(), nontrypticDigestion.end()); set nontrypticPeptideSet(nontrypticPeptides.begin(), nontrypticPeptides.end()); if (os_) { BOOST_FOREACH(DigestedPeptide peptide, nontrypticPeptides) { *os_ << peptide.offset() << "\t" << peptide.missedCleavages() << "\t" << peptide.specificTermini() << "\t" << peptide.sequence().length() << "\t" << peptide.sequence() << "\n"; } } // test count unit_assert(nontrypticPeptides.size() > 3); // test order of enumeration and peptides at the N terminus unit_assert_operator_equal("MKWVT", nontrypticPeptides[0].sequence()); unit_assert_operator_equal("MKWVTF", nontrypticPeptides[1].sequence()); unit_assert_operator_equal("MKWVTFI", nontrypticPeptides[2].sequence()); // test digestion metadata unit_assert_operator_equal(0, nontrypticPeptides[0].offset()); unit_assert_operator_equal(1, nontrypticPeptides[0].missedCleavages()); unit_assert_operator_equal(1, nontrypticPeptides[0].specificTermini()); unit_assert(nontrypticPeptides[0].NTerminusIsSpecific() && !nontrypticPeptides[0].CTerminusIsSpecific()); peptideItr = nontrypticPeptideSet.find("MKWVTFISLLLLFSSAYSR"); unit_assert(peptideItr != nontrypticPeptideSet.end()); unit_assert_operator_equal(0, peptideItr->offset()); unit_assert_operator_equal(1, peptideItr->missedCleavages()); unit_assert_operator_equal(2, peptideItr->specificTermini()); unit_assert(peptideItr->NTerminusIsSpecific() && peptideItr->CTerminusIsSpecific()); peptideItr = nontrypticPeptideSet.find("KWVTFISLLLLFSSAYSR"); unit_assert(peptideItr != nontrypticPeptideSet.end()); unit_assert_operator_equal(1, peptideItr->offset()); unit_assert_operator_equal(1, peptideItr->missedCleavages()); unit_assert_operator_equal(2, peptideItr->specificTermini()); unit_assert(peptideItr->NTerminusIsSpecific() && peptideItr->CTerminusIsSpecific()); peptideItr = nontrypticPeptideSet.find("KWVTFISLLLLFSSAYSRG"); // 2 missed cleavages unit_assert(peptideItr == nontrypticPeptideSet.end()); peptideItr = nontrypticPeptideSet.find("WVTFISLLLLFSSAYSR"); unit_assert(peptideItr != nontrypticPeptideSet.end()); unit_assert_operator_equal(2, peptideItr->offset()); unit_assert_operator_equal(0, peptideItr->missedCleavages()); unit_assert_operator_equal(2, peptideItr->specificTermini()); unit_assert(peptideItr->NTerminusIsSpecific() && peptideItr->CTerminusIsSpecific()); peptideItr = nontrypticPeptideSet.find("WVTFISLLLLFSSAYSRG"); unit_assert(peptideItr != nontrypticPeptideSet.end()); unit_assert_operator_equal(2, peptideItr->offset()); unit_assert_operator_equal(1, peptideItr->missedCleavages()); unit_assert_operator_equal(1, peptideItr->specificTermini()); unit_assert(peptideItr->NTerminusIsSpecific() && !peptideItr->CTerminusIsSpecific()); peptideItr = nontrypticPeptideSet.find("VTFISLLLLFSSAYSRG"); unit_assert(peptideItr != nontrypticPeptideSet.end()); unit_assert_operator_equal(3, peptideItr->offset()); unit_assert_operator_equal(1, peptideItr->missedCleavages()); unit_assert_operator_equal(0, peptideItr->specificTermini()); unit_assert(!peptideItr->NTerminusIsSpecific() && !peptideItr->CTerminusIsSpecific()); // test for peptides of all specificities unit_assert(nontrypticPeptideSet.count("WVTFISLLLLFSSAYSR")); // tryptic unit_assert(nontrypticPeptideSet.count("VTFISLLLLFSSAYSR")); // semi-tryptic unit_assert(nontrypticPeptideSet.count("VTFISLLLLFSSAYS")); // non-tryptic // test non-specific peptides at the C terminus unit_assert(nontrypticPeptideSet.count("FAVEGPKLVVSTQTALA")); // semi-tryptic unit_assert(nontrypticPeptideSet.count("FAVEGPKLVVSTQTAL")); // non-tryptic unit_assert_operator_equal("QTALA", nontrypticPeptides.back().sequence()); // semi-tryptic // test maximum missed cleavages unit_assert(nontrypticPeptideSet.count("KWVTFISLLLLFSSAYSR")); unit_assert(!nontrypticPeptideSet.count("KWVTFISLLLLFSSAYSRG")); // test minimum peptide length unit_assert(!nontrypticPeptideSet.count("LR")); unit_assert(!nontrypticPeptideSet.count("QRLR")); unit_assert(nontrypticPeptideSet.count("VLASSAR")); // test maximum peptide length unit_assert(!nontrypticPeptideSet.count("EYEATLEECCAKDDPHACYSTVFDK")); } void testSemitrypticMethionineClippingBSA(const Digestion& semitrypticDigestion) { if (os_) *os_ << "Semi-specific BSA digest w/ methionine clipping (offset, missed cleavages, specific termini, length, sequence)" << endl; set::const_iterator peptideItr; vector semitrypticPeptides(semitrypticDigestion.begin(), semitrypticDigestion.end()); set semitrypticPeptideSet(semitrypticPeptides.begin(), semitrypticPeptides.end()); if (os_) { BOOST_FOREACH(DigestedPeptide peptide, semitrypticPeptides) { *os_ << peptide.offset() << "\t" << peptide.missedCleavages() << "\t" << peptide.specificTermini() << "\t" << peptide.sequence().length() << "\t" << peptide.sequence() << "\n"; } } // test count unit_assert(semitrypticPeptides.size() > 3); // test order of enumeration and peptides at the N terminus; // even with methionine clipping, MKWVT contains just one missed cleavage unit_assert_operator_equal("MKWVT", semitrypticPeptides[0].sequence()); unit_assert_operator_equal("MKWVTF", semitrypticPeptides[1].sequence()); unit_assert_operator_equal("MKWVTFI", semitrypticPeptides[2].sequence()); // test order of enumeration and peptides at the C terminus unit_assert_operator_equal("QTALA", semitrypticPeptides.rbegin()->sequence()); unit_assert_operator_equal("TQTALA", (semitrypticPeptides.rbegin()+1)->sequence()); unit_assert_operator_equal("STQTALA", (semitrypticPeptides.rbegin()+2)->sequence()); unit_assert_operator_equal("LVVSTQTALA", (semitrypticPeptides.rbegin()+5)->sequence()); unit_assert_operator_equal("LVVSTQTAL", (semitrypticPeptides.rbegin()+6)->sequence()); unit_assert_operator_equal("LVVST", (semitrypticPeptides.rbegin()+10)->sequence()); // test digestion metadata ([0]: MKWVT) unit_assert_operator_equal(0, semitrypticPeptides[0].offset()); unit_assert_operator_equal(1, semitrypticPeptides[0].missedCleavages()); unit_assert_operator_equal(1, semitrypticPeptides[0].specificTermini()); unit_assert(semitrypticPeptides[0].NTerminusIsSpecific() && !semitrypticPeptides[0].CTerminusIsSpecific()); peptideItr = semitrypticPeptideSet.find("KWVTFISLLLLFSSAYS"); // clipped methionine unit_assert(peptideItr != semitrypticPeptideSet.end()); unit_assert_operator_equal(1, peptideItr->offset()); unit_assert_operator_equal(1, peptideItr->missedCleavages()); unit_assert_operator_equal(1, peptideItr->specificTermini()); unit_assert(peptideItr->NTerminusIsSpecific()); peptideItr = semitrypticPeptideSet.find("KWVTFISLLLLFSSAYSR"); // clipped methionine unit_assert(peptideItr != semitrypticPeptideSet.end()); unit_assert_operator_equal(1, peptideItr->offset()); unit_assert_operator_equal(1, peptideItr->missedCleavages()); unit_assert_operator_equal(2, peptideItr->specificTermini()); unit_assert(peptideItr->NTerminusIsSpecific() && peptideItr->CTerminusIsSpecific()); peptideItr = semitrypticPeptideSet.find("KWVTFISLLLLFSSAYSRG"); // 2 missed cleavages unit_assert(peptideItr == semitrypticPeptideSet.end()); peptideItr = semitrypticPeptideSet.find("WVTFISLLLLFSSAYSR"); unit_assert(peptideItr != semitrypticPeptideSet.end()); unit_assert_operator_equal(2, peptideItr->offset()); unit_assert_operator_equal(0, peptideItr->missedCleavages()); unit_assert_operator_equal(2, peptideItr->specificTermini()); unit_assert(peptideItr->NTerminusIsSpecific() && peptideItr->CTerminusIsSpecific()); peptideItr = semitrypticPeptideSet.find("WVTFISLLLLFSSAYSRG"); unit_assert(peptideItr != semitrypticPeptideSet.end()); unit_assert_operator_equal(2, peptideItr->offset()); unit_assert_operator_equal(1, peptideItr->missedCleavages()); unit_assert_operator_equal(1, peptideItr->specificTermini()); unit_assert(peptideItr->NTerminusIsSpecific() && !peptideItr->CTerminusIsSpecific()); peptideItr = semitrypticPeptideSet.find("VTFISLLLLFSSAYSRG"); // non-tryptic unit_assert(peptideItr == semitrypticPeptideSet.end()); // test for non-specific peptides unit_assert(semitrypticPeptideSet.count("WVTFISLLLLFSSAYSR")); // tryptic unit_assert(semitrypticPeptideSet.count("KWVTFISLLLLFSSAYSR")); // semi-tryptic unit_assert(semitrypticPeptideSet.count("KWVTFISLLLLFSSAYS")); // clipped methionine & semi-specific unit_assert(!semitrypticPeptideSet.count("VTFISLLLLFSSAYS")); // non-specific // test semi-specific peptides at the C terminus unit_assert(semitrypticPeptideSet.count("FAVEGPKLVVSTQTALA")); // semi-tryptic unit_assert(!semitrypticPeptideSet.count("FAVEGPKLVVSTQTAL")); // non-tryptic } void testBSADigestion() { if (os_) *os_ << "BSA digestion test" << endl; // >P02769|ALBU_BOVIN Serum albumin - Bos taurus (Bovine). Peptide bsa("MKWVTFISLLLLFSSAYSRGVFRRDTHKSEIAHRFKDLGEEHFKGLVLIAFSQYLQQCPF" "DEHVKLVNELTEFAKTCVADESHAGCEKSLHTLFGDELCKVASLRETYGDMADCCEKQEP" "ERNECFLSHKDDSPDLPKLKPDPNTLCDEFKADEKKFWGKYLYEIARRHPYFYAPELLYY" "ANKYNGVFQECCQAEDKGACLLPKIETMREKVLASSARQRLRCASIQKFGERALKAWSVA" "RLSQKFPKAEFVEVTKLVTDLTKVHKECCHGDLLECADDRADLAKYICDNQDTISSKLKE" "CCDKPLLEKSHCIAEVEKDAIPENLPPLTADFAEDKDVCKNYQEAKDAFLGSFLYEYSRR" "HPEYAVSVLLRLAKEYEATLEECCAKDDPHACYSTVFDKLKHLVDEPQNLIKQNCDQFEK" "LGEYGFQNALIVRYTRKVPQVSTPTLVEVSRSLGKVGTRCCTKPESERMPCTEDYLSLIL" "NRLCVLHEKTPVSEKVTKCCTESLVNRRPCFSALTPDETYVPKAFDEKLFTFHADICTLP" "DTEKQIKKQTALVELLKHKPKATEEQLKTVMENFVAFVDKCCAADDKEACFAVEGPKLVV" "STQTALA"); // test fully-specific trypsin digest testTrypticBSA(Digestion(bsa, MS_Trypsin_P, Digestion::Config(3, 5, 40))); testTrypticBSA(Digestion(bsa, "(?<=[KR])", Digestion::Config(3, 5, 40))); // test semi-specific trypsin digest testSemitrypticBSA(Digestion(bsa, MS_Trypsin_P, Digestion::Config(1, 5, 20, Digestion::SemiSpecific))); testSemitrypticBSA(Digestion(bsa, "(?<=[KR])", Digestion::Config(1, 5, 20, Digestion::SemiSpecific))); // test non-specific trypsin digest testNontrypticBSA(Digestion(bsa, MS_Trypsin_P, Digestion::Config(1, 5, 20, Digestion::NonSpecific))); testNontrypticBSA(Digestion(bsa, "(?<=[KR])", Digestion::Config(1, 5, 20, Digestion::NonSpecific))); // test semi-specific trypsin digest with n-terminal methionine clipping (motif and regex only) testSemitrypticMethionineClippingBSA(Digestion(bsa, "(?<=^M)|(?<=[KR])", Digestion::Config(1, 5, 20, Digestion::SemiSpecific))); testSemitrypticMethionineClippingBSA(Digestion(bsa, "(?<=(^M)|([KR]))", Digestion::Config(1, 5, 20, Digestion::SemiSpecific))); // test funky digestion Digestion funkyDigestion(bsa, "(?<=A[DE])(?=[FG])", Digestion::Config(0, 5, 100000, Digestion::FullySpecific, false)); vector funkyPeptides(funkyDigestion.begin(), funkyDigestion.end()); unit_assert_operator_equal("MKWVTFISLLLLFSSAYSRGVFRRDTHKSEIAHRFKDLGEEHFKGLVLIAFSQYLQQCPFDEHVKLVNELTEFAKTCVADESHAGCEKSLHTLFGDELCKVASLRETYGDMADCCEKQEPERNECFLSHKDDSPDLPKLKPDPNTLCDEFKADEKKFWGKYLYEIARRHPYFYAPELLYYANKYNGVFQECCQAEDKGACLLPKIETMREKVLASSARQRLRCASIQKFGERALKAWSVARLSQKFPKAE", funkyPeptides[0].sequence()); unit_assert_operator_equal("FVEVTKLVTDLTKVHKECCHGDLLECADDRADLAKYICDNQDTISSKLKECCDKPLLEKSHCIAEVEKDAIPENLPPLTAD", funkyPeptides[1].sequence()); unit_assert_operator_equal("FAEDKDVCKNYQEAKDAFLGSFLYEYSRRHPEYAVSVLLRLAKEYEATLEECCAKDDPHACYSTVFDKLKHLVDEPQNLIKQNCDQFEKLGEYGFQNALIVRYTRKVPQVSTPTLVEVSRSLGKVGTRCCTKPESERMPCTEDYLSLILNRLCVLHEKTPVSEKVTKCCTESLVNRRPCFSALTPDETYVPKAFDEKLFTFHADICTLPDTEKQIKKQTALVELLKHKPKATEEQLKTVMENFVAFVDKCCAADDKEACFAVEGPKLVVSTQTALA", funkyPeptides[2].sequence()); // test fully specific Asp-N digest (thus testing ambiguous residue disambiguation) Digestion aspnDigestion(bsa, MS_Asp_N, Digestion::Config(0, 5, 100000, Digestion::FullySpecific, false)); vector aspnPeptides(aspnDigestion.begin(), aspnDigestion.end()); unit_assert_operator_equal("MKWVTFISLLLLFSSAYSRGVFRR", aspnPeptides[0].sequence()); unit_assert_operator_equal("DTHKSEIAHRFK", aspnPeptides[1].sequence()); unit_assert_operator_equal("DLGEEHFKGLVLIAFSQYLQQCPF", aspnPeptides[2].sequence()); unit_assert_operator_equal("DEHVKLV", aspnPeptides[3].sequence()); unit_assert_operator_equal("NELTEFAKTCVA", aspnPeptides[4].sequence()); // test no cleavage "digestion" Digestion noCleavageDigestion("ELVISLIVESK", MS_no_cleavage); vector noCleavagePeptides(noCleavageDigestion.begin(), noCleavageDigestion.end()); unit_assert_operator_equal(1, noCleavagePeptides.size()); unit_assert_operator_equal("ELVISLIVESK", noCleavagePeptides[0].sequence()); // test unspecific cleavage digestion Digestion unspecificCleavageDigestion("ELVISLK", MS_unspecific_cleavage, Digestion::Config(0, 5, 5, Digestion::FullySpecific, false)); vector unspecificCleavagePeptides(unspecificCleavageDigestion.begin(), unspecificCleavageDigestion.end()); unit_assert_operator_equal(3, unspecificCleavagePeptides.size()); unit_assert_operator_equal("ELVIS", unspecificCleavagePeptides[0].sequence()); unit_assert_operator_equal("LVISL", unspecificCleavagePeptides[1].sequence()); unit_assert_operator_equal("VISLK", unspecificCleavagePeptides[2].sequence()); } void testFind() { Digestion fully("PEPKTIDEKPEPTIDERPEPKTIDEKKKPEPTIDER", MS_Lys_C_P, Digestion::Config(2, 5, 10)); Digestion semi("PEPKTIDEKPEPTIDERPEPKTIDEKKKPEPTIDER", MS_Lys_C_P, Digestion::Config(2, 5, 10, Digestion::SemiSpecific)); Digestion non("PEPKTIDEKPEPTIDERPEPKTIDEKKKPEPTIDER", MS_Lys_C_P, Digestion::Config(2, 5, 10, Digestion::NonSpecific)); Digestion clipped("MPEPKTIDEKPEPTIDERPEPKTIDEKKKPEPTIDER", MS_Lys_C_P, Digestion::Config(2, 5, 10)); // test find_all unit_assert(fully.find_all("ABC").empty()); // not in peptide unit_assert(fully.find_all("PEPK").empty()); // too short unit_assert(fully.find_all("PEPKTIDEKK").empty()); // no N-terminal cleavage unit_assert(fully.find_all("PEPTIDERPEPK").empty()); // too long unit_assert(fully.find_all("PEPTIDERPEPTIDEK").empty()); // too long unit_assert(semi.find_all("PEPKTIDEKKK").empty()); // too many missed cleavages unit_assert(semi.find_all("EPKTIDE").empty()); // no specific termini unit_assert(non.find_all("EPKTIDEKKK").empty()); // too many missed cleavages unit_assert(fully.find_all("PEPKTIDEK").size() == 1); unit_assert(testDigestionMetadata(fully.find_all("PEPKTIDEK")[0], "PEPKTIDEK", 0, 1, 2, "", "P")); unit_assert(fully.find_all("TIDEK").size() == 2); unit_assert(testDigestionMetadata(fully.find_all("TIDEK")[0], "TIDEK", 4, 0, 2, "K", "P")); unit_assert(testDigestionMetadata(fully.find_all("TIDEK")[1], "TIDEK", 21, 0, 2, "K", "K")); unit_assert(fully.find_all("TIDEKK").size() == 1); unit_assert(testDigestionMetadata(fully.find_all("TIDEKK")[0], "TIDEKK", 21, 1, 2, "K", "K")); unit_assert(fully.find_all("TIDEKKK").size() == 1); unit_assert(testDigestionMetadata(fully.find_all("TIDEKKK")[0], "TIDEKKK", 21, 2, 2, "K", "P")); unit_assert(fully.find_all("PEPTIDER").size() == 1); unit_assert(testDigestionMetadata(fully.find_all("PEPTIDER")[0], "PEPTIDER", 28, 0, 2, "K", "")); unit_assert(semi.find_all("PEPKTIDEKK").size() == 1); unit_assert(testDigestionMetadata(semi.find_all("PEPKTIDEKK")[0], "PEPKTIDEKK", 17, 2, 1, "R", "K")); unit_assert(semi.find_all("EPKTIDEKK").size() == 1); unit_assert(testDigestionMetadata(semi.find_all("EPKTIDEKK")[0], "EPKTIDEKK", 18, 2, 1, "P", "K")); unit_assert(non.find_all("PEPKTIDE").size() == 2); unit_assert(testDigestionMetadata(non.find_all("PEPKTIDE")[0], "PEPKTIDE", 0, 1, 1, "", "K")); unit_assert(testDigestionMetadata(non.find_all("PEPKTIDE")[1], "PEPKTIDE", 17, 1, 0, "R", "K")); unit_assert(fully.find_all("EPKTIDEK").empty()); // N-terminal 'P' is not clipped unit_assert(clipped.find_all("PEPKTIDEK").size() == 1); // N-terminal 'M' is clipped unit_assert(testDigestionMetadata(clipped.find_all("PEPKTIDEK")[0], "PEPKTIDEK", 1, 1, 2, "M", "P")); // test find_first unit_assert_throws(fully.find_first("ABC"), runtime_error); // not in peptide unit_assert_throws(fully.find_first("PEPK"), runtime_error); // too short unit_assert_throws(fully.find_first("PEPKTIDEKK"), runtime_error); // no N-terminal cleavage unit_assert_throws(fully.find_first("PEPTIDERPEPK"), runtime_error); // too long unit_assert_throws(fully.find_first("PEPTIDERPEPTIDEK"), runtime_error); // too long unit_assert_throws(semi.find_first("EPKTIDE"), runtime_error); // no specific termini unit_assert_throws(semi.find_first("PEPKTIDEKKK"), runtime_error); // too many missed cleavages unit_assert_throws(non.find_first("PEPKTIDEKKK"), runtime_error); // too many missed cleavages unit_assert(testDigestionMetadata(fully.find_first("PEPKTIDEK"), "PEPKTIDEK", 0, 1, 2, "", "P")); unit_assert(testDigestionMetadata(fully.find_first("PEPKTIDEK", 4242), "PEPKTIDEK", 0, 1, 2, "", "P")); unit_assert(testDigestionMetadata(fully.find_first("TIDEK"), "TIDEK", 4, 0, 2, "K", "P")); unit_assert(testDigestionMetadata(fully.find_first("TIDEK", 4242), "TIDEK", 4, 0, 2, "K", "P")); unit_assert(testDigestionMetadata(fully.find_first("TIDEK", 15), "TIDEK", 21, 0, 2, "K", "K")); unit_assert(testDigestionMetadata(fully.find_first("TIDEK", 21), "TIDEK", 21, 0, 2, "K", "K")); unit_assert(testDigestionMetadata(fully.find_first("TIDEKK"), "TIDEKK", 21, 1, 2, "K", "K")); unit_assert(testDigestionMetadata(fully.find_first("TIDEKKK"), "TIDEKKK", 21, 2, 2, "K", "P")); unit_assert(testDigestionMetadata(fully.find_first("PEPTIDER"), "PEPTIDER", 28, 0, 2, "K", "")); unit_assert(testDigestionMetadata(semi.find_first("IDEKK"), "IDEKK", 22, 1, 1, "T", "K")); unit_assert(testDigestionMetadata(semi.find_first("IDEKKK"), "IDEKKK", 22, 2, 1, "T", "P")); unit_assert(testDigestionMetadata(semi.find_first("PEPTIDER"), "PEPTIDER", 9, 0, 1, "K", "P")); unit_assert(testDigestionMetadata(semi.find_first("PEPTIDER", 28), "PEPTIDER", 28, 0, 2, "K", "")); unit_assert(testDigestionMetadata(non.find_first("EPTIDE"), "EPTIDE", 10, 0, 0, "P", "R")); unit_assert(testDigestionMetadata(non.find_first("EPTIDE", 29), "EPTIDE", 29, 0, 0, "P", "R")); } struct ThreadStatus { boost::exception_ptr exception; ThreadStatus() {} ThreadStatus(const boost::exception_ptr& e) : exception(e) {} }; void testThreadSafetyWorker(boost::barrier* testBarrier, ThreadStatus& status) { testBarrier->wait(); // wait until all threads have started try { testCleavageAgents(); testBSADigestion(); testFind(); } catch (exception& e) { status.exception = boost::copy_exception(runtime_error(e.what())); } catch (...) { status.exception = boost::copy_exception(runtime_error("Unhandled exception in worker thread.")); } } void testThreadSafety(const int& testThreadCount) { using boost::thread; boost::barrier testBarrier(testThreadCount); list, ThreadStatus> > threads; for (int i=0; i < testThreadCount; ++i) { threads.push_back(make_pair(boost::shared_ptr(), ThreadStatus())); threads.back().first.reset(new thread(testThreadSafetyWorker, &testBarrier, boost::ref(threads.back().second))); } set > finishedThreads; while (finishedThreads.size() < threads.size()) BOOST_FOREACH_FIELD((boost::shared_ptr& t)(ThreadStatus& status), threads) { if (t->timed_join(boost::posix_time::seconds(1))) finishedThreads.insert(t); if (status.exception != NULL) // non-null exception? boost::rethrow_exception(status.exception); } } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; if (os_) *os_ << "DigestionTest\n"; try { //testThreadSafety(1); // does not test thread-safety of singleton initialization testThreadSafety(2); testThreadSafety(4); //testThreadSafety(8); //testThreadSafety(16); // high thread count fails non-deterministically on MSVC; I haven't been able to find the cause. } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/proteome/ProteomeDataFile.cpp0000664000175100017510000001155512664775621023206 0ustar teamcityteamcity00000000000000// // $Id: ProteomeDataFile.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "ProteomeDataFile.hpp" #include "TextWriter.hpp" #include "Reader_FASTA.hpp" #include "Serializer_FASTA.hpp" #include "DefaultReaderList.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/data/common/BinaryIndexStream.hpp" #include "boost/iostreams/device/file.hpp" #include "boost/iostreams/filtering_stream.hpp" #include "boost/iostreams/filter/gzip.hpp" namespace pwiz { namespace proteome { using namespace pwiz::util; using namespace pwiz::data; using boost::shared_ptr; namespace { void readFile(const string& uri, ProteomeData& pd, const Reader& reader) { shared_ptr uriStreamPtr(new random_access_compressed_ifstream(uri.c_str())); if (!reader.accept(uri, uriStreamPtr)) throw runtime_error("[ProteomeDataFile::readFile()] Unsupported file format."); reader.read(uri, uriStreamPtr, pd); } } // namespace PWIZ_API_DECL ProteomeDataFile::ProteomeDataFile(const string& uri, bool indexed) { readFile(uri, *this, DefaultReaderList(indexed)); } PWIZ_API_DECL ProteomeDataFile::ProteomeDataFile(const string& uri, const Reader& reader) { readFile(uri, *this, reader); } PWIZ_API_DECL void ProteomeDataFile::write(const string& uri, const WriteConfig& config, const IterationListenerRegistry* iterationListenerRegistry) { write(*this, uri, config, iterationListenerRegistry); } namespace { shared_ptr openFile(const string& uri, bool gzipped) { if (gzipped) { // use boost's filter stack to count outgoing bytes, and gzip them shared_ptr filt(new bio::filtering_ostream); shared_ptr result(filt); if (filt) { //filt->push(pwiz::minimxml::charcounter()); // for counting bytes before compression filt->push(bio::gzip_compressor(9)); // max compression filt->push(bio::file_sink(uri, ios::binary)); } if (!result.get() || !*result || !filt->good()) throw runtime_error(("[ProteomeDataFile::openFile()] Unable to open " + uri).c_str()); return result; } else { shared_ptr result(new ofstream(uri.c_str(), ios::binary)); if (!result.get() || !*result) throw runtime_error(("[ProteomeDataFile::openFile()] Unable to open " + uri).c_str()); return result; } } } // namespace PWIZ_API_DECL void ProteomeDataFile::write(const ProteomeData& pd, const string& uri, const WriteConfig& config, const IterationListenerRegistry* iterationListenerRegistry) { shared_ptr os = openFile(uri, config.gzipped); switch (config.format) { case ProteomeDataFile::Format_Text: { TextWriter(*os,0)(pd); break; } case ProteomeDataFile::Format_FASTA: { Serializer_FASTA serializer; serializer.write(*os, pd, iterationListenerRegistry); break; } default: throw runtime_error("[ProteomeDataFile::write()] Format not implemented."); } } PWIZ_API_DECL ostream& operator<<(ostream& os, ProteomeDataFile::Format format) { switch (format) { case ProteomeDataFile::Format_Text: os << "Text"; return os; case ProteomeDataFile::Format_FASTA: os << "FASTA"; return os; default: os << "Unknown"; return os; } } PWIZ_API_DECL ostream& operator<<(ostream& os, const ProteomeDataFile::WriteConfig& config) { os << config.format; if (config.format == ProteomeDataFile::Format_FASTA) os << " indexed=\"" << boolalpha << config.indexed << "\""; return os; } } // namespace proteome } // namespace pwiz pwiz/pwiz/data/proteome/ReaderTest.cpp0000664000175100017510000001312612664775621022060 0ustar teamcityteamcity00000000000000// // $Id: ReaderTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "Reader.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::proteome; ostream* os_ = 0; class Reader1 : public Reader { public: struct Config { string name; mutable bool done; Config() : name("default"), done(false) {} }; Config config; virtual std::string identify(const std::string& uri, boost::shared_ptr uriStreamPtr) const { bool result = (uri == "1"); if (os_) *os_ << "Reader1::identify(): " << boolalpha << result << endl; return std::string (result?uri:std::string("")); } virtual void read(const std::string& uri, boost::shared_ptr uriStreamPtr, ProteomeData& result) const { if (os_) *os_ << "Reader1::read()\n"; config.done = true; } virtual const char *getType() const {return "Reader1";} // satisfy inheritance }; class Reader2 : public Reader { public: struct Config { string color; mutable bool done; Config() : color("orange"), done(false) {} }; Config config; virtual std::string identify(const std::string& uri, boost::shared_ptr uriStreamPtr) const { bool result = (uri == "2"); if (os_) *os_ << "Reader2::identify(): " << boolalpha << result << endl; return std::string (result?uri:std::string("")); } virtual void read(const std::string& uri, boost::shared_ptr uriStreamPtr, ProteomeData& result) const { if (os_) *os_ << "Reader2::read()\n"; config.done = true; } const char *getType() const {return "Reader2";} // satisfy inheritance }; void testGet() { if (os_) *os_ << "testGet()\n"; ReaderList readers; readers.push_back(ReaderPtr(new Reader1)); readers.push_back(ReaderPtr(new Reader2)); unit_assert(readers.size() == 2); Reader1* reader1 = readers.get(); unit_assert(reader1); if (os_) *os_ << "reader1 config: " << reader1->config.name << endl; unit_assert(reader1->config.name == "default"); reader1->config.name = "raw"; if (os_) *os_ << "reader1 config: " << reader1->config.name << endl; unit_assert(reader1->config.name == "raw"); Reader2* reader2 = readers.get(); unit_assert(reader2); if (os_) *os_ << "reader2 config: " << reader2->config.color << endl; unit_assert(reader2->config.color == "orange"); reader2->config.color = "purple"; if (os_) *os_ << "reader2 config: " << reader2->config.color << endl; unit_assert(reader2->config.color == "purple"); const ReaderList& const_readers = readers; const Reader2* constReader2 = const_readers.get(); unit_assert(constReader2); if (os_) *os_ << "constReader2 config: " << constReader2->config.color << endl; if (os_) *os_ << endl; } void testAccept() { if (os_) *os_ << "testAccept()\n"; ReaderList readers; readers.push_back(ReaderPtr(new Reader1)); readers.push_back(ReaderPtr(new Reader2)); if (os_) *os_ << "accept 1:\n"; unit_assert(readers.accept("1", shared_ptr())); if (os_) *os_ << "accept 2:\n"; unit_assert(readers.accept("2", shared_ptr())); if (os_) *os_ << "accept 3:\n"; unit_assert(!readers.accept("3", shared_ptr())); if (os_) *os_ << endl; } void testRead() { if (os_) *os_ << "testRead()\n"; ReaderList readers; readers.push_back(ReaderPtr(new Reader1)); readers.push_back(ReaderPtr(new Reader2)); ProteomeData pd; // note: composite pattern with accept/read will cause two calls // to accept(); the alternative is to maintain state between accept() // and read(), which opens possibility for misuse. unit_assert(readers.get()->config.done == false); if (readers.accept("1", shared_ptr())) readers.read("1", shared_ptr(), pd); unit_assert(readers.get()->config.done == true); readers.get()->config.done = false; unit_assert(readers.get()->config.done == false); if (readers.accept("2", shared_ptr())) readers.read("2", shared_ptr(), pd); unit_assert(readers.get()->config.done == false); unit_assert(readers.get()->config.done == true); if (os_) *os_ << endl; } void test() { testGet(); testAccept(); testRead(); } int main(int argc, char* argv[]) { TEST_PROLOG_EX(argc, argv, "_ProteomeData") try { if (argc==2 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/proteome/ProteomeData.hpp0000664000175100017510000000510712664775621022407 0ustar teamcityteamcity00000000000000// // $Id: ProteomeData.hpp 1623 2009-12-17 20:58:35Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PROTEOMEDATA_HPP_ #define _PROTEOMEDATA_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "Peptide.hpp" #include namespace pwiz { namespace proteome { struct PWIZ_API_DECL Protein : public Peptide { Protein(const std::string& id, size_t index, const std::string& description, const std::string& sequence); bool empty() const; std::string id; size_t index; std::string description; }; typedef boost::shared_ptr ProteinPtr; // note: derived container to support dynamic linking on Windows class IndexList : public std::vector {}; class PWIZ_API_DECL ProteinList { public: virtual size_t size() const = 0; virtual ProteinPtr protein(size_t index, bool getSequence = true) const = 0; virtual bool empty() const; virtual size_t find(const std::string& id) const; virtual IndexList findKeyword(const std::string& keyword, bool caseSensitive = true) const; virtual ~ProteinList() {} }; typedef boost::shared_ptr ProteinListPtr; struct PWIZ_API_DECL ProteinListSimple : public ProteinList { std::vector proteins; // ProteinList implementation virtual size_t size() const {return proteins.size();} virtual bool empty() const {return proteins.empty();} virtual ProteinPtr protein(size_t index, bool getSequence = true) const; }; struct PWIZ_API_DECL ProteomeData { std::string id; ProteinListPtr proteinListPtr; ProteomeData() {} virtual ~ProteomeData() {} bool empty() const; private: // no copying ProteomeData(const ProteomeData&); ProteomeData& operator=(const ProteomeData&); }; } // namespace proteome } // namespace pwiz #endif // _PROTEOMEDATA_HPP_ pwiz/pwiz/data/proteome/Reader_FASTA.hpp0000664000175100017510000000402112664775621022135 0ustar teamcityteamcity00000000000000// // $Id: Reader_FASTA.hpp 1623 2009-12-17 20:58:35Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _READER_FASTA_HPP_ #define _READER_FASTA_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "ProteomeData.hpp" #include "Reader.hpp" namespace pwiz { namespace proteome { /// FASTA -> ProteomeData stream serialization class PWIZ_API_DECL Reader_FASTA : public Reader { public: /// Reader_FASTA configuration struct PWIZ_API_DECL Config { /// read with a side-by-side index bool indexed; Config() {} }; /// constructor Reader_FASTA(const Config& config = Config()); const char* getType() const {return "FASTA";} virtual std::string identify(const std::string& uri, boost::shared_ptr uriStreamPtr) const; /// fill in the ProteomeData structure virtual void read(const std::string& uri, boost::shared_ptr uriStreamPtr, ProteomeData& result) const; private: Config config_; Reader_FASTA(Reader_FASTA&); Reader_FASTA& operator=(Reader_FASTA&); }; PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const Reader_FASTA::Config& config); } // namespace proteome } // namespace pwiz #endif // _READER_FASTA_HPP_ pwiz/pwiz/data/proteome/Peptide.cpp0000664000175100017510000005534312664775621021417 0ustar teamcityteamcity00000000000000// // $Id: Peptide.cpp 2901 2011-08-03 20:16:57Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Peptide.hpp" #include "Modification.hpp" #include "AminoAcid.hpp" #include #include "pwiz/utility/misc/Exception.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/Singleton.hpp" namespace pwiz { namespace proteome { using namespace chemistry; using boost::shared_ptr; class Peptide::Impl { public: Impl(const std::string& sequence, ModificationParsing mp, ModificationDelimiter md) : sequence_(new string(sequence)) { parse(mp, md); } Impl(const char* sequence, ModificationParsing mp, ModificationDelimiter md) : sequence_(new string(sequence)) { parse(mp, md); } Impl(string::const_iterator begin, string::const_iterator end, ModificationParsing mp, ModificationDelimiter md) : sequence_(new string(begin, end)) { parse(mp, md); } Impl(const char* begin, const char* end, ModificationParsing mp, ModificationDelimiter md) : sequence_(new string(begin, end)) { parse(mp, md); } Impl(const Impl& other) : sequence_(other.sequence_), mods_(other.mods_ ? new ModificationMap(*other.mods_) : 0), monoMass_(other.monoMass_), avgMass_(other.avgMass_), valid_(other.valid_) { } ~Impl() { } inline const string& sequence() const { return *sequence_; } inline Formula formula(bool modified) const { string& sequence = *sequence_; // an empty or unparsable sequence returns an empty formula if (sequence.empty() || !valid_) return Formula(); Formula formula; ModificationMap::const_iterator modItr; if (mods_.get()) modItr = mods_->begin(); // add N terminus formula and modifications formula[Element::H] += 1; if (mods_.get() && modified && modItr != mods_->end() && modItr->first == ModificationMap::NTerminus()) { const ModificationList& modList = modItr->second; for (size_t i=0, end=modList.size(); i < end; ++i) { const Modification& mod = modList[i]; if (!mod.hasFormula()) throw runtime_error("[Peptide::formula()] peptide formula cannot be generated when any modifications have no formula info"); formula += mod.formula(); } ++modItr; } for (size_t i=0, end=sequence.length(); i < end; ++i) { formula += AminoAcid::Info::record(sequence[i]).residueFormula; // add AA residue formula // add modification formulae if (mods_ && modified && modItr != mods_->end() && modItr->first == (int) i) { const ModificationList& modList = modItr->second; for (size_t i=0, end=modList.size(); i < end; ++i) { const Modification& mod = modList[i]; if (!mod.hasFormula()) throw runtime_error("[Peptide::formula()] peptide formula cannot be generated when any modifications have no formula info"); formula += mod.formula(); } ++modItr; } } // add C terminus formula and modifications formula[Element::O] += 1; formula[Element::H] += 1; if (mods_.get() && modified && modItr != mods_->end() && modItr->first == ModificationMap::CTerminus()) { const ModificationList& modList = modItr->second; for (size_t i=0, end=modList.size(); i < end; ++i) { const Modification& mod = modList[i]; if (!mod.hasFormula()) throw runtime_error("[Peptide::formula()] peptide formula cannot be generated when any modifications have no formula info"); formula += mod.formula(); } ++modItr; } return formula; } inline double monoMass(bool modified) const { return modified && mods_.get() ? monoMass_ + mods_->monoisotopicDeltaMass() : monoMass_; } inline double avgMass(bool modified) const { return modified && mods_.get() ? avgMass_ + mods_->averageDeltaMass() : avgMass_; } inline ModificationMap& modifications() { initMods(); return *mods_; } inline const ModificationMap& modifications() const { static ModificationMap emptyModMap; return emptyModMap; } inline Fragmentation fragmentation(const Peptide& peptide, bool mono, bool mods) const { return Fragmentation(peptide, mono, mods); } private: // since sequence can't be changed after a Peptide is constructed, // the sequence can be shared between copies of the same Peptide shared_ptr sequence_; shared_ptr mods_; double monoMass_; double avgMass_; bool valid_; inline void initMods() { // TODO: use boost::thread::once to make initialization thread safe if (!mods_.get()) mods_.reset(new ModificationMap()); } inline void parse(ModificationParsing mp, ModificationDelimiter md) { string& sequence = *sequence_; valid_ = false; // strip non-AA characters and behave according to the specified parsing style char startDelimiter, endDelimiter; switch (md) { default: case ModificationDelimiter_Parentheses: startDelimiter = '('; endDelimiter = ')'; break; case ModificationDelimiter_Brackets: startDelimiter = '['; endDelimiter = ']'; break; case ModificationDelimiter_Braces: startDelimiter = '{'; endDelimiter = '}'; break; } try { switch (mp) { case ModificationParsing_Off: for (size_t i=0, end=sequence.length(); i < end; ++i) try { AminoAcid::Info::record(sequence[i]); } catch (runtime_error&) { throw runtime_error("[Peptide::Impl::parse()] Invalid amino acid in sequence " + sequence); } break; case ModificationParsing_ByFormula: for (size_t i=0; i < sequence.length(); ++i) { char& c = sequence[i]; if (c == startDelimiter) { for (size_t j=i+1; j < sequence.length(); ++j) if (sequence[j] == endDelimiter) { if (parseModByFormula(sequence, i, j)) break; throw runtime_error("[Peptide::Impl::parse()] Expected a chemical formula for all modifications in sequence " + sequence); } else if (j+1 == sequence.length()) throw runtime_error("[Peptide::Impl::parse()] Modification started but not ended in sequence " + sequence); } } break; case ModificationParsing_ByMass: for (size_t i=0; i < sequence.length(); ++i) { char& c = sequence[i]; if (c == startDelimiter) { for (size_t j=i+1; j < sequence.length(); ++j) if (sequence[j] == endDelimiter) { if (parseModByMass(sequence, i, j)) break; throw runtime_error("[Peptide::Impl::parse()] Expected one or two comma-separated numbers in sequence " + sequence); } else if (j+1 == sequence.length()) throw runtime_error("[Peptide::Impl::parse()] Modification started but not ended in sequence " + sequence); } } break; default: case ModificationParsing_Auto: for (size_t i=0; i < sequence.length(); ++i) { char& c = sequence[i]; if (c == startDelimiter) { for (size_t j=i+1; j < sequence.length(); ++j) if (sequence[j] == endDelimiter) { if (parseModByFormula(sequence, i, j) || parseModByMass(sequence, i, j)) break; throw runtime_error("[Peptide::Impl::parse()] Modification not parseable as either a formula or a mass in sequence " + sequence); } else if (j+1 == sequence.length()) throw runtime_error("[Peptide::Impl::parse()] Modification started but not ended in sequence " + sequence); } } } valid_ = true; Formula unmodifiedFormula = formula(false); monoMass_ = unmodifiedFormula.monoisotopicMass(); avgMass_ = unmodifiedFormula.molecularWeight(); } catch (exception&) { // TODO: log a warning about an unparsable peptide with no mass information monoMass_ = 0; avgMass_ = 0; } } inline bool parseModByFormula(string& sequence_, size_t& i, size_t& j) { string& sequence = sequence_; initMods(); int offset = (i == 0 ? ModificationMap::NTerminus() : (j == sequence.length() ? ModificationMap::CTerminus() : i-1)); try { (*mods_)[offset].push_back(Formula(sequence.substr(i+1, j-i-1))); // exclude delimiters } catch (exception&) { return false; } sequence.erase(i, j-i+1); // erase the mod from the sequence --i; return true; } inline bool parseModByMass(string& sequence_, size_t& i, size_t& j) { string& sequence = sequence_; initMods(); int offset = (i == 0 ? ModificationMap::NTerminus() : (j == sequence.length() ? ModificationMap::CTerminus() : i-1)); try { string massStr = sequence.substr(i+1, j-i-1); // exclude delimiters vector tokens; split(tokens, massStr, bal::is_any_of(",")); if (tokens.size() == 1) (*mods_)[offset].push_back(Modification(lexical_cast(massStr), lexical_cast(massStr))); else if (tokens.size() == 2) (*mods_)[offset].push_back(Modification(lexical_cast(tokens[0]), lexical_cast(tokens[1]))); else return false; } catch (exception&) { return false; } sequence.erase(i, j-i+1); // erase the mod from the sequence --i; return true; } }; PWIZ_API_DECL Peptide::Peptide(const string& sequence, ModificationParsing mp, ModificationDelimiter md) : impl_(new Impl(sequence, mp, md)) {} PWIZ_API_DECL Peptide::Peptide(const char* sequence, ModificationParsing mp, ModificationDelimiter md) : impl_(new Impl(sequence, mp, md)) {} PWIZ_API_DECL Peptide::Peptide(std::string::const_iterator begin, std::string::const_iterator end, ModificationParsing mp, ModificationDelimiter md) : impl_(new Impl(begin, end, mp, md)) {} PWIZ_API_DECL Peptide::Peptide(const char* begin, const char* end, ModificationParsing mp, ModificationDelimiter md) : impl_(new Impl(begin, end, mp, md)) {} PWIZ_API_DECL Peptide::Peptide(const Peptide& other) : impl_(new Impl(*other.impl_)) { } PWIZ_API_DECL Peptide& Peptide::operator=(const Peptide& rhs) { impl_.reset(new Impl(*rhs.impl_)); return *this; } PWIZ_API_DECL Peptide::~Peptide() { } PWIZ_API_DECL const string& Peptide::sequence() const { return impl_->sequence(); } PWIZ_API_DECL Formula Peptide::formula(bool modified) const { return impl_->formula(modified); } PWIZ_API_DECL double Peptide::monoisotopicMass(int charge, bool modified) const { return impl_->monoMass(false) == 0 ? 0 : charge == 0 ? impl_->monoMass(modified) : (impl_->monoMass(modified) + chemistry::Proton * charge) / charge; } PWIZ_API_DECL double Peptide::molecularWeight(int charge, bool modified) const { return impl_->avgMass(false) == 0 ? 0 : charge == 0 ? impl_->avgMass(modified) : (impl_->avgMass(modified) + chemistry::Proton * charge) / charge; } PWIZ_API_DECL ModificationMap& Peptide::modifications() { return impl_->modifications(); } PWIZ_API_DECL const ModificationMap& Peptide::modifications() const { return impl_->modifications(); } PWIZ_API_DECL Fragmentation Peptide::fragmentation(bool monoisotopic, bool modified) const { return impl_->fragmentation(*this, monoisotopic, modified); } PWIZ_API_DECL bool Peptide::operator==(const Peptide& rhs) const { return sequence() == rhs.sequence() && modifications() == rhs.modifications(); } PWIZ_API_DECL bool Peptide::operator<(const Peptide& rhs) const { if (sequence().length() == rhs.sequence().length()) { int cmp = sequence().compare(rhs.sequence()); if (cmp == 0) return modifications() < rhs.modifications(); return cmp < 0; } return sequence().length() < rhs.sequence().length(); } class Fragmentation::Impl { public: Impl(const Peptide& peptide, bool mono, bool modified) : NTerminalDeltaMass(0), CTerminalDeltaMass(0) { StaticData::lease staticData; aMass = (mono ? staticData->aFormula.monoisotopicMass() : staticData->aFormula.molecularWeight()); bMass = (mono ? staticData->bFormula.monoisotopicMass() : staticData->bFormula.molecularWeight()); cMass = (mono ? staticData->cFormula.monoisotopicMass() : staticData->cFormula.molecularWeight()); xMass = (mono ? staticData->xFormula.monoisotopicMass() : staticData->xFormula.molecularWeight()); yMass = (mono ? staticData->yFormula.monoisotopicMass() : staticData->yFormula.molecularWeight()); zMass = (mono ? staticData->zFormula.monoisotopicMass() : staticData->zFormula.molecularWeight()); const string& sequence = peptide.sequence(); maxLength = sequence.length(); const ModificationMap& mods = peptide.modifications(); ModificationMap::const_iterator modItr = mods.begin(); if (modified && modItr != mods.end() && modItr->first == ModificationMap::NTerminus()) { const ModificationList& modList = modItr->second; for (size_t i=0, end=modList.size(); i < end; ++i) { const Modification& mod = modList[i]; NTerminalDeltaMass += (mono ? mod.monoisotopicDeltaMass() : mod.averageDeltaMass()); } ++modItr; } double mass = 0; masses.resize(maxLength, 0); for (size_t i=0, end=maxLength; i < end; ++i) { const Formula& f = AminoAcid::Info::record(sequence[i]).residueFormula; mass += (mono ? f.monoisotopicMass() : f.molecularWeight()); if (modified && modItr != mods.end() && modItr->first == (int) i) { const ModificationList& modList = modItr->second; for (size_t i=0, end=modList.size(); i < end; ++i) { const Modification& mod = modList[i]; mass += (mono ? mod.monoisotopicDeltaMass() : mod.averageDeltaMass()); } ++modItr; } masses[i] = mass; } if (modified && modItr != mods.end() && modItr->first == ModificationMap::CTerminus()) { const ModificationList& modList = modItr->second; for (size_t i=0, end=modList.size(); i < end; ++i) { const Modification& mod = modList[i]; CTerminalDeltaMass += (mono ? mod.monoisotopicDeltaMass() : mod.averageDeltaMass()); } } } Impl(const Impl& other) { } ~Impl() { } inline double a(size_t length, size_t charge) const { return charge == 0 ? NTerminalDeltaMass+f(length)+aMass : (NTerminalDeltaMass+f(length)+aMass+chemistry::Proton*charge) / charge; } inline double b(size_t length, size_t charge) const { return charge == 0 ? NTerminalDeltaMass+f(length)+bMass : (NTerminalDeltaMass+f(length)+bMass+chemistry::Proton*charge) / charge; } inline double c(size_t length, size_t charge) const { return charge == 0 ? NTerminalDeltaMass+f(length)+cMass : (NTerminalDeltaMass+f(length)+cMass+chemistry::Proton*charge) / charge; } inline double x(size_t length, size_t charge) const { return charge == 0 ? CTerminalDeltaMass+masses.back()-f(maxLength-length)+xMass : (CTerminalDeltaMass+masses.back()-f(maxLength-length)+xMass+chemistry::Proton*charge) / charge; } inline double y(size_t length, size_t charge) const { return charge == 0 ? CTerminalDeltaMass+masses.back()-f(maxLength-length)+yMass : (CTerminalDeltaMass+masses.back()-f(maxLength-length)+yMass+chemistry::Proton*charge) / charge; } inline double z(size_t length, size_t charge) const { return charge == 0 ? CTerminalDeltaMass+masses.back()-f(maxLength-length)+zMass : (CTerminalDeltaMass+masses.back()-f(maxLength-length)+zMass+chemistry::Proton*charge) / charge; } inline double zRadical(size_t length, size_t charge) const { return charge == 0 ? CTerminalDeltaMass+masses.back()-f(maxLength-length)+zMass+chemistry::Proton : (CTerminalDeltaMass+masses.back()-f(maxLength-length)+zMass+chemistry::Proton*(charge+1)) / charge; } size_t maxLength; private: vector masses; // N terminal fragment masses inline double f(size_t length) const {return length == 0 ? 0 : masses[length-1];} double NTerminalDeltaMass; double CTerminalDeltaMass; double aMass; double bMass; double cMass; double xMass; double yMass; double zMass; struct StaticData : public boost::singleton { StaticData(boost::restricted) { aFormula = Formula("C-1O-1"); bFormula = Formula(""); // proton only cFormula = Formula("N1H3"); xFormula = Formula("C1O1H-2") + Formula("H2O1"); yFormula = Formula("H2O1"); zFormula = Formula("N-1H-3") + Formula("H2O1"); } chemistry::Formula aFormula; chemistry::Formula bFormula; chemistry::Formula cFormula; chemistry::Formula xFormula; chemistry::Formula yFormula; chemistry::Formula zFormula; }; }; PWIZ_API_DECL Fragmentation::Fragmentation(const Peptide& peptide, bool monoisotopic, bool modified) : impl_(new Impl(peptide, monoisotopic, modified)) { } PWIZ_API_DECL Fragmentation::Fragmentation(const Fragmentation& other) : impl_(new Impl(*other.impl_)) { } PWIZ_API_DECL Fragmentation::~Fragmentation() {} PWIZ_API_DECL double Fragmentation::a(size_t length, size_t charge) const { return impl_->a(length, charge); } PWIZ_API_DECL double Fragmentation::b(size_t length, size_t charge) const { return impl_->b(length, charge); } PWIZ_API_DECL double Fragmentation::c(size_t length, size_t charge) const { if (length == impl_->maxLength) throw runtime_error("[Fragmentation::c()] c for full peptide length is impossible"); return impl_->c(length, charge); } PWIZ_API_DECL double Fragmentation::x(size_t length, size_t charge) const { if (length == impl_->maxLength) throw runtime_error("[Fragmentation::x()] x for full peptide length is impossible"); return impl_->x(length, charge); } PWIZ_API_DECL double Fragmentation::y(size_t length, size_t charge) const { return impl_->y(length, charge); } PWIZ_API_DECL double Fragmentation::z(size_t length, size_t charge) const { return impl_->z(length, charge); } PWIZ_API_DECL double Fragmentation::zRadical(size_t length, size_t charge) const { return impl_->zRadical(length, charge); } } // namespace proteome } // namespace pwiz pwiz/pwiz/analysis/common/WhittakerSmootherTest.cpp0000664000175100017510000000570712664775613024720 0ustar teamcityteamcity00000000000000// // $Id: WhittakerSmootherTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "WhittakerSmoother.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::analysis; ostream* os_ = 0; const double testArrayX[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56 }; const double testArrayY[] = { 1, 15, 29, 20, 10, 40, 1, 50, 3, 40, 3, 25, 23, 90, 1, 15, 29, 20, 10, 40, 1, 50, 3, 40, 3, 25, 23, 90, 1, 15, 29, 20, 10, 40, 1, 50, 3, 40, 3, 25, 23, 90, 1, 15, 29, 20, 10, 40, 1, 50, 3, 40, 3, 25, 23, 90 }; void test() { // test that invalid value exceptions are thrown // lambda too low unit_assert_throws_what(WhittakerSmoother(1), runtime_error, \ "[WhittakerSmoother::ctor()] Invalid value for lamda coefficient; valid range is [2, infinity)"); WhittakerSmoother(100001); // lambda is valid up to numeric limits vector testX(testArrayX, testArrayX+(14*4)); vector testY(testArrayY, testArrayY+(14*4)); if (os_) { *os_ << "Unsmoothed data (" << testY.size() << "):\t"; copy(testY.begin(), testY.end(), ostream_iterator(*os_, "\t")); *os_ << endl; } WhittakerSmoother smoother(10); vector smoothedX, smoothedY; smoother.smooth(testX, testY, smoothedX, smoothedY); if (os_) { *os_ << "Smoothed data (" << smoothedY.size() << "):\t"; copy(smoothedY.begin(), smoothedY.end(), ostream_iterator(*os_, "\t")); *os_ << endl; } // smoothed data should be same size as the unsmoothed data //unit_assert(smoothData.size() == testY.size()); // TODO: add output testing } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/common/SavitzkyGolaySmoother.cpp0000664000175100017510000001624512664775613024735 0ustar teamcityteamcity00000000000000// // $Id: SavitzkyGolaySmoother.cpp 2901 2011-08-03 20:16:57Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SavitzkyGolaySmoother.hpp" #include "ZeroSampleFiller.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/Exception.hpp" #include "pwiz/utility/math/round.hpp" #include #include #include #include "pwiz/utility/misc/Singleton.hpp" namespace pwiz { namespace analysis { using std::min; using std::max; namespace { // we generate the SG coefficients on the fly for a given window size and polynomial order void generateSavitzkyGolayCoefficients(vector& coefficients, int leftWindowSize, int rightWindowSize, int polynomialOrder) { using namespace boost::numeric; int size = leftWindowSize + rightWindowSize + 1; int& order = polynomialOrder; int& left = leftWindowSize; int& right = rightWindowSize; vector& c = coefficients; c.resize(size, 0.0); ublas::matrix a(order+1, order+1); ublas::vector b(order+1, 0.0); b[0] = 1.0; // 0=smooth // set up equations of least-squares fit; // loop derived from "Numerical Recipes in C: The Art of Scientific Computing", §14.8 for (int ipj=0; ipj <= (order << 1); ++ipj) { double sum = ipj ? 0.0 : 1.0; for (int k=1; k <= right; ++k) sum += pow((double)k, (double)ipj); for (int k=1; k <= left; ++k) sum += pow((double)-k, (double)ipj); int mm = min(ipj, 2*order - ipj); for (int imj = -mm; imj <= mm; imj += 2) a((ipj+imj)/2, (ipj-imj)/2) = sum; } ublas::permutation_matrix pm(order+1); ublas::lu_factorize(a, pm); ublas::lu_substitute(a, pm, b); // another loop derived from Numerical Recipes for (int k = -left; k <= right; ++k) { double sum = b[0]; double fac = 1.0; for (int mm=0; mm < order; ++mm) sum += b[mm+1] * (fac *= k); c[k+left]=sum; } } /// singleton that caches the SG coefficients; /// access is constant-time after the first time class CoefficientCache : public boost::singleton { public: CoefficientCache(boost::restricted) { } /// If the coefficients corresponding to the requested order and width /// have not been cached, this calculates them. /// Returns the cached coefficients vector. const vector& coefficients(int order, int width) const { size_t orderIndex = order-2; // order 2 (quadratic) is index 0 size_t widthIndex = (width-3)/2; // width 3 is index 0, width 5 is index 1, etc. if (cache_.size() <= orderIndex) cache_.resize(orderIndex+1); if (cache_[orderIndex].size() <= widthIndex) cache_[orderIndex].resize(widthIndex+1); if (cache_[orderIndex][widthIndex].empty()) generateSavitzkyGolayCoefficients(cache_[orderIndex][widthIndex], (width-1)/2, (width-1)/2, order); return cache_[orderIndex][widthIndex]; } private: // cache_[order][width] = coefficients mutable vector< vector< vector > > cache_; }; } // namespace struct SavitzkyGolaySmoother::Impl { Impl(int order, int window) : order_(order), window_(window) { } ~Impl() {} int order_; int window_; }; PWIZ_API_DECL SavitzkyGolaySmoother::SavitzkyGolaySmoother(int polynomialOrder, int windowSize) : impl_(new Impl(polynomialOrder, windowSize)) { if (polynomialOrder < 2 || polynomialOrder > 20) throw runtime_error("[SavitzkyGolaySmoother::ctor()] Invalid value for polynomial order: valid range is [2, 20]"); if (windowSize < 5 || (windowSize % 2) == 0) throw runtime_error("[SavitzkyGolaySmoother::ctor()] Invalid value for window size: value must be odd and in range [5, infinity)"); if (polynomialOrder > windowSize) throw runtime_error("[SavitzkyGolaySmoother::ctor()] Invalid values for polynomial order and window size: window size must be greater than polynomial order."); } PWIZ_API_DECL SavitzkyGolaySmoother::~SavitzkyGolaySmoother() { } PWIZ_API_DECL void SavitzkyGolaySmoother::smooth_copy(vector& x, vector& y) { smooth(x, y, x, y); } PWIZ_API_DECL void SavitzkyGolaySmoother::smooth(const std::vector& x, const std::vector& y, std::vector& xSmoothed, std::vector& ySmoothed) { if (x.size() != y.size()) throw runtime_error("[SavitzkyGolaySmoother::smooth()] x and y arrays must be the same size"); vector::const_iterator start; // the Gram polynomial coefficients to use in the SG algorithm; // we only use half of them because our window is symmetric const vector& c = CoefficientCache::instance->coefficients(impl_->order_, impl_->window_); // the size of the window in either direction size_t flank = size_t(impl_->window_-1) / 2; // fill in missing samples based on window size // note: we don't need all the missing samples because a window full of zeros // will always smooth to a 0, regardless of the X values involved vector yCopy; ZeroSampleFiller::fill(x, y, xSmoothed, yCopy, flank+1); // calculate the smoothed y values ySmoothed.reserve(yCopy.size()); ySmoothed.insert(ySmoothed.end(), yCopy.begin(), yCopy.begin()+flank); for (size_t i=flank, end=yCopy.size()-flank; i < end; ++i) { // start the smoothed y value with the current point double smoothY = c[flank] * yCopy[i]; for (size_t offset=1; offset <= flank; ++offset) { smoothY += c[flank-offset] * yCopy[i-offset]; smoothY += c[flank-offset] * yCopy[i+offset]; } ySmoothed.push_back(max(0.0, smoothY)); } ySmoothed.insert(ySmoothed.end(), yCopy.begin(), yCopy.begin()+flank); /*ofstream xpoints("xpoints.txt"), ypoints("ypoints.txt"); xpoints.precision(15); ypoints.precision(15); for (size_t i=0; i < ySmoothed.size(); ++i) { xpoints << xSmoothed[i] << " "; ypoints << ySmoothed[i] << " "; }*/ } } // namespace analysis } // namespace msdata pwiz/pwiz/analysis/common/LocalMaximumPeakDetectorTest.cpp0000664000175100017510000000642012664775613026111 0ustar teamcityteamcity00000000000000// // $Id: LocalMaximumPeakDetectorTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "LocalMaximumPeakDetector.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::analysis; ostream* os_ = 0; struct TestData { size_t windowSize; const char* xRaw; const char* yRaw; const char* xPeakValues; const char* yPeakValues; }; const TestData testData[] = { { 3, "1 2 3 4 5 6 7 8 9", "0 1 0 1 2 3 0 0 4", "2 6 9", "1 3 4" }, { 5, "1 2 3 4 5 6 7 8 9", "0 1 0 1 2 3 0 0 4", "2 6 9", "1 3 4" }, { 7, "1 2 3 4 5 6 7 8 9", "0 1 0 1 2 3 0 0 4", "9", "4" } }; const size_t testDataSize = sizeof(testData) / sizeof(TestData); vector parseDoubleArray(const string& doubleArray) { vector doubleVector; vector tokens; bal::split(tokens, doubleArray, bal::is_space(), bal::token_compress_on); if (!tokens.empty() && !tokens[0].empty()) for (size_t i=0; i < tokens.size(); ++i) doubleVector.push_back(lexical_cast(tokens[i])); return doubleVector; } void test() { for (size_t i=0; i < testDataSize; ++i) { const TestData& data = testData[i]; vector xRaw = parseDoubleArray(data.xRaw); vector yRaw = parseDoubleArray(data.yRaw); vector target_xPeakValues = parseDoubleArray(data.xPeakValues); vector target_yPeakValues = parseDoubleArray(data.yPeakValues); // sanity checks unit_assert(xRaw.size() == yRaw.size()); unit_assert(target_xPeakValues.size() == target_yPeakValues.size()); LocalMaximumPeakDetector peakDetector(data.windowSize); vector xPeakValues, yPeakValues; peakDetector.detect(xRaw, yRaw, xPeakValues, yPeakValues); unit_assert(xPeakValues.size() == target_xPeakValues.size()); for (size_t j=0; j < xPeakValues.size(); ++j) { unit_assert_equal(xPeakValues[j], target_xPeakValues[j], 1e-5); unit_assert_equal(yPeakValues[j], target_yPeakValues[j], 1e-5); } } } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/common/CwtPeakDetector.hpp0000664000175100017510000000560312664775613023425 0ustar teamcityteamcity00000000000000// // $Id: CwtPeakDetector.hpp 6389 2014-06-13 19:46:19Z frenchwr $ // // // Original author: William French vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _CWTPEAKDETECTOR_HPP_ #define _CWTPEAKDETECTOR_HPP_ // custom type for storing ridge line info typedef struct { int Col; int Row; } ridgeLine; #include "PeakDetector.hpp" namespace pwiz { namespace analysis { struct PWIZ_API_DECL CwtPeakDetector : public PeakDetector { CwtPeakDetector(double minSnr, int fixedPeaksKeep, double mzTol ); virtual void detect(const std::vector& x, const std::vector& y, std::vector& xPeakValues, std::vector& yPeakValues, std::vector* peaks = NULL); void getScales( const std::vector &, const std::vector &, std::vector > > &, std::vector &) const; void calcCorrelation( const std::vector &, const std::vector &, const std::vector > > &, const std::vector &, std::vector < std::vector > &) const; void getPeakLines(const std::vector < std::vector > &, const std::vector &, std::vector &, std::vector &) const; void refinePeaks( const std::vector &, const std::vector &, const std::vector &, const std::vector &, std::vector &, std::vector &, std::vector &) const; private: // parameters double minSnr_; int fixedPeaksKeep_; double mzTol_; int nScales; std::vector scalings; // how to scale the wavelet widths, unchanged once it's initialized }; } // namespace analysis } // namespace pwiz // Helper functions used by detect. The client does not need to see these. void ricker2d(const std::vector &, const int, const int, const int, const double, const double, const double, std::vector &); int getColLowBound(const std::vector &,const double); int getColHighBound(const std::vector &,const double); double scoreAtPercentile( const double, const std::vector &, const int ); double convertColToMZ( const std::vector &, const int ); #endif // _CWTPEAKDETECTOR_HPP_ pwiz/pwiz/analysis/common/LocalMaximumPeakDetector.hpp0000664000175100017510000000306512664775613025260 0ustar teamcityteamcity00000000000000// // $Id: LocalMaximumPeakDetector.hpp 1191 2009-08-14 19:33:05Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SIMPLEPEAKDETECTOR_HPP_ #define _SIMPLEPEAKDETECTOR_HPP_ #include "PeakDetector.hpp" namespace pwiz { namespace analysis { struct PWIZ_API_DECL LocalMaximumPeakDetector : public PeakDetector { LocalMaximumPeakDetector(size_t windowSize); /// finds all local maxima, i.e. any point that has a greater y value than both /// of its neighboring points; /// note: the peaks array, if non-NULL, only provides x and y values virtual void detect(const std::vector& x, const std::vector& y, std::vector& xPeakValues, std::vector& yPeakValues, std::vector* peaks = NULL); private: size_t window_; }; } // namespace analysis } // namespace pwiz #endif // _SIMPLEPEAKDETECTOR_HPP_ pwiz/pwiz/analysis/common/PeakDetector.hpp0000664000175100017510000000365512664775613022754 0ustar teamcityteamcity00000000000000// // $Id: PeakDetector.hpp 1191 2009-08-14 19:33:05Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PEAKDETECTOR_HPP_ #define _PEAKDETECTOR_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "boost/shared_ptr.hpp" #include namespace pwiz { namespace analysis { /// represents some generic metadata about a peak detected in a signal struct PWIZ_API_DECL Peak { double x; /// x value of a signal peak (or centroid) double y; /// y value of a signal peak (or centroid), aka intensity/abundance/amplitude double start; // x value where the peak's profile starts double stop; // x value where the peak's profile stops double area; // area under the profile between start and stop }; struct PWIZ_API_DECL PeakDetector { /// find peaks in the signal profile described by the x and y vectors virtual void detect(const std::vector& x, const std::vector& y, std::vector& xPeakValues, std::vector& yPeakValues, std::vector* peaks = NULL) = 0; virtual ~PeakDetector() {} }; typedef boost::shared_ptr PeakDetectorPtr; } // namespace analysis } // namespace pwiz #endif // _PEAKDETECTOR_HPP_ pwiz/pwiz/analysis/common/CwtPeakDetectorTest.cpp0000664000175100017510000015200712664775613024261 0ustar teamcityteamcity00000000000000// // $Id: CwtPeakDetectorTest.cpp 6389 2014-06-13 19:46:19Z frenchwr $ // // // Original author: William French vanderbilt.edu> // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "CwtPeakDetector.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::analysis; ostream* os_ = 0; struct TestData { const char* xRaw; const char* yRaw; const char* xPeakValues; const char* yPeakValues; }; const TestData testData[] = { // Thermo Q-Exactive Jurkat Cell Lysate data { "351.166 351.167 351.169 351.17 351.172 351.173 351.175 351.177 351.178 351.18 351.181 351.183 351.184 351.186 351.191 351.192 351.194 351.195 351.197 351.198 351.2 351.202 351.203 351.205 351.206 351.208 351.209 351.211 351.212 351.214 351.216 351.217 351.219 351.22 351.222 351.223 351.647 351.648 351.65 351.652 351.653 351.655 351.656 351.658 351.659 351.661 351.662 351.664 351.666 351.667 351.669 351.675 351.677 351.678 351.68 351.681 351.683 351.684 351.686 351.687 351.689 351.691 351.692 351.694 351.695 351.825 351.827 351.828 351.83 351.831 351.833 351.835 351.836 351.838 351.839 351.841 351.844 351.846 351.847 351.849 351.996 351.997 351.999 352.001 352.002 352.004 352.005 352.007 352.008 352.01 352.012 352.013 352.015 352.016 352.018 352.019 352.019 352.021 352.022 352.024 352.066 352.068 352.069 352.071 352.073 352.074 352.076 352.077 352.079 352.08 352.082 352.084 352.085 352.087 352.088 352.09 352.091 352.093 352.095 352.096 352.098 352.099 352.101 352.102 352.104 352.106 352.107 352.109 352.111 352.113 352.114 352.116 352.117 352.119 352.12 352.122 352.124 352.125 352.127 352.128 352.129 352.131 352.132 352.136 352.137 352.139 352.14 352.145 352.146 352.148 352.15 352.151 352.153 352.154 352.156 352.157 352.159 352.16 352.162 352.163 352.165 352.166 352.168 352.169 352.171 352.171 352.173 352.174 352.176 352.177 352.179 352.181 352.182 352.184 352.185 352.187 352.188 352.19 352.192 352.193 352.195 352.196 352.198 352.199 352.201 352.203 352.204 352.206 352.207 352.209 352.211 352.212 352.214 352.215 352.217 352.218 352.22 352.222 352.223 352.225 352.226 352.228 352.229 352.231 352.233 352.234 352.236 352.237 352.239 352.24 352.242 352.243 352.245 352.247 352.248 352.25 352.251 352.253 352.254 352.256 352.258 352.259 352.261 352.262 352.264 352.265 352.267 352.269 352.27 352.272 352.273 352.275 352.276 352.278 352.28 352.281 352.283 352.284 352.286 352.287 352.289 352.291 352.292 352.294 352.295 352.297 352.298 352.3 352.301 352.303 352.305 352.325 352.327 352.328 352.33 352.331 352.333 352.334 352.336 352.338 352.339 352.341 352.342 352.344 352.345 352.347 352.349 352.35 352.352 352.353 352.355 352.356 352.358 352.36 352.361 352.363 352.364 352.366 352.367 352.369 352.371 352.372 352.374 352.375 352.377 352.378 352.38 352.382 352.383 352.49 352.491 352.493 352.494 352.496 352.498 352.499 352.501 352.502 352.504 352.505 352.507 352.509 352.51 352.512 352.513 352.515 352.516 352.518 352.52 352.521 352.523 352.524 352.526 352.527 352.529 352.531 352.532 352.534 352.535 352.537 352.538 352.54 352.542 352.543 352.545 352.546 352.548 352.549 352.551 352.553 352.554 352.556 352.557 352.568 352.57 352.571 352.573 352.575 352.576 352.578 352.579 352.581 352.582 352.584 352.586 352.587 352.589 352.59 352.592 352.593 352.595 352.597 352.598 352.6 352.601 352.603 352.604 352.606 352.608 352.609 352.611 352.612 352.614 352.615 352.617 352.619 352.62 352.622 352.623 352.625 352.628 352.629 352.631 352.633 352.659 352.661 352.662 352.664 352.666 352.667 352.669 352.67 352.672 352.672 352.674 352.675 352.677 352.678 352.68 352.681 352.683 352.684 352.686 352.688 352.689 352.691 352.692 352.694 352.695 352.697 352.699 352.699 352.7 352.702 352.703 352.705 352.706 352.708 352.71 352.711 352.713 352.714 352.717 352.719 352.721 352.722 352.724 352.725 352.727 352.728 352.73 352.732 352.733 352.735 352.736 352.738 352.739 352.743 352.744 352.746 352.747 352.749 352.75 352.752 352.754 352.755 352.757 352.758 352.76 352.761 352.763 352.765 352.766 352.768 352.769 352.771 352.772 352.774 352.776 352.777 352.779 352.78 352.782 352.783 352.785 352.787 352.788 352.79 352.791 352.793 352.794 352.796 352.798 352.799 352.801 352.838 352.84 352.842 352.843 352.845 352.846 352.848 352.85 352.851 352.853 352.854 352.856 352.857 352.859 352.861 352.862 352.864 352.865 352.867 352.868 352.87 352.872 352.873 352.875 352.876 352.878 352.879 352.881 352.883 353.002 353.004 353.005 353.007 353.008 353.01 353.011 353.013 353.015 353.016 353.018 353.019 353.021 353.022 353.173 353.175 353.176 353.178 353.18 353.181 353.183 353.184 353.186 353.187 353.189 353.191 353.192 353.194 353.195 353.197 353.199 353.2 353.201 353.203 353.205 353.206 353.51 353.512 353.513 353.515 353.516 353.518 353.52 353.521 353.523 353.524 353.526 353.528 353.529 353.531 353.533 353.534 353.536 353.664 353.665 353.667 353.668 353.67 353.672 353.673 353.675 353.676 353.678 353.679 353.681 353.683 353.684 353.686 353.687 353.689 353.69 353.692 353.694 353.695 353.697 353.698 353.7 353.701 353.703 353.704 353.706 353.845 353.846 353.848 353.849 353.851 353.853 353.854 353.856 353.857 353.859 353.861 353.862 353.864 353.866 353.867 353.869 353.87 354.167 354.169 354.171 354.172 354.174 354.175 354.177 354.178 354.18 354.182 354.183 354.185 354.186 354.188 354.19 354.191 354.193 354.194 354.196 354.197 354.199 354.201 354.202 354.204 354.205 354.207 354.209 354.21 354.212 354.213 354.215 354.216 354.218 354.22 354.221 354.671 354.672 354.674 354.675 354.677 354.679 354.68 354.682 354.683 354.685 354.687 354.688 354.69", "0 0 0 0 8120.02 23237.3 38803 41467.4 30047.5 15008.8 0 0 0 0 0 0 0 0 15759.8 25237.7 29474.8 23502.4 12698.3 0 0 0 12610.6 26647.5 36362.6 32099.8 18001.4 6000.35 0 0 0 0 0 0 0 0 4528.55 17484.2 35392.4 42725.1 34221.6 18680.2 6308.08 0 0 0 0 0 0 0 0 10422.8 19134.8 24311.8 24054.1 17420.9 8268.2 0 0 0 0 0 0 0 0 7107.35 22527.8 44300.4 85892.3 67082.5 32158.8 0 0 0 0 0 0 0 0 0 15810.4 33994.3 55078.3 85641 151659 334684 554916 732310 590781 331957 70691.2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11789.5 64744.7 121807 193186 243317 202497 115645 24317.1 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 960573 174916 0 136374 993586 1.8441e+006 1.92991e+006 3.03495e+006 1.31047e+007 4.65182e+007 9.16249e+007 1.37986e+008 1.33314e+008 8.60013e+007 4.19191e+007 1.32598e+007 4.04162e+006 1.41205e+006 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 7754.61 67937.3 99051.1 150531 216079 244565 159661 63595.9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14452.5 29005.7 35286 30588.2 21185 11831.1 0 0 0 0 0 0 0 0 1366.36 91701 179496 288109 434197 517406 359182 151024 0 0 0 63243.7 160312 171636 95034 5596.75 0 0 0 0 0 0 0 0 8179.66 16440.3 27712.5 38477.4 47929.2 31342.5 26019.9 59155.3 135782 216038 241642 167755 85729.4 12481.1 0 0 0 0 0 0 0 14483.3 49421 110574 180946 217687 173260 105397 43313.1 0 0 0 21248.7 35694.3 19325.8 5368.26 0 0 0 0 0 0 0 0 10690.2 22788 27664.4 19704 7061.11 0 0 0 6988.12 25745.4 73160.7 83506.9 50202.2 21890.8 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 1.65038e+006 6.93915e+006 2.13171e+007 3.68888e+007 4.91278e+007 4.01078e+007 2.41707e+007 9.51399e+006 2.85991e+006 620248 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 8530.51 25618 66293.5 86071.8 68466.5 37744.3 8736.74 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15988 31223.3 38828.8 30780.3 14679.4 0 0 4020.74 20084.3 96902 143334 136421 67184 3937.96 0 0 0 29215.9 58376.9 28367.3 3875.2 0 0 0 0 0 0 0 0 13779.3 28950.1 38985.4 34583.4 19994.8 7077.35 0 0 0 0 0 0 0 0 649.605 42703.1 102863 675627 2.62112e+006 5.99173e+006 9.6241e+006 1.07436e+007 7.58946e+006 4.21331e+006 1.46704e+006 480636 159069 0 0 0 0 0 0 0 0 0 6856.14 39156.2 104291 175803 203283 147265 86650.4 35519.8 10675.3 0 0 0 0 0 0 0 0 12418.6 17400.1 37178.9 107531 256363 441343 490807 339063 148145 48226.6 116906 383579 861486 1.39413e+006 1.63679e+006 1.2132e+006 707134 261800 78553.8 10524.9 0 0 0 0 0 0 0 0 785.907 25861.9 84745.9 148329 189330 150522 91819.8 38901.2 7876.87 0 0 0 0 0 0 0 0 11175.5 43705.4 97099.8 164607 190669 138639 72177.2 20538.4 17121.5 63480.2 175339 293057 374461 300567 183447 78540.5 20050.9 0 0 0 0 3744.07 17056.1 29686.2 29232.4 17226.6 5500.15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "351.177 351.658 351.836 352.013 352.091 352.188 352.361 352.512 352.535 352.592 352.689 353.191 353.679 353.692 354.193", "41467.4 42725.1 85892.3 732310 243317 1.37986e+008 517406 241642 217687 83506.9 4.91278e+007 1.07436e+007 490807 1.63679e+006 374461"}, { "346.657 346.658 346.66 346.661 346.663 346.664 346.666 346.667 346.669 346.67 346.672 346.673 346.675 346.677 346.678 346.68 346.681 346.683 346.684 346.686 346.687 346.689 346.69 346.692 346.693 347.172 347.173 347.175 347.176 347.178 347.179 347.181 347.182 347.184 347.185 347.187 347.189 347.19 347.192 347.193 347.195 347.196 347.198 347.199 347.201 347.202 347.204 347.205 347.207 347.209 347.21 347.212 347.213 347.215 347.216 347.218 347.219 347.496 347.497 347.499 347.5 347.502 347.503 347.505 347.506 347.508 347.509 347.511 347.514 347.515 347.517 347.519 347.638 347.64 347.641 347.643 347.645 347.646 347.648 347.649 347.651 347.652 347.654 347.655 347.657 347.657 347.659 347.66 347.662 347.663 347.665 347.666 347.668 347.669 347.671 347.672 347.674 347.676 347.677 347.679 347.68 347.682 347.683 347.685 347.686 347.688 347.689 347.691 347.692 347.694 347.695 347.697 347.698 347.7 347.701 347.703 347.704 347.706 347.707 347.709 347.71 347.712 347.714 347.715 347.717 347.718 347.889 347.891 347.892 347.894 347.895 347.897 347.898 347.9 347.901 347.903 347.905 347.906 347.908 347.909 347.911 348.166 348.168 348.17 348.171 348.173 348.174 348.176 348.177 348.179 348.18 348.182 348.183 348.185 348.186 348.188 348.19 348.191 348.192 348.194 348.196 348.205 348.206 348.208 348.209 348.211 348.213 348.214 348.216 348.217 348.219 348.22 348.222 348.223 348.225 348.226 348.228 348.229 348.231 348.404 348.405 348.407 348.408 348.41 348.411 348.413 348.414 348.416 348.418 348.419 348.421 348.422 348.424 348.425 348.427 348.428 348.546 348.547 348.549 348.55 348.552 348.553 348.555 348.557 348.558 348.56 348.562 348.563 348.565 348.605 348.606 348.608 348.609 348.611 348.613 348.614 348.616 348.617 348.619 348.62 348.622 348.623 348.625 348.626 348.628 348.668 348.67 348.671 348.673 348.674 348.676 348.677 348.679 348.68 348.682 348.683 348.685 348.687 348.688 348.69 348.691 348.692 348.694 348.695 348.711 348.712 348.714 348.716 348.717 348.719 348.72 348.722 348.723 348.725 348.726 348.728 348.729 348.731 348.733 348.807 348.808 348.81 348.811 348.813 348.814 348.816 348.818 348.819 348.821 348.822 348.824 348.825 348.881 348.882 348.884 348.886 348.887 348.889 348.89 348.892 348.893 348.895 348.896 348.898 348.899 348.901 349.158 349.159 349.161 349.162 349.164 349.165 349.167 349.169 349.17 349.172 349.173 349.175 349.176 349.178 349.179 349.181 349.182 349.184 349.186 349.187 349.189 349.19 349.192 349.193 349.213 349.215 349.217 349.218 349.22 349.221 349.223 349.224 349.226 349.227 349.229 349.23 349.232 349.667 349.669 349.67 349.672 349.674 349.675 349.677 349.678 349.68 349.681 349.683 349.684 349.686 349.688 349.689 349.691 349.84 349.841 349.843 349.844 349.846 349.847 349.849 349.85 349.852 349.854 349.855 349.857 349.858 349.86 349.919 349.92 349.922 349.923 349.925 349.926 349.928 349.93 349.931 349.933 349.934 349.936 349.937 349.939 349.94 349.942 350.15 350.152 350.153 350.155 350.156 350.158 350.159 350.161 350.163 350.164 350.166 350.167 350.169 350.17", "0 0 0 0 10961 19736 23900.7 17191.3 5730.37 0 0 0 0 3925.75 20286.6 75526.5 108467 91495.9 53060.8 18969.6 10484.3 0 0 0 0 0 0 0 0 9116.28 24824.4 60098.4 85781.8 63491.9 25226.3 7365.68 0 0 0 0 0 0 0 40008.4 163375 431393 722337 905032 693399 404135 131466 30054.5 3886.23 0 0 0 0 0 0 0 0 11650.6 20274.6 28407.2 33232.8 29180.1 16913 6058.11 0 0 0 0 0 0 0 0 7175.64 29635.3 75098.1 140327 201812 157294 79670.4 19492.5 11838 0 0 0 0 0 0 0 0 27246.2 110637 321655 1.10743e+006 3.39252e+006 6.24381e+006 8.97551e+006 8.13047e+006 5.06563e+006 2.2355e+006 589552 96055 22711.6 0 0 0 0 0 0 0 0 79486.7 135314 217641 303927 274002 158762 50415.3 5843.65 0 0 0 0 0 0 0 0 6378.47 16452 30734.8 41688.5 39587.3 24186.9 7521.96 0 0 0 0 0 0 0 0 0 137228 520728 1.47305e+006 2.54686e+006 3.43152e+006 2.89775e+006 1.7807e+006 738850 205995 25882.7 0 0 0 0 0 0 0 0 0 15056.6 18107 61576.1 140634 220529 240301 167534 90248.8 19140.2 0 0 0 0 0 0 0 0 0 3490.77 28803.8 92736.3 155649 191499 148143 86985.5 27287.5 8427.73 0 0 0 0 0 0 0 0 5484.38 18207.8 28203.5 25960.7 14556.8 0 0 0 0 0 0 0 0 13145.8 49422.9 91213.8 138111 143102 93875.7 45495.6 11453.6 0 0 0 0 0 0 0 0 0 20773.2 102388 290060 494374 663565 568254 350979 140934 25125.8 0 0 0 0 0 0 0 0 0 5373.93 18669 38749.3 52802.1 49014.6 31515.1 14239.2 0 0 0 0 0 0 0 0 12293.6 20885.9 22571.3 18410.3 13445.9 0 0 0 0 0 0 0 0 9753.48 19434 24437.9 23820.9 20193.2 13995 0 0 0 0 0 0 0 0 5937.7 17324.7 27357.2 27101.8 18934.3 11837.1 0 0 8061.73 16699.2 35868.9 65709.6 93781.2 48854.5 32311.7 13667 0 0 0 0 0 0 0 0 13770.8 25438.2 31622.3 26281.8 14405.3 0 0 0 0 0 0 0 0 11981.8 39357.6 75818.3 112272 113305 74893.5 33392.6 5898.17 0 0 0 0 0 0 0 0 6927.62 21253.5 33414.9 32682.9 21266.5 9401.1 0 0 0 0 0 0 0 0 7396.2 22461.8 57287 89930.3 82061.1 35789.6 16420.5 5355.56 0 0 0 0 0 0 0 0 15290.6 35150 47154.2 39139.1 19452.8 4374.33 0 0 0 0", "347.205 347.679 347.706 348.18 348.219 348.416 348.617 348.682 349.182 349.68 349.93 350.159", "905032 8.97551e+006 303927 3.43152e+006 240301 191499 143102 663565 93781.2 113305 89930.3 47154.2"}, { "331.417 331.418 331.42 331.421 331.422 331.424 331.425 331.427 331.428 331.43 331.431 331.432 331.434 331.435 331.498 331.5 331.501 331.503 331.504 331.505 331.507 331.508 331.51 331.511 331.513 331.514 331.515 331.527 331.528 331.53 331.531 331.533 331.534 331.536 331.537 331.538 331.54 331.541 331.543 331.544 331.546 331.657 331.659 331.66 331.662 331.663 331.664 331.666 331.667 331.669 331.67 331.672 331.673 331.674 331.676 331.679 331.68 331.682 331.683 331.684 331.686 331.687 331.689 331.69 331.692 331.693 331.695 331.696 331.697 331.699 331.7 331.702 331.703 331.705 331.706 331.707 331.709 332.168 332.169 332.171 332.172 332.174 332.175 332.176 332.178 332.179 332.181 332.182 332.184 332.185 332.187 332.188 332.189 332.191 332.192 332.194 332.195 332.197 332.198 332.199 332.201 332.202 332.204 332.205 332.207 332.208 332.209 332.211 332.212 332.214 332.215 332.217 332.218 332.22 332.221 332.488 332.49 332.491 332.493 332.494 332.495 332.497 332.498 332.5 332.501 332.503 332.504 332.506 332.507 332.508 332.51 332.511 332.513 332.514 332.516 332.517 332.529 332.53 332.531 332.533 332.534 332.536 332.537 332.539 332.54 332.541 332.543 332.544 332.546 332.547 332.644 332.645 332.647 332.648 332.649 332.651 332.652 332.654 332.655 332.657 332.658 332.66 332.661 332.662 332.664 332.665 332.667 332.668 332.67 332.671 332.672 332.674 332.675 332.677 332.678 332.68 332.681 332.682 332.684 332.685 332.687 332.688 332.69 332.691 332.693 333.148 333.149 333.151 333.152 333.154 333.155 333.157 333.158 333.16 333.161 333.162 333.164 333.165 333.167 333.168 333.17 333.171 333.172 333.174 333.175 333.177 333.178 333.18 333.181 333.182 333.184 333.185 333.187 333.188 333.19 333.191 333.193 333.194 333.195 333.197 333.198 333.2 333.201 333.203 333.204 333.206 333.207 333.208 333.21 333.426 333.428 333.429 333.431 333.432 333.434 333.435 333.436 333.438 333.439 333.441 333.442 333.444 333.445 333.447 333.496 333.497 333.499 333.5 333.501 333.503 333.504 333.506 333.507 333.509 333.51 333.512 333.513 333.65 333.652 333.653 333.655 333.656 333.658 333.659 333.66 333.662 333.663 333.665 333.666 333.668 333.669 333.671 333.672 333.673 333.675 333.676 333.678 333.679 333.681 333.682 333.684 333.685 333.686 333.688 333.689 333.691 333.692 333.694 333.695 333.697 333.698 333.7 333.701 333.702 333.825 333.827 333.828 333.83 333.831 333.833 333.834 333.836 333.837 333.838 333.84 333.841 333.843 333.844 333.846 333.847 333.848 333.85 333.908 333.909 333.911 333.912 333.914 333.915 333.916 333.918 333.919 333.921 333.922 333.924 333.925 333.927 333.928 333.929 333.931 333.932 333.934 333.935 333.937 333.938 334.022 334.024 334.025 334.026 334.028 334.029 334.031 334.032 334.034 334.035 334.037 334.038 334.039 334.041 334.042 334.044 334.096 334.097 334.099 334.1 334.102 334.103 334.105 334.106 334.108 334.109 334.11 334.112 334.113 334.145 334.147 334.148 334.15 334.151 334.152 334.154 334.155 334.157 334.158 334.16 334.161 334.163 334.164 334.165 334.167 334.169 334.17 334.172 334.173 334.175 334.176 334.178 334.179 334.18 334.181 334.183 334.184 334.193 334.194 334.196 334.197 334.199 334.2 334.202 334.203 334.205 334.206 334.208 334.209 334.21 334.212 334.416 334.418 334.419 334.421 334.422 334.424 334.425 334.426 334.428 334.429 334.431 334.432 334.434 334.435 334.437 334.438 334.496 334.498 334.499 334.5 334.502 334.503 334.505 334.506 334.508 334.509 334.511 334.512 334.513 334.515 334.516 334.518 334.519 334.521 334.522 334.524 334.525 334.759 334.76 334.762 334.763 334.765 334.766 334.768 334.769 334.77 334.772 334.773 334.775 334.776 335.137 335.138 335.14 335.141 335.143 335.144 335.146 335.147 335.149 335.15 335.151 335.153 335.154 335.156 335.157 335.159", "0 0 0 0 9061.45 22475.3 35268.8 36668.2 25438.2 11599.9 0 0 0 0 0 0 0 0 9684.82 23491.2 29876.5 22922.6 10094.9 0 0 0 0 0 0 0 0 9180.43 24616.9 35830.4 33489.6 22024.2 10769.9 0 0 0 0 0 0 0 0 12611.7 26630.1 38491 37169.5 22907.8 8361.95 0 0 0 0 0 0 0 0 6017.46 16451.4 33026.8 45513 41936.2 24121.9 31508.3 96500.6 185384 268754 251719 157307 66427.3 7982.26 0 0 0 0 0 0 0 0 5301.39 16999.7 30492.7 34702 26142 13513 0 0 12371.7 21439.5 27209.5 22933.4 11143 0 0 0 12152.6 21551.1 29616.9 29137 19870.6 9552.69 0 0 9583.44 22087.5 33917 33539.6 20342.9 6326.05 0 0 0 0 0 0 0 0 16012.6 18628.8 20134.9 20056.2 14757.2 0 0 11785.8 17414.9 18161.4 17906.6 18225.8 14577.7 0 0 0 0 0 0 0 0 16134.3 28511.5 37712.6 37489.8 25852.6 10667.3 0 0 0 0 0 0 0 0 0 19508.7 82443.3 188324 619945 1.9855e+006 4.06909e+006 6.30896e+006 6.52736e+006 4.33407e+006 2.20647e+006 626399 125657 31194.3 1467.24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 47966.7 212774 645467 1.35099e+006 2.12093e+006 2.31954e+006 1.61098e+006 869432 252399 24052.1 0 0 0 0 0 0 0 9829.23 47044.5 132065 260114 387895 434599 325228 193752 69077.4 1391.99 0 0 0 8567.48 16858.3 23593.1 19598.4 7774.21 0 0 0 0 0 0 0 0 15543.2 30067.6 41837.8 46424.1 40943.3 26134.3 10412 0 0 0 0 0 0 0 0 14687.1 24819.6 25448.2 18512.5 10335.4 0 0 0 0 0 0 0 0 5301.43 51854.2 139870 260759 390680 429501 308773 167807 48458.4 5679.48 26536.5 134058 275259 435874 415263 258480 120893 32803.5 21268.6 46093.2 77285.9 92951.2 63307.6 14315 6965.15 18630.5 30464.6 27335.3 13797.5 0 0 0 0 0 0 0 0 12223.4 40058 119628 290418 479852 572483 416679 233121 72538 13497.8 0 0 0 0 0 0 0 0 12797.7 17167.8 19493.1 18767.9 8198.32 23479.1 75136.8 150069 228020 228488 152024 81751.4 21547.1 0 0 0 0 0 0 0 0 0 6580.25 17297.4 34296.3 75219.4 90418.4 64444.5 27870.2 9619.08 0 0 0 0 0 0 0 0 9016.14 20745.7 26748.5 21052.4 9637.64 0 0 0 0 0 0 0 0 16005 31629.4 46047.7 49578.3 30034.5 0 0 18948.3 26620.7 24795.6 24223.6 34790.6 72499.6 161932 259385 313444 232452 127072 32151.1 299.507 0 0 0 0 0 0 0 0 14594.4 28556.9 39565.4 36836.2 21346.9 6174.35 0 0 0 0 0 0 0 0 10190.9 22115.6 36619.6 48988 73627.5 45387.1 21244.9 8144.69 0 0 0 0 0 0 0 0 6833.54 21736.1 33703.5 33385.7 23986.6 13445.4 0 0 15747.5 29735.5 35209.2 26973.5 13284 0 0 0 0 0 0 0 0 10951.5 18995.9 20908.2 17786.5 12780.8 0 0 0 0 0 0 0 0 9567.52 20894.6 61242.1 105287 138616 106383 57357 15748.4 0 0 0 0", "331.427 331.507 331.536 331.666 331.697 332.178 332.199 332.211 332.497 332.537 332.661 333.162 333.187 333.663 333.675 333.838 333.927 334.034 334.173 334.428 335.149", "36668.2 29876.5 35830.4 38491 268754 34702 29616.9 33917 20134.9 37712.6 6.52736e+006 2.31954e+006 434599 429501 435874 572483 228488 90418.4 313444 73627.5 138616"}, { "323.501 323.502 323.503 323.505 323.506 323.507 323.509 323.51 323.512 323.513 323.514 323.516 323.517 323.518 323.644 323.646 323.647 323.648 323.65 323.651 323.652 323.654 323.655 323.657 323.658 323.659 323.661 323.662 323.663 323.665 323.666 323.668 323.669 323.677 323.679 323.68 323.681 323.683 323.684 323.686 323.687 323.688 323.69 323.691 323.692 323.694 323.695 323.697 323.698 323.699 323.701 323.702 323.704 323.705 323.706 323.708 323.709 323.71 323.712 323.713 323.715 323.716 323.717 323.719 323.72 323.721 323.723 323.724 323.726 323.727 323.728 323.73 323.731 323.733 323.734 323.736 323.737 323.738 323.83 323.831 323.832 323.834 323.835 323.836 323.838 323.839 323.841 323.842 323.843 323.845 323.846 323.847 323.849 323.85 323.851 324.135 324.136 324.138 324.139 324.14 324.142 324.143 324.145 324.146 324.147 324.149 324.15 324.152 324.153 324.154 324.156 324.157 324.158 324.16 324.165 324.167 324.168 324.17 324.171 324.172 324.174 324.175 324.176 324.178 324.179 324.181 324.182 324.183 324.185 324.186 324.516 324.517 324.519 324.52 324.521 324.523 324.524 324.526 324.527 324.529 324.531 324.532 324.533 324.639 324.64 324.642 324.643 324.644 324.646 324.647 324.648 324.65 324.651 324.653 324.654 324.655 324.656 324.657 324.659 324.66 324.662 324.663 324.664 324.666 324.667 324.669 324.67 324.671 324.673 324.674 324.675 324.677 324.678 324.68 324.681 324.682 324.684 324.685 324.687 324.688 324.689 324.691 324.692 324.694 324.695 324.696 324.918 324.92 324.921 324.923 324.924 324.925 324.927 324.928 324.93 324.931 324.932 324.934 324.935 324.937 324.938 324.939 324.941 324.942 324.943 324.945 325.142 325.144 325.145 325.146 325.148 325.149 325.15 325.152 325.153 325.155 325.156 325.157 325.159 325.16 325.162 325.163 325.164 325.166 325.167 325.169 325.17 325.171 325.173 325.174 325.176 325.177 325.178 325.18 325.181 325.183 325.184 325.185 325.187 325.188 325.19 325.191 325.192 325.194 325.195 325.196 325.198 325.199 325.201 325.202 325.203 325.205 325.206 325.208 325.209 325.21 325.212 325.214 325.215 325.216 325.421 325.422 325.424 325.425 325.426 325.428 325.429 325.431 325.432 325.433 325.435 325.436 325.438 325.439 325.44 325.442 325.443 325.444 325.489 325.49 325.492 325.493 325.495 325.496 325.497 325.499 325.5 325.502 325.503 325.504 325.506 325.507 325.508 325.51 325.511 325.675 325.677 325.678 325.68 325.681 325.682 325.684 325.685 325.687 325.688 325.689 325.691 325.692 325.694 325.695 325.697 325.698 325.699 325.701 325.702 325.704 325.705 325.706 325.708 325.709 325.711 325.712 325.713 325.714 325.716 325.825 325.826 325.827 325.829 325.83 325.832 325.833 325.834 325.836 325.837 325.839 325.84 325.841 325.843 325.844 325.846 325.847 325.848 325.85 326.16 326.161 326.162 326.164 326.165 326.167 326.168 326.169 326.171 326.172 326.174 326.175 326.176 326.178 326.197 326.199 326.2 326.202 326.203 326.204 326.206 326.207 326.209 326.21 326.211 326.213 326.214 326.216 326.501 326.502 326.504 326.505 326.506 326.508 326.509 326.511 326.512 326.513 326.515 326.516 326.518 326.519 326.651 326.652 326.653 326.655 326.656 326.658 326.659 326.66 326.662 326.663 326.665 326.666 326.667 326.669 326.67 326.672 326.673 326.674 326.676 326.677 326.679 326.68 326.681 326.683 326.684 326.686 326.995 326.997 326.998 326.999 327.001 327.002 327.004 327.005 327.007 327.008 327.009 327.011 327.012 327.014 327.015 327.016 327.018 327.065 327.067 327.068 327.07 327.071 327.072 327.074 327.075 327.077 327.078 327.079 327.081 327.082 327.084 327.085 327.086 327.151 327.152 327.154 327.155 327.157 327.158 327.159 327.161 327.162 327.164 327.165 327.167 327.168 327.169 327.171 327.172 327.174 327.175 327.176 327.178 327.179", "0 0 0 0 10337.1 18844 26745.4 27338.4 17689.7 5789.13 0 0 0 0 0 0 0 0 7286.37 14779.3 25612.3 34223.1 35399.5 33187 35262.3 38108.1 32455.4 19427.3 8598.15 0 0 0 0 0 0 0 0 13092.2 14060.2 15507.1 15363.8 10135.6 0 0 0 0 0 5642.38 15458.7 21145.9 18790.8 12537.6 0 0 0 0 0 0 0 0 12489.5 23207.2 33056 39926.3 38876.1 27563.1 13567.1 0 0 13769.2 14960.1 16061.1 15998.7 11080.1 0 0 0 0 0 0 0 0 444.065 22480.7 71263.8 120113 161383 135434 80233.6 27299.1 10688.8 0 0 0 0 0 0 0 0 7735.29 45031.6 162487 388211 638507 727670 508868 274897 82367.1 21216.6 11121.1 0 0 0 0 0 0 0 0 10105 25859 52954.1 77839.5 47540.5 32527.4 18670.8 9286.83 0 0 0 0 0 0 0 0 8622.65 20560.3 25392.8 19865.1 10677.6 0 0 0 0 0 0 0 0 4480.47 34809.1 86216.4 139740 163679 117988 63350.3 15869.6 4045.84 9890.41 28426.1 58851.2 97328 93800.3 56353.2 19169.8 0 0 0 0 0 21221.9 49062.5 178545 592302 1.4445e+006 2.36277e+006 2.81404e+006 2.08062e+006 1.19528e+006 392884 94920.7 19428.2 20638.6 0 0 0 0 0 0 0 0 0 7383.33 48332.3 197738 610304 1.15209e+006 1.70499e+006 1.65698e+006 1.07908e+006 533628 147334 15178.8 0 0 0 0 0 0 0 0 0 6147.82 19463.3 31613 31705.4 20236.4 7952.21 0 0 0 0 0 0 0 12524.1 28646.6 31545.5 20771.6 9887.13 0 0 0 45165 167066 360552 567111 636125 456093 252319 75731 6306.24 0 0 0 0 0 0 11094.4 43336.7 140496 263926 377126 339672 213119 92716.1 24500.9 9376.3 0 0 0 0 0 0 0 0 11563.4 14262.4 48032.6 111463 177177 209161 154221 84562.3 20214.7 0 0 0 0 0 0 0 0 0 9671.24 44132.1 130536 228343 319246 284670 173476 68365.2 9568.61 0 0 0 0 0 0 0 0 12291.4 26865.5 40631.8 44295.3 33657.2 16909.4 6274.83 0 0 0 0 0 0 5595.9 26001.6 79324.7 140353 195225 181277 116702 52946 6656.33 0 0 0 0 0 0 0 0 9116.18 18771.7 26816.6 30238.6 26806.1 17842.7 11908.6 17560.3 24388.6 20879.8 10532.4 0 0 0 0 0 0 0 0 10891.5 19324.2 23277.8 21311.3 13945 3618.28 0 0 0 0 0 0 0 0 5046.92 15072.7 22015.1 21299.4 16234 10706.6 0 0 0 0 0 0 0 0 6362.38 15238.3 20163 20221.7 16411.6 9357.98 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22970.5 119833 406086 1.06384e+006 1.76941e+006 2.21103e+006 1.69738e+006 996431 330715 68393.4 0 0 0 0 0 0 0 0 0 6718.85 15941.2 58296.8 107245 139328 103126 57174.5 18600.5 6787.18 0 0 0 0 0 0 0 0 5769.67 16235.3 34910.2 71867.3 87315 65822.9 34335.3 10711.2 0 0 0 0 0 0 0 0 10055.3 18030.2 23946.1 26828 27876.2 31409.9 0 0 8799.44 77698.1 249057 523952 824207 895430 618459 331061 98200.3", "323.659 323.841 324.147 324.175 324.681 324.931 325.183 325.203 325.433 325.5 325.705 326.673 327.007 327.077 327.175", "38108.1 161383 727670 77839.5 2.81404e+006 1.70499e+006 636125 377126 209161 319246 195225 2.21103e+006 139328 87315 895430"}, { "316.93 316.931 316.933 316.934 316.935 316.937 316.938 316.939 316.941 316.942 316.943 316.945 316.946 317.152 317.153 317.155 317.156 317.157 317.159 317.16 317.162 317.163 317.164 317.166 317.167 317.168 317.17 317.171 317.172 317.174 317.175 317.176 317.178 317.179 317.18 317.182 317.183 317.184 317.186 317.187 317.188 317.19 317.191 317.192 317.194 317.499 317.501 317.502 317.503 317.505 317.506 317.507 317.509 317.51 317.511 317.513 317.514 317.515 317.654 317.655 317.656 317.658 317.659 317.66 317.662 317.663 317.664 317.666 317.667 317.669 317.67 317.671 317.673 317.674 317.675 317.677 317.678 317.679 317.681 317.682 317.683 317.685 317.686 317.687 317.689 317.69 317.691 317.693 317.694 317.695 317.697 317.698 317.699 317.701 317.702 317.703 317.705 317.706 317.707 317.81 317.811 317.812 317.814 317.815 317.816 317.818 317.819 317.82 317.822 317.823 317.824 317.826 317.827 317.829 317.83 317.831 317.833 317.834 317.835 317.837 317.838 317.839 317.841 317.842 317.843 317.845 317.846 317.847 317.849 317.85 317.851 317.853 317.854 317.855 317.857 317.858 317.859 317.861 317.862 317.863 317.865 317.866 317.868 317.869 317.928 317.929 317.931 317.932 317.933 317.935 317.936 317.937 317.939 317.94 317.941 317.943 317.944 317.945 317.947 317.948 317.949 317.951 318.158 318.159 318.161 318.162 318.163 318.165 318.166 318.167 318.169 318.17 318.171 318.173 318.174 318.175 318.177 318.178 318.179 318.181 318.182 318.183 318.185 318.186 318.188 318.189 318.19 318.192 318.193 318.194 318.196 318.197 318.198 318.2 318.201 318.202 318.203 318.205 318.206 318.207 318.49 318.492 318.493 318.494 318.496 318.497 318.498 318.5 318.501 318.502 318.504 318.505 318.506 318.508 318.509 318.51 318.512 318.514 318.515 318.516 318.518 318.683 318.685 318.686 318.688 318.689 318.69 318.692 318.693 318.694 318.696 318.697 318.698 318.7 318.825 318.826 318.828 318.829 318.831 318.832 318.833 318.835 318.836 318.837 318.839 318.84 318.841 318.843 318.844 318.845 318.847 318.848 318.85 319.094 319.095 319.097 319.098 319.099 319.101 319.102 319.104 319.105 319.106 319.108 319.109 319.11 319.112 319.113 319.162 319.163 319.164 319.166 319.167 319.168 319.17 319.171 319.172 319.174 319.175 319.177 319.178 319.179 319.181 319.499 319.5 319.501 319.503 319.504 319.505 319.507 319.508 319.51 319.511 319.512 319.514 319.515 319.661 319.663 319.664 319.665 319.667 319.668 319.669 319.671 319.672 319.673 319.675 319.676 319.678 319.698 319.699 319.701 319.702 319.703 319.705 319.706 319.707 319.709 319.71 319.711 319.713 319.714 319.716 319.717 319.853 319.854 319.855 319.857 319.858 319.859 319.861 319.862 319.863 319.865 319.866 319.867 319.869 320.185 320.187 320.188 320.189 320.191 320.192 320.193 320.195 320.196 320.197 320.199 320.2 320.201 320.203 320.204 320.206 320.207 320.208 320.21 320.211 320.212 320.214 320.215 320.216 320.218 320.219 320.502 320.503 320.505 320.506 320.507 320.509 320.51 320.512 320.513 320.514 320.516 320.517 320.518 320.52 320.521 320.522", "0 0 0 0 7241.27 19682.1 27785.8 23786.1 11817.8 0 0 0 0 0 0 0 0 13211.6 54540.5 99481.3 152403 159280 100901 44174.8 5942.52 669.91 19020 24047.2 29295.1 32228.6 28107.4 17978.6 8561.04 0 0 11118.5 22135 31201.2 30940.3 22511.4 13362.5 0 0 0 0 0 0 0 0 6274.15 15618.1 18945.5 13924.8 6489.34 0 0 0 0 0 0 0 0 7115.21 22347.8 38114 40847 28384.4 12714.9 0 9728.08 20270.1 30845.3 33839 25561.4 11791.7 0 0 0 0 2838.75 30794.9 110881 264181 433533 494283 346541 186229 58071.1 31575 56479.1 88848.2 99857.9 74113.7 27142.1 10370.1 0 0 0 0 0 0 0 0 4210.3 14196.8 29404.4 40223.1 40661.7 31569.1 18046.1 6584.65 0 0 0 0 0 0 9015.66 84507.7 303362 881869 1.56398e+006 2.1689e+006 1.89473e+006 1.1745e+006 506045 129958 8192.9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9526.5 50942.6 157815 283530 398647 363474 232571 106562 26483.7 2350.44 0 0 0 0 0 0 0 0 0 257639 990140 1.72868e+006 2.28545e+006 1.82081e+006 1.13244e+006 598491 488134 431208 425376 153198 0 0 0 0 0 0 31092.5 77243.6 92134.5 42742.4 20480.1 9110.67 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32241.4 201430 596658 1.01718e+006 1.32269e+006 1.07921e+006 674702 312270 150738 76963.9 26837.7 0 0 0 0 0 0 0 0 0 10405.6 18454.8 19731.5 14720 9263.62 0 0 0 0 0 0 0 0 0 30631.5 110156 256053 414666 490873 373001 223590 87841.3 20101.4 0 0 0 0 0 0 0 0 0 9320.82 22152.1 33638 38100.6 35254.2 26050.6 13168.7 0 0 0 0 0 0 0 0 13529.5 29369.4 47257.8 83492.8 58642.4 22383.5 6423.32 0 0 0 0 0 0 0 0 9006.56 21523.2 28310.6 22433.6 9918.16 0 0 0 0 0 0 0 0 5278.34 14654 21399.3 18021.8 7602 0 0 0 0 0 0 0 0 11153 59868.5 100026 127742 92760.2 45584.7 5273.03 0 0 0 0 0 0 0 0 7645.86 17039.9 21039.8 17552.4 11361 0 0 0 0 0 0 0 0 5561.98 14489.5 27837.5 40524.3 42870.9 31134.9 14509.6 4109.08 0 0 7191 20899.1 40191.3 78693.5 48652.2 35130.9 20294.4 8769.44 0 0 0 0 0 0 0 0 5084.17 17373 54040.9 90767.3 93585.1 56167.4 22545.6 8011.93 0 0 0 0", "317.163 317.689 317.841 317.939 318.169 318.502 318.837 319.707 320.208 320.513", "159280 494283 2.1689e+006 398647 2.28545e+006 1.32269e+006 490873 127742 78693.5 93585.1"}, { "415.179 415.181 415.183 415.185 415.187 415.189 415.191 415.193 415.195 415.197 415.199 415.201 415.203 415.205 415.832 415.834 415.836 415.838 415.84 415.842 415.844 415.846 415.848 415.85 415.852 415.854 415.856 415.858 415.86 415.862 415.864 415.866 415.868 415.87 415.872 415.874 415.876 415.878 415.88 415.882 415.884 415.886 415.888 415.89 415.892 415.894 415.896 415.898 415.9 415.902 415.904 415.906 416.116 416.118 416.12 416.122 416.124 416.126 416.128 416.13 416.132 416.134 416.136 416.138 416.14 416.142 416.203 416.205 416.207 416.209 416.211 416.213 416.215 416.217 416.219 416.221 416.223 416.225 416.227 416.229 416.231 416.233 416.235 416.237 416.239 416.249 416.251 416.253 416.255 416.257 416.259 416.261 416.263 416.265 416.269 416.271 416.273 416.275 416.543 416.545 416.547 416.549 416.551 416.553 416.555 416.557 416.559 416.561 416.563 416.565 416.565 416.567 416.569 416.571 416.686 416.688 416.69 416.692 416.694 416.696 416.698 416.7 416.702 416.704 416.706 416.708 416.71 416.712 416.715 416.719 416.721 416.723 416.725 416.878 416.88 416.882 416.884 416.886 416.888 416.89 416.892 416.894 416.896 416.898 416.9 416.901 416.903 416.905 416.907 417.189 417.191 417.194 417.196 417.198 417.2 417.202 417.204 417.206 417.208 417.21 417.212 417.214 417.216 417.217 417.219 417.221 417.223 417.231 417.233 417.235 417.237 417.239 417.241 417.243 417.245 417.247 417.25 417.252 417.254 417.256 417.258 417.684 417.687 417.689 417.691 417.693 417.695 417.697 417.699 417.701 417.703 417.705 417.707 417.709 417.711 417.713 417.715 417.717 417.719 417.721", "0 0 0 0 13068 30313.6 44327 42763.5 27143 10681.3 0 0 0 0 0 0 0 0 12861.9 23932.4 28395.7 23919.2 16205.1 0 0 0 0 0 0 12611.1 32209.5 48624.5 29001 9739.21 0 0 0 9396.9 94225.4 360072 829765 1.33793e+006 1.52372e+006 1.08989e+006 607260 198301 46043.7 894.783 0 0 0 0 0 0 0 0 12735.4 22188 27313.5 26983.9 21415.5 11976.7 0 0 0 0 0 0 0 0 0 22379.6 82187.5 223771 484210 773082 879781 626408 345808 101896 14446.1 0 0 0 0 0 0 0 0 20150.6 32063.4 35461 26247.8 12074.9 0 0 0 0 0 0 0 0 15138 102952 166212 231266 242733 165744 82543 6802.75 0 0 0 0 0 0 0 0 1200.84 44406.5 158943 424244 713443 903608 698826 411095 139820 33835.6 2461.56 0 0 0 0 0 0 0 0 9622.32 28799.5 112977 153068 136163 77972.9 25924.5 0 0 0 0 0 0 0 0 0 7630.18 50758.5 145197 263044 375578 339783 212564 93956.1 23367.7 5491.11 0 0 0 0 0 0 0 0 13068.6 27194.7 39076.3 39616.8 27151.2 11416.8 0 0 0 0 0 0 0 0 20127.6 35614.7 43645.7 33615.7 9873.6 0 21477.2 42504.8 42405.9 24642.2 8445.45 0 0 0 0", "415.888 416.223 416.559 416.704 417.206", "1.52372e+006 879781 242733 903608 375578"}, { "300.703 300.704 300.705 300.707 300.708 300.709 300.71 300.712 300.713 300.714 300.715 300.716 300.718 300.719 300.72 300.721 301.177 301.178 301.18 301.181 301.182 301.183 301.185 301.186 301.187 301.188 301.19 301.191 301.192 301.193 301.491 301.492 301.494 301.495 301.496 301.497 301.498 301.5 301.501 301.502 301.503 301.505 301.506 301.655 301.656 301.657 301.659 301.66 301.661 301.662 301.664 301.665 301.666 301.667 301.669 301.67 301.671 301.672 301.674 301.675 301.676 301.677 301.679 301.68 301.681 301.682 301.684 301.825 301.827 301.828 301.829 301.83 301.832 301.833 301.834 301.835 301.836 301.838 301.839 301.84 301.841 301.843 301.844 302.149 302.15 302.151 302.153 302.154 302.155 302.156 302.158 302.159 302.16 302.161 302.163 302.164 302.165 302.166 302.168 302.169 302.17 302.171 302.173 302.174 302.175 302.176 302.178 302.637 302.638 302.639 302.64 302.642 302.643 302.644 302.645 302.647 302.648 302.649 302.65 302.652 302.736 302.738 302.739 302.74 302.741 302.743 302.744 302.745 302.746 302.748 302.749 302.75 302.751 302.753 303.145 303.147 303.148 303.149 303.15 303.152 303.153 303.154 303.155 303.157 303.158 303.159 303.16 303.162 303.167 303.168 303.169 303.17 303.172 303.173 303.174 303.175 303.177 303.178 303.179 303.18 303.182 303.183 303.184 303.186 303.193 303.194 303.196 303.197 303.198 303.199 303.201 303.202 303.203 303.204 303.206 303.207 303.208 303.452 303.454 303.455 303.456 303.457 303.459 303.46 303.461 303.462 303.464 303.465 303.466 303.467 303.477 303.479 303.48 303.481 303.482 303.484 303.485 303.486 303.487 303.489 303.49 303.491 303.493 303.494 303.495 303.657 303.658 303.659 303.661 303.662 303.663 303.664 303.666 303.667 303.668 303.669 303.671 303.672 303.673 303.674 303.813 303.814 303.815 303.816 303.818 303.819 303.82 303.821 303.823 303.824 303.825 303.826 303.828 303.829 303.83 303.831 303.833 303.834 303.835 304.142 304.143 304.144 304.146 304.147 304.148 304.149 304.151 304.152 304.153 304.154 304.156 304.157 304.158 304.159", "0 0 0 0 4021.59 14948.3 29089.3 36172.3 33002.6 23872.1 13677 5631.91 0 0 0 0 0 0 0 0 3857.72 12358.4 21296.1 23339.3 16310.7 6581.76 0 0 0 0 0 0 0 0 5103.45 14404.9 20128 17722.4 11071 0 0 0 0 0 0 0 0 5040.13 35337.3 92693 150038 188818 156826 95523.6 36488.8 1633.48 0 14570.6 13804.9 13959 16252.2 16043.7 10491.2 0 0 0 0 0 0 0 0 11491.4 23253.9 33391.5 38064.9 35915.8 26480.2 13339.6 3360.52 0 0 0 0 0 0 0 0 9994.41 18678.4 23105.4 23357.1 21846.8 17762.7 12243 1230.6 23060.6 60254.8 97465.7 113113 88507.4 54246.1 18156.2 6643.82 0 0 0 0 0 0 0 0 9123.52 17445.2 21036 16344.5 7770.44 0 0 0 0 0 0 0 0 8312 20822.9 29108.9 25567.8 13950.4 3781.06 0 0 0 0 0 0 0 0 9115.97 17822.3 25208.4 25012.8 16827.3 8086.82 0 0 0 0 0 0 0 0 3947.37 12745.8 24975.9 32592.2 31830.1 24391.1 13880.6 4732.84 0 0 0 0 0 0 0 0 6750.57 14914.3 18383.8 16081.2 11665.7 0 0 0 0 0 0 0 0 4826.25 12462.4 16962.6 13627.1 6053.79 0 0 0 0 0 0 0 0 7090.97 18737.1 29710.3 31932.3 24547.1 13431.4 4401.52 0 0 0 0 0 0 0 0 8864.78 24483.2 54372.2 81053.3 67322.2 27272.1 10297.5 0 0 0 0 0 0 0 0 11422.7 23786.6 33943.1 32175 18417.9 5897.95 6002.16 14535.1 18982.7 14518.1 6290.84 0 0 0 0 0 0 0 0 11744.6 23937.1 31048 29687.7 22535 13681.6 8906.82 14661.8 27257.5 43105 43170.2", "300.712 301.186 301.665 301.834 302.168 302.644 302.744 303.153 303.175 303.486 303.666 303.82 304.159", "36172.3 23339.3 188818 38064.9 113113 21036 29108.9 25208.4 32592.2 31932.3 81053.3 33943.1 43170.2"}, { "452.06 452.062 452.065 452.067 452.069 452.071 452.074 452.076 452.078 452.081 452.082 452.084 452.087 452.089 452.192 452.194 452.196 452.198 452.201 452.203 452.205 452.208 452.21 452.212 452.214 452.217 452.22 452.222 452.224 452.226 452.446 452.448 452.45 452.452 452.455 452.457 452.459 452.461 452.464 452.466 452.468 452.471 452.473 452.475 452.477 452.48 452.482 452.484 452.694 452.697 452.699 452.701 452.704 452.706 452.708 452.71 452.713 452.715 452.717 452.72 452.722 452.724 452.726 452.729 452.731 452.733 452.95 452.953 452.955 452.957 452.96 452.962 452.964 452.966 452.969 452.971 452.973 452.976 452.978 452.98 452.982 453.454 453.456 453.458 453.461 453.463 453.465 453.468 453.47 453.472 453.474 453.477 453.479 453.481 454.158 454.16 454.162 454.165 454.167 454.169 454.172 454.174 454.176 454.178 454.181 454.183 454.185 454.188 454.714 454.716 454.718 454.721 454.723 454.725 454.728 454.73 454.732 454.735 454.737 454.739 454.741", "0 0 0 0 9364.36 24041.2 38252.2 41150.4 31605.1 17604.6 0 0 0 0 0 0 0 0 3930.9 41824.5 95963.9 154164 152063 95638.9 43562 12495.1 0 0 0 0 0 0 0 0 0 28332.8 103440 204407 311126 307518 199724 97813.7 28554.9 2987.27 0 0 0 0 0 0 0 0 0 37076.2 121274 226216 331181 324273 217272 115224 35782.4 0 0 0 0 0 0 0 0 0 18286.8 60113.4 102915 133571 104506 59294.7 17472.9 0 0 0 0 0 0 0 0 10894.4 21954.3 28972.5 28655.5 21029.8 0 0 0 0 0 0 0 0 17264.7 32830.8 41807.6 38619.2 26607.2 12618.2 0 0 0 0 0 0 0 0 19933.8 29881.3 34532.2 30762.8 19924.3 0 0 0 0", "452.208 452.464 452.713 452.966 453.468 454.172 454.728", "154164 311126 331181 133571 28972.5 41807.6 34532.2"}, { "307.696 307.697 307.699 307.7 307.701 307.702 307.704 307.705 307.706 307.708 307.709 307.71 307.711 307.713 307.714 307.715 307.717 307.718 308.17 308.172 308.173 308.174 308.175 308.177 308.178 308.179 308.181 308.182 308.183 308.185 308.186 308.2 308.201 308.203 308.204 308.205 308.206 308.208 308.209 308.21 308.212 308.213 308.214 308.215 308.217 308.218 308.219 308.22 308.222 308.491 308.493 308.494 308.495 308.496 308.498 308.499 308.5 308.502 308.503 308.504 308.505 308.507 308.508 308.509 308.628 308.629 308.63 308.631 308.633 308.634 308.635 308.637 308.638 308.639 308.64 308.642 308.643 308.644 308.645 308.647 308.662 308.663 308.665 308.666 308.667 308.668 308.67 308.671 308.672 308.674 308.675 308.676 308.677 308.679 308.68 308.682 308.683 308.702 308.703 308.705 308.706 308.707 308.709 308.71 308.711 308.712 308.714 308.715 308.716 308.718 308.719 308.72 308.721 308.723 308.833 308.835 308.836 308.837 308.839 308.84 308.841 308.842 308.844 308.845 308.846 308.848 308.849 308.85 308.851 308.853 308.854 308.855 308.857 308.858 308.859 308.86 308.89 308.891 308.893 308.894 308.895 308.896 308.898 308.899 308.9 308.902 308.903 308.905 308.906 309.157 309.158 309.16 309.161 309.162 309.164 309.165 309.166 309.167 309.169 309.17 309.171 309.173 309.174 309.175 309.176 309.177 309.178 309.18 309.181 309.182 309.184 309.185 309.186 309.187 309.189 309.19 309.192 309.193 309.194 309.491 309.492 309.494 309.495 309.496 309.498 309.499 309.5 309.501 309.503 309.504 309.505 309.507 309.508 309.509 309.51 309.512 309.513 309.514 309.515 309.517 309.518 309.519 309.521 309.522 309.523 309.524 309.526 309.527 309.664 309.665 309.667 309.668 309.669 309.67 309.672 309.673 309.674 309.676 309.677 309.678 309.679 309.681 309.682 309.683 309.685 309.686 309.827 309.828 309.83 309.831 309.832 309.833 309.835 309.836 309.837 309.839 309.84 309.841 309.843 309.844 309.845 309.846 310.166 310.167 310.169 310.17 310.171 310.173 310.174 310.175 310.177 310.178 310.179 310.18 310.182 310.183 310.184 310.186 310.187 310.188 310.189 310.191 310.192 310.193 310.195 310.651 310.653 310.654 310.655 310.656 310.658 310.659 310.66 310.662 310.663 310.664 310.666 310.667 310.668 310.67 310.671 310.816 310.818 310.819 310.82 310.822 310.823 310.824 310.826 310.827 310.828 310.829 310.831 310.832 310.833 310.835 310.836 310.837 310.838 310.84 310.841 310.842 310.844 310.845 310.858 310.859 310.86 310.862 310.863 310.864 310.866 310.867 310.868 310.87 310.871 310.872 310.874 310.875 311.122 311.123 311.125 311.126 311.127 311.129 311.13 311.131 311.133 311.134 311.135 311.136 311.138 311.139 311.14 311.141 311.143 311.144 311.145 311.147 311.148 311.149 311.151 311.152 311.153 311.154 311.156 311.157 311.158 311.16 311.161 311.162 311.164 311.165 311.166 311.167 311.169 311.17 311.171 311.173 311.174 311.175 311.177 311.178 311.179 311.181", "0 0 0 0 9802.36 23098.1 80318.2 168123 260050 249021 153699 69134.6 15860.2 0 0 0 0 0 0 0 0 0 6603.17 16854.7 22242.6 17002.5 6384.9 0 0 0 0 0 0 0 0 3259.21 45522.7 136253 256874 378108 384887 264149 143498 38861.2 0 0 0 0 0 0 0 0 0 9568.38 16779.6 25703.4 34804.3 36903.4 27626.5 13210.8 0 0 0 0 0 0 0 0 6020.72 19418.9 41247.7 87139.4 101517 51696.3 31958.5 13406.6 0 0 0 0 0 0 0 0 8887.19 32368.8 88172.5 150448 183012 138562 83560.8 34576.6 9382.31 0 0 0 0 0 0 0 0 6136.98 17078.9 37706.1 99369.4 120669 89079.4 48058.7 16632.9 5690.8 0 0 0 0 0 0 0 0 13659 36722.7 21354.1 19439.5 43622.3 141202 361101 593217 725619 549023 320363 106084 18987.1 0 0 0 0 0 0 0 0 0 7044.94 21287 31346.9 27932.1 15042.7 0 0 0 0 0 0 0 0 12545.5 66956 196850 483967 796603 1.00996e+006 800685 478608 175846 31025.8 0 0 0 21565.5 116573 248949 372585 340360 208008 89705.4 16994.2 0 0 0 0 0 0 0 0 0 0 20664.3 76813.8 211847 360938 474556 391964 238310 96484.5 13402.4 0 0 15903.2 18823.3 38109.2 78987.2 115813 103941 60973.3 21474.4 8379.21 0 0 0 0 0 0 0 0 5010.87 39835 145701 261216 355012 297678 181623 70393.1 19551.4 9556.91 0 0 0 0 0 0 0 0 13098.9 30137.5 82208.8 121291 126226 84746 41315 13074.1 0 0 0 0 0 0 0 0 7583.31 24991.6 42441.5 47113.5 37361.7 22733.3 11295.4 0 0 15445.3 25939.6 29374.9 24399.7 16278.2 8806.05 0 0 0 0 0 0 0 0 13501.6 32925.8 78379.3 112170 101026 58511.2 22918.4 7815.47 0 0 0 0 0 0 0 0 0 16485.2 87297.2 250447 436618 588792 489043 298868 118211 35326.5 17949.5 28044.3 49970.6 30360.5 12383.3 0 0 0 0 0 0 0 0 12935.3 27576.7 33616.7 27724.5 17214.9 8642.67 0 0 0 0 0 0 0 0 4327.09 28941.4 100849 182836 253955 223430 137468 54432.1 7270.05 0 0 0 0 0 11368.6 20920.1 27685.4 29939.4 25376 15654.1 0 0 0 0 26913.6 134469 249526 300649 223246 136273 126863 259141 410598 488277 350133 183857 33436.7 0 0 0 0 0", "307.706 308.212 308.672 308.712 308.849 309.169 309.182 309.503 309.674 310.828 311.133 311.17", "260050 384887 183012 120669 725619 1.00996e+006 372585 474556 355012 588792 253955 488277"}, { "507.723 507.726 507.729 507.731 507.734 507.737 507.74 507.742 507.745 507.748 507.75 507.753 507.756 507.758 507.761 507.764 508.228 508.231 508.234 508.236 508.239 508.242 508.245 508.247 508.25 508.253 508.255 508.258 508.261 508.264 510.229 510.231 510.234 510.237 510.24 510.242 510.245 510.248 510.251 510.253 510.256 510.259 510.262 510.264", "0 0 0 0 20993.6 79292.2 151677 219202 191318 115566 45767.5 12062.2 0 0 0 0 0 0 0 0 10042.1 24206 34397.5 33192 22528.5 10434.2 0 0 0 0 0 0 0 0 9028.83 22351.6 35166.6 38509.2 29599.8 14844.1 0 0 0 0", "507.742 508.245 510.248", "219202 34397.5 38509.2"}, }; const size_t testDataSize = sizeof(testData) / sizeof(TestData); vector parseDoubleArray(const string& doubleArray) { vector doubleVector; vector tokens; bal::split(tokens, doubleArray, bal::is_space(), bal::token_compress_on); if (!tokens.empty() && !tokens[0].empty()) for (size_t i=0; i < tokens.size(); ++i) doubleVector.push_back(lexical_cast(tokens[i])); return doubleVector; } void test() { for (size_t i=0; i < testDataSize; ++i) { const TestData& data = testData[i]; vector xRaw = parseDoubleArray(data.xRaw); vector yRaw = parseDoubleArray(data.yRaw); vector target_xPeakValues = parseDoubleArray(data.xPeakValues); vector target_yPeakValues = parseDoubleArray(data.yPeakValues); // sanity checks unit_assert(xRaw.size() == yRaw.size()); unit_assert(target_xPeakValues.size() == target_yPeakValues.size()); CwtPeakDetector peakDetector(1.0,0,0.01); vector xPeakValues, yPeakValues; peakDetector.detect(xRaw, yRaw, xPeakValues, yPeakValues); unit_assert(xPeakValues.size() == target_xPeakValues.size()); for (size_t j=0; j < xPeakValues.size(); ++j) { unit_assert_equal(xPeakValues[j], target_xPeakValues[j], 1e-5); unit_assert_equal(yPeakValues[j], target_yPeakValues[j], 1e-5); } } } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/common/ExtraZeroSamplesFilter.cpp0000664000175100017510000000607212664775613025007 0ustar teamcityteamcity00000000000000// // $Id: ExtraZeroSamplesFilter.cpp 3550 2012-04-18 16:23:06Z chambm $ // // // // Original author: Brian Pratt insilicos.com> // // Copyright 2012 Spielberg Family Center for Applied Proteomics // University of Southern California, Los Angeles, California 90033 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "pwiz/utility/misc/Std.hpp" #include "ExtraZeroSamplesFilter.hpp" namespace pwiz { namespace analysis { /// removes zero samples in signal profiles, except those flanking nonzero samples /// simply looks for runs of 0 values, removes all but start and end of run void ExtraZeroSamplesFilter::remove_zeros(const vector& x, const vector& y, vector& xProcessed, vector& yProcessed, bool preserveFlankingZeros) { if (x.size() != y.size()) throw runtime_error("[ExtraZeroSamplesFilter::remove_zeros()] x and y arrays must be the same size"); xProcessed.resize(0); yProcessed.resize(0); if (preserveFlankingZeros) { if (y.size() > 3) { xProcessed.reserve(x.size()); yProcessed.reserve(y.size()); // leave flanking zeros around non-zero data points int i, end = y.size()-1; for (i=0; i < end; ++i) { if (y[i] || y[i+1] || (i && y[i-1])) { xProcessed.push_back(x[i]); yProcessed.push_back(y[i]); } } if (y[i] || y[i-1]) { xProcessed.push_back(x[i]); yProcessed.push_back(y[i]); } xProcessed.resize(xProcessed.size()); // offer to trim excess capacity yProcessed.resize(yProcessed.size()); // offer to trim excess capacity } else { xProcessed = x; yProcessed = y; } } else { xProcessed.reserve(x.size()); yProcessed.reserve(y.size()); for (size_t i=0; i < y.size(); ++i) { if (y[i]) { xProcessed.push_back(x[i]); yProcessed.push_back(y[i]); } } xProcessed.resize(xProcessed.size()); // offer to trim excess capacity yProcessed.resize(yProcessed.size()); // offer to trim excess capacity } } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/common/LocalMaximumPeakDetector.cpp0000664000175100017510000000516412664775613025255 0ustar teamcityteamcity00000000000000// // $Id: LocalMaximumPeakDetector.cpp 2908 2011-08-05 16:41:41Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "LocalMaximumPeakDetector.hpp" #include "pwiz/utility/misc/Std.hpp" #include "ZeroSampleFiller.hpp" namespace pwiz { namespace analysis { PWIZ_API_DECL LocalMaximumPeakDetector::LocalMaximumPeakDetector(size_t windowSize) : window_(windowSize) { } PWIZ_API_DECL void LocalMaximumPeakDetector::detect(const vector& x, const vector& y, vector& xPeakValues, vector& yPeakValues, vector* peaks) { if (x.size() != y.size()) throw runtime_error("[LocalMaximumPeakDetector::detect()] x and y arrays must be the same size"); // the size of the window in either direction size_t flank = size_t(window_-1) / 2; // fill in missing samples based on window size // note: we don't need all the missing samples because a window full of zeros // will always smooth to a 0, regardless of the X values involved vector xCopy; vector yCopy; ZeroSampleFiller::fill(x, y, xCopy, yCopy, flank+1); for (size_t i=flank, end=yCopy.size()-flank; i < end; ++i) { bool isPeak = true; for (size_t j=1; j <= flank; ++j) if (yCopy[i] < yCopy[i-j] || yCopy[i] < yCopy[i+j]) { isPeak = false; break; } if (isPeak) { xPeakValues.push_back(xCopy[i]); yPeakValues.push_back(yCopy[i]); } } if (peaks) { peaks->resize(xPeakValues.size()); for (size_t i=0; i < xPeakValues.size(); ++i) { Peak& p = (*peaks)[i]; p.x = xPeakValues[i]; p.y = yPeakValues[i]; p.start = 0; p.stop = 0; p.area = 0; } } } } // namespace analysis } // namespace msdata pwiz/pwiz/analysis/common/ExtraZeroSamplesFilter.hpp0000664000175100017510000000312512664775613025010 0ustar teamcityteamcity00000000000000// // $Id: ExtraZeroSamplesFilter.hpp 3550 2012-04-18 16:23:06Z chambm $ // // // Original author: Brian Pratt insilicos.com> // // Copyright 2012 Spielberg Family Center for Applied Proteomics // University of Southern California, Los Angeles, California 90033 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _EXTRAZEROSAMPLESFILTER_HPP_ #define _EXTRAZEROSAMPLESFILTER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include namespace pwiz { namespace analysis { /// removes (most) zero samples in signal profiles, except those flanking nonzero samples /// simply looks for runs of 0 values, removes all but start and end of run struct PWIZ_API_DECL ExtraZeroSamplesFilter { static void remove_zeros(const std::vector& x, const std::vector& y, std::vector& xProcessed, std::vector& yProcessed, bool preserveFlankingZeros); }; } // namespace analysis } // namespace pwiz #endif // _EXTRAZEROSAMPLESFILTER_HPP_ pwiz/pwiz/analysis/common/Smoother.hpp0000664000175100017510000000356512664775613022202 0ustar teamcityteamcity00000000000000// // $Id: Smoother.hpp 1191 2009-08-14 19:33:05Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SMOOTHER_HPP_ #define _SMOOTHER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "boost/shared_ptr.hpp" #include namespace pwiz { namespace analysis { /// interface for a one-dimensional smoothing algorithm struct PWIZ_API_DECL Smoother { /// smooth y values to existing vectors; /// note: in the case of sparse vectors, smoothing may fill in samples not present /// in the original data, so make sure to check the size of the output vectors virtual void smooth(const std::vector& x, const std::vector& y, std::vector& xSmoothed, std::vector& ySmoothed) = 0; /// smooth y values and copy back to the input vectors; /// note: in the case of sparse vectors, smoothing may fill in samples not present /// in the original data, so make sure to check the size of the output vectors virtual void smooth_copy(std::vector& x, std::vector& y) = 0; virtual ~Smoother() {}; }; typedef boost::shared_ptr SmootherPtr; } // namespace analysis } // namespace pwiz #endif // _SMOOTHER_HPP_ pwiz/pwiz/analysis/common/WhittakerSmoother.cpp0000664000175100017510000000621612664775613024054 0ustar teamcityteamcity00000000000000// // $Id: WhittakerSmoother.cpp 1191 2009-08-14 19:33:05Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "WhittakerSmoother.hpp" #include "pwiz/utility/misc/Export.hpp" #include "pwiz/utility/misc/Container.hpp" #include #include #include "pwiz/utility/math/MatrixInverse.hpp" #include namespace pwiz { namespace analysis { PWIZ_API_DECL WhittakerSmoother::WhittakerSmoother(double lambdaCoefficient) : lambda(lambdaCoefficient) { if (lambdaCoefficient < 2.0) throw std::runtime_error("[WhittakerSmoother::ctor()] Invalid value for lamda coefficient; valid range is [2, infinity)"); } PWIZ_API_DECL void WhittakerSmoother::smooth_copy(vector& x, vector& y) { smooth(x, y, x, y); } PWIZ_API_DECL void WhittakerSmoother::smooth(const std::vector& x, const std::vector& y, std::vector& xSmoothed, std::vector& ySmoothed) { using namespace boost::numeric::ublas; using std::cerr; using std::endl; typedef compressed_matrix Matrix; typedef compressed_matrix::iterator1 Iterator1; typedef compressed_matrix::iterator2 Iterator2; size_t m = y.size(); identity_matrix E(m); Matrix D(m-1, m, (m-1)*2); for (size_t row = 0; row < m-1; ++row) for (size_t col = 0; col < m; ++col) if (row == col) D(row,col) = -1; else if (row == col - 1) D(row,col) = 1; Matrix transD, t1, temp; transD.resize(m, m-1, false); t1.resize(m, m, false); temp.resize(m, m, false); noalias(transD) = trans(D); noalias(t1) = prod(transD, D); noalias(temp) = E + (lambda * t1); boost::numeric::ublas::vector yv(y.size()); std::copy(y.begin(), y.end(), yv.begin()); bool singular; Matrix temp2 = gjinverse(temp, singular); boost::numeric::ublas::vector z = prod(temp2, yv); ySmoothed.resize(z.size()); std::copy(z.begin(), z.end(), ySmoothed.begin()); /*for (Iterator1 i1 = D.begin1(); i1 != D.end1(); ++i1) { for (Iterator2 i2 = i1.begin(); i2 != i1.end(); ++i2) cerr << "(" << i2.index1() << "," << i2.index2() << ":" << *i2 << ") "; cerr << endl; }*/ } } // namespace analysis } // namespace msdata pwiz/pwiz/analysis/common/SavitzkyGolaySmoother.hpp0000664000175100017510000000355212664775613024737 0ustar teamcityteamcity00000000000000// // $Id: SavitzkyGolaySmoother.hpp 1807 2010-02-12 16:32:36Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SAVITZKYGOLAYSMOOTHER_HPP_ #define _SAVITZKYGOLAYSMOOTHER_HPP_ #include "Smoother.hpp" #include #include namespace pwiz { namespace analysis { struct PWIZ_API_DECL SavitzkyGolaySmoother : public Smoother { SavitzkyGolaySmoother(int polynomialOrder, int windowSize); ~SavitzkyGolaySmoother(); /// smooth y values to existing vectors using Savitzky-Golay algorithm; /// preconditions: /// - samples within the window must be (approximately) equally spaced virtual void smooth(const std::vector& x, const std::vector& y, std::vector& xSmoothed, std::vector& ySmoothed); /// smooth y values and copy back to the input vectors using Savitzky-Golay algorithm; /// preconditions: /// - samples within the window must be (approximately) equally spaced virtual void smooth_copy(std::vector& x, std::vector& y); private: struct Impl; boost::shared_ptr impl_; }; } // namespace analysis } // namespace pwiz #endif // _SAVITZKYGOLAYSMOOTHER_HPP_ pwiz/pwiz/analysis/common/WhittakerSmoother.hpp0000664000175100017510000000376712664775613024071 0ustar teamcityteamcity00000000000000// // $Id: WhittakerSmoother.hpp 1191 2009-08-14 19:33:05Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Derived from ACS article: // A Perfect Smoother // Paul H. C. Eilers // Anal. Chem., 2003, 75 (14), 3631-3636 • DOI: 10.1021/ac034173t #ifndef _WHITTAKERSMOOTHER_HPP_ #define _WHITTAKERSMOOTHER_HPP_ #include "Smoother.hpp" namespace pwiz { namespace analysis { struct PWIZ_API_DECL WhittakerSmoother : public Smoother { WhittakerSmoother(double lambdaCoefficient); /// smooth y values to existing vectors using Whittaker algorithm; /// note: in the case of sparse vectors, smoothing may fill in samples not present /// in the original data, so make sure to check the size of the output vectors virtual void smooth(const std::vector& x, const std::vector& y, std::vector& xSmoothed, std::vector& ySmoothed); /// smooth y values and copy back to the input vectors using Whittaker algorithm; /// note: in the case of sparse vectors, smoothing may fill in samples not present /// in the original data, so make sure to check the size of the output vectors virtual void smooth_copy(std::vector& x, std::vector& y); private: double lambda; }; } // namespace analysis } // namespace pwiz #endif // _WHITTAKERSMOOTHER_HPP_ pwiz/pwiz/analysis/common/SavitzkyGolaySmootherTest.cpp0000664000175100017510000055031712664775613025600 0ustar teamcityteamcity00000000000000// // $Id: SavitzkyGolaySmootherTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "SavitzkyGolaySmoother.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::analysis; ostream* os_ = 0; struct TestData { int polynomialOrder, windowSize; const char* xRaw; const char* yRaw; const char* xSmoothed; const char* ySmoothed; }; const TestData testData[] = { /*{ 2, 7, "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46", "0 0 0 0 0 0 0 5 10 20 40 20 10 5 0 0 0 0 3 4 10 9 7 3 0 0 0 0 0 0 10 30 60 100 80 20 5 0 0 0 0 0 0 0 0 0", "4.611696e-16 6.422213e-15 3.142785e-15 2.869500e-15 -4.761905e-01 -2.380952e-01 9.523810e-01 3.571429e+00 1.428571e+01 2.357143e+01 2.666667e+01 2.357143e+01 1.428571e+01 3.571429e+00 9.523810e-01 -5.238095e-01 -4.285714e-01 4.761905e-01 2.714286e+00 5.666667e+00 8.190476e+00 8.571429e+00 6.809524e+00 3.333333e+00 1.000000e+00 -2.380952e-01 -2.857143e-01 -9.523810e-01 -1.428571e+00 1.428571e+00 1.095238e+01 3.666667e+01 6.809524e+01 7.904762e+01 6.738095e+01 3.952381e+01 9.285714e+00 -3.333333e+00 -1.190476e+00 -4.761905e-01 -1.366428e-16 -6.832142e-16 -2.391250e-16 4.577535e-15 6.832142e-15 2.186285e-15" }, { 2, 7, "7 8 9 10 11 12 13 14 15 18 19 20 21 22 23 24 25 30 31 32 33 34 35 36 37 38", "0 5 10 20 40 20 10 5 0 0 3 4 10 9 7 3 0 0 10 30 60 100 80 20 5 0", "7 8 9 10 11 12 13 14 15 18 19 20 21 22 23 24 25 30 31 32 33 34 35 36 37 38" },*/ { 2, 11, "300.000066203793 300.000611626572 300.001157051333 300.001702478078 300.058437690186 300.058983325233 300.059528962264 300.06007460128 300.06062024228 300.061165885264 300.061711530233 300.062257177186 300.062802826123 300.063348477046 300.063894129952 300.064439784843 300.064985441719 300.065531100579 300.066076761424 301.055887660805 301.056436929468 301.056986200136 301.057535472809 301.058084747485 301.058634024166 301.059183302851 301.059732583541 301.060281866235 301.060831150933 301.061380437635 301.061929726342 301.062479017053 301.063028309769 301.063577604489 311.869088211176 311.869677645283 311.870267081618 311.870856520182 311.871445960974 311.872035403993 311.872624849241 311.873214296717 311.873803746421 311.874393198353 311.874982652514 311.875572108902 311.876161567519 311.876751028364 311.877340491437 311.877929956739 311.878519424268 311.879108894026 311.879698366013 311.880287840227 311.88087731667 311.881466795341 311.882056276241 315.73174362051 315.732347745926 315.732951873654 315.733556003694 315.734160136047 315.734764270711 315.735368407687 315.735972546974 315.736576688574 315.737180832486 315.73778497871 315.738389127246 316.901416544052 316.902025153901 316.902633766087 316.90324238061 316.903850997471 316.90445961667 316.905068238207 316.905676862081 316.906285488293 316.906894116843 316.907502747731 316.908111380957 316.90872001652 316.909328654421 326.293591849569 326.294237069432 326.294882291847 326.295527516814 326.296172744332 326.296817974402 326.297463207024 326.298108442198 326.298753679923 326.299398920201 326.30004416303 327.074882186811 327.075530500256 327.076178816272 327.076827134858 327.077475456014 327.07812377974 327.078772106036 327.079420434903 327.080068766339 327.080717100346 327.081365436923 327.082013776071 327.082662117789 327.083310462077 327.083958808935 341.007109159311 341.007813880848 341.008518605298 341.00922333266 341.009928062936 341.010632796124 341.011337532225 341.012042271238 341.012747013165 " "341.013451758004 341.014156505757 341.014861256422 341.01556601 341.016270766491 341.016975525895 341.017680288212 341.018385053442 341.019089821585 341.019794592642 341.020499366611 341.021204143493 341.021908923288 341.022613705997 341.023318491618 341.024023280153 341.024728071601 342.01359244987 342.014301337525 342.015010228119 342.015719121651 342.016428018122 342.017136917532 342.01784581988 342.018554725167 342.019263633392 342.019972544557 342.02068145866 342.021390375702 342.022099295682 342.022808218602 342.02351714446 342.873501341248 342.874213798035 342.874926257782 342.87563872049 342.876351186159 342.877063654789 342.87777612638 342.878488600932 342.879201078445 342.879913558918 342.880626042353 342.881338528749 344.97306118134 344.9737823902 344.974503602076 344.975224816967 344.975946034874 344.976667255797 344.977388479735 344.978109706689 344.978830936658 344.979552169644 344.980273405644 344.980994644661 344.981715886693 355.063935356091 355.064699374529 355.065463396255 355.066227421269 355.066991449572 355.067755481162 355.06851951604 355.069283554207 355.070047595661 355.070811640404 355.071575688435 355.072339739754 355.073103794361 355.073867852257 355.074631913441 355.075395977913 355.076160045673 355.076924116722 355.077688191059 355.078452268685 356.064553240471 356.065321571195 356.066089905234 356.06685824259 356.067626583261 356.068394927249 356.069163274552 356.069931625172 356.070699979107 356.071468336359 356.072236696926 356.07300506081 356.073773428009 356.074541798525 356.075310172357 356.076078549505 356.076846929969 356.07761531375 356.078383700846 356.079152091259 356.079920484988 356.080688882034 357.062327559534 357.063100202372 357.063872848555 357.064645498081 357.065418150951 357.066190807165 357.066963466723 357.067736129625 357.068508795871 357.069281465461 357.070054138395 357.070826814673 357.071599494295 357.072372177261 357.073144863571 357.073917553225 357.074690246224 357.075462942566 357.076235642253 " "357.077008345284 357.077781051659 357.078553761379 357.079326474442 357.08009919085 359.023183355092 359.023964507385 359.024745663078 359.02552682217 359.026307984661 359.027089150551 359.027870319841 359.028651492531 359.029432668619 359.030213848107 359.030995030994 359.031776217281 359.032557406967 359.033338600053 359.034119796538 359.034900996422 359.035682199706 360.023491974674 360.024277485921 360.025063000597 360.0258485187 360.02663404023 360.027419565189 360.028205093575 360.028990625389 360.029776160632 360.030561699301 360.031347241399 360.032132786925 360.032918335879 360.03370388826 360.03448944407 361.021491400285 361.02228127251 361.023071148191 361.023861027329 361.024650909923 361.025440795974 361.026230685481 361.027020578444 361.027810474864 361.02860037474 361.029390278072 361.030180184861 361.030970095107 361.031760008809 371.095690561049 371.096525130684 371.097359704072 371.098194281215 371.099028862111 371.099863446762 371.100698035166 371.101532627324 371.102367223236 371.103201822902 371.104036426322 371.104871033497 371.105705644425 371.106540259107 371.107374877543 371.108209499734 371.109044125678 371.109878755377 371.11071338883 372.078066820464 372.078905814551 372.079744812421 372.080583814075 372.081422819513 372.082261828735 372.083100841741 372.08393985853 372.084778879103 372.08561790346 372.086456931601 372.087295963526 372.095686490895 372.096525564444 372.097364641778 372.098203722896 372.099042807799 372.099881896485 372.100720988956 372.101560085211 372.102399185251 372.103238289075 372.104077396683 372.104916508076 372.105755623254 372.106594742216 372.107433864962 372.108272991493 373.076623237254 373.077466740653 373.078310247866 373.079153758894 373.079997273735 373.080840792391 373.081684314862 373.082527841147 373.083371371246 373.084214905159 373.085058442887 373.08590198443 373.086745529787 373.101086384495 373.101929998517 373.102773616354 373.103617238007 373.104460863474 373.105304492756 373.106148125853 " "373.106991762765 373.107835403493 373.108679048035 373.109522696393 373.110366348566 373.111210004555 415.030543316388 415.031587197383 415.032631083628 415.033674975125 415.034718871873 415.035762773872 415.036806681123 415.037850593625 415.038894511378 415.039938434383 415.040982362639 415.042026296147 415.043070234906 415.044114178917 415.045158128179 415.046202082693 415.047246042459 416.004675140758 416.005723927765 416.006772720059 416.007821517642 416.008870320513 416.009919128672 416.01096794212 416.012016760856 416.01306558488 416.014114414193 416.015163248794 416.016212088684 416.030896402465 416.031945321688 416.032994246201 416.034043176002 416.035092111093 416.036141051473 416.037189997143 416.038238948102 416.03928790435 416.040336865888 416.041385832715 416.042434804832 416.043483782239 416.044532764935 416.04558175292 416.046630746196 416.047679744761 417.027651705639 417.028705657034 417.029759613757 417.030813575807 417.031867543184 417.032921515889 417.033975493922 417.035029477282 417.036083465969 417.037137459984 417.038191459327 417.039245463997 417.040299473995 417.041353489321 426.357976566382 426.359078206359 426.360179852029 426.361281503392 426.362383160449 426.363484823198 426.36458649164 426.365688165776 426.366789845604 426.367891531126 426.368993222341 428.935877697296 428.936992699323 428.938107707146 428.939222720767 428.940337740184 428.941452765398 428.94256779641 428.943682833218 428.944797875823 428.945912924226 428.947027978426 429.083108101101 429.0842238687 429.085339642101 429.086455421305 429.087571206312 429.088686997122 429.089802793735 429.090918596151 429.09203440437 429.093150218392 429.094266038217 429.095381863845 429.096497695277 429.097613532512 429.09872937555 429.099845224392 429.100961079037 429.102076939486 429.134439417209 429.135555451783 429.136671492162 429.137787538345 429.138903590334 429.140019648128 429.141135711726 429.14225178113 429.143367856339 429.144483937353 429.145600024173 429.146716116797 " "429.85101025753 429.852130022341 429.853249792985 429.854369569464 429.855489351777 429.856609139924 429.857728933905 429.858848733721 429.859968539371 429.861088350855 429.862208168173 429.863327991326 429.864447820313 429.865567655135 429.866687495792 429.867807342283 429.868927194608 429.870047052768 429.871166916764 429.872286786593 429.873406662258 429.874526543758 429.875646431092 429.876766324261 429.877886223266 430.081805059062 430.082926026641 430.084047000064 430.08516797933 430.086288964439 430.087409955392 430.088530952189 430.089651954829 430.090772963313 430.091893977641 430.093014997813 430.094136023828 430.095257055687 430.09637809339 430.097499136937 430.098620186328 430.099741241563 430.100862302643 430.101983369566 431.078404724764 431.079530893455 431.08065706803 431.081783248489 431.082909434832 431.08403562706 431.085161825172 431.086288029168 431.087414239049 431.088540454814 431.089666676463 431.090792903997 431.091919137416 431.093045376719 431.094171621907 431.09529787298 431.096424129938 431.09755039278 431.098676661507 431.099802936119 432.079633824813 432.080765230898 432.081896642908 432.083028060844 432.084159484704 432.085290914491 432.086422350202 432.087553791839 432.088685239402 432.08981669289 432.090948152304 432.092079617643 432.093211088908 444.61606065115 444.617258663358 444.618456682022 444.619654707142 444.620852738719 444.622050776751 444.62324882124 444.624446872186 444.625644929587 444.626842993445 444.62804106376 444.629239140531 444.630437223759 445.111389571898 445.112590254911 445.113790944402 445.114991640371 445.116192342817 445.117393051741 445.118593767143 445.119794489023 445.120995217382 445.122195952218 445.123396693532 445.124597441324 445.125798195595 445.126998956343 445.128199723571 445.129400497276 445.13060127746 446.092099627601 446.093305607359 446.094511593638 446.095717586437 446.096923585757 446.098129591598 446.099335603959 446.100541622841 446.101747648245 446.102953680169 446.104159718614 " "446.10536576358 446.106571815068 446.107777873076 446.108983937606 446.110190008657 446.111396086229 446.112602170323 446.113808260938 446.115014358075 446.116220461733 446.117426571913 446.118632688614 446.119838811837 446.121044941582 446.122251077849 446.123457220638 446.124663369948 446.12586952578 446.127075688135 446.128281857011 446.12948803241 446.130694214331 446.131900402774 446.133106597739 447.092888369096 447.09409976606 447.095311169589 447.096522579682 447.09773399634 447.098945419563 447.100156849351 447.101368285703 447.10257972862 447.103791178103 447.10500263415 447.106214096762 447.10742556594 447.108637041682 447.10984852399 447.111060012863 447.112271508302 447.113483010306 447.114694518875 447.115906034009 447.11711755571 447.118329083975 447.119540618807 447.120752160204 447.121963708167 447.123175262696 447.12438682379 447.125598391451 447.126809965677 447.128021546469 447.129233133828 447.130444727752 447.131656328243 449.794778250235 449.796004332987 449.797230422424 449.798456518544 449.799682621349 449.800908730839 449.802134847013 449.803360969872 449.804587099415 449.805813235643 449.807039378556 449.808265528153 476.291926493584 476.293301287096 476.294676088545 476.296050897931 476.297425715253 476.298800540512 476.300175373707 476.30155021484 476.30292506391 476.304299920917 476.305674785861 476.307049658742 487.815419569054 487.81686169142 487.818303822312 487.819745961732 487.821188109678 487.822630266151 487.824072431152 487.825514604679 487.826956786733 487.828398977315 487.829841176424 489.047206755368 489.048656169973 489.050105593169 489.051555024957 489.053004465336 489.054453914307 489.05590337187 489.057352838025 489.058802312771 489.06025179611 489.06170128804 489.063150788563 489.064600297678 489.066049815385 489.067499341685 494.497639238354 494.499121140501 494.500603051529 494.50208497144 494.503566900233 494.505048837908 494.506530784465 494.508012739904 494.509494704226 494.510976677431 494.512458659517 " "503.097384350016 503.098918243574 503.100452146485 503.10198605875 503.103519980368 503.10505391134 503.106587851665 503.108121801345 503.109655760378 503.111189728765 503.112723706507 503.114257693603 503.115791690052 503.117325695857 503.118859711015 503.120393735528 503.121927769396 503.123461812619 503.124995865196 504.057895208494 504.059434964655 504.060974730222 504.062514505197 504.064054289579 504.065594083369 504.067133886566 504.06867369917 504.070213521182 504.071753352602 504.073293193429 504.097931926196 504.099471926969 504.101011937151 504.102551956742 504.104091985743 504.105632024154 504.107172071974 504.108712129204 504.110252195844 504.111792271893 504.113332357353 504.114872452223 504.116412556503 504.117952670193 504.119492793294 504.121032925805 504.122573067726 504.124113219059 504.136434768509 504.137975004541 504.139515249984 504.141055504838 504.142595769105 504.144136042783 504.145676325873 504.147216618374 504.148756920288 504.150297231614 504.151837552352 504.153377882502 505.094736580555 505.096282677762 505.097828784435 505.099374900573 505.100921026176 505.102467161245 505.104013305779 505.105559459779 505.107105623245 505.108651796177 505.110197978574 505.111744170438 505.113290371768 505.114836582564 505.116382802826 505.117929032555 505.11947527175 505.121021520412 505.12256777854 506.095491214212 506.097043444127 506.098595683563 506.100147932522 506.101700191001 506.103252459003 506.104804736527 506.106357023573 506.107909320141 506.109461626231 506.111013941844 506.112566266978 506.114118601636 517.627784100423 517.62940787711 517.631031663984 517.632655461045 517.634279268294 517.635903085731 517.637526913356 517.639150751169 517.64077459917 517.642398457359 517.644022325736 519.117811946194 519.11944508466 519.121078233402 519.122711392419 519.124344561713 519.125977741282 519.127610931128 519.129244131249 519.130877341647 519.132510562322 519.134143793272 519.1357770345 519.137410286004 519.139043547785 519.140676819843 " "519.142310102177 519.143943394789 519.145576697678 519.147210010844 519.148843334287 519.150476668008 519.152110012007 519.153743366283 520.107741759837 520.109381132867 520.111020516231 520.11265990993 520.114299313963 520.115938728332 520.117578153035 520.119217588074 520.120857033448 520.122496489157 520.124135955201 520.125775431581 520.130693922735 520.132333440458 520.133972968517 520.135612506911 520.137252055643 520.13889161471 520.140531184113 520.142170763854 520.14381035393 520.145449954343 520.147089565093 520.14872918618 520.150368817604 520.152008459365 520.153648111463 520.155287773898 521.127785814089 521.129431623767 521.131077443839 521.132723274308 521.134369115172 521.136014966432 521.137660828088 521.13930670014 521.140952582588 521.142598475432 521.144244378673 521.14589029231 521.147536216343 531.114696350534 531.11640584546 531.118115351391 531.119824868327 531.121534396267 531.123243935212 531.124953485163 531.126663046119 531.12837261808 531.130082201046 531.131791795019 531.179664894929 531.181374808109 531.183084732298 531.184794667495 531.186504613701 531.188214570917 531.189924539141 531.191634518375 531.193344508618 531.195054509871 531.196764522133 531.198474545405 539.793121824335 539.79488764215 539.796653471517 539.798419312438 539.800185164913 539.80195102894 539.803716904521 539.805482791656 539.807248690344 539.809014600586 539.810780522383 544.657227988968 544.659025773986 544.660823570872 544.662621379626 544.664419200249 544.66621703274 544.6680148771 544.669812733329 544.671610601426 544.673408481392 544.675206373228 544.677004276933 544.678802192507 544.68060011995 544.682398059264 544.684196010447 544.685993973499 544.687791948422 544.689589935214 544.691387933877 564.063114662872 564.065042838848 564.066971028006 564.068899230347 564.07082744587 564.072755674577 564.074683916467 564.076612171539 564.078540439795 564.080468721235 564.082397015858 564.084325323664 564.086253644655 577.113045862246 577.115064289413 " "577.1170827307 577.119101186105 577.12111965563 577.123138139273 577.125156637036 577.127175148919 577.129193674921 577.131212215043 577.133230769285 577.135249337647 577.137267920129 577.139286516732 577.141305127455 577.143323752299 578.095668254573 578.09769356096 578.099718881538 578.101744216308 578.103769565269 578.105794928421 578.107820305765 578.1098456973 578.111871103028 578.113896522947 578.115921957059 578.117947405363 578.119972867859 578.121998344549 578.124023835431 578.126049340506 578.128074859774 578.130100393235 578.13212594089 578.134151502738 578.13617707878 578.138202669016 578.140228273445 578.142253892069 578.144279524888 578.1463051719 579.112127291178 579.114159725986 579.116192175059 579.118224638399 579.120257116005 579.122289607877 579.124322114016 579.126354634422 579.128387169095 579.130419718034 579.132452281241 579.134484858716 579.136517450457 579.138550056467 579.140582676744 579.142615311289 593.146836106552 593.148968246848 593.151100402472 593.153232573424 593.155364759706 593.157496961317 593.159629178256 593.161761410526 593.163893658125 593.166025921053 593.168158199311 593.1702904929 593.172422801818 593.174555126067 594.334675871054 594.336816559592 594.338957263551 594.341097982931 594.343238717732 594.345379467954 594.347520233598 594.349661014664 594.351801811151 594.35394262306 594.356083450392 594.358224293146 602.991717202929 602.993920708033 602.996124229242 602.998327766555 603.000531319973 603.002734889497 603.004938475125 603.007142076859 603.009345694699 603.011549328644 603.013752978696 603.015956644853 603.018160327117 603.020364025487 603.022567739964 603.024771470548 603.026975217238 647.653798614949 647.656340625328 647.65888265566 647.661424705948 647.66396677619 647.666508866388 647.669050976542 647.671593106651 647.674135256716 647.676677426738 647.679219616716 647.681761826651 647.684304056543 647.686846306392 647.689388576198 647.691930865962 647.694473175684 647.697015505364 647.699557855003 " "651.129472007141 651.132041374488 651.134610762114 651.137180170017 651.139749598198 651.142319046658 651.144888515396 651.147458004413 651.150027513709 651.152597043284 651.155166593139 651.157736163274 651.160305753689 651.162875364383 651.165444995359 651.168014646615 652.130488515969 652.133065789459 652.135643083321 652.138220397554 652.140797732159 652.143375087136 652.145952462485 652.148529858207 652.151107274301 652.153684710768 652.156262167609 652.158839644823 652.16141714241 652.163994660372 652.166572198708 652.169149757418 652.594726156514 652.597307100729 652.599888065358 652.602469050403 652.605050055862 652.607631081738 652.610212128029 652.612793194736 652.615374281859 652.617955389399 652.620536517356 653.126832071549 653.129417226335 653.132002401586 653.134587597302 653.137172813482 653.139758050129 653.142343307241 653.14492858482 653.147513882864 653.150099201375 653.152684540353 653.155269899798 653.157855279709 653.160440680089 653.163026100936 660.922514101737 660.925161337446 660.927808594361 660.930455872483 660.933103171812 660.935750492348 660.938397834091 660.941045197042 660.943692581201 660.946339986568 660.948987413144 660.951634860928 660.954282329921 660.983405888706 660.986053612226 660.988701356959 660.991349122903 660.993996910061 660.996644718431 660.999292548015 661.001940398812 661.004588270823 661.007236164048 661.009884078488 661.012532014142 664.411346114577 664.414021372197 664.41669665136 664.419371952069 664.422047274321 664.424722618119 664.427397983461 664.430073370349 664.432748778782 664.435424208761 664.438099660286 664.440775133357 664.443450627975 664.44612614414 664.448801681852 664.451477241112 664.454152821919 664.456828424273 664.459504048176 664.462179693628 664.464855360628 667.159443330433 667.162140764336 667.164838220052 667.16753569758 667.170233196922 667.172930718076 667.175628261044 667.178325825826 667.181023412421 667.183721020831 667.186418651055 667.189116303095 667.191813976949 " "667.194511672619 667.197209390104 667.199907129405 668.145457833561 668.148163246605 668.150868681559 668.153574138422 668.156279617196 668.158985117879 668.161690640472 668.164396184977 668.167101751392 668.169807339718 668.172512949956 668.175218582105 668.177924236166 668.180629912139 668.183335610025 668.186041329824 668.188747071536 668.19145283516 668.194158620699 668.196864428151 668.199570257517 670.158915513485 670.161637256666 670.164359021956 670.167080809353 670.16980261886 670.172524450475 670.175246304198 670.177968180032 670.180690077974 670.183411998027 670.186133940189 670.188855904462 670.191577890846 677.272020770102 677.274800597507 677.277580447732 677.280360320776 677.283140216641 677.285920135325 677.28870007683 677.291480041156 677.294260028303 677.297040038272 677.299820071062 677.302600126674 677.305380205108 677.308160306364 677.310940430444 677.313720577346 677.316500747072 677.319280939622 677.322061154995 677.324841393193 677.327621654214 677.330401938061 677.333182244733 677.33596257423 684.185792158615 684.188629030244 684.191465925398 684.194302844078 684.197139786283 684.199976752015 684.202813741274 684.205650754059 684.208487790372 684.211324850212 684.21416193358 684.216999040475 684.2198361709 684.222673324852 684.225510502334 685.302497766186 685.305343905889 685.308190069232 685.311036256217 685.313882466843 685.316728701111 685.319574959021 685.322421240572 685.325267545767 685.328113874604 685.330960227085 685.333806603209 685.336653002977 685.339499426388 685.345192344145 685.34803883849 685.350885356481 685.353731898117 685.356578463399 685.359425052328 685.362271664902 685.365118301123 685.367964960991 685.370811644507 685.37365835167 685.376505082481 686.165961086862 686.168814403222 686.171667743312 686.174521107133 686.177374494685 686.180227905968 686.183081340982 686.185934799728 686.188788282207 686.191641788417 686.19449531836 686.197348872036 699.464091765658 699.467056750447 699.470021760373 699.472986795436 " "699.475951855637 699.478916940975 699.481882051452 699.484847187067 699.487812347821 699.490777533714 699.493742744746 699.496707980919 699.499673242231 699.502638528684 699.505603840277 699.508569177012 699.511534538887 699.514499925905 707.540962759248 707.54399661424 707.54703049525 707.550064402278 707.553098335324 707.556132294389 707.559166279473 707.562200290576 707.565234327699 707.568268390842 707.571302480006 707.574336595191 707.577370736396 707.580404903623 707.583439096872 707.586473316143 707.589507561437 707.592541832753 707.595576130092 712.253358999635 712.256433401729 712.259507830364 712.26258228554 712.265656767258 712.268731275519 712.271805810321 712.274880371667 712.277954959555 712.281029573987 712.284104214963 714.637817537752 714.640912559113 714.644007607282 714.647102682261 714.650197784048 714.653292912646 714.656388068053 714.65948325027 714.662578459298 714.665673695137 714.668768957787 714.671864247249 725.142802571441 725.145989253758 725.149175964084 725.152362702418 725.155549468761 725.158736263113 725.161923085476 725.165109935848 725.168296814231 725.171483720624 725.174670655029 725.177857617445 725.181044607873 725.184231626314 725.187418672767 725.190605747233 725.193792849713 725.196979980206 726.144799061961 726.147994557046 726.151190080255 726.15438563159 726.15758121105 726.160776818635 726.163972454346 726.167168118184 726.170363810149 726.17355953024 726.176755278459 726.179951054806 726.183146859281 726.186342691885 726.189538552617 727.133547186777 727.136751390037 727.139955621536 727.143159881275 727.146364169255 727.149568485475 727.152772829936 727.155977202638 727.159181603583 727.162386032769 727.165590490198 727.16879497587 727.171999489785 727.175204031944 727.178408602347 727.181613200995 727.184817827887 727.188022483024 728.144269729676 728.147482846893 728.150695992466 728.153909166398 728.157122368687 728.160335599336 728.163548858343 728.16676214571 728.169975461436 728.173188805523 728.17640217797 " "728.179615578778 728.182829007947 728.623337067404 728.626554414027 728.629771789064 728.632989192515 728.63620662438 728.639424084659 728.642641573354 728.645859090464 728.64907663599 728.652294209931 728.65551181229 728.658729443065 739.579801260267 739.583116094462 739.586430958371 739.589745851995 739.593060775335 739.596375728391 739.599690711162 739.603005723651 739.606320765856 739.609635837779 739.61295093942 741.174345003278 741.177674146565 741.18100331976 741.184332522862 741.187661755872 741.190991018791 741.194320311618 741.197649634355 741.200978987002 741.204308369558 741.207637782025 741.210967224403 741.214296696693 741.217626198894 741.220955731007 741.224285293032 742.067626706004 742.070963878878 742.074301081766 742.077638314671 742.080975577592 742.08431287053 742.087650193485 742.090987546457 742.094324929448 742.097662342457 742.100999785484 742.104337258531 742.107674761597 742.111012294683 742.11434985779 742.117687450917 742.121025074066 742.124362727236 742.127700410428 742.131038123643 742.13437586688 742.137713640141 742.141051443425 742.174431127655 742.177769261226 742.181107424826 742.184445618454 742.187783842111 742.191122095798 742.194460379515 742.197798693263 742.201137037042 742.204475410852 742.207813814694 742.211152248568 742.214490712474 742.217829206413 742.221167730386 742.224506284392 742.227844868433 743.1470966977 743.150443586686 743.153790505819 743.157137455098 743.160484434525 743.1638314441 743.167178483823 743.170525553695 743.173872653716 743.177219783887 743.180566944208 743.183914134679 743.187261355301 743.190608606074 743.193955886998 743.197303198075 743.200650539304 743.203997910686 743.20734531222 743.210692743909 743.214040205752 743.217387697749 743.220735219901 743.224082772208 743.227430354671 743.23077796729 744.176009584717 744.179365747906 744.182721941368 744.186078165103 744.18943441911 744.192790703391 744.196147017945 744.199503362773 744.202859737876 744.206216143254 744.209572578908 " "744.212929044837 744.216285541042 744.219642067524 744.222998624283 758.202410978174 758.205894849435 758.209378752713 758.212862688007 758.216346655318 758.219830654647 758.223314685994 758.226798749359 758.230282844744 758.233766972148 758.237251131571 758.240735323015 758.24421954648 758.247703801965 758.251188089473 758.254672409002 759.203597733713 759.207090811794 759.210583922019 759.214077064387 759.2175702389 759.221063445557 759.22455668436 759.228049955308 759.231543258401 759.235036593642 759.238529961029 759.242023360563 759.245516792245 759.249010256075 760.200427521877 760.203929778783 760.207432067959 760.210934389405 760.214436743123 760.217939129111 760.221441547372 760.224943997905 760.228446480711 760.231948995789 760.235451543142 760.238954122768 760.24245673467 760.316019040799 760.319522362853 760.323025717192 760.326529103815 760.330032522725 760.33353597392 760.337039457402 760.340542973171 760.344046521228 760.347550101572 760.351053714205 760.354557359126 760.358061036338 760.361564745838 777.189954415057 777.193614963706 777.197275546837 777.200936164451 777.204596816548 777.208257503129 777.211918224194 777.215578979744 777.219239769779 777.2229005943 777.226561453308 777.230222346802 777.233883274784 777.237544237253 799.160490663856 799.164361099883 799.1682315734 799.172102084408 799.175972632907 799.179843218898 799.183713842382 799.187584503358 799.191455201828 799.195325937792 799.19919671125 799.203067522204 799.206938370653 799.210809256599 799.214680180041 799.21855114098 800.16418774129 800.168067905512 800.171948107365 800.175828346849 800.179708623967 800.183588938718 800.187469291103 800.191349681123 800.195230108777 800.199110574067 800.202991076993 800.206871617555 800.210752195754 801.158739593593 801.162629409414 801.166519263006 801.170409154372 801.174299083511 801.178189050424 801.182079055111 801.185969097572 801.18985917781 801.193749295823 801.197639451613 801.20152964518 801.205419876525 801.209310145647 " "801.213200452549 810.055165196855 810.059141881054 810.063118604297 810.067095366586 810.07107216792 810.0750490083 810.079025887728 810.083002806202 810.086979763725 810.090956760296 810.094933795916 810.098910870585 810.102887984305 810.106865137076 815.189564537267 815.19359179245 815.197619087424 815.20164642219 815.205673796749 815.209701211101 815.213728665248 815.217756159189 815.221783692925 815.225811266457 815.229838879786 815.233866532911 815.237894225833 815.241921958555 815.245949731074 815.249977543393 815.395005298192 815.3990345835 815.40306390863 815.407093273582 815.411122678358 815.415152122956 815.419181607379 815.423211131626 815.427240695699 815.431270299597 815.435299943322 815.439329626874 816.169358934812 816.17339587673 816.177432858584 816.181469880374 816.1855069421 816.189544043764 816.193581185365 816.197618366904 816.201655588382 816.2056928498 816.209730151157 816.213767492455 816.217804873695 816.221842294876 816.225879756 816.229917257066 816.233954798077 816.237992379031 816.24202999993 816.246067660775 816.250105361565 816.254143102302 817.183885871236 817.187932855536 817.19197987992 817.196026944389 817.200074048944 817.204121193585 817.208168378313 817.212215603128 817.216262868032 817.220310173024 817.224357518104 817.228404903275 817.232452328536 817.236499793888 817.240547299332 817.244594844868 817.248642430496 817.252690056218 818.164426363991 818.16848306611 818.172539808458 818.176596591035 818.180653413842 818.18471027688 818.18876718015 818.192824123651 818.196881107384 818.200938131351 818.204995195551 818.209052299986 818.213109444656 818.21716662956 818.221223854701 818.225281120079 818.229338425694 818.233395771546 818.237453157638 818.241510583968 818.245568050537 818.249625557347 819.18392233678 819.18798915515 819.1920560139 819.19612291303 819.200189852541 819.204256832432 819.208323852706 819.212390913362 819.216458014401 819.220525155824 819.224592337631 819.228659559823 819.2327268224 819.236794125363 " "819.240861468713 819.24492885245 820.193731546341 820.197808397262 820.201885288712 820.205962220691 820.210039193201 820.214116206241 820.218193259813 820.222270353916 820.226347488553 820.230424663722 820.234501879425 820.238579135663 832.21883436359 832.223031634984 832.227228948716 832.231426304787 832.235623703196 832.239821143946 832.244018627035 832.248216152466 832.252413720239 832.256611330353 832.260808982811 832.265006677613 832.269204414758 832.273402194249 832.277600016085 832.281797880267 832.285995786796 832.290193735673 832.294391726897 832.298589760471 833.218980432568 833.223187798465 833.227395206852 833.231602657731 833.235810151102 833.240017686965 833.244225265321 833.248432886172 833.252640549516 833.256848255356 833.261056003692 833.265263794525 833.269471627854 833.273679503681 834.221533310184 834.225750807043 834.229968346546 834.234185928695 834.238403553488 834.242621220928 834.246838931015 834.251056683749 834.255274479132 834.259492317163 834.263710197844 834.267928121174 835.218046494203 835.222274073065 835.226501694725 835.230729359182 835.234957066438 835.239184816494 835.243412609349 835.247640445004 835.251868323461 835.256096244719 835.26032420878 835.264552215644 835.268780265312 835.273008357784 835.277236493061 873.174235302306 873.178855854748 873.18347645609 873.188097106335 873.192717805482 873.197338553533 873.201959350488 873.206580196348 873.211201091114 873.215822034786 873.220443027366 873.225064068854 873.229685159251 873.234306298558 873.238927486775 874.17804253512 874.182673717335 874.18730494862 874.191936228976 874.196567558404 874.201198936904 874.205830364477 874.210461841124 874.215093366845 874.219724941642 874.224356565516 874.228988238466 874.233619960494 874.238251731601 874.303101680785 874.307734188164 874.312366744634 874.316999350196 874.321632004851 874.3262647086 874.330897461442 874.335530263379 874.340163114412 874.344796014542 874.349428963769 874.354061962094 875.174876842222 875.179518592457 " "875.184160391931 875.188802240643 875.193444138596 875.198086085788 875.202728082222 875.207370127898 875.212012222817 875.216654366978 875.221296560385 875.225938803036 875.230581094934 889.200602342844 889.205394064883 889.210185838565 889.214977663891 889.219769540862 889.224561469479 889.229353449744 889.234145481656 889.238937565216 889.243729700426 889.248521887286 889.253314125797 889.25810641596 889.262898757776 889.267691151245 889.272483596368 889.277276093147 889.282068641582 889.286861241673 889.291653893423 889.296446596831 889.301239351898 889.306032158626 889.310825017014 889.315617927065 889.320410888778 889.325203902155 889.329996967196 889.334790083902 890.02073813417 890.0255386994 890.030339316416 890.03513998522 890.039940705812 890.044741478193 890.049542302364 890.054343178326 890.059144106079 890.063945085625 890.068746116964 890.073547200097 890.078348335025 890.083149521749 890.174381911812 890.179184134627 890.183986409256 890.188788735699 890.193591113957 890.198393544031 890.203196025921 890.207998559629 890.212801145155 890.217603782501 890.222406471667 890.227209212653 890.232012005462 890.236814850093 890.241617746547 890.246420694826 890.25122369493 890.25602674686 890.260829850616 890.2656330062 890.270436213613 890.275239472855 890.280042783927 891.198426546905 891.203239824931 891.208053154948 891.212866536959 891.217679970964 891.222493456964 891.22730699496 891.232120584952 891.236934226942 891.24174792093 891.246561666917 891.251375464905 891.256189314893 891.261003216882 891.265817170875 891.27063117687 891.27544523487 891.280259344875 892.200708915166 892.205533025772 892.210357188546 892.21518140349 892.220005670603 892.224829989886 892.229654361341 892.234478784968 892.239303260768 892.244127788742 892.248952368891 892.253777001215 892.258601685716 892.263426422395 892.268251211251 892.273076052286 893.142398272161 893.147232571559 893.15206692329 893.156901327355 893.161735783755 893.166570292491 893.171404853563 " "893.176239466974 893.181074132723 893.185908850811 893.190743621239 893.20041331912 893.205248246574 893.210083226371 893.214918258513 893.219753343 893.224588479834 893.229423669014 893.234258910542 893.239094204419 893.243929550645 893.248764949222 893.25360040015 893.25843590343 893.263271459063 893.26810706705 893.272942727391 894.197514830975 894.202360559179 894.207206339903 894.212052173146 894.21689805891 894.221743997196 894.226589988005 894.231436031336 894.236282127192 894.241128275573 894.24597447648 894.250820729913 894.255667035874 894.260513394364 894.265359805383 894.270206268932 906.234202718878 906.239179781027 906.244156897845 906.249134069332 906.25411129549 906.259088576319 906.26406591182 906.269043301994 906.274020746843 906.278998246366 906.283975800565 906.288953409441 906.293931072995 906.298908791226 907.235692252254 907.240680320926 907.245668444448 907.250656622821 907.255644856045 907.260633144123 907.265621487054 907.270609884839 907.27559833748 907.280586844978 907.285575407332 907.290564024546 907.295552696618 907.30054142355 908.234398692328 908.239397749042 908.244396860787 908.249396027565 908.254395249375 908.25939452622 908.2643938581 908.269393245016 908.274392686968 908.279392183959 908.284391735988 908.289391343056 922.842856257044 922.84801742175 922.853178644185 922.858339924351 922.86350126225 922.86866265788 922.873824111245 922.878985622344 922.884147191179 922.88930881775 922.894470502059 934.042623867136 934.0479110658 934.053198324322 934.058485642702 934.063773020941 934.069060459041 934.074347957002 934.079635514825 934.084923132512 934.090210810063 934.09549854748 934.100786344763 934.106074201913 934.111362118932 962.94815872668 962.953778232548 962.959397804004 962.96501744105 962.970637143686 962.976256911914 962.981876745735 962.987496645149 962.993116610159 962.998736640765 963.004356736968 963.00997689877 963.217969011729 963.223591667127 963.229214388169 963.234837174856 963.240460027188 963.246082945167 " "963.251705928794 963.257328978069 963.262952092996 963.268575273574 963.274198519804 963.279821831688 963.285445209227 963.291068652422 963.296692161274 963.302315735784 963.307939375954 963.313563081784 963.319186853277 963.324810690432 963.420425969611 963.426050988895 963.431676073865 963.43730122452 963.442926440862 963.448551722892 963.454177070612 963.459802484022 963.465427963124 963.471053507919 963.476679118408 963.482304794592 964.21420252401 964.219836816216 964.225471174269 964.23110559817 964.236740087921 964.242374643523 964.248009264976 964.253643952283 964.259278705443 964.26491352446 964.270548409332 964.276183360063 964.281818376652 964.287453459101 964.293088607411 964.298723821583 964.304359101619 964.309994447519 964.315629859286 964.321265336919 964.32690088042 964.33253648979 964.338172165031 964.343807906143 964.349443713128 964.355079585987 964.36071552472 964.36635152933 964.467810878442 964.473448134917 964.479085457292 964.484722845568 964.490360299745 964.495997819824 964.501635405808 964.507273057696 964.512910775491 964.518548559193 964.524186408804 964.529824324324 965.201207199106 965.206853032182 965.212498931307 965.218144896483 965.223790927711 965.229437024992 965.235083188328 965.240729417718 965.246375713166 965.252022074672 965.257668502236 965.26331499586 965.268961555546 965.274608181294 965.280254873106 965.285901630983 965.291548454925 965.297195344935 965.302842301012 965.308489323159 965.314136411377 965.319783565667 965.325430786029 965.331078072465 966.212864647697 966.218522322157 966.224180062874 966.22983786985 966.235495743085 966.241153682582 966.246811688342 966.252469760364 966.258127898651 966.263786103204 966.269444374024 966.275102711111 966.280761114469 966.286419584096 966.292078119995 966.297736722167 966.303395390612 966.309054125333 966.31471292633 966.320371793604 966.326030727157 967.215306113877 967.220975534084 967.226645020755 967.232314573891 967.237984193494 967.243653879564 967.249323632103 " "967.254993451112 967.260663336592 967.266333288544 967.272003306969 967.277673391869 967.283343543245 967.289013761098 967.294684045428 967.300354396238 967.306024813528 967.3116952973 967.317365847555 967.323036464293 967.328707147517 967.334377897227 967.340048713424 967.345719596109 967.351390545285 980.194309595126 980.200132191883 980.205954857816 980.211777592926 980.217600397214 980.223423270681 980.229246213329 980.235069225159 980.240892306172 980.24671545637 980.252538675753 980.258361964323 980.264185322081 980.270008749028 980.275832245166 980.281655810496 980.287479445018 980.293303148735 980.299126921648 980.304950763757 980.310774675063 980.31659865557 980.322422705276 989.849128120579 989.855065986618 989.861003923897 989.866941932417 989.872880012179 989.878818163186 989.884756385438 989.890694678936 989.896633043682 989.902571479677 989.908509986923 989.91444856542 1024.22504311064 1024.23140056509 1024.23775809846 1024.24411571076 1024.25047340198 1024.25683117213 1024.26318902121 1024.26954694921 1024.27590495616 1024.28226304203 1024.28862120684 1024.29497945058 1024.30133777326 1024.30769617489 1024.31405465545 1024.32041321495 1024.3267718534 1024.3331305708 1024.33948936714 1024.62571693597 1024.63207936544 1024.63844187393 1024.64480446143 1024.65116712796 1024.6575298735 1024.66389269807 1024.67025560165 1024.67661858427 1024.6829816459 1024.68934478657 1024.69570800627 1024.80389483394 1024.8102594764 1024.81662419793 1024.82298899851 1024.82935387816 1024.83571883686 1024.84208387463 1024.84844899146 1024.85481418736 1024.86117946232 1024.86754481635 1024.87391024946 1024.88027576163 1024.88664135288 1037.17792520177 1037.18444447285 1037.19096382588 1037.19748326088 1037.20400277783 1037.21052237674 1037.21704205761 1037.22356182045 1037.23008166525 1037.23660159202 1037.24312160075 1037.24964169146 1037.25616186413 1037.26268211878 1037.2692024554 1037.275722874 1037.28224337457 1037.28876395712 1037.29528462166 1037.30180536817 " "1037.30832619667 1037.31484710715 1037.32136809962 1037.32788917408 1038.22205208364 1038.22858448726 1038.2351169731 1038.24164954113 1038.24818219137 1038.25471492382 1038.26124773848 1038.26778063535 1038.27431361443 1038.28084667573 1038.28737981924 1038.29391304497 1038.30044635292 1038.30697974309 1038.31351321548 1038.32004677009 1038.32658040693 1039.22901160479 1039.235556686 1039.24210184966 1039.24864709577 1039.25519242432 1039.26173783531 1039.26828332876 1039.27482890466 1039.28137456301 1039.28792030381 1039.29446612706 1039.30101203278 1039.30755802095 1039.31410409158 1039.32065024467 1039.32719648023 1039.33374279825 1039.34028919873 1039.34683568169 1040.22481095549 1040.23136858588 1040.23792629894 1040.24448409469 1040.25104197312 1040.25759993424 1040.26415797804 1040.27071610453 1040.27727431371 1040.28383260558 1040.29039098014 1040.2969494374 1040.30350797735 1040.3100666 1040.31662530535 1040.32318409339 1040.32974296414 1041.2290907215 1041.2356610201 1041.24223140163 1041.24880186607 1041.25537241343 1041.26194304372 1041.26851375694 1041.27508455308 1041.28165543215 1041.28822639415 1041.29479743909 1041.30136856695 1041.30793977776 1041.3145110715 1041.32108244817 1041.32765390779 1041.33422545035 1041.34079707585 1041.3473687843 1041.35394057569 1041.36051245003 1041.36708440732 1041.37365644756 1041.38022857076 1041.3868007769 1041.39337306601 1041.39994543807 1041.40651789309 1041.41309043107 1041.41966305201 1088.79279195134 1088.79997622919 1088.80716060185 1088.81434506932 1088.82152963161 1088.82871428871 1088.83589904063 1088.84308388737 1088.85026882893 1088.85745386531 1088.86463899652 1098.12539546821 1098.13270343459 1098.14001149825 1098.14731965918 1098.15462791738 1098.16193627285 1098.1692447256 1098.17655327563 1098.18386192294 1098.19117066753 1098.19847950941 1098.20578844857 1098.21309748502 1098.22040661877 1098.2277158498 1098.23502517813 1098.24233460375 1098.24964412667 1098.2569537469 1098.26426346442 " "1098.27157327925 1111.23703980607 1111.2445233295 1111.25200695373 1111.25949067876 1111.26697450458 1111.27445843121 1111.28194245863 1111.28942658687 1111.29691081591 1111.30439514576 1111.31187957642 1111.31936410789 1111.32684874018 1111.33433347329 1111.34181830722 1111.34930324196 1112.25572512581 1112.26322237607 1112.27071972739 1112.27821717979 1112.28571473327 1112.29321238783 1112.30071014346 1112.30820800018 1112.31570595798 1112.32320401687 1112.33070217685 1112.33820043792 1112.34569880008 1112.41318860905 1112.42068798226 1112.42818745657 1112.43568703201 1112.44318670856 1112.45068648624 1112.45818636504 1112.46568634496 1112.47318642601 1112.48068660819 1112.48818689151 1112.49568727595 1112.50318776154 1112.57819818028 1112.58569977849 1112.59320147786 1112.60070327839 1112.60820518009 1112.61570718295 1112.62320928699 1112.63071149219 1112.63821379856 1112.64571620611 1112.65321871484 1112.66072132475 1114.26108654592 1114.26861085524 1114.27613526618 1114.28365977874 1114.29118439293 1114.29870910874 1114.30623392618 1114.31375884525 1114.32128386596 1114.32880898829 1114.33633421227 1115.25517475482 1115.2627124958 1115.27025033867 1115.27778828344 1115.28532633011 1115.29286447867 1115.30040272913 1115.3079410815 1115.31547953577 1115.32301809195 1115.33055675004 1115.33809551004 1115.34563437195 1130.2815779083 1130.28932013803 1130.29706247383 1130.30480491569 1130.31254746363 1130.32029011764 1130.32803287773 1130.33577574389 1130.34351871613 1130.35126179446 1130.35900497886 1147.66276619636 1147.67074837394 1147.67873066254 1147.68671306219 1147.69469557288 1147.70267819461 1147.71066092738 1147.7186437712 1147.72662672607 1147.73460979199 1147.74259296897 1147.750576257 1147.75855965609 1147.76654316625 1147.77452678746 1182.98466783959 1182.99314891893 1183.00163011987 1183.01011144242 1183.01859288659 1183.02707445237 1183.03555613976 1183.04403794878 1183.05251987942 1183.06100193168 1183.06948410557 1183.07796640108 1183.1712796801 " "1183.17976343539 1183.18824731234 1183.19673131095 1183.20521543123 1183.21369967318 1183.22218403681 1183.23066852212 1183.2391531291 1183.24763785777 1183.25612270812 1183.26460768015 1183.27309277388 1183.68052043171 1183.68901149146 1183.69750267303 1183.70599397643 1183.71448540165 1183.7229769487 1183.73146861758 1183.7399604083 1183.74845232085 1183.75694435525 1183.76543651148 1183.77392878956 1188.27493289966 1188.28349000304 1188.29204722968 1188.30060457956 1188.30916205269 1188.31771964907 1188.32627736871 1188.3348352116 1188.34339317776 1188.35195126718 1188.36050947987 1209.74923184622 1209.75810103042 1209.76697034466 1209.77583978896 1209.78470936331 1209.79357906772 1209.80244890218 1209.81131886671 1209.82018896131 1209.82905918597 1209.83792954071 1209.87341226042 1209.88228326555 1209.89115440077 1209.90002566609 1209.9088970615 1209.917768587 1209.92664024261 1209.93551202832 1209.94438394413 1209.95325599005 1209.96212816609 1214.99579864251 1215.00474492341 1215.01369133607 1215.02263788047 1215.03158455663 1215.04053136455 1215.04947830422 1215.05842537566 1215.06737257887 1215.07631991384 1215.08526738058 1215.0942149791 1215.10316270939 1215.11211057146 1240.4233010027 1240.43262565993 1240.44195045736 1240.45127539499 1240.46060047282 1240.46992569085 1240.47925104909 1240.48857654754 1240.4979021862 1240.50722796507 1240.51655388417 1240.52587994349 1240.53520614303 1240.5445324828 1243.04905650569 1243.05842068214 1243.06778499968 1243.0771494583 1243.08651405802 1243.09587879883 1243.10524368075 1243.11460870376 1243.12397386788 1243.13333917311 1243.14270461945 1243.15207020691 1243.16143593548 1243.17080180517 1243.18016781599 1243.18953396794 1250.94602927114 1250.95551280543 1250.96499648351 1250.97448030538 1250.98396427106 1250.99344838053 1251.00293263381 1251.0124170309 1251.0219015718 1251.03138625652 1251.04087108505 1251.05035605741 1261.31128248752 1261.32092383336 1261.33056532659 1261.34020696722 1261.34984875525 " "1261.35949069069 1261.36913277353 1261.37877500379 1261.38841738147 1261.39805990657 1261.40770257909 1261.94792763215 1261.95757871339 1261.96722994224 1261.97688131873 1261.98653284283 1261.99618451457 1262.00583633394 1262.01548830095 1262.02514041559 1262.03479267788 1262.04444508782 1262.05409764541 1262.06375035065 1262.07340320354 1262.32442921749 1262.33408605841 1262.34374304707 1262.35340018349 1262.36305746766 1262.3727148996 1262.3823724793 1262.39203020678 1262.40168808202 1262.41134610504 1262.42100427584 1262.43066259442 1262.44032106079 1263.28117374346 1263.29084522825 1263.30051686113 1263.31018864211 1263.31986057118 1263.32953264835 1263.33920487361 1263.34887724699 1263.35854976847 1263.36822243806 1263.37789525577 1263.3875682216 1263.39724133555 1263.40691459763 1265.31544052296 1265.32514318102 1265.33484598788 1265.34454894355 1265.35425204803 1265.36395530132 1265.37365870343 1265.38336225437 1265.39306595413 1265.40276980271 1265.41247380013 1265.42217794639 1273.46930606141 1273.47913417338 1273.48896243705 1273.49879085242 1273.5086194195 1273.51844813829 1273.5282770088 1273.53810603102 1273.54793520496 1273.55776453063 1273.56759400803 1273.57742363715 1273.58725341802 1273.59708335062 1273.60691343496 1273.61674367105 1273.62657405888 1281.32087896611 1281.33082864257 1281.34077847355 1281.35072845906 1281.3606785991 1281.37062889368 1281.38057934279 1281.39052994644 1281.40048070464 1281.41043161738 1281.42038268468 1281.43033390653 1281.44028528294 1281.45023681392 1281.46018849946 1281.47014033957 1281.48009233426 1293.16997731079 1293.18011185941 1293.19024656688 1293.2003814332 1293.21051645839 1293.22065164243 1293.23078698534 1293.24092248711 1293.25105814776 1293.26119396729 1293.27132994569 1293.28146608298 1409.30396671911 1409.31600329167 1409.32804006984 1409.34007705362 1409.35211424301 1409.36415163802 1409.37618923866 1409.38822704493 1409.40026505684 1409.4123032744 1409.4243416976 1409.43638032645 1439.81291838247 " "1439.82548173949 1439.83804531576 1439.85060911129 1439.86317312607 1439.87573736013 1439.88830181346 1439.90086648606 1439.91343137795 1439.92599648913 1439.93856181961 1439.97625912687 1439.98882533458 1440.00139176163 1440.013958408 1440.0265252737 1440.03909235875 1440.05165966315 1440.0642271869 1440.07679493 1440.08936289247 1440.10193107432 1456.39679555874 1456.40964999523 1456.42250465864 1456.43535954896 1456.44821466621 1456.46107001039 1456.47392558151 1456.48678137957 1456.49963740459 1456.51249365655 1456.52535013548 1456.53820684138 1456.55106377425 1456.5639209341 1456.57677832093 1469.49643693345 1469.5095236508 1469.52261060125 1469.5356977848 1469.54878520145 1469.56187285121 1469.57496073409 1469.58804885009 1469.60113719922 1469.61422578149 1469.6273145969 1469.64040364545 1477.46994793765 1477.48317705841 1477.49640641608 1477.50963601066 1477.52286584217 1477.53609591059 1477.54932621596 1477.56255675826 1477.5757875375 1477.58901855369 1477.60224980685 1477.61548129696 1477.62871302405 1477.64194498811 1477.65517718916 1477.6684096272 1477.68164230223 1477.69487521426 1477.7081083633 1477.72134174936 1478.91331787051 1478.9265728516 1478.93982807029 1478.9530835266 1478.96633922051 1478.97959515204 1478.99285132121 1479.006107728 1479.01936437244 1479.03262125452 1479.04587837426 1480.17360285036 1480.18688043216 1480.20015825217 1480.2134363104 1480.22671460685 1480.23999314153 1480.25327191444 1480.2665509256 1480.279830175 1480.29310966266 1480.30638938858 1480.31966935276 1480.33294955522 1480.34622999596 1480.35951067499 1480.37279159231 1480.38607274793 1480.39935414185 1480.41263577409 1480.42591764464 1480.73146645809 1480.74475405022 1480.75804188082 1480.77132994991 1480.78461825749 1480.79790680357 1480.81119558816 1480.82448461126 1480.83777387287 1480.85106337301 1480.86435311168 1480.87764308888 1480.89093330463 1480.90422375893 1480.91751445178 1480.9308053832 1480.94409655318 1480.95738796174 1480.97067960888 1480.983971494 " "1480.99726361894 1481.01055598187 1481.0238485834 1481.03714142355 1481.05043450231 1481.06372781971 1481.07702137574 1481.34294261915 1481.35624118796 1481.36953999554 1481.38283904191 1481.39613832706 1481.409437851 1481.42273761375 1481.4360376153 1481.44933785567 1481.46263833486 1481.47593905287 1481.48924000971 1481.50254120539 1481.51584263992 1481.5291443133 1481.54244622554 1481.55574837664 1481.56905076662 1481.58235339547 1481.5956562632 1481.60895936983 1481.62226271535 1481.63556629978 1481.64887012311 1481.66217418536 1481.67547848654 1482.36763154258 1482.38094851586 1482.39426572841 1482.40758318025 1482.42090087136 1482.43421880177 1482.44753697147 1482.46085538047 1482.47417402879 1482.48749291642 1482.50081204337 1482.51413140965 1482.52745101526 1482.54077086022 1493.62532276273 1493.63884277381 1493.65236302966 1493.66588353027 1493.67940427566 1493.69292526583 1493.70644650079 1493.71996798055 1493.73348970511 1493.74701167448 1493.76053388867 1493.77405634768 1511.59045068974 1511.60429789207 1511.6181453481 1511.63199305785 1511.64584102131 1511.65968923849 1511.6735377094 1511.68738643405 1511.70123541244 1511.71508464459 1511.72893413049 1599.95476419777 1599.97027768381 1599.98579147069 1600.00130555844", "0 0 0 0 0 0 0 0 0 193.855026245117 641.106506347656 877.26220703125 700.196716308594 274.883911132813 0 0 0 0 0 0 0 0 0 0 224.89469909668 511.670349121094 595.136657714844 452.148010253906 234.596389770508 74.6820220947266 0 0 0 0 0 0 0 0 119.225784301758 185.543075561523 200.134750366211 188.900192260742 160.073196411133 0 0 0 0 0 0 0 172.296859741211 200.144027709961 165.512985229492 0 0 0 0 0 0 0 0 83.4415893554688 208.525405883789 177.816024780273 100.466018676758 0 0 0 0 0 0 0 0 93.3426513671875 177.81330871582 221.383926391602 233.153823852539 185.899673461914 84.1839904785156 0 0 0 0 0 0 0 0 126.048049926758 184.371139526367 97.8295288085938 0 0 0 0 0 0 0 0 25.8681793212891 261.258850097656 531.637878417969 574.53076171875 413.904724121094 218.982650756836 112.732650756836 0 0 0 0 0 0 0 0 94.0497131347656 191.148391723633 161.991897583008 0 0 0 0 0 0 0 402.995788574219 1600.27600097656 3017.67749023438 3685.970703125 3078.0078125 1699.85888671875 531.254028320313 44.9793395996094 0 0 0 0 0 0 0 0 3.05120849609375 326.982971191406 918.194396972656 1295.37927246094 1141.49755859375 577.818969726563 26.3272705078125 0 0 0 0 0 0 0 0 125.907791137695 264.531921386719 266.280029296875 158.506088256836 0 0 0 0 0 0 0 0 45.1534271240234 245.012252807617 337.062133789063 230.558639526367 35.3934326171875 0 0 0 0 0 0 0 0 21.4011077880859 269.609924316406 302.905334472656 3843.85766601563 9906.61328125 14627.65625 14086.5751953125 8667.4873046875 2666.59497070313 152.549850463867 452.571411132813 21.2885437011719 0 0 0 0 0 0 0 0 0 242.630386352539 1476.34033203125 2982.52856445313 3656.2958984375 2926.99194335938 1440.77648925781 378.651611328125 617.814758300781 1036.13317871094 1038.09765625 677.166748046875 273.266662597656 106.01123046875 0 0 0 0 0 0 0 0 0 644.765441894531 1669.39282226563 2428.14697265625 2279.11108398438 1350.7001953125 456.782958984375 195.992416381836 144.774459838867 138.42707824707 203.370742797852 302.340209960938 350.181884765625 " "314.466613769531 225.259658813477 125.442489624023 0 0 0 0 0 0 0 0 0 229.676986694336 1286.525390625 3076.466796875 4448.58984375 4288.94775390625 2695.29956054688 856.980102539063 0 0 0 0 0 0 0 0 0 0 297.09423828125 790.947937011719 1078.3701171875 895.997009277344 377.297119140625 0 0 0 0 0 0 0 0 0 54.2761840820313 380.800170898438 604.678894042969 530.256896972656 239.020004272461 14.5890960693359 0 0 0 0 0 0 0 0 0 315.951721191406 1584.78002929688 3584.27490234375 4964.8896484375 4550.10595703125 2648.34790039063 761.737854003906 336.893249511719 327.000427246094 103.404342651367 0 0 0 0 0 0 0 0 137.308151245117 232.669479370117 225.336959838867 131.02082824707 0 0 0 0 0 0 0 0 0 309.901550292969 806.588073730469 1159.07531738281 1105.30993652344 695.416931152344 245.27473449707 13.4951171875 0 0 0 0 0 0 0 0 114.433959960938 215.006851196289 272.628845214844 187.665817260742 12.0498352050781 0 0 0 0 0 0 0 0 127.550247192383 182.018173217773 211.423233032227 191.385147094727 141.782333374023 0 0 0 0 0 0 0 0 0 745.767456054688 2422.9541015625 3720.92529296875 3568.47998046875 2088.86743164063 510.764953613281 183.886978149414 136.265151977539 0 0 0 0 0 0 0 0 171.257888793945 188.640060424805 192.395614624023 154.632247924805 0 0 0 0 0 0 0 0 130.887710571289 642.11865234375 1160.51184082031 1294.43505859375 977.964050292969 544.39794921875 308.192199707031 211.437362670898 76.1909332275391 0 0 0 0 0 0 0 0 0 229.855178833008 543.525207519531 586.220275878906 314.952575683594 0 0 0 0 0 0 0 0 0 154.422073364258 196.758010864258 149.831283569336 0 0 0 0 0 0 0 0 123.318832397461 188.429489135742 169.386795043945 0 0 0 0 0 0 0 0 2959.08642578125 8616.0419921875 13691.96484375 14140.76953125 9577.6708984375 3752.03759765625 393.419616699219 324.138061523438 232.52278137207 0 0 0 0 0 0 0 0 0 133.11164855957 205.964584350586 199.730422973633 139.437789916992 0 0 0 0 0 0 0 0 101.496200561523 185.133193969727 259.655029296875 244.710922241211 160.866897583 0 0 0 0 0 0 0 0 " "171.158157348633 209.737930297852 216.904006958008 153.206130981445 0 0 0 0 0 0 0 0 0 1064.01928710938 2744.22631835938 3925.62744140625 3728.50854492188 2484.57104492188 1484.09924316406 1184.474609375 801.294799804688 276.304870605469 0 0 0 0 0 0 0 0 0 0 300.0966796875 1263.98876953125 2300.80615234375 2527.240234375 1658.1162109375 416.934509277344 362.052856445313 510.349609375 422.890075683594 293.749877929688 96.1615142822266 0 0 0 0 0 0 0 0 277.112182617188 552.278137207031 634.911743164063 465.758728027344 230.118118286133 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 338.728454589844 100.444885253906 1113.40734863281 4002.13525390625 6734.62841796875 7179.69189453125 4943.12939453125 1888.85778808594 87.8339996337891 0 0 0 0 0 0 0 0 166.607498168945 203.203231811523 88.5599517822266 0 0 134.797103881836 252.799118041992 321.236206054688 317.407653808594 177.626174926758 0 0 0 0 0 0 0 0 420.235168457031 1400.63110351563 2127.62890625 2036.72399902344 1375.9619140625 1018.35345458984 909.901550292969 528.322021484375 118.658309936523 0 0 0 0 0 0 0 0 6.52516174316406 184.584854125977 399.570495605469 472.823852539063 311.700012207031 67.0648040771484 0 0 0 0 0 0 0 0 4.97833251953125 518.760131835938 1195.45788574219 1522.00109863281 1192.40087890625 457.996826171875 236.555740356445 455.735107421875 494.134094238281 419.947204589844 169.757431030273 0 0 0 0 0 0 0 0 158.202651977539 249.356582641602 255.182876586914 181.06364440918 0 0 0 0 0 0 0 0 173.365737915039 243.861038208008 222.755081176758 104.503341674805 0 0 0 0 0 0 0 0 127.732864379883 184.066452026367 159.648910522461 0 0 0 0 0 0 0 0 0 216.264389038086 564.540100097656 758.490661621094 593.172241210938 186.406509399414 0 0 0 0 0 0 0 0 0 57.8870544433594 189.093154907227 180.032363891602 0 0 0 0 0 0 0 0 107.181259155273 588.624389648438 3296.2294921875 6859.40966796875 8629.48046875 6954.76904296875 3204.29370117188 530.406066894531 701.101257324219 446.318359375 172.379989624023 0 0 0 0 0 0 0 0 " "106.025817871094 219.603103637695 171.653244018555 0 0 0 0 0 0 0 0 66.6060028076172 816.289489746094 2058.00170898438 2839.88916015625 2264.32885742188 887.272766113281 1098.07897949219 1184.8994140625 515.840759277344 0 0 0 0 0 0 0 0 0 107.923675537109 213.511978149414 238.096145629883 157.005569458008 0 0 0 0 0 0 0 0 84.7611541748047 279.91943359375 997.471740722656 1668.52087402344 1678.548828125 1062.6884765625 456.879150390625 261.066772460938 414.542724609375 400.814636230469 181.47590637207 0 0 0 0 0 0 0 0 162.703384399414 402.678283691406 606.938415527344 584.632751464844 322.495727539063 0 0 0 0 0 0 0 0 203.609512329102 221.824447631836 103.749816894531 0 0 0 0 0 0 0 0 139.273239135742 246.041458129883 237.826309204102 138.225112915039 0 0 0 102.917053222656 540.358703613281 1507.14807128906 2255.67041015625 2121.10278320313 1207.01428222656 254.796005249023 0 0 0 0 0 0 0 0 0 180.893783569336 216.125747680664 186.408401489258 92.5867767333984 0 0 0 0 0 0 0 0 67.1141357421875 314.660339355469 430.744506835938 249.505142211914 110.873168945313 311.952087402344 298.573059082031 158.444198608398 0 0 0 0 0 0 0 0 0 203.841903686523 330.667297363281 305.950500488281 171.00895690918 0 0 0 0 0 0 0 0 150.461807250977 187.074295043945 122.066360473633 0 0 0 0 0 0 0 0 128.328475952148 228.142013549805 224.649185180664 115.597442626953 0 0 0 0 0 0 0 0 121.621292114258 209.864395141602 180.903396606445 0 0 0 0 0 0 0 0 180.190689086914 221.191635131836 230.223587036133 203.161819458008 163.631942749023 0 0 0 103.920654296875 254.635330200195 239.919662475586 117.75276184082 0 0 0 0 0 0 0 0 127.274429321289 277.754516601563 418.050842285156 364.745910644531 108.102828979492 0 0 0 0 0 0 0 0 122.235366821289 204.649490356445 1283.6416015625 2732.66333007813 3403.52026367188 2677.83666992188 1189.97729492188 91.4230346679688 0 0 0 0 0 0 0 0 179.184860229492 218.383316040039 188.207290649414 103.431289672852 0 0 0 0 0 19.3411254882813 320.543273925781 708.724914550781 " "746.338012695313 324.464965820313 498.983642578125 805.302062988281 584.451416015625 150.821365356445 0 0 0 0 0 0 0 0 18.6659393310547 273.791931152344 556.722961425781 580.784423828125 324.137634277344 118.86296081543 192.937911987305 133.19303894043 0 0 0 0 0 0 0 0 156.306106567383 528.205383300781 857.985168457031 865.72802734375 528.765258789063 126.998458862305 0 0 0 0 0 0 0 0 141.282363891602 213.537307739258 188.727676391602 83.9633941650391 0 0 0 0 0 0 0 0 53.5650329589844 300.0869140625 496.208679199219 543.627502441406 469.730163574219 370.066101074219 289.648376464844 183.115615844727 57.3272399902344 0 0 0 0 0 0 0 0 128.359512329102 282.553894042969 428.125305175781 518.781311035156 625.49609375 722.9619140625 704.251159667969 596.822631835938 501.902587890625 382.079040527344 159.27229309082 0 0 0 0 0 0 0 0 65.7273559570313 820.538696289063 2162.48120117188 3311.76513671875 3299.95263671875 2090.16650390625 672.241455078125 0 0 0 0 0 0 0 0 0 0 308.417297363281 836.372497558594 1054.75146484375 828.995056152344 520.746643066406 281.113220214844 0 0 0 0 0 0 0 0 0 135.923385620117 224.629806518555 176.55793762207 0 0 0 0 0 0 0 0 0 243.977737426758 679.087585449219 930.161682128906 790.303100585938 379.179931640625 152.314804077148 0 0 0 0 0 0 0 0 136.929214477539 317.641784667969 361.6630859375 256.365356445313 53.1949462890625 0 0 0 0 0 0 0 0 79.8312377929688 199.234237670898 225.433242797852 110.191116333008 0 0 0 0 0 0 0 0 88.5470733642578 328.809631347656 486.254577636719 566.095397949219 679.935241699219 807.850219726563 851.315795898438 785.165161132813 654.703979492188 527.893920898438 423.899841308594 256.051086425781 0 0 0 0 0 0 0 0 0 0 325.090454101563 1122.31469726563 1884.14013671875 2005.18811035156 1370.16577148438 511.172485351563 0 0 0 0 0 0 0 0 0 144.137466430664 222.952560424805 139.711410522461 0 0 0 31.4209136962891 456.088439941406 906.362609863281 992.082092285156 640.056396484375 191.88249206543 0 0 0 0 0 0 0 0 0 142.481643676758 " "248.23698425293 361.091796875 321.38818359375 84.5967559814453 0 0 0 0 0 0 0 0 68.5481414794922 229.667556762695 342.556030273438 233.595016479492 12.875 284.913818359375 586.492919921875 765.540771484375 846.076843261719 837.908752441406 736.949829101563 570.628051757813 422.32958984375 338.351196289063 265.928649902344 102.936645507813 0 0 0 0 0 0 0 0 111.217437744141 194.165725708008 498.359680175781 810.423156738281 786.201354980469 424.384338378906 32.8225250244141 0 0 0 0 0 0 0 0 126.047775268555 188.677780151367 216.424392700195 207.760787963867 193.143905639648 173.67204284668 0 0 0 0 0 0 0 0 230.711318969727 263.243713378906 218.297134399414 121.326461791992 0 0 0 0 0 0 0 0 85.8698425292969 222.64518737793 225.071212768555 111.491928100586 0 0 0 0 0 0 0 0 158.272689819336 319.939025878906 405.672607421875 543.889831542969 709.350402832031 762.2890625 669.657836914063 464.710327148438 230.338363647461 135.231704711914 0 0 0 0 0 0 0 0 112.85188293457 340.410949707031 556.054382324219 649.1904296875 642.006286621094 595.709777832031 552.84423828125 532.100952148438 509.958984375 393.80126953125 147.021102905273 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 163.031021118164 257.087280273438 222.833755493164 69.1905975341797 0 0 0 0 0 0 0 0 0 193.01008605957 1283.4189453125 2651.75854492188 3263.72827148438 2533.265625 1061.58337402344 237.298934936523 292.41845703125 36.6092681884766 0 0 0 0 0 0 0 0 0 412.251708984375 1201.08520507813 1691.83618164063 1483.95202636719 787.549011230469 140.731460571289 0 0 0 0 0 0 0 0 155.059463500977 197.582107543945 226.128463745117 389.715087890625 812.975402832031 1328.24084472656 1494.00390625 1091.52282714844 416.5791015625 13.3121490478516 0 0 0 0 0 0 0 0 30.8641204833984 259.902893066406 398.201293945313 307.794982910156 89.9954833984375 0 0 0 0 0 0 0 0 250.239639282227 294.914489746094 240.247360229492 36.3681182861328 0 0 0 0 0 0 0 0 168.141342163086 211.644943237305 185.341293334961 0 0 0 0 0 0 0 0 0 1255.41430664063 " "4270.45751953125 7186.3505859375 7656.57861328125 5270.84912109375 2048.24633789063 131.94660949707 0 0 0 0 0 0 0 0 171.324295043945 234.151138305664 188.494430541992 85.8521118164063 0 0 0 0 0 0 0 177.790451049805 196.738876342773 191.143508911133 173.924301147461 0 0 0 0 0 0 0 0 27.4716339111328 870.664428710938 2696.56469726563 4313.33056640625 4373.56005859375 2848.65014648438 1105.826171875 363.445678710938 95.8519592285156 0 0 0 0 0 0 0 0 165.054183959961 190.630477905273 212.371444702148 119.549850463867 0 0 0 0 144.282302856445 1497.27661132813 3014.11791992188 3372.33959960938 2141.125 440.955444335938 486.9052734375 473.754028320313 237.800888061523 10.4761962890625 0 0 0 0 0 0 0 0 187.649795532227 717.752685546875 1004.04693603516 895.356262207031 611.759887695313 231.517959594727 0 0 0 0 0 0 0 0 0 0 380.191772460938 1166.65649414063 1580.28991699219 1321.69921875 695.5244140625 219.708572387695 60.3770294189453 0 0 0 0 0 0 0 0 168.744674682617 496.461608886719 797.966979980469 819.004150390625 524.868408203125 148.768051147461 0 0 0 0 0 0 0 0 114.591278076172 230.604568481445 404.740417480469 400.008056640625 149.154037475586 0 0 0 0 0 0 0 0 102.017929077148 332.576171875 431.327087402344 395.180480957031 291.81103515625 179.464797973633 0 0 0 0 0 0 0 0 328.818298339844 432.372192382813 513.603515625 524.003845214844 455.190307617188 323.07763671875 0 0 0 0 0 0 0 0 0 500.822875976563 1250.17626953125 1691.61279296875 1446.947265625 741.710021972656 242.135177612305 131.856307983398 0 0 0 0 0 0 0 0 106.934600830078 416.481811523438 591.3037109375 471.31884765625 154.692947387695 0 0 0 0 0 0 0 0 58.2242736816406 451.217834472656 867.215209960938 952.283020019531 683.782348632813 327.990234375 53.9348297119141 0 0 0 0 0 0 0 0 112.282455444336 194.305465698242 247.864517211914 283.480651855469 251.062362670898 154.861434936523 0 0 0 0 0 0 0 0 0 2550.76782226563 7417.4248046875 11472.3154296875 11331.73046875 7126.333984375 2372.173828125 154.968887329 0 0 " "0 0 0 0 0 0 171.941879272461 235.122146606445 189.759658813477 86.6224975585938 0 0 0 0 0 0 0 0 161.515548706055 191.835342407227 263.086181640625 280.552551269531 146.46711730957 354.734191894531 1819.36071777344 4197.60791015625 5904.71484375 5515.97998046875 3378.09521484375 1216.07165527344 240.816360473633 160.06672668457 0 0 0 0 0 0 0 0 168.925979614258 417.149658203125 1732.84704589844 3627.1572265625 4610.03076171875 3790.7890625 1980.00671386719 757.338623046875 314.47314453125 0 0 0 0 0 0 0 0 0 151.324813842773 253.94270324707 329.051940917969 266.352722167969 111.870147705078 0 196.40153503418 1169.40258789063 2201.71215820313 2499.97778320313 1842.07995605469 847.819702148438 294.143676757813 154.02375793457 0 0 0 0 0 0 0 0 0 263.716003417969 663.424133300781 945.621276855469 900.181091308594 586.183349609375 242.737838745117 0 0 0 0 0 0 0 0 0 87.7988586425781 273.416259765625 275.446044921875 122.881698608398 0 0 0 0 0 0 0 0 139.006607055664 632.857299804688 1046.19299316406 1076.18725585938 721.538818359375 282.741760253906 33.4364013671875 0 92.9069519042969 201.903335571289 216.809951782227 66.0712280273438 0 0 0 0 0 0 0 0 0 262.810607910156 583.060974121094 697.79833984375 522.555419921875 181.537673950195 0 0 0 0 0 0 0 0 258.55615234375 289.532775878906 243.079086303711 173.991165161133 0 0 0 0 0 0 0 0 37.7136077880859 214.55876159668 243.370010375977 18.9360961914063 35.8999176025391 191.428115844727 166.77082824707 0 0 0 0 0 0 0 0 0 258.869323730469 651.99658203125 911.448181152344 810.898193359375 421.798156738281 54.3055572509766 0 0 0 0 0 0 0 0 60.1159057617188 292.62109375 475.166442871094 465.994323730469 265.969482421875 59.4075927734375 0 0 0 0 0 0 0 0 129.671829223633 203.134628295898 214.902053833008 142.065078735352 0 0 0 0 0 0 0 0 68.9898071289063 258.451477050781 349.82421875 288.4658203125 184.60481262207 0 0 0 0 0 0 0 0 60.4415130615234 757.99267578125 4146.55859375 8593.078125 10882.390625 9079.6171875 4740.5390625 1125.72338867 " "0 0 0 0 0 0 0 0 0 102.086837768555 209.562088012695 285.004333496094 167.125106811523 0 0 0 0 0 0 0 0 153.054061889648 218.63932800293 227.450668334961 199.439254760742 191.222061157227 179.493179321289 0 0 0 0 0 0 0 0 136.84049987793 243.085250854492 175.279190063477 0 0 0 165.884048461914 1627.97961425781 4570.39892578125 7233.904296875 7538.84521484375 5242.4697265625 2183.01293945313 247.249221801758 94.0259094238281 0 0 0 0 0 0 0 0 0 708.975402832031 2684.54736328125 4892.7626953125 5664.70263671875 4346.48974609375 2153.0361328125 792.776916503906 328.806335449219 26.2600402832031 0 0 0 0 0 0 0 0 0 600.651245117188 1863.01184082031 2856.58935546875 2825.29223632813 1829.23559570313 678.683837890625 156.775985717773 0 0 0 0 0 0 0 0 177.269912719727 213.871047973633 146.206100463867 0 0 0 0 0 0 0 0 0 438.628295898438 1067.17602539063 1423.88037109375 1322.46948242188 846.637451171875 222.935501098633 8.62030029296875 0 0 0 0 0 0 0 0 1.40678405761719 204.166915893555 495.588256835938 711.029602050781 672.086486816406 440.136291503906 197.460708618164 25.0921783447266 0 0 0 0 0 0 0 0 181.639419555664 454.123840332031 630.59228515625 540.996643066406 248.280014038086 0 0 0 0 0 0 0 0 0 0 272.537475585938 507.36669921875 482.3701171875 228.514022827148 0 0 0 0 0 0 0 0 0 173.016799926758 282.362365722656 239.30632019043 89.6678161621094 0 0 0 0 0 0 0 0 163.693313598633 238.812973022461 181.945022583008 0 0 0 0 0 0 0 0 154.68586730957 251.716812133789 301.325927734375 285.520263671875 212.902420043945 125.696426391602 0 0 0 0 0 0 0 0 144.465744018555 280.485534667969 282.486389160156 171.469833374023 0 0 0 0 0 0 0 0 168.80158996582 1852.96484375 4451.087890625 6223.240234375 5698.3251953125 3317.40869140625 947.944641113281 0 72.4445648193359 222.517288208008 190.692306518555 8.54414367675781 0 0 0 0 0 0 0 0 173.518569946289 287.66455078125 315.665649414063 180.375747680664 0 0 0 0 0 0 0 0 22.9653015136719 377.313659667969 1943.11608886719 3810.626464843 4614.140625 " "3648.7470703125 1708.49145507813 216.385025024414 180.797805786133 220.440505981445 66.8912200927734 0 0 0 0 0 143.90119934082 216.902420043945 185.753768920898 98.3815460205078 0 0 0 0 0 0 0 0 162.759536743164 215.904861450195 208.337875366211 127.708084106445 0 0 0 0 0 0 0 0 105.314514160156 217.56315612793 204.984756469727 103.096450805664 1431.53564453125 2977.5546875 3651.64916992188 2931.84326171875 1398.70080566406 87.1452484130859 320.6357421875 384.557983398438 269.201110839844 237.787063598633 238.22102355957 131.059158325195 0 0 0 0 0 0 0 0 82.7467803955078 540.114013671875 1467.232421875 2395.43090820313 2641.54028320313 2010.16149902344 989.484558105469 192.628158569336 0 0 179.865524291992 275.410278320313 175.700149536133 0 0 0 0 0 0 0 0 59.9419708251953 485.762634277344 988.358093261719 1207.15466308594 963.307312011719 438.903381347656 31.6091766357422 0 0 0 0 0 47.9591827392578 196.635208129883 252.011154174805 211.016983032227 150.474960327148 0 0 0 0 0 0 0 0 168.648544311523 212.75212097168 246.239303588867 241.005111694336 180.050369262695 0 0 0 0 93.9449157714844 308.76171875 510.256713867188 547.370849609375 379.794067382813 126.207992553711 0 0 0 0 0 0 0 0 165.212295532227 203.172348022461 187.95915222168 180.575973510742 0 0 0 0 0 0 0 0 75.0355987548828 196.667404174805 286.693542480469 310.418090820313 283.288269042969 260.312194824219 292.165649414063 351.78125 356.774780273438 261.874694824219 112.601119995117 0 0 0 0 0 0 0 0 147.65412902832 199.247695922852 206.355667114258 137.159103393555 0 0 0 0 0 0 0 0 153.178085327148 250.377090454102 305.382019042969 294.765869140625 215.430770874023 81.4587097167969 0 0 0 0 0 0 0 0 89.8516693115234 217.64045715332 309.367736816406 283.979248046875 149.045394897461 0 0 0 182.38005065918 418.089721679688 1096.13757324219 1732.892578125 1712.91027832031 1019.67010498047 253.890274047852 63.1096954345703 0 0 0 0 0 0 0 0 146.927871704102 197.823593139648 450.705383300781 1247.59985351563 " "2147.16479492188 2419.29248046875 1796.34436035156 783.829040527344 106.181396484375 0 0 0 0 0 0 0 0 0 334.013916015625 997.858215332031 1538.47912597656 1550.04187011719 1073.02502441406 532.429992675781 248.089309692383 200.781692504883 213.394241333008 177.545181274414 0 0 0 0 0 0 0 0 26.6942443847656 209.29020690918 520.969909667969 869.404174804688 1070.1162109375 975.004333496094 655.297485351563 316.672058105469 99.7084808349609 0 0 0 0 0 0 0 0 79.5495910644531 288.576049804688 554.977966308594 746.154174804688 740.367309570313 521.067321777344 227.974136352539 72.0663757324219 0 0 0 0 0 0 0 0 171.190017700195 314.421569824219 429.333374023438 416.543640136719 251.908309936523 31.249267578125 0 0 0 0 0 0 0 0 180.657669067383 192.169876098633 162.963485717773 0 0 0 0 0 0 0 0 155.606674194336 333.596923828125 371.658142089844 244.003341674805 111.538848876953 0 0 0 55.3578186035156 199.379867553711 277.664733886719 246.347457885742 148.267105102539 0 0 0 0 0 0 0 0 90.9604797363281 198.196731567383 372.608276367188 566.121337890625 624.478515625 473.921447753906 201.671371459961 0 0 0 0 0 0 0 0 0 120.198684692383 400.147033691406 571.140441894531 478.692626953125 229.758438110352 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 152.600845336914 225.899429321289 240.899063110352 190.175918579102 0 0 0 0 0 0 0 0 225.349227905273 261.482971191406 145.197463989258 0 0 0 0 0 0 0 0 64.5845184326172 213.417953491211 267.813903808594 201.623031616211 117.913467407227 0 0 0 0 0 0 0 0 182.848587036133 203.188278198242 155.740859985352 0 0 0 0 0 0 0 0 184.153060913086 247.411849975586 282.429565429688 316.498046875 347.890441894531 314.713134765625 179.080673217773 0 0 0 0 0 0 0 0 115.904327392578 226.538375854492 215.979263305664 129.574813842773 0 0 0 0 0 0 0 0 129.243606567383 308.855651855469 363.072937011719 252.200698852539 36.5062561035156 0 0 0 0 0 0 0 0 168.485580444336 221.236099243164 203.256454467773 118.937698364258 0 0 0 0 0 0 0 0 135.065872192383 197.25260925293 " "164.043045043945 0 0 0 0 0 0 0 0 101.22346496582 199.961135864258 181.580459594727 0 0 0 0 0 0 0 0 171.627029418945 216.893325805664 165.188735961914 0 0 0 0 0 0 0 0 184.577438354492 315.924865722656 400.736938476563 401.748779296875 309.456359863281 177.526077270508 0 0 0 0 0 0 0 0 71.3968505859375 196.379440307617 317.622741699219 323.017578125 218.84977722168 108.977661132813 0 0 0 0 0 0 0 0 143.710311889648 248.819686889648 318.435913085938 338.807861328125 306.490661621094 239.977798461914 197.418716430664 128.426620483398 0 0 0 0 0 0 0 0 126.655654907227 226.479202270508 229.53288269043 179.628677368164 0 0 0 0 0 0 0 0 144.30647277832 214.861099243164 189.256454467773 0 0 0 0 0 0 0 0 188.085342407227 308.395935058594 374.08056640625 337.305053710938 193.459030151367 33.2561950683594 0 0 0 0 0 0 0 0 101.20735168457 200.764785766602 247.183944702148 206.08268737793 87.9416961669922 0 0 0 0 0 0 0 0 95.3595581054688 225.91584777832 248.077072143555 250.59260559082 257.277648925781 180.943740844727 0 0 0 0 0 0 0 0 155.655776977539 238.868362426758 250.283981323242 157.468978881836 0 0 0 0 0 0 0 0 165.849624633789 341.285217285156 449.087829589844 465.197448730469 414.669006347656 350.80908203125 287.216369628906 202.29280090332 102.295700073242 0 0 0 0 0 0 0 0 122.961654663086 216.524826049805 227.398483276367 197.743057250977 252.932815551758 368.044921875 412.497924804688 332.376770019531 189.94221496582 0 0 0 0 0 0 0 0 110.821487426758 205.431838989258 197.784744262695 165.351150512695 0 0 0 0 0 0 0 0 148.747482299805 197.384048461914 222.412368774414 130.84407043457 0 0 0 0 0 0 0 0 186.619369506836 231.119979858398 185.139663696289 0 0 0 0 0 0 0 0 129.717819213867 224.055252075195 180.142196655273 0 0 0 0 0 0 0 0 176.265243530273 223.66975402832 295.446105957031 361.572326660156 360.102111816406 244.047714233398 41.8561553955078 0 0 0 0 0 0 0 0 160.23698425293 238.57145690918 249.646987915039 191.794631958008 0 0 0 0 0 0 0 0 177.559341430664 308.058898925781 " "348.306823730469 288.753173828125 157.469802856445 0 0 50.9171905517578 233.195449829102 366.537780761719 333.827880859375 112.628784179688 0 0 0 0 0 0 0 0 146.29948425293 221.006973266602 185.588424682617 0 0 0 0 0 0 0 0 169.829788208008 298.886840820313 375.022705078125 349.165283203125 326.073608398438 321.16162109375 301.307739257813 280.400939941406 268.34130859375 250.299697875977 206.922592163086 161.804183959961 0 0 0 0 0 0 0 0 106.515991210938 216.509872436523 174.441055297852 0 47.4068908691406 197.185470581055 263.215942382813 352.870300292969 434.091491699219 407.799926757813 297.367797851563 209.839736938477 246.22785949707 378.100463867188 491.783874511719 505.840270996094 403.557006835938 229.298934936523 54.6394348144531 0 0 0 0 0 0 0 0 50.5400085449219 198.851058959961 280.1474609375 285.830627441406 210.564895629883 50.8290405273438 0 0 0 0 0 170.184860229492 335.466613769531 475.362731933594 547.797119140625 496.642517089844 292.609191894531 4.42018127441406 0 0 0 0 0 0 0 0 386.298461914063 549.150512695313 612.910278320313 599.075317382813 479.97314453125 260.072143554688 0 0 0 0 0 0 0 0 157.101547241211 216.543563842773 210.621841430664 151.346878051758 0 0 0 0 0 0 0 0 163.830764770508 225.50910949707 155.86100769043 0 0 0 0 0 0 0 0", "300.000066203793 300.000611626572 300.001157051333 300.001702478078 300.057892033313 300.058437690186 300.058983325233 300.059528962264 300.06007460128 300.06062024228 300.061165885264 300.061711530233 300.062257177186 300.062802826123 300.063348477046 300.063894129952 300.064439784843 300.064985441719 300.065531100579 300.066076761424 300.066622424263 301.05533837009 301.055887660805 301.056436929468 301.056986200136 301.057535472809 301.058084747485 301.058634024166 301.059183302851 301.059732583541 301.060281866235 301.060831150933 301.061380437635 301.061929726342 301.062479017053 301.063028309769 301.063577604489 301.064126901211 301.064676199938 311.867909300619 311.868498757012 311.869088211176 311.869677645283 311.870267081618 311.870856520182 311.871445960974 311.872035403993 311.872624849241 311.873214296717 311.873803746421 311.874393198353 311.874982652514 311.875572108902 311.876161567519 311.876751028364 311.877340491437 311.877929956739 311.878519424268 311.879108894026 311.879698366013 311.880287840227 311.88087731667 311.881466795341 311.882056276241 311.882645759373 311.883235244734 315.73053532575 315.731139474286 315.73174362051 315.732347745926 315.732951873654 315.733556003694 315.734160136047 315.734764270711 315.735368407687 315.735972546974 315.736576688574 315.737180832486 315.73778497871 315.738389127246 315.738993278088 315.739597431241 316.900199279936 316.900807913163 316.901416544052 316.902025153901 316.902633766087 316.90324238061 316.903850997471 316.90445961667 316.905068238207 316.905676862081 316.906285488293 316.906894116843 316.907502747731 316.908111380957 316.90872001652 316.909328654421 316.909937294661 316.910545937239 326.292301361357 326.292946606739 326.293591849569 326.294237069432 326.294882291847 326.295527516814 326.296172744332 326.296817974402 326.297463207024 326.298108442198 326.298753679923 326.299398920201 326.30004416303 326.300689408412 326.301334656346 327.073585511089 327.074233850235 327.074882186811 " "327.075530500256 327.076178816272 327.076827134858 327.077475456014 327.07812377974 327.078772106036 327.079420434903 327.080068766339 327.080717100346 327.081365436923 327.082013776071 327.082662117789 327.083310462077 327.083958808935 327.084607158362 327.085255510359 341.005699660892 341.006404411558 341.007109159311 341.007813880848 341.008518605298 341.00922333266 341.009928062936 341.010632796124 341.011337532225 341.012042271238 341.012747013165 341.013451758004 341.014156505757 341.014861256422 341.01556601 341.016270766491 341.016975525895 341.017680288212 341.018385053442 341.019089821585 341.019794592642 341.020499366611 341.021204143493 341.021908923288 341.022613705997 341.023318491618 341.024023280153 341.024728071601 341.025432865961 341.026137663234 342.012174618732 342.01288353577 342.01359244987 342.014301337525 342.015010228119 342.015719121651 342.016428018122 342.017136917532 342.01784581988 342.018554725167 342.019263633392 342.019972544557 342.02068145866 342.021390375702 342.022099295682 342.022808218602 342.02351714446 342.024226073253 342.024935004984 342.872076371417 342.872788857813 342.873501341248 342.874213798035 342.874926257782 342.87563872049 342.876351186159 342.877063654789 342.87777612638 342.878488600932 342.879201078445 342.879913558918 342.880626042353 342.881338528749 342.882051018106 342.882763510424 344.971618706329 344.972339945342 344.97306118134 344.9737823902 344.974503602076 344.975224816967 344.975946034874 344.976667255797 344.977388479735 344.978109706689 344.978830936658 344.979552169644 344.980273405644 344.980994644661 344.981715886693 344.982437131737 344.983158379796 355.062407256743 355.063171308061 355.063935356091 355.064699374529 355.065463396255 355.066227421269 355.066991449572 355.067755481162 355.06851951604 355.069283554207 355.070047595661 355.070811640404 355.071575688435 355.072339739754 355.073103794361 355.073867852257 355.074631913441 355.075395977913 355.076160045673 355.076924116722 " "355.077688191059 355.078452268685 355.079216349597 355.079980433797 356.063784873266 356.064553240471 356.065321571195 356.066089905234 356.06685824259 356.067626583261 356.068394927249 356.069163274552 356.069931625172 356.070699979107 356.071468336359 356.072236696926 356.07300506081 356.073773428009 356.074541798525 356.075310172357 356.076078549505 356.076846929969 356.07761531375 356.078383700846 356.079152091259 356.079920484988 356.080688882034 356.0814572824 356.082225686083 357.061554879912 357.062327559534 357.063100202372 357.063872848555 357.064645498081 357.065418150951 357.066190807165 357.066963466723 357.067736129625 357.068508795871 357.069281465461 357.070054138395 357.070826814673 357.071599494295 357.072372177261 357.073144863571 357.073917553225 357.074690246224 357.075462942566 357.076235642253 357.077008345284 357.077781051659 357.078553761379 357.079326474442 357.08009919085 357.080871910601 357.081644633697 359.022402165402 359.023183355092 359.023964507385 359.024745663078 359.02552682217 359.026307984661 359.027089150551 359.027870319841 359.028651492531 359.029432668619 359.030213848107 359.030995030994 359.031776217281 359.032557406967 359.033338600053 359.034119796538 359.034900996422 359.035682199706 359.036463406393 360.02270642572 360.023491974674 360.024277485921 360.025063000597 360.0258485187 360.02663404023 360.027419565189 360.028205093575 360.028990625389 360.029776160632 360.030561699301 360.031347241399 360.032132786925 360.032918335879 360.03370388826 360.03448944407 360.035275003295 361.019911590167 361.020701496954 361.021491400285 361.02228127251 361.023071148191 361.023861027329 361.024650909923 361.025440795974 361.026230685481 361.027020578444 361.027810474864 361.02860037474 361.029390278072 361.030180184861 361.030970095107 361.031760008809 361.032549925965 361.033339846577 371.094855950121 371.095690561049 371.096525130684 371.097359704072 371.098194281215 371.099028862111 371.099863446762 371.100698035166 " "371.101532627324 371.102367223236 371.103201822902 371.104036426322 371.104871033497 371.105705644425 371.106540259107 371.107374877543 371.108209499734 371.109044125678 371.109878755377 371.11071338883 371.111548026036 371.112382666995 372.076388760396 372.077227792322 372.078066820464 372.078905814551 372.079744812421 372.080583814075 372.081422819513 372.082261828735 372.083100841741 372.08393985853 372.084778879103 372.08561790346 372.086456931601 372.087295963526 372.08813499923 372.088974038718 372.09484737572 372.095686490895 372.096525564444 372.097364641778 372.098203722896 372.099042807799 372.099881896485 372.100720988956 372.101560085211 372.102399185251 372.103238289075 372.104077396683 372.104916508076 372.105755623254 372.106594742216 372.107433864962 372.108272991493 372.109112121811 372.109951255914 373.074936157977 373.075779699523 373.076623237254 373.077466740653 373.078310247866 373.079153758894 373.079997273735 373.080840792391 373.081684314862 373.082527841147 373.083371371246 373.084214905159 373.085058442887 373.08590198443 373.086745529787 373.087589078956 373.088432631939 373.099399083966 373.100242736138 373.101086384495 373.101929998517 373.102773616354 373.103617238007 373.104460863474 373.105304492756 373.106148125853 373.106991762765 373.107835403493 373.108679048035 373.109522696393 373.110366348566 373.111210004555 373.112053664363 373.112897327987 415.029499377631 415.030543316388 415.031587197383 415.032631083628 415.033674975125 415.034718871873 415.035762773872 415.036806681123 415.037850593625 415.038894511378 415.039938434383 415.040982362639 415.042026296147 415.043070234906 415.044114178917 415.045158128179 415.046202082693 415.047246042459 415.048290007473 415.049333977738 416.002577466261 416.003626306154 416.004675140758 416.005723927765 416.006772720059 416.007821517642 416.008870320513 416.009919128672 416.01096794212 416.012016760856 416.01306558488 416.014114414193 416.015163248794 416.016212088684 416.01726093386 " "416.018309784324 416.028798463515 416.029847435635 416.030896402465 416.031945321688 416.032994246201 416.034043176002 416.035092111093 416.036141051473 416.037189997143 416.038238948102 416.03928790435 416.040336865888 416.041385832715 416.042434804832 416.043483782239 416.044532764935 416.04558175292 416.046630746196 416.047679744761 416.048728748618 416.049777757765 417.026597695644 417.027651705639 417.028705657034 417.029759613757 417.030813575807 417.031867543184 417.032921515889 417.033975493922 417.035029477282 417.036083465969 417.037137459984 417.038191459327 417.039245463997 417.040299473995 417.041353489321 417.04240750997 426.355773178261 426.356874875168 426.357976566382 426.359078206359 426.360179852029 426.361281503392 426.362383160449 426.363484823198 426.36458649164 426.365688165776 426.366789845604 426.367891531126 426.368993222341 426.370094919248 426.371196621848 428.93364758309 428.934762643092 428.935877697296 428.936992699323 428.938107707146 428.939222720767 428.940337740184 428.941452765398 428.94256779641 428.943682833218 428.944797875823 428.945912924226 428.947027978426 428.948143038428 428.949258104228 429.080876455648 429.081992281276 429.083108101101 429.0842238687 429.085339642101 429.086455421305 429.087571206312 429.088686997122 429.089802793735 429.090918596151 429.09203440437 429.093150218392 429.094266038217 429.095381863845 429.096497695277 429.097613532512 429.09872937555 429.099845224392 429.100961079037 429.102076939486 429.103192805742 429.132207237776 429.133323330395 429.134439417209 429.135555451783 429.136671492162 429.137787538345 429.138903590334 429.140019648128 429.141135711726 429.14225178113 429.143367856339 429.144483937353 429.145600024173 429.146716116797 429.147832215231 429.148948319471 429.848770617062 429.849890440213 429.85101025753 429.852130022341 429.853249792985 429.854369569464 429.855489351777 429.856609139924 429.857728933905 429.858848733721 429.859968539371 429.861088350855 429.862208168173 " "429.863327991326 429.864447820313 429.865567655135 429.866687495792 429.867807342283 429.868927194608 429.870047052768 429.871166916764 429.872286786593 429.873406662258 429.874526543758 429.875646431092 429.876766324261 429.877886223266 429.879006128111 429.880126038792 430.080684027207 430.081805059062 430.082926026641 430.084047000064 430.08516797933 430.086288964439 430.087409955392 430.088530952189 430.089651954829 430.090772963313 430.091893977641 430.093014997813 430.094136023828 430.095257055687 430.09637809339 430.097499136937 430.098620186328 430.099741241563 430.100862302643 430.101983369566 430.103104442333 431.077278491348 431.078404724764 431.079530893455 431.08065706803 431.081783248489 431.082909434832 431.08403562706 431.085161825172 431.086288029168 431.087414239049 431.088540454814 431.089666676463 431.090792903997 431.091919137416 431.093045376719 431.094171621907 431.09529787298 431.096424129938 431.09755039278 431.098676661507 431.099802936119 431.100929216617 431.102055503 432.077370900075 432.078502365406 432.079633824813 432.080765230898 432.081896642908 432.083028060844 432.084159484704 432.085290914491 432.086422350202 432.087553791839 432.088685239402 432.08981669289 432.090948152304 432.092079617643 432.093211088908 432.094342566101 432.09547404922 444.61606065115 444.617258663358 444.618456682022 444.619654707142 444.620852738719 444.622050776751 444.62324882124 444.624446872186 444.625644929587 444.626842993445 444.62804106376 444.629239140531 444.630437223759 445.108988082791 445.110188830584 445.111389571898 445.112590254911 445.113790944402 445.114991640371 445.116192342817 445.117393051741 445.118593767143 445.119794489023 445.120995217382 445.122195952218 445.123396693532 445.124597441324 445.125798195595 445.126998956343 445.128199723571 445.129400497276 445.13060127746 445.131802064126 445.133002857271 446.0896875442 446.09089358916 446.092099627601 446.093305607359 446.094511593638 446.095717586437 446.096923585757 " "446.098129591598 446.099335603959 446.100541622841 446.101747648245 446.102953680169 446.104159718614 446.10536576358 446.106571815068 446.107777873076 446.108983937606 446.110190008657 446.111396086229 446.112602170323 446.113808260938 446.115014358075 446.116220461733 446.117426571913 446.118632688614 446.119838811837 446.121044941582 446.122251077849 446.123457220638 446.124663369948 446.12586952578 446.127075688135 446.128281857011 446.12948803241 446.130694214331 446.131900402774 446.133106597739 446.13431279922 446.135519007222 447.090465450435 447.091676913048 447.092888369096 447.09409976606 447.095311169589 447.096522579682 447.09773399634 447.098945419563 447.100156849351 447.101368285703 447.10257972862 447.103791178103 447.10500263415 447.106214096762 447.10742556594 447.108637041682 447.10984852399 447.111060012863 447.112271508302 447.113483010306 447.114694518875 447.115906034009 447.11711755571 447.118329083975 447.119540618807 447.120752160204 447.121963708167 447.123175262696 447.12438682379 447.125598391451 447.126809965677 447.128021546469 447.129233133828 447.130444727752 447.131656328243 447.132867935294 447.134079548911 449.792325957731 449.793552107325 449.794778250235 449.796004332987 449.797230422424 449.798456518544 449.799682621349 449.800908730839 449.802134847013 449.803360969872 449.804587099415 449.805813235643 449.807039378556 449.808265528153 449.809491684437 449.810717847406 476.28917675577 476.290551628645 476.291926493584 476.293301287096 476.294676088545 476.296050897931 476.297425715253 476.298800540512 476.300175373707 476.30155021484 476.30292506391 476.304299920917 476.305674785861 476.307049658742 476.308424539565 476.309799428326 487.8125351623 487.813977369941 487.815419569054 487.81686169142 487.818303822312 487.819745961732 487.821188109678 487.822630266151 487.824072431152 487.825514604679 487.826956786733 487.828398977315 487.829841176424 487.831283384065 487.832725600234 489.045757246253 489.047206755368 " "489.048656169973 489.050105593169 489.051555024957 489.053004465336 489.054453914307 489.05590337187 489.057352838025 489.058802312771 489.06025179611 489.06170128804 489.063150788563 489.064600297678 489.066049815385 489.067499341685 489.068948876582 494.494675265302 494.496157256269 494.497639238354 494.499121140501 494.500603051529 494.50208497144 494.503566900233 494.505048837908 494.506530784465 494.508012739904 494.509494704226 494.510976677431 494.512458659517 494.513940650484 494.515422650332 503.094316385189 503.095850372279 503.097384350016 503.098918243574 503.100452146485 503.10198605875 503.103519980368 503.10505391134 503.106587851665 503.108121801345 503.109655760378 503.111189728765 503.112723706507 503.114257693603 503.115791690052 503.117325695857 503.118859711015 503.120393735528 503.121927769396 503.123461812619 503.124995865196 503.126529927119 503.128063998395 504.054815517436 504.056355367669 504.057895208494 504.059434964655 504.060974730222 504.062514505197 504.064054289579 504.065594083369 504.067133886566 504.06867369917 504.070213521182 504.071753352602 504.073293193429 504.074833043661 504.076372903301 504.094851745874 504.09639184074 504.097931926196 504.099471926969 504.101011937151 504.102551956742 504.104091985743 504.105632024154 504.107172071974 504.108712129204 504.110252195844 504.111792271893 504.113332357353 504.114872452223 504.116412556503 504.117952670193 504.119492793294 504.121032925805 504.122573067726 504.124113219059 504.125653379799 504.13335411762 504.134894447771 504.136434768509 504.137975004541 504.139515249984 504.141055504838 504.142595769105 504.144136042783 504.145676325873 504.147216618374 504.148756920288 504.150297231614 504.151837552352 504.153377882502 504.154918222058 504.156458571024 505.091644206301 505.093190398161 505.094736580555 505.096282677762 505.097828784435 505.099374900573 505.100921026176 505.102467161245 505.104013305779 505.105559459779 505.107105623245 505.108651796177 505.110197978574 " "505.111744170438 505.113290371768 505.114836582564 505.116382802826 505.117929032555 505.11947527175 505.121021520412 505.12256777854 505.124114046132 505.12566032319 506.092386573466 506.0939388986 506.095491214212 506.097043444127 506.098595683563 506.100147932522 506.101700191001 506.103252459003 506.104804736527 506.106357023573 506.107909320141 506.109461626231 506.111013941844 506.112566266978 506.114118601636 506.115670945814 506.117223299513 517.62453635348 517.626160232046 517.627784100423 517.62940787711 517.631031663984 517.632655461045 517.634279268294 517.635903085731 517.637526913356 517.639150751169 517.64077459917 517.642398457359 517.644022325736 517.645646204301 517.647270093055 519.11454547401 519.11617871524 519.117811946194 519.11944508466 519.121078233402 519.122711392419 519.124344561713 519.125977741282 519.127610931128 519.129244131249 519.130877341647 519.132510562322 519.134143793272 519.1357770345 519.137410286004 519.139043547785 519.140676819843 519.142310102177 519.143943394789 519.145576697678 519.147210010844 519.148843334287 519.150476668008 519.152110012007 519.153743366283 519.155376730835 520.104462817426 520.106102293798 520.107741759837 520.109381132867 520.111020516231 520.11265990993 520.114299313963 520.115938728332 520.117578153035 520.119217588074 520.120857033448 520.122496489157 520.124135955201 520.125775431581 520.1274149183 520.129054415356 520.130693922735 520.132333440458 520.133972968517 520.135612506911 520.137252055643 520.13889161471 520.140531184113 520.142170763854 520.14381035393 520.145449954343 520.147089565093 520.14872918618 520.150368817604 520.152008459365 520.153648111463 520.155287773898 520.15692744667 520.15856712978 521.126139890057 521.127785814089 521.129431623767 521.131077443839 521.132723274308 521.134369115172 521.136014966432 521.137660828088 521.13930670014 521.140952582588 521.142598475432 521.144244378673 521.14589029231 521.147536216343 521.149182150772 521.150828095596 531.111277151579 " "531.112986756559 531.114696350534 531.11640584546 531.118115351391 531.119824868327 531.121534396267 531.123243935212 531.124953485163 531.126663046119 531.12837261808 531.130082201046 531.131791795019 531.1335014 531.135211015986 531.17624485941 531.177954882673 531.179664894929 531.181374808109 531.183084732298 531.184794667495 531.186504613701 531.188214570917 531.189924539141 531.191634518375 531.193344508618 531.195054509871 531.196764522133 531.198474545405 531.20018457969 531.201894624984 539.789589969187 539.791355902538 539.793121824335 539.79488764215 539.796653471517 539.798419312438 539.800185164913 539.80195102894 539.803716904521 539.805482791656 539.807248690344 539.809014600586 539.810780522383 539.812546455734 539.814312400639 544.653632193427 544.655430097132 544.657227988968 544.659025773986 544.660823570872 544.662621379626 544.664419200249 544.66621703274 544.6680148771 544.669812733329 544.671610601426 544.673408481392 544.675206373228 544.677004276933 544.678802192507 544.68060011995 544.682398059264 544.684196010447 544.685993973499 544.687791948422 544.689589935214 544.691387933877 544.693185944405 544.694983966802 564.059258060445 564.06118636825 564.063114662872 564.065042838848 564.066971028006 564.068899230347 564.07082744587 564.072755674577 564.074683916467 564.076612171539 564.078540439795 564.080468721235 564.082397015858 564.084325323664 564.086253644655 564.088181978832 564.090110326193 577.109008739641 577.111027308003 577.113045862246 577.115064289413 577.1170827307 577.119101186105 577.12111965563 577.123138139273 577.125156637036 577.127175148919 577.129193674921 577.131212215043 577.133230769285 577.135249337647 577.137267920129 577.139286516732 577.141305127455 577.143323752299 577.145342391261 577.147361044343 578.091617372157 578.093642820461 578.095668254573 578.09769356096 578.099718881538 578.101744216308 578.103769565269 578.105794928421 578.107820305765 578.1098456973 578.111871103028 578.113896522947 578.115921957059 " "578.117947405363 578.119972867859 578.121998344549 578.124023835431 578.126049340506 578.128074859774 578.130100393235 578.13212594089 578.134151502738 578.13617707878 578.138202669016 578.140228273445 578.142253892069 578.144279524888 578.1463051719 578.148330833106 578.150356508506 579.108062150497 579.110094727971 579.112127291178 579.114159725986 579.116192175059 579.118224638399 579.120257116005 579.122289607877 579.124322114016 579.126354634422 579.128387169095 579.130419718034 579.132452281241 579.134484858716 579.136517450457 579.138550056467 579.140582676744 579.142615311289 579.144647960104 579.146680623187 593.142571534721 593.144703828301 593.146836106552 593.148968246848 593.151100402472 593.153232573424 593.155364759706 593.157496961317 593.159629178256 593.161761410526 593.163893658125 593.166025921053 593.168158199311 593.1702904929 593.172422801818 593.174555126067 593.176687465641 593.178819820543 594.330394200968 594.332535043722 594.334675871054 594.336816559592 594.338957263551 594.341097982931 594.343238717732 594.345379467954 594.347520233598 594.349661014664 594.351801811151 594.35394262306 594.356083450392 594.358224293146 594.360365151322 594.362506024921 602.987309886737 602.989513552885 602.991717202929 602.993920708033 602.996124229242 602.998327766555 603.000531319973 603.002734889497 603.004938475125 603.007142076859 603.009345694699 603.011549328644 603.013752978696 603.015956644853 603.018160327117 603.020364025487 603.022567739964 603.024771470548 603.026975217238 603.029178980037 603.031382758944 647.648714215036 647.65125642497 647.653798614949 647.656340625328 647.65888265566 647.661424705948 647.66396677619 647.666508866388 647.669050976542 647.671593106651 647.674135256716 647.676677426738 647.679219616716 647.681761826651 647.684304056543 647.686846306392 647.689388576198 647.691930865962 647.694473175684 647.697015505364 647.699557855003 647.702100224594 647.704642614142 651.124332887163 651.126902457291 651.129472007141 " "651.132041374488 651.134610762114 651.137180170017 651.139749598198 651.142319046658 651.144888515396 651.147458004413 651.150027513709 651.152597043284 651.155166593139 651.157736163274 651.160305753689 651.162875364383 651.165444995359 651.168014646615 651.17058431815 652.127911018382 652.130488515969 652.133065789459 652.135643083321 652.138220397554 652.140797732159 652.143375087136 652.145952462485 652.148529858207 652.151107274301 652.153684710768 652.156262167609 652.158839644823 652.16141714241 652.163994660372 652.166572198708 652.169149757418 652.171727336504 652.589563880196 652.592145028563 652.594726156514 652.597307100729 652.599888065358 652.602469050403 652.605050055862 652.607631081738 652.610212128029 652.612793194736 652.615374281859 652.617955389399 652.620536517356 652.623117665722 652.625698834504 653.124246691635 653.126832071549 653.129417226335 653.132002401586 653.134587597302 653.137172813482 653.139758050129 653.142343307241 653.14492858482 653.147513882864 653.150099201375 653.152684540353 653.155269899798 653.157855279709 653.160440680089 653.163026100936 653.165611542249 653.168197004028 660.917219227388 660.919866675166 660.922514101737 660.925161337446 660.927808594361 660.930455872483 660.933103171812 660.935750492348 660.938397834091 660.941045197042 660.943692581201 660.946339986568 660.948987413144 660.951634860928 660.954282329921 660.956929820121 660.959577331529 660.978110038611 660.980757974266 660.983405888706 660.986053612226 660.988701356959 660.991349122903 660.993996910061 660.996644718431 660.999292548015 661.001940398812 661.004588270823 661.007236164048 661.009884078488 661.012532014142 661.015179971004 661.01782794908 664.405995189996 664.408670663059 664.411346114577 664.414021372197 664.41669665136 664.419371952069 664.422047274321 664.424722618119 664.427397983461 664.430073370349 664.432748778782 664.435424208761 664.438099660286 664.440775133357 664.443450627975 664.44612614414 664.448801681852 664.451477241112 " "664.454152821919 664.456828424273 664.459504048176 664.462179693628 664.464855360628 664.467531049175 667.156745656581 667.159443330433 667.162140764336 667.164838220052 667.16753569758 667.170233196922 667.172930718076 667.175628261044 667.178325825826 667.181023412421 667.183721020831 667.186418651055 667.189116303095 667.191813976949 667.194511672619 667.197209390104 667.199907129405 667.202604890514 668.140046591184 668.142752223328 668.145457833561 668.148163246605 668.150868681559 668.153574138422 668.156279617196 668.158985117879 668.161690640472 668.164396184977 668.167101751392 668.169807339718 668.172512949956 668.175218582105 668.177924236166 668.180629912139 668.183335610025 668.186041329824 668.188747071536 668.19145283516 668.194158620699 668.196864428151 668.199570257517 668.202276108794 670.153471607066 670.156193571329 670.158915513485 670.161637256666 670.164359021956 670.167080809353 670.16980261886 670.172524450475 670.175246304198 670.177968180032 670.180690077974 670.183411998027 670.186133940189 670.188855904462 670.191577890846 670.194299899327 670.197021929917 677.266460681704 677.269240737313 677.272020770102 677.274800597507 677.277580447732 677.280360320776 677.283140216641 677.285920135325 677.28870007683 677.291480041156 677.294260028303 677.297040038272 677.299820071062 677.302600126674 677.305380205108 677.308160306364 677.310940430444 677.313720577346 677.316500747072 677.319280939622 677.322061154995 677.324841393193 677.327621654214 677.330401938061 677.333182244733 677.33596257423 677.338742926553 677.3415233017 684.180117968355 684.182955075248 684.185792158615 684.188629030244 684.191465925398 684.194302844078 684.197139786283 684.199976752015 684.202813741274 684.205650754059 684.208487790372 684.211324850212 684.21416193358 684.216999040475 684.2198361709 684.222673324852 684.225510502334 684.228347703342 684.231184927879 685.296805037587 685.299651413708 685.302497766186 685.305343905889 685.308190069232 685.311036256217 " "685.313882466843 685.316728701111 685.319574959021 685.322421240572 685.325267545767 685.328113874604 685.330960227085 685.333806603209 685.336653002977 685.339499426388 685.342345873435 685.345192344145 685.34803883849 685.350885356481 685.353731898117 685.356578463399 685.359425052328 685.362271664902 685.365118301123 685.367964960991 685.370811644507 685.37365835167 685.376505082481 685.379351836937 685.38219861504 686.160254003255 686.163107556924 686.165961086862 686.168814403222 686.171667743312 686.174521107133 686.177374494685 686.180227905968 686.183081340982 686.185934799728 686.188788282207 686.191641788417 686.19449531836 686.197348872036 686.200202449442 686.20305605058 699.458161318452 699.461126554625 699.464091765658 699.467056750447 699.470021760373 699.472986795436 699.475951855637 699.478916940975 699.481882051452 699.484847187067 699.487812347821 699.490777533714 699.493742744746 699.496707980919 699.499673242231 699.502638528684 699.505603840277 699.508569177012 699.511534538887 699.514499925905 699.517465338063 699.520430775363 707.534894554911 707.537928670089 707.540962759248 707.54399661424 707.54703049525 707.550064402278 707.553098335324 707.556132294389 707.559166279473 707.562200290576 707.565234327699 707.568268390842 707.571302480006 707.574336595191 707.577370736396 707.580404903623 707.583439096872 707.586473316143 707.589507561437 707.592541832753 707.595576130092 707.59861045345 707.601644802831 712.253358999635 712.256433401729 712.259507830364 712.26258228554 712.265656767258 712.268731275519 712.271805810321 712.274880371667 712.277954959555 712.281029573987 712.284104214963 714.631626985655 714.634722275108 714.637817537752 714.640912559113 714.644007607282 714.647102682261 714.650197784048 714.653292912646 714.656388068053 714.65948325027 714.662578459298 714.665673695137 714.668768957787 714.671864247249 714.674959563515 714.678054906591 725.139615581024 725.142802571441 725.145989253758 725.149175964084 725.152362702418 " "725.155549468761 725.158736263113 725.161923085476 725.165109935848 725.168296814231 725.171483720624 725.174670655029 725.177857617445 725.181044607873 725.184231626314 725.187418672767 725.190605747233 725.193792849713 725.196979980206 725.200167138713 725.203354325232 726.141603257488 726.144799061961 726.147994557046 726.151190080255 726.15438563159 726.15758121105 726.160776818635 726.163972454346 726.167168118184 726.170363810149 726.17355953024 726.176755278459 726.179951054806 726.183146859281 726.186342691885 726.189538552617 726.192734441476 726.195930358462 727.127138243687 727.130342729352 727.133547186777 727.136751390037 727.139955621536 727.143159881275 727.146364169255 727.149568485475 727.152772829936 727.155977202638 727.159181603583 727.162386032769 727.165590490198 727.16879497587 727.171999489785 727.175204031944 727.178408602347 727.181613200995 727.184817827887 727.188022483024 727.191227166403 727.194431878026 728.13784295644 728.141056357237 728.144269729676 728.147482846893 728.150695992466 728.153909166398 728.157122368687 728.160335599336 728.163548858343 728.16676214571 728.169975461436 728.173188805523 728.17640217797 728.179615578778 728.182829007947 728.186042465468 728.189255951349 728.616901834271 728.620119465045 728.623337067404 728.626554414027 728.629771789064 728.632989192515 728.63620662438 728.639424084659 728.642641573354 728.645859090464 728.64907663599 728.652294209931 728.65551181229 728.658729443065 728.66194710225 728.66516478985 739.57317102729 739.576486158636 739.579801260267 739.583116094462 739.586430958371 739.589745851995 739.593060775335 739.596375728391 739.599690711162 739.603005723651 739.606320765856 739.609635837779 739.61295093942 739.616266070766 739.619581231827 741.17101553099 741.174345003278 741.177674146565 741.18100331976 741.184332522862 741.187661755872 741.190991018791 741.194320311618 741.197649634355 741.200978987002 741.204308369558 741.207637782025 741.210967224403 741.214296696693 " "741.217626198894 741.220955731007 741.224285293032 741.227614884965 741.230944506809 742.06095178994 742.064289262981 742.067626706004 742.070963878878 742.074301081766 742.077638314671 742.080975577592 742.08431287053 742.087650193485 742.090987546457 742.094324929448 742.097662342457 742.100999785484 742.104337258531 742.107674761597 742.111012294683 742.11434985779 742.117687450917 742.121025074066 742.124362727236 742.127700410428 742.131038123643 742.13437586688 742.137713640141 742.141051443425 742.144389276727 742.147727140052 742.167754289952 742.171092723818 742.174431127655 742.177769261226 742.181107424826 742.184445618454 742.187783842111 742.191122095798 742.194460379515 742.197798693263 742.201137037042 742.204475410852 742.207813814694 742.211152248568 742.214490712474 742.217829206413 742.221167730386 742.224506284392 742.227844868433 742.231183482498 742.234522126595 743.140402346922 743.143749537385 743.1470966977 743.150443586686 743.153790505819 743.157137455098 743.160484434525 743.1638314441 743.167178483823 743.170525553695 743.173872653716 743.177219783887 743.180566944208 743.183914134679 743.187261355301 743.190608606074 743.193955886998 743.197303198075 743.200650539304 743.203997910686 743.20734531222 743.210692743909 743.214040205752 743.217387697749 743.220735219901 743.224082772208 743.227430354671 743.23077796729 743.234125610057 743.237473282979 744.169296683152 744.172653149071 744.176009584717 744.179365747906 744.182721941368 744.186078165103 744.18943441911 744.192790703391 744.196147017945 744.199503362773 744.202859737876 744.206216143254 744.209572578908 744.212929044837 744.216285541042 744.219642067524 744.222998624283 744.226355211311 758.198926754719 758.202410978174 758.205894849435 758.209378752713 758.212862688007 758.216346655318 758.219830654647 758.223314685994 758.226798749359 758.230282844744 758.233766972148 758.237251131571 758.240735323015 758.24421954648 758.247703801965 758.251188089473 758.254672409002 " "758.25815676055 758.26164114412 759.196610966793 759.200104366326 759.203597733713 759.207090811794 759.210583922019 759.214077064387 759.2175702389 759.221063445557 759.22455668436 759.228049955308 759.231543258401 759.235036593642 759.238529961029 759.242023360563 759.245516792245 759.249010256075 759.252503752057 759.255997280187 760.193422394897 760.196924974524 760.200427521877 760.203929778783 760.207432067959 760.210934389405 760.214436743123 760.217939129111 760.221441547372 760.224943997905 760.228446480711 760.231948995789 760.235451543142 760.238954122768 760.24245673467 760.245959378841 760.249462055285 760.309011783251 760.312515428169 760.316019040799 760.319522362853 760.323025717192 760.326529103815 760.330032522725 760.33353597392 760.337039457402 760.340542973171 760.344046521228 760.347550101572 760.351053714205 760.354557359126 760.358061036338 760.361564745838 760.365068487616 760.368572261681 777.182632662569 777.186293556055 777.189954415057 777.193614963706 777.197275546837 777.200936164451 777.204596816548 777.208257503129 777.211918224194 777.215578979744 777.219239769779 777.2229005943 777.226561453308 777.230222346802 777.233883274784 777.237544237253 777.241205234203 777.24486626564 799.156619815419 799.160490663856 799.164361099883 799.1682315734 799.172102084408 799.175972632907 799.179843218898 799.183713842382 799.187584503358 799.191455201828 799.195325937792 799.19919671125 799.203067522204 799.206938370653 799.210809256599 799.214680180041 799.21855114098 799.222422139414 799.226293175344 800.156426697814 800.160307238369 800.16418774129 800.168067905512 800.171948107365 800.175828346849 800.179708623967 800.183588938718 800.187469291103 800.191349681123 800.195230108777 800.199110574067 800.202991076993 800.206871617555 800.210752195754 800.214632811577 800.218513465034 801.150959244253 801.15484943781 801.158739593593 801.162629409414 801.166519263006 801.170409154372 801.174299083511 801.178189050424 801.182079055111 " "801.185969097572 801.18985917781 801.193749295823 801.197639451613 801.20152964518 801.205419876525 801.209310145647 801.213200452549 801.217090797225 801.220981179677 810.047211086567 810.051188161235 810.055165196855 810.059141881054 810.063118604297 810.067095366586 810.07107216792 810.0750490083 810.079025887728 810.083002806202 810.086979763725 810.090956760296 810.094933795916 810.098910870585 810.102887984305 810.106865137076 810.110842328887 810.114819559745 815.185536844356 815.189564537267 815.19359179245 815.197619087424 815.20164642219 815.205673796749 815.209701211101 815.213728665248 815.217756159189 815.221783692925 815.225811266457 815.229838879786 815.233866532911 815.237894225833 815.241921958555 815.245949731074 815.249977543393 815.254005395497 815.258033287397 815.386945970921 815.390975654469 815.395005298192 815.3990345835 815.40306390863 815.407093273582 815.411122678358 815.415152122956 815.419181607379 815.423211131626 815.427240695699 815.431270299597 815.435299943322 815.439329626874 815.443359350241 815.447389113433 816.161284292178 816.165321633463 816.169358934812 816.17339587673 816.177432858584 816.181469880374 816.1855069421 816.189544043764 816.193581185365 816.197618366904 816.201655588382 816.2056928498 816.209730151157 816.213767492455 816.217804873695 816.221842294876 816.225879756 816.229917257066 816.233954798077 816.237992379031 816.24202999993 816.246067660775 816.250105361565 816.254143102302 816.258180882971 816.262218703583 817.175791140998 817.179838526161 817.183885871236 817.187932855536 817.19197987992 817.196026944389 817.200074048944 817.204121193585 817.208168378313 817.212215603128 817.216262868032 817.220310173024 817.224357518104 817.228404903275 817.232452328536 817.236499793888 817.240547299332 817.244594844868 817.248642430496 817.252690056218 817.256737722019 818.156312195362 818.160369299793 818.164426363991 818.16848306611 818.172539808458 818.176596591035 818.180653413842 818.18471027688 818.18876718015 " "818.192824123651 818.196881107384 818.200938131351 818.204995195551 818.209052299986 818.213109444656 818.21716662956 818.221223854701 818.225281120079 818.229338425694 818.233395771546 818.237453157638 818.241510583968 818.245568050537 818.249625557347 818.253683104384 818.257740691659 819.179855074215 819.18392233678 819.18798915515 819.1920560139 819.19612291303 819.200189852541 819.204256832432 819.208323852706 819.212390913362 819.216458014401 819.220525155824 819.224592337631 819.228659559823 819.2327268224 819.236794125363 819.240861468713 819.24492885245 819.248996276561 820.185577074408 820.189654330641 820.193731546341 820.197808397262 820.201885288712 820.205962220691 820.210039193201 820.214116206241 820.218193259813 820.222270353916 820.226347488553 820.230424663722 820.234501879425 820.238579135663 820.242656432421 820.246733769709 832.210439016361 832.214636711145 832.21883436359 832.223031634984 832.227228948716 832.231426304787 832.235623703196 832.239821143946 832.244018627035 832.248216152466 832.252413720239 832.256611330353 832.260808982811 832.265006677613 832.269204414758 832.273402194249 832.277600016085 832.281797880267 832.285995786796 832.290193735673 832.294391726897 832.298589760471 832.302787836383 832.306985954642 833.214772599242 833.218980432568 833.223187798465 833.227395206852 833.231602657731 833.235810151102 833.240017686965 833.244225265321 833.248432886172 833.252640549516 833.256848255356 833.261056003692 833.265263794525 833.269471627854 833.273679503681 833.277887422002 833.282095382819 834.213097506187 834.217315429509 834.221533310184 834.225750807043 834.229968346546 834.234185928695 834.238403553488 834.242621220928 834.246838931015 834.251056683749 834.255274479132 834.259492317163 834.263710197844 834.267928121174 834.272146087143 834.276364095759 835.209590523302 835.213818530152 835.218046494203 835.222274073065 835.226501694725 835.230729359182 835.234957066438 835.239184816494 835.243412609349 835.247640445004 " "835.251868323461 835.256096244719 835.26032420878 835.264552215644 835.268780265312 835.273008357784 835.277236493061 835.281464671138 835.285692892018 873.169614211921 873.174235302306 873.178855854748 873.18347645609 873.188097106335 873.192717805482 873.197338553533 873.201959350488 873.206580196348 873.211201091114 873.215822034786 873.220443027366 873.225064068854 873.229685159251 873.234306298558 873.238927486775 873.243548723895 873.248170009922 874.168779238317 874.173410911255 874.17804253512 874.182673717335 874.18730494862 874.191936228976 874.196567558404 874.201198936904 874.205830364477 874.210461841124 874.215093366845 874.219724941642 874.224356565516 874.228988238466 874.233619960494 874.238251731601 874.242883551777 874.24751542103 874.293835733264 874.298468731571 874.303101680785 874.307734188164 874.312366744634 874.316999350196 874.321632004851 874.3262647086 874.330897461442 874.335530263379 874.340163114412 874.344796014542 874.349428963769 874.354061962094 874.358695009507 874.363328106014 875.165592406175 875.17023464882 875.174876842222 875.179518592457 875.184160391931 875.188802240643 875.193444138596 875.198086085788 875.202728082222 875.207370127898 875.212012222817 875.216654366978 875.221296560385 875.225938803036 875.230581094934 875.235223436068 875.239865826445 889.191017917482 889.195810155987 889.200602342844 889.205394064883 889.210185838565 889.214977663891 889.219769540862 889.224561469479 889.229353449744 889.234145481656 889.238937565216 889.243729700426 889.248521887286 889.253314125797 889.25810641596 889.262898757776 889.267691151245 889.272483596368 889.277276093147 889.282068641582 889.286861241673 889.291653893423 889.296446596831 889.301239351898 889.306032158626 889.310825017014 889.315617927065 889.320410888778 889.325203902155 889.329996967196 889.334790083902 889.339583252267 889.344376472295 890.011136019719 890.015937102839 890.02073813417 890.0255386994 890.030339316416 890.03513998522 890.039940705812 " "890.044741478193 890.049542302364 890.054343178326 890.059144106079 890.063945085625 890.068746116964 890.073547200097 890.078348335025 890.083149521749 890.087950760261 890.092752050565 890.164776481687 890.169579222658 890.174381911812 890.179184134627 890.183986409256 890.188788735699 890.193591113957 890.198393544031 890.203196025921 890.207998559629 890.212801145155 890.217603782501 890.222406471667 890.227209212653 890.232012005462 890.236814850093 890.241617746547 890.246420694826 890.25122369493 890.25602674686 890.260829850616 890.2656330062 890.270436213613 890.275239472855 890.280042783927 890.284846146813 890.289649561525 891.193612696933 891.198426546905 891.203239824931 891.208053154948 891.212866536959 891.217679970964 891.222493456964 891.22730699496 891.232120584952 891.236934226942 891.24174792093 891.246561666917 891.251375464905 891.256189314893 891.261003216882 891.265817170875 891.27063117687 891.27544523487 891.280259344875 891.285073506869 891.289887720863 892.195884230679 892.200708915166 892.205533025772 892.210357188546 892.21518140349 892.220005670603 892.224829989886 892.229654361341 892.234478784968 892.239303260768 892.244127788742 892.248952368891 892.253777001215 892.258601685716 892.263426422395 892.268251211251 892.273076052286 892.277900945486 892.28272589086 893.132728678992 893.137563501745 893.142398272161 893.147232571559 893.15206692329 893.156901327355 893.161735783755 893.166570292491 893.171404853563 893.176239466974 893.181074132723 893.185908850811 893.190743621239 893.195578443991 893.20041331912 893.205248246574 893.210083226371 893.214918258513 893.219753343 893.224588479834 893.229423669014 893.234258910542 893.239094204419 893.243929550645 893.248764949222 893.25360040015 893.25843590343 893.263271459063 893.26810706705 893.272942727391 893.277778440074 893.282614205108 894.187822376649 894.192668630074 894.197514830975 894.202360559179 894.207206339903 894.212052173146 894.21689805891 894.221743997196 " "894.226589988005 894.231436031336 894.236282127192 894.241128275573 894.24597447648 894.250820729913 894.255667035874 894.260513394364 894.265359805383 894.270206268932 894.275052784995 894.279899353585 906.224247555827 906.229225164689 906.234202718878 906.239179781027 906.244156897845 906.249134069332 906.25411129549 906.259088576319 906.26406591182 906.269043301994 906.274020746843 906.278998246366 906.283975800565 906.288953409441 906.293931072995 906.298908791226 906.303886564125 907.230703580199 907.235692252254 907.240680320926 907.245668444448 907.250656622821 907.255644856045 907.260633144123 907.265621487054 907.270609884839 907.27559833748 907.280586844978 907.285575407332 907.290564024546 907.295552696618 907.30054142355 907.305530205327 908.224399533254 908.229399140308 908.234398692328 908.239397749042 908.244396860787 908.249396027565 908.254395249375 908.25939452622 908.2643938581 908.269393245016 908.274392686968 908.279392183959 908.284391735988 908.289391343056 908.294391005152 908.299390722284 922.8325328307 922.837694572739 922.842856257044 922.84801742175 922.853178644185 922.858339924351 922.86350126225 922.86866265788 922.873824111245 922.878985622344 922.884147191179 922.88930881775 922.894470502059 922.899632244099 922.904794043873 934.032048332465 934.037336129731 934.042623867136 934.0479110658 934.053198324322 934.058485642702 934.063773020941 934.069060459041 934.074347957002 934.079635514825 934.084923132512 934.090210810063 934.09549854748 934.100786344763 934.106074201913 934.111362118932 934.116650095803 934.121938132538 962.936918468701 962.942538630487 962.94815872668 962.953778232548 962.959397804004 962.96501744105 962.970637143686 962.976256911914 962.981876745735 962.987496645149 962.993116610159 962.998736640765 963.004356736968 963.00997689877 963.015597126149 963.021217419121 963.206722453644 963.21234576551 963.217969011729 963.223591667127 963.229214388169 963.234837174856 963.240460027188 963.246082945167 " "963.251705928794 963.257328978069 963.262952092996 963.268575273574 963.274198519804 963.279821831688 963.285445209227 963.291068652422 963.296692161274 963.302315735784 963.307939375954 963.313563081784 963.319186853277 963.324810690432 963.330434593232 963.33605856169 963.409174682961 963.414800359131 963.420425969611 963.426050988895 963.431676073865 963.43730122452 963.442926440862 963.448551722892 963.454177070612 963.459802484022 963.465427963124 963.471053507919 963.476679118408 963.482304794592 963.487930536452 963.493556344003 964.202932688446 964.208567639153 964.21420252401 964.219836816216 964.225471174269 964.23110559817 964.236740087921 964.242374643523 964.248009264976 964.253643952283 964.259278705443 964.26491352446 964.270548409332 964.276183360063 964.281818376652 964.287453459101 964.293088607411 964.298723821583 964.304359101619 964.309994447519 964.315629859286 964.321265336919 964.32690088042 964.33253648979 964.338172165031 964.343807906143 964.349443713128 964.355079585987 964.36071552472 964.36635152933 964.371987599797 964.377623736134 964.456535113329 964.462173028838 964.467810878442 964.473448134917 964.479085457292 964.484722845568 964.490360299745 964.495997819824 964.501635405808 964.507273057696 964.512910775491 964.518548559193 964.524186408804 964.529824324324 964.535462305732 964.541100353044 965.189914277939 965.19556077155 965.201207199106 965.206853032182 965.212498931307 965.218144896483 965.223790927711 965.229437024992 965.235083188328 965.240729417718 965.246375713166 965.252022074672 965.257668502236 965.26331499586 965.268961555546 965.274608181294 965.280254873106 965.285901630983 965.291548454925 965.297195344935 965.302842301012 965.308489323159 965.314136411377 965.319783565667 965.325430786029 965.331078072465 965.336725424962 965.342372843529 966.20154803981 966.207206376885 966.212864647697 966.218522322157 966.224180062874 966.22983786985 966.235495743085 966.241153682582 966.246811688342 966.252469760364 " "966.258127898651 966.263786103204 966.269444374024 966.275102711111 966.280761114469 966.286419584096 966.292078119995 966.297736722167 966.303395390612 966.309054125333 966.31471292633 966.320371793604 966.326030727157 966.331689726967 966.337348793051 967.203966010578 967.209636095462 967.215306113877 967.220975534084 967.226645020755 967.232314573891 967.237984193494 967.243653879564 967.249323632103 967.254993451112 967.260663336592 967.266333288544 967.272003306969 967.277673391869 967.283343543245 967.289013761098 967.294684045428 967.300354396238 967.306024813528 967.3116952973 967.317365847555 967.323036464293 967.328707147517 967.334377897227 967.340048713424 967.345719596109 967.351390545285 967.35706156094 967.36273264308 980.1826630872 980.188486375754 980.194309595126 980.200132191883 980.205954857816 980.211777592926 980.217600397214 980.223423270681 980.229246213329 980.235069225159 980.240892306172 980.24671545637 980.252538675753 980.258361964323 980.264185322081 980.270008749028 980.275832245166 980.281655810496 980.287479445018 980.293303148735 980.299126921648 980.304950763757 980.310774675063 980.31659865557 980.322422705276 980.328246824169 980.334071012257 989.83725103487 989.843189613347 989.849128120579 989.855065986618 989.861003923897 989.866941932417 989.872880012179 989.878818163186 989.884756385438 989.890694678936 989.896633043682 989.902571479677 989.908509986923 989.91444856542 989.920387215148 989.926325936123 1024.21232670211 1024.21868494584 1024.22504311064 1024.23140056509 1024.23775809846 1024.24411571076 1024.25047340198 1024.25683117213 1024.26318902121 1024.26954694921 1024.27590495616 1024.28226304203 1024.28862120684 1024.29497945058 1024.30133777326 1024.30769617489 1024.31405465545 1024.32041321495 1024.3267718534 1024.3331305708 1024.33948936714 1024.34584824235 1024.35220719649 1024.61299057556 1024.61935379528 1024.62571693597 1024.63207936544 1024.63844187393 1024.64480446143 1024.65116712796 1024.6575298735 " "1024.66389269807 1024.67025560165 1024.67661858427 1024.6829816459 1024.68934478657 1024.69570800627 1024.7020713049 1024.70843468254 1024.79116404677 1024.79752947989 1024.80389483394 1024.8102594764 1024.81662419793 1024.82298899851 1024.82935387816 1024.83571883686 1024.84208387463 1024.84844899146 1024.85481418736 1024.86117946232 1024.86754481635 1024.87391024946 1024.88027576163 1024.88664135288 1024.89300702314 1024.89937277246 1037.16488510239 1037.17140519306 1037.17792520177 1037.18444447285 1037.19096382588 1037.19748326088 1037.20400277783 1037.21052237674 1037.21704205761 1037.22356182045 1037.23008166525 1037.23660159202 1037.24312160075 1037.24964169146 1037.25616186413 1037.26268211878 1037.2692024554 1037.275722874 1037.28224337457 1037.28876395712 1037.29528462166 1037.30180536817 1037.30832619667 1037.31484710715 1037.32136809962 1037.32788917408 1037.33441033044 1037.34093156877 1038.20898571443 1038.21551894014 1038.22205208364 1038.22858448726 1038.2351169731 1038.24164954113 1038.24818219137 1038.25471492382 1038.26124773848 1038.26778063535 1038.27431361443 1038.28084667573 1038.28737981924 1038.29391304497 1038.30044635292 1038.30697974309 1038.31351321548 1038.32004677009 1038.32658040693 1038.33311412598 1038.33964792725 1039.22246561664 1039.22901160479 1039.235556686 1039.24210184966 1039.24864709577 1039.25519242432 1039.26173783531 1039.26828332876 1039.27482890466 1039.28137456301 1039.28792030381 1039.29446612706 1039.30101203278 1039.30755802095 1039.31410409158 1039.32065024467 1039.32719648023 1039.33374279825 1039.34028919873 1039.34683568169 1039.35338224708 1039.35992889493 1040.21169412377 1040.21825258097 1040.22481095549 1040.23136858588 1040.23792629894 1040.24448409469 1040.25104197312 1040.25759993424 1040.26415797804 1040.27071610453 1040.27727431371 1040.28383260558 1040.29039098014 1040.2969494374 1040.30350797735 1040.3100666 1040.31662530535 1040.32318409339 1040.32974296414 1040.33630191754 1040.34286095363 " "1041.21594854869 1041.22251967656 1041.2290907215 1041.2356610201 1041.24223140163 1041.24880186607 1041.25537241343 1041.26194304372 1041.26851375694 1041.27508455308 1041.28165543215 1041.28822639415 1041.29479743909 1041.30136856695 1041.30793977776 1041.3145110715 1041.32108244817 1041.32765390779 1041.33422545035 1041.34079707585 1041.3473687843 1041.35394057569 1041.36051245003 1041.36708440732 1041.37365644756 1041.38022857076 1041.3868007769 1041.39337306601 1041.39994543807 1041.40651789309 1041.41309043107 1041.41966305201 1041.42623575597 1041.4328085429 1088.77842159412 1088.78560682014 1088.79279195134 1088.79997622919 1088.80716060185 1088.81434506932 1088.82152963161 1088.82871428871 1088.83589904063 1088.84308388737 1088.85026882893 1088.85745386531 1088.86463899652 1088.87182422254 1088.87900954338 1098.11077768719 1098.11808662634 1098.12539546821 1098.13270343459 1098.14001149825 1098.14731965918 1098.15462791738 1098.16193627285 1098.1692447256 1098.17655327563 1098.18386192294 1098.19117066753 1098.19847950941 1098.20578844857 1098.21309748502 1098.22040661877 1098.2277158498 1098.23502517813 1098.24233460375 1098.24964412667 1098.2569537469 1098.26426346442 1098.27157327925 1098.27888319132 1098.28619320068 1111.22207084412 1111.22955537549 1111.23703980607 1111.2445233295 1111.25200695373 1111.25949067876 1111.26697450458 1111.27445843121 1111.28194245863 1111.28942658687 1111.29691081591 1111.30439514576 1111.31187957642 1111.31936410789 1111.32684874018 1111.33433347329 1111.34181830722 1111.34930324196 1111.35678827748 1112.24072870492 1112.2482269659 1112.25572512581 1112.26322237607 1112.27071972739 1112.27821717979 1112.28571473327 1112.29321238783 1112.30071014346 1112.30820800018 1112.31570595798 1112.32320401687 1112.33070217685 1112.33820043792 1112.34569880008 1112.35319726328 1112.36069582756 1112.41318860905 1112.42068798226 1112.42818745657 1112.43568703201 1112.44318670856 1112.45068648624 1112.45818636504 1112.46568634496 " "1112.47318642601 1112.48068660819 1112.48818689151 1112.49568727595 1112.50318776154 1112.56319306158 1112.57069567152 1112.57819818028 1112.58569977849 1112.59320147786 1112.60070327839 1112.60820518009 1112.61570718295 1112.62320928699 1112.63071149219 1112.63821379856 1112.64571620611 1112.65321871484 1112.66072132475 1112.66822403575 1112.67572684791 1114.24603599637 1114.25356132196 1114.26108654592 1114.26861085524 1114.27613526618 1114.28365977874 1114.29118439293 1114.29870910874 1114.30623392618 1114.31375884525 1114.32128386596 1114.32880898829 1114.33633421227 1114.34385953786 1114.35138496508 1115.2400973368 1115.24763609676 1115.25517475482 1115.2627124958 1115.27025033867 1115.27778828344 1115.28532633011 1115.29286447867 1115.30040272913 1115.3079410815 1115.31547953577 1115.32301809195 1115.33055675004 1115.33809551004 1115.34563437195 1115.35317333572 1115.36071240139 1130.2660914334 1130.27383472389 1130.2815779083 1130.28932013803 1130.29706247383 1130.30480491569 1130.31254746363 1130.32029011764 1130.32803287773 1130.33577574389 1130.34351871613 1130.35126179446 1130.35900497886 1130.36674826935 1130.37449166592 1147.64679973146 1147.65478301943 1147.66276619636 1147.67074837394 1147.67873066254 1147.68671306219 1147.69469557288 1147.70267819461 1147.71066092738 1147.7186437712 1147.72662672607 1147.73460979199 1147.74259296897 1147.750576257 1147.75855965609 1147.76654316625 1147.77452678746 1147.78251051974 1147.79049436308 1182.96770337032 1182.97618566576 1182.98466783959 1182.99314891893 1183.00163011987 1183.01011144242 1183.01859288659 1183.02707445237 1183.03555613976 1183.04403794878 1183.05251987942 1183.06100193168 1183.06948410557 1183.07796640108 1183.08644881825 1183.09493135705 1183.15430985772 1183.16279482975 1183.1712796801 1183.17976343539 1183.18824731234 1183.19673131095 1183.20521543123 1183.21369967318 1183.22218403681 1183.23066852212 1183.2391531291 1183.24763785777 1183.25612270812 1183.26460768015 1183.27309277388 " "1183.28157798921 1183.29006332621 1183.66353599748 1183.67202827551 1183.68052043171 1183.68901149146 1183.69750267303 1183.70599397643 1183.71448540165 1183.7229769487 1183.73146861758 1183.7399604083 1183.74845232085 1183.75694435525 1183.76543651148 1183.77392878956 1183.78242118948 1183.79091371124 1188.25781635104 1188.26637468698 1188.27493289966 1188.28349000304 1188.29204722968 1188.30060457956 1188.30916205269 1188.31771964907 1188.32627736871 1188.3348352116 1188.34339317776 1188.35195126718 1188.36050947987 1188.36906781581 1188.37762627501 1209.73149100685 1209.74036149156 1209.74923184622 1209.75810103042 1209.76697034466 1209.77583978896 1209.78470936331 1209.79357906772 1209.80244890218 1209.81131886671 1209.82018896131 1209.82905918597 1209.83792954071 1209.84680002542 1209.85567064018 1209.87341226042 1209.88228326555 1209.89115440077 1209.90002566609 1209.9088970615 1209.917768587 1209.92664024261 1209.93551202832 1209.94438394413 1209.95325599005 1209.96212816609 1209.97100047225 1209.97987290852 1214.97790357742 1214.98685117584 1214.99579864251 1215.00474492341 1215.01369133607 1215.02263788047 1215.03158455663 1215.04053136455 1215.04947830422 1215.05842537566 1215.06737257887 1215.07631991384 1215.08526738058 1215.0942149791 1215.10316270939 1215.11211057146 1215.12105856523 1215.13000669076 1240.40464902433 1240.41397508362 1240.4233010027 1240.43262565993 1240.44195045736 1240.45127539499 1240.46060047282 1240.46992569085 1240.47925104909 1240.48857654754 1240.4979021862 1240.50722796507 1240.51655388417 1240.52587994349 1240.53520614303 1240.5445324828 1240.55385896272 1240.56318558285 1243.03032547186 1243.03969105933 1243.04905650569 1243.05842068214 1243.06778499968 1243.0771494583 1243.08651405802 1243.09587879883 1243.10524368075 1243.11460870376 1243.12397386788 1243.13333917311 1243.14270461945 1243.15207020691 1243.16143593548 1243.17080180517 1243.18016781599 1243.18953396794 1243.198900261 1243.20826669518 1250.92705947029 " "1250.93654444262 1250.94602927114 1250.95551280543 1250.96499648351 1250.97448030538 1250.98396427106 1250.99344838053 1251.00293263381 1251.0124170309 1251.0219015718 1251.03138625652 1251.04087108505 1251.05035605741 1251.05984117355 1251.0693264335 1261.29199699524 1261.30163981508 1261.31128248752 1261.32092383336 1261.33056532659 1261.34020696722 1261.34984875525 1261.35949069069 1261.36913277353 1261.37877500379 1261.38841738147 1261.39805990657 1261.40770257909 1261.41734539893 1261.42698836617 1261.92862266474 1261.93827522226 1261.94792763215 1261.95757871339 1261.96722994224 1261.97688131873 1261.98653284283 1261.99618451457 1262.00583633394 1262.01548830095 1262.02514041559 1262.03479267788 1262.04444508782 1262.05409764541 1262.06375035065 1262.07340320354 1262.08305620408 1262.09270935227 1262.30511272825 1262.31477104675 1262.32442921749 1262.33408605841 1262.34374304707 1262.35340018349 1262.36305746766 1262.3727148996 1262.3823724793 1262.39203020678 1262.40168808202 1262.41134610504 1262.42100427584 1262.43066259442 1262.44032106079 1262.44997967483 1262.45963843663 1263.26182796013 1263.27150092584 1263.28117374346 1263.29084522825 1263.30051686113 1263.31018864211 1263.31986057118 1263.32953264835 1263.33920487361 1263.34887724699 1263.35854976847 1263.36822243806 1263.37789525577 1263.3875682216 1263.39724133555 1263.40691459763 1263.41658800777 1263.42626156602 1265.29603237936 1265.30573652557 1265.31544052296 1265.32514318102 1265.33484598788 1265.34454894355 1265.35425204803 1265.36395530132 1265.37365870343 1265.38336225437 1265.39306595413 1265.40276980271 1265.41247380013 1265.42217794639 1265.43188224148 1265.4415866854 1273.44964695491 1273.45947658402 1273.46930606141 1273.47913417338 1273.48896243705 1273.49879085242 1273.5086194195 1273.51844813829 1273.5282770088 1273.53810603102 1273.54793520496 1273.55776453063 1273.56759400803 1273.57742363715 1273.58725341802 1273.59708335062 1273.60691343496 1273.61674367105 1273.62657405888 " "1273.6364045985 1273.64623528987 1281.30097667712 1281.31092789888 1281.32087896611 1281.33082864257 1281.34077847355 1281.35072845906 1281.3606785991 1281.37062889368 1281.38057934279 1281.39052994644 1281.40048070464 1281.41043161738 1281.42038268468 1281.43033390653 1281.44028528294 1281.45023681392 1281.46018849946 1281.47014033957 1281.48009233426 1281.49004448347 1281.49999678724 1293.14970519514 1293.1598413324 1293.16997731079 1293.18011185941 1293.19024656688 1293.2003814332 1293.21051645839 1293.22065164243 1293.23078698534 1293.24092248711 1293.25105814776 1293.26119396729 1293.27132994569 1293.28146608298 1293.29160237905 1293.30173883398 1409.27988966716 1409.29192829595 1409.30396671911 1409.31600329167 1409.32804006984 1409.34007705362 1409.35211424301 1409.36415163802 1409.37618923866 1409.38822704493 1409.40026505684 1409.4123032744 1409.4243416976 1409.43638032645 1409.44841916087 1409.46045820092 1439.78778750238 1439.80035305206 1439.81291838247 1439.82548173949 1439.83804531576 1439.85060911129 1439.86317312607 1439.87573736013 1439.88830181346 1439.90086648606 1439.91343137795 1439.92599648913 1439.93856181961 1439.95112736929 1439.96369313824 1439.97625912687 1439.98882533458 1440.00139176163 1440.013958408 1440.0265252737 1440.03909235875 1440.05165966315 1440.0642271869 1440.07679493 1440.08936289247 1440.10193107432 1440.11449947547 1440.12706809597 1456.37108237404 1456.38393907986 1456.39679555874 1456.40964999523 1456.42250465864 1456.43535954896 1456.44821466621 1456.46107001039 1456.47392558151 1456.48678137957 1456.49963740459 1456.51249365655 1456.52535013548 1456.53820684138 1456.55106377425 1456.5639209341 1456.57677832093 1456.58963593471 1456.60249377546 1469.47025906961 1469.48334811809 1469.49643693345 1469.5095236508 1469.52261060125 1469.5356977848 1469.54878520145 1469.56187285121 1469.57496073409 1469.58804885009 1469.60113719922 1469.61422578149 1469.6273145969 1469.64040364545 1469.65349292705 1469.66658244177 " "1477.44348519436 1477.45671668448 1477.46994793765 1477.48317705841 1477.49640641608 1477.50963601066 1477.52286584217 1477.53609591059 1477.54932621596 1477.56255675826 1477.5757875375 1477.58901855369 1477.60224980685 1477.61548129696 1477.62871302405 1477.64194498811 1477.65517718916 1477.6684096272 1477.68164230223 1477.69487521426 1477.7081083633 1477.72134174936 1477.73457537235 1477.74780923233 1478.88680339341 1478.90006075078 1478.91331787051 1478.9265728516 1478.93982807029 1478.9530835266 1478.96633922051 1478.97959515204 1478.99285132121 1479.006107728 1479.01936437244 1479.03262125452 1479.04587837426 1479.05913573163 1479.07239332664 1480.14704316047 1480.16032312453 1480.17360285036 1480.18688043216 1480.20015825217 1480.2134363104 1480.22671460685 1480.23999314153 1480.25327191444 1480.2665509256 1480.279830175 1480.29310966266 1480.30638938858 1480.31966935276 1480.33294955522 1480.34622999596 1480.35951067499 1480.37279159231 1480.38607274793 1480.39935414185 1480.41263577409 1480.42591764464 1480.43919975341 1480.45248210047 1480.70488674232 1480.71817671946 1480.73146645809 1480.74475405022 1480.75804188082 1480.77132994991 1480.78461825749 1480.79790680357 1480.81119558816 1480.82448461126 1480.83777387287 1480.85106337301 1480.86435311168 1480.87764308888 1480.89093330463 1480.90422375893 1480.91751445178 1480.9308053832 1480.94409655318 1480.95738796174 1480.97067960888 1480.983971494 1480.99726361894 1481.01055598187 1481.0238485834 1481.03714142355 1481.05043450231 1481.06372781971 1481.07702137574 1481.09031517027 1481.1036092034 1481.31634094436 1481.32964190116 1481.34294261915 1481.35624118796 1481.36953999554 1481.38283904191 1481.39613832706 1481.409437851 1481.42273761375 1481.4360376153 1481.44933785567 1481.46263833486 1481.47593905287 1481.48924000971 1481.50254120539 1481.51584263992 1481.5291443133 1481.54244622554 1481.55574837664 1481.56905076662 1481.58235339547 1481.5956562632 1481.60895936983 1481.62226271535 " "1481.63556629978 1481.64887012311 1481.66217418536 1481.67547848654 1481.68878302651 1481.70208780537 1482.34099304957 1482.35431241572 1482.36763154258 1482.38094851586 1482.39426572841 1482.40758318025 1482.42090087136 1482.43421880177 1482.44753697147 1482.46085538047 1482.47417402879 1482.48749291642 1482.50081204337 1482.51413140965 1482.52745101526 1482.54077086022 1482.5540909444 1482.56741126789 1493.5982780897 1493.61180054861 1493.62532276273 1493.63884277381 1493.65236302966 1493.66588353027 1493.67940427566 1493.69292526583 1493.70644650079 1493.71996798055 1493.73348970511 1493.74701167448 1493.76053388867 1493.77405634768 1493.78757905144 1493.801102 1511.56275146435 1511.57660120391 1511.59045068974 1511.60429789207 1511.6181453481 1511.63199305785 1511.64584102131 1511.65968923849 1511.6735377094 1511.68738643405 1511.70123541244 1511.71508464459 1511.72893413049 1511.74278387005 1511.75663386334 1599.95476419777 1599.97027768381 1599.98579147069 1600.00130555844", "0 0 0 0 0 0 0 0 56.580329059165 222.670531230651 384.428314386826 483.544970105578 520.020498386908 493.854899230815 405.048172637299 253.600318606361 80.6321002809041 0 0 0 0 0 0 0 0 63.1937789027786 177.170824740039 287.593692521671 365.067335897948 393.750113818473 373.642026283247 304.743073292268 187.053254845537 68.2775071150773 0 0 0 0 0 0 0 0 0 26.5531008704837 64.2443677639905 115.98666236006 147.825064207846 159.759573307349 151.790189658567 123.916913261502 76.139744116154 33.749000104713 0 0 0 51.7119753110659 82.9031363178244 101.554580012679 107.666306395631 101.238315466678 82.2706072258227 50.7631816730632 6.71603880840022 0 0 0 0 0 0 0 30.1075875875833 70.2224843129689 97.0448626538256 110.574722610153 110.812064181952 97.7568873692226 71.4091921719637 31.7689785901761 0 0 0 0 0 0 0 0 18.3294783372145 58.8736362412815 110.537404378255 156.846788810961 179.944579437896 179.83077625906 156.505379274453 109.968388484075 60.0197602385408 18.9203823774288 0 0 0 0 0 0 0 8.58646017576987 41.2356907771184 64.3686342394991 77.985290562912 82.0856597473572 76.6697417928345 61.737536699344 37.2890444668856 3.32426509545953 0 0 0 0 0 0 0 0 78.9325434900386 191.263742620295 293.355350485493 369.501770161804 395.790015125052 372.220085375237 298.791980912358 180.992891289415 67.186402469804 1.06252827677693 0 0 0 0 0 0 0 0.0625048728533582 38.1302716092908 65.7740289648097 82.99377693941 89.7895155330917 86.1612447458548 72.1089645776994 47.6326750286254 0 0 0 0 464.834393836957 1182.28302428772 1901.39633271189 2402.71116385649 2585.80436190803 2441.13485483023 1968.70264262308 1253.9916804387 526.546510994295 23.8594603638548 0 0 0 0 0 0 0 0 0 0 78.7486744416065 320.65786394595 583.556565647081 752.05728398392 820.575446424507 789.111052968842 657.664103616924 426.88182441338 165.292091778664 0 0 0 0 0 0 0 0 0 39.6674667038284 97.8364408266294 137.002481847376 157.165589766069 158.325764582707 140.483006297292 103.637314909822 47.7886904202975 0 0 0 0 0 0 0 0 " "20.1155565879839 84.6860871570649 135.944271594494 166.382412072384 176.000508590734 164.798561149544 132.776569748814 79.9345343885444 15.8504547617096 0 0 0 0 0 0 0 0 0 0 0 878.523046533544 3533.54161768915 6597.61115654365 8946.62553775672 10018.5698880638 9907.26689265325 8573.87583987363 6006.3995425351 2960.21581124259 513.821274692918 0 0 0 0 0 0 0 0 0 0 0 0 421.945560197452 1134.6227427307 1824.51103569689 2237.41520996805 2374.5619220867 2300.36824263282 2021.34070677857 1530.49420521698 996.809708032853 641.61360705538 528.468407406396 531.361696612307 464.464233398438 260.778715547148 68.9924579611467 0 0 0 0 0 0 0 0 0 134.609378556827 578.260282929961 1074.93768168274 1446.2596667452 1636.63645465558 1632.36158176236 1423.41207736356 1010.5181634365 540.379547048004 196.247308477655 84.5798738208401 150.894825933141 250.318398606805 276.0162302653 258.330770141317 212.850712062596 145.902348124897 75.0209929993102 20.4909287743912 0 0 0 0 0 0 0 0 0 300.845798021152 1114.43657888844 2054.2882292065 2782.39238530939 3116.96538908276 3058.00724052661 2605.51793964093 1808.21684723968 876.364110417578 130.946627387912 0 0 0 0 0 0 0 0 76.3418424023892 283.125607506101 489.762458000984 616.219671645087 662.497248438411 628.595188380955 514.51349147272 320.252157713706 108.831177042359 0 0 0 0 0 0 0 0 15.9746526260199 124.960080446897 241.25387989391 318.133682322113 352.504830989527 344.36732589615 293.721167041983 200.566354427026 76.4160180080742 0 0 0 0 0 0 0 0 0 0 406.708752185315 1334.78267514956 2349.32185360213 3068.03144605232 3393.7700774364 3335.58019052075 2852.29924267322 1989.01304146293 995.7183964158 227.016740278764 0 0 0 0 0 0 0 0 0 0 0.0546699648414517 39.6806581581667 90.1680477115657 123.724541724145 140.350140195904 140.044843126844 122.808650516963 88.6415623662632 37.5435786747432 0 0 0 0 0 0 0 0 64.1342712260068 274.122147282242 516.021753413416 708.081059275807 801.952577390871 794.773707143077 686.544448532425 477.264801558915 " "232.671458708934 39.340255239349 0 0 0 0 0 0 0 0 0 30.4287526235159 87.8759740015845 129.18958679057 151.813565340909 155.747909652603 140.992619725652 107.547695560055 55.4131371558129 8.86281480766951 0 0 0 0 0 0 0 0 27.558765687031 68.0522128018466 118.710231007396 149.457779891008 160.294859452681 151.221469692417 122.237610610215 73.3432822060752 31.594597520806 0.815041032982236 0 0 0 0 0 0 0 147.065229082441 816.937306508595 1594.57035205192 2160.73973186644 2445.81752099524 2447.96061400656 2138.26428169304 1516.72852405468 741.546437830359 123.28685957902 0 0 0 0 0 0 0 0 0 5.37730891443355 37.952812568291 86.8506389342265 119.270008149403 135.210920213819 134.673375127477 117.657372890375 84.1629135025131 34.1899969638923 4.06605423080336 0 0 0 0 0 0 0 2.63267410385011 193.022110518875 447.13469210538 680.1333845801 842.849257711486 921.179299058892 891.052504390547 736.307160597581 484.707327498145 236.76334361541 74.5047025880612 9.88939145672835 0 0 0 0 0 0 0 0 0 78.5846299035843 199.159299908262 280.700094903266 323.207014888595 326.680059864249 291.119229830228 216.524524786533 102.895944733164 0 0 0 0 0 0 0 7.39269724314586 48.1607391428559 77.2501943806113 94.6610629564122 100.393344870258 94.4470401221501 76.8221487120871 47.5186706400696 6.53660590609747 0 0 0 0 0 0 2.38687507255929 42.7141680950885 71.8261903349336 89.7229417920946 96.4044224665714 91.8706323583642 76.1215714674729 49.1572397938974 10.9776373376379 0 0 0 0 0 0 0 460.239607235212 2862.44145405376 5839.56022704509 8350.2375135444 9678.68241274107 9810.33116694097 8739.8425216497 6417.89346263681 3472.16898931045 923.290802073089 0 0 0 0 0 0 0 0 0 0 1.21281717651646 35.0232140601098 82.6014301148883 114.369752328157 130.328180699915 130.476715230164 114.815355918902 83.3441027661303 36.0629557718486 1.2077191759656 0 0 0 0 0 0 0 20.2247096419612 67.9158100403834 127.542260656823 164.980780185797 180.231368627302 173.294025981341 144.168752247913 92.8555474270181 40.8839086074638 0 0 " "0 3.75304439518002 40.7344921618909 92.7082375124063 127.176010238541 144.137810340295 143.593637817667 125.54349267066 89.9873748992707 36.925284503501 2.6634972845757 0 0 0 0 0 0 0 222.069063342257 922.071941242353 1699.46145309769 2332.56524558612 2762.37139650714 2932.97623868645 2749.76402172453 2154.12462155358 1371.75909907557 694.588988973267 296.186114686908 127.10528834772 26.9340466052504 0 0 0 0 0 0 0 0 14.0997288843967 411.915607016681 938.814124758705 1326.40101534615 1542.15077277052 1612.96328429464 1521.26588977022 1249.39873911895 824.933991154313 413.748029802229 184.349373237237 151.395683946587 170.435887939169 89.7732302081057 11.6400089930822 0 0 0 0 0 0 0 0 75.4495806927448 198.667384149867 320.344301059252 391.667397238992 412.636672689087 383.252127409537 303.513761400343 173.421574661504 51.7569392633328 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 218.289064349549 1375.4185408301 2853.53691716405 4111.87394234184 4773.71754000293 4820.43625567954 4323.88157973923 3212.97951537801 1724.93808477797 413.467460863518 0 0 0 0 0 0 0 0 13.9193490479653 49.4962683902197 74.3885564559544 77.2845681641762 73.7332380245892 77.1295705586323 94.8237774900066 130.334876178306 164.777472613853 195.814271726809 221.110580764451 218.01382962029 179.423323624618 112.770667122794 46.6491851806641 0 0 0 0 84.9664134490185 453.04162996021 855.94201873566 1203.17425622473 1482.54422644413 1635.17299298195 1581.35360550603 1295.91611948436 868.001328226013 480.103207746029 236.811169284206 107.43062451058 6.90438675602574 0 0 0 0 0 0 0 0 0 55.7104535225111 151.168876487892 227.233838772718 269.679472845473 278.505778706157 253.71275635477 195.300405791312 104.652852234029 19.144869113024 0 0 0 0 0 138.891268643466 437.569434248206 699.524413351135 853.877060434479 933.274479934942 940.569107482483 871.230297026378 683.531829620574 450.146854142764 283.595072570659 224.223552712749 210.192749877076 141.173638190423 42.4980949277366 0 0 0 0 0 0 0 " "0.0432223162173031 41.1795508466956 101.05418726781 141.259691856402 161.796064612471 162.663305536017 143.86141462704 105.39039188554 47.2502373115166 2.99908920323652 0 0 0 0 0 0 4.2043330763881 48.799060670368 98.2071964290593 130.261364845685 144.961565920245 142.30779965274 122.300066043169 84.9383650915329 30.2226967978311 0 0 0 0 0 0 0 3.56522918914582 42.772335025814 70.9899717033048 88.2181392216182 94.4568375807542 89.7060667807128 73.9658268214939 47.2361177030977 9.516939425524 0 0 0 0 0 0 0 58.821031512636 207.741213356143 342.149165226863 422.50411240371 448.806054886682 421.054992675781 339.250925771006 203.393854172358 59.3580422212472 0 0 0 0 0 0 0 0 32.48157773318 60.2129703334996 77.9906898978709 85.8147364262936 83.6851099187679 71.6018103752938 49.5648377958712 17.5741921805002 0 0 0 0 0 0 0 0 0 968.603915661365 2653.86673578293 4283.40980807218 5263.356996763 5634.95406894639 5356.74031134474 4403.79027562709 2835.16697596837 1198.53091476903 99.3317592238491 0 0 43.7005128304719 0 0 0 0 0 0 0 1.07703294731796 43.1776158259465 73.6865398344738 92.6038049728999 99.9294112412247 95.6633586394482 79.8056471675704 52.3562768255914 13.3152476135112 0 0 0 0 0 0 0 0 224.974633561426 768.975833314839 1200.82574775892 1532.35896891703 1810.51670186503 1924.64049008954 1765.30956647113 1346.65247705989 823.656264369583 415.831654084035 232.806001107454 153.075705930625 0 0 0 0 0 0 0 0 31.07674932591 83.1869365274211 118.594620960298 137.29980262454 139.302481520148 124.602657647122 93.2003310054611 45.095501595166 3.1810702877445 0 0 0 0 0 0 0 0 58.0700804525877 349.994400949189 694.454611611533 968.727648150394 1112.31297817986 1149.25511354389 1085.70508424274 904.114671578219 602.249157458752 322.46461700226 170.141715665519 129.989040312511 109.655052345116 57.0866252836925 0 0 0 0 0 0 0 0 31.1422953216623 144.076980697525 276.947856236171 361.346737308102 397.273623913318 384.728516051819 323.711413723606 214.222316928677 90.7740647820605 0 0 0 0 0 " "0 0 16.8304083052771 57.6761780852205 86.1866616913767 102.361859123746 106.201770382328 97.7063954671224 76.87573437813 43.7097871153504 0 0 0 0 0 0 0 0 41.0256652120666 94.135655756597 129.498184310806 147.113250874695 138.344459373634 85.9153107329683 0 0 129.488300492435 527.067957062265 1000.05021941356 1346.99716801855 1496.12085985304 1459.02060509173 1235.69640373461 847.979145859227 382.422087413726 19.9891446698237 0 0 0 0 0 0 0 7.44465210387754 47.4026937418051 91.2424360510909 119.32425972465 131.648164762484 128.214151164591 109.022218930971 74.0723680616259 23.3645985565541 0 0 0 0 0 0 31.1665401858884 103.860189549017 146.554329114083 195.753168030497 253.418050841574 299.427352514023 300.171697585455 255.651086055871 180.101849749372 121.966266054096 92.4298811336774 53.3473170353815 0 0 0 0 0 0 0 2.16977021188442 58.7684953240524 128.064489653616 173.783125977416 195.924404295452 194.488324607725 169.474886914233 120.884091214978 48.7159375099592 0 0 0 0 0 0 0 9.11328484239557 45.9480907377941 72.0695525127136 87.4776701671539 92.172443701115 86.153873114597 69.4219584075999 41.9766995801237 3.81809663216825 0 0 0 0 0 0 0 39.051860533672 87.2874872878993 119.282621797148 135.037264061419 134.551414080711 117.825071855025 84.8582373843604 35.6509106687177 0 0 0 0 0 0 0 1.69602361647959 44.8811960642711 76.1225670234307 95.4201364939586 102.773904475855 98.1838709691188 81.6500359737512 53.1723994897518 12.7509615171205 0 0 0 0 0 0 3.8020184212353 39.4493619478666 85.0018297742297 141.991383977148 175.708218518949 186.152333399633 164.603114272609 118.034558027219 73.7157701256669 71.4067476357057 90.1063530839683 108.46793982588 125.35972406703 139.403204751181 123.020032691511 89.9415597270974 40.1677858579408 0 0 0 0 0 0 0 0 27.1206040815874 111.052126157534 187.706427158454 234.152603967484 250.390656584626 236.420585009879 192.242389243244 117.856069284719 40.2592313539731 0 0 0 0 0 0 0 0 0 0 398.852037585421 1062.65146567605 1700.46363133429 " "2084.80266327403 2196.2757965657 2034.88303120931 1626.55308137907 981.359526805391 326.033995870667 0 0 0 0 0 0 0 0 7.16578375542911 46.4870872942161 91.6829358080884 120.81335876038 133.878356151092 130.877927980223 111.812074247774 75.0577634442381 0 0 0 107.782782281195 222.248625641936 305.267269534665 430.256208939986 573.133296513057 651.057089105353 632.035175883687 520.170219830422 378.181396342102 270.606431974398 189.369573846563 59.2234124670495 0 0 0 0 0 0 0 0 0 89.7750522995884 203.418093061114 282.425017492477 343.024862578421 380.616778820545 366.947697352696 302.017618174875 189.785982963367 83.2391572965611 27.3657364211717 16.5044280365631 7.73395881563912 0 0 0 0 0 0 0 24.6662371797717 177.35019753196 363.077968108348 504.323164613097 574.146720014808 572.548634313481 499.528907509117 355.087539601715 172.380371378296 20.8220308388308 0 0 0 0 0 0 0 3.13301499017747 41.5384418336385 83.126995593518 110.088259325717 122.422233030235 120.128916707072 103.208310356229 71.6604139777053 25.4852275715008 0 0 0 0 0 0 0 0 4.18438116042486 81.6340404590526 184.237271609006 288.975303952233 380.977933941465 443.93454189345 454.637123232399 400.925354324021 294.161514886887 183.3917595212 96.5255568711075 38.7303105778906 3.02359535199502 0 0 0 0 0 0 0 0 15.0726765452566 72.8836913208862 156.47641812838 271.243299079664 405.814256681429 531.454790306536 626.386107011275 674.981889062272 666.860740714974 593.166164869473 478.423894886648 339.627820706312 203.89971884703 97.5393991181344 25.2512227305165 0 0 0 0 0 0 0 0 0 159.195879031451 755.611733461039 1465.07687498862 2027.56122992811 2300.46812599022 2283.79756317494 1977.54954148228 1395.66622732736 694.27564102564 113.818217671001 0 0 0 0 0 0 0 0 87.9490083280976 276.782974634415 469.754560990767 633.069600138631 707.098015062737 691.839805763085 587.294972239675 393.463514492506 175.767283477428 27.5048187896088 0 0 0 0 0 0 0 3.83732277752358 48.604770473667 80.8521452150145 100.579447001566 " "107.786675833322 102.473831710282 84.640914632446 54.2879245998142 11.4148616123866 0 0 0 0 0 0 0 62.0859234505322 237.157430582113 409.419941117436 539.981749456802 596.533654735361 579.075656953114 487.60775611006 322.1299522062 134.395098635089 1.91269422411075 0 0 0 0 0 0 0 0 40.6763852348416 115.908585270524 176.182268369448 210.213658046056 218.002754300347 199.549557132321 154.854066541979 83.9162825293197 15.7817960441252 0 0 0 0 0 0 0 0 28.7568318471486 73.109018890452 103.132771560918 118.828089858546 120.194973783337 107.233423335291 79.9434385144072 38.3250193206859 0 0 0 0 0 0 0 0 10.6625377948467 74.9142424754607 165.494804649086 287.059236113008 434.534418741862 586.533972964698 710.76455329237 776.748612695085 785.413608506566 762.271802782179 673.909408747178 535.384800197362 377.341590721291 233.20957295878 120.30560103552 40.7944522315249 0 0 0 0 0 0 0 0 38.6563572739117 364.499308837322 781.749915489784 1139.17763080019 1328.35192757275 1349.27280580748 1201.94026550435 886.354306663389 471.473510457642 106.703597915757 0 0 0 0 0 0 0 7.73662188336564 48.980887032889 78.4115988635795 96.0287573754371 99.1956425380041 58.2084386509894 14.7314589351486 35.9568292577783 146.482631265422 324.900631208798 495.755628430204 599.271237851301 616.05365328133 557.826909169728 424.591005516497 223.010984620848 41.2635390986374 0 0 0 0 0 0 0 0 28.9825461149772 104.503168955272 170.980321283941 210.469236680678 222.969915145483 208.482356678356 167.006561279297 98.5425289483059 33.3136386471194 0 0 0 0 0 0 0 0 22.164983540426 89.3156778117716 114.606955041419 123.795334182419 152.155981637381 213.065699721828 304.57126085686 413.880444648938 530.896991294025 649.506209615783 751.232561018084 791.851777190095 731.249636919071 617.617943112389 476.905889764533 335.457150617124 213.174913526415 121.290352347848 58.6050446339144 15.4890085500438 0 0 0 0 0 0 0 0 0 55.1470522224764 205.248684756406 376.77187196247 488.647291312407 533.91258901316 512.567765064729 " "424.612819467113 293.639329923616 130.501937048141 0 0 0 0 0 0 0 0 0 26.7308857524312 65.3755704439604 108.690081367404 163.069601739203 191.674607319154 194.505098107256 171.561074103509 122.842535307913 75.0868885956166 33.9400274103338 4.43001554618073 0 0 0 10.86665411818 58.5051887707833 112.448902299076 146.961878565364 162.044117569646 157.695619311922 133.916383792192 90.7064110104576 28.0657009667171 0 0 0 0 0 0 0 0 32.0124449474273 78.0469590122606 109.04468587951 125.005625549174 125.929778021255 111.817143295751 82.6677213726623 38.4815122519896 0 0 0 0 0 0 0 0 21.1402150756551 75.9409963612234 167.425308725495 296.82683870898 446.085191099794 580.561820503715 653.153247682087 651.881193752333 581.633140403908 467.109662569486 320.388051813299 173.048924763998 61.2694148350429 0 0 0 0 0 0 0 0 0 10.2529036870924 93.6242285952978 209.564040141784 337.962966172011 458.582199736908 556.476431466483 624.809225051275 650.47037362052 613.96121717333 525.526058170345 419.746564353818 311.244555208789 205.813153282468 109.199933672285 30.0832366943358 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3.41523369208915 51.458328851731 97.5781555531465 127.097920379994 140.017623332275 136.337264409988 116.056843613133 79.1763609417113 25.6958163957218 0 0 0 0 0 0 0 0 0 372.079539336803 1016.65002743737 1610.38992558548 1968.29416128306 2116.70497867611 2003.57856608215 1621.14932115817 1010.35877731074 390.808202498998 0 0 0 0 0 0 0 0 0 0 0 100.46006906505 412.467642261711 749.729029230862 983.569686533968 1084.13748617106 1051.43242814213 885.45451244719 586.203739086232 241.127440268065 0 0 0 0 0 0 0 0 1.07279875784213 17.2450552987052 25.2870257539905 52.7916675203054 164.1861986636 393.581850847719 686.799061488438 924.798064260772 1022.84418130088 1011.00502476548 888.903006209083 663.630723077379 372.76392970941 101.44183605701 0 0 0 0 0 0 0 0 0 14.1457899044721 87.5922147310697 154.796218231841 196.667849382876 213.207108184174 204.413994635735 170.28850873756 " "110.830650489647 32.5873545399913 0 0 0 0 0 0 0 11.6920036547112 72.4842579092458 121.835492789884 152.031258963205 163.071556429207 154.956385187892 127.685745239258 81.259636583306 15.6780592200361 0 0 0 0 0 0 0 6.13225404254762 52.6391649223986 85.9729387687915 106.133575581726 113.121075361203 106.935438107222 87.5766638197822 55.0447524988846 9.33970414452897 0 0 0 0 0 0 0 148.167932897181 1388.05229731206 2976.45391205474 4342.85406750232 5088.76170669236 5186.18815488304 4635.13341207438 3435.59747826636 1853.88035789792 453.450956331267 0 0 0 0 0 0 0 0 6.66626976030965 48.3212128041229 92.3405437691783 120.513208633814 132.83920739803 129.318540061826 109.951206625203 74.7372070881592 23.6765414506961 0 0 0 38.1889706769468 89.7086560798414 123.988314968723 141.027947343591 140.827553204445 123.387132551287 88.7066853841146 36.7862117029292 5.33883748799218 0 0 0 0 0 0 0 0 145.464155005964 904.990516822656 1823.29311600265 2567.20284845668 2993.22855389646 3050.41713783958 2718.43636651028 2003.11355619275 1081.64283706203 290.874158098981 0 0 0 0 0 0 0 0 0 3.10649507251377 40.5222100389031 87.2688733080883 117.987425690764 132.677867186931 131.340197796588 101.866811685629 0 0 0 453.972310348548 1151.65821340423 1659.45029988323 1962.0662062496 2075.50547580675 1963.25049610627 1577.71579897154 947.284497916838 350.211003656987 29.6131019503359 4.44898613349534 62.1006770989833 0 0 0 0 0 0 0 0 0 49.7262262019801 222.611733603311 426.196186376897 593.853597325324 676.474096231528 674.057683095511 586.604357917271 414.114120696809 196.391473516718 34.5097690751222 0 0 0 0 0 0 0 0 103.047914731753 393.530483432584 693.196257051056 909.36366969111 1011.89433523325 987.981005012852 837.623679029915 560.82235728444 238.223779389352 13.6118697942272 0 0 0 0 0 0 0 0 0 26.0728362468016 167.871154927429 343.088860749643 480.963335619662 549.937720203177 550.012014500189 481.186218510697 343.460332234701 172.628680604877 27.9800269564826 0 0 0 0 0 0 0 0 " "17.0064636799561 96.9148907072338 178.180039946016 229.163176174208 249.864299391811 240.283409598824 200.420506795247 130.275590981081 54.1559029603616 0 0 0 0 0 0 0 0 26.4056763193268 101.508346877732 187.251913537512 270.682010712879 313.730347924577 316.396925172606 278.681742456965 200.584799777656 103.746263908617 30.8895239841132 0 0 0 0 0 0 0 0 64.0352733407543 159.398966329081 271.666252509698 392.393694826495 453.049673369437 453.634188138522 394.147239133751 274.588826355123 164.708285814121 66.5432133174443 0 0 0 0 0 0 0 0 122.841370340272 440.753407155995 764.413820066652 991.46218178489 1106.4972962066 1081.54964345652 916.619223534644 611.706036440976 273.045237685695 29.2376758424273 0 0 0 0 0 0 0 0 0 32.7690956809304 145.477944683084 250.423947598829 314.793448921684 338.58644865165 321.802946788726 264.442943332912 166.506438284209 50.6765287883908 0 0 0 0 0 0 0 0 0 135.516833183093 324.403155062304 500.465067261027 608.838382712055 638.082379961347 588.197059008903 459.182419854722 263.389066007032 80.6505240771598 0 0 0 0 0 0 0 0 0 19.3995503601216 63.5382819542518 122.552791675488 185.422363636933 219.297602549022 224.178508411754 200.065081225131 146.957320989151 88.6727182526132 35.8050960727504 0 0 0 0 0 0 0 0 460.788375605515 2508.82573025932 4939.40949439558 6874.84518169413 7854.2086463697 7844.62770020099 6846.10234318801 4858.63257533074 2423.29035892796 417.804882840934 0 0 0 0 0 0 0 0 6.64380953417508 48.4820306239984 92.7635744535006 121.113971843586 133.533222794255 130.021327305507 110.578285377342 75.2040970097611 23.8987622027631 0 0 0 0 0 0 0 0 27.6298641391568 83.0580266850257 115.464066512101 37.8512631929836 0 22.0332041564798 604.300217421739 1634.0828638677 2794.83638185443 3678.08531007567 4095.16125367349 4042.49495730811 3462.76448528583 2414.8137783593 1200.11309547691 242.642732100053 0 0 0 0 0 0 0 0 0 0 0 0 546.056452717815 1428.50190147987 2286.81531305913 2881.15280571073 3136.63219578172 2986.54705867456 " "2466.7301779438 1619.59712301045 713.12902775122 79.1337964607008 0 0 0 0 0 0 0 0 0 34.9362717208327 100.422996432075 163.706364878408 184.575098033274 118.461565208879 57.8737510200977 145.435167859484 441.347950506323 878.652717536982 1285.74163576495 1563.3104759163 1679.0391052175 1578.95694755786 1254.90524003889 757.932619037051 282.530123944049 0 0 0 0 0 0 0 0 0 0 54.757898148401 225.022785320149 420.95868432105 584.424901255361 663.931591540784 659.478755177318 571.066392164964 398.694502503722 198.302844494373 38.6952030564243 0 0 0 0 0 0 0 0 37.6310254788343 91.9962408248083 128.656494354035 147.611786066513 148.862115962244 132.407484041227 98.2478903034627 46.3833347489505 0 0 0 0 0 0 0 0 18.9048317151187 198.336802378123 422.811895090383 613.581958406178 719.790485977849 726.548520246031 642.251383570247 484.06224465537 292.224921344322 135.10041439172 59.6607853460419 61.9697238948796 89.3677225535289 95.3564121984381 70.4656856865873 29.3031057433371 0 0 0 0 0 0 0 0 72.8596847285201 212.536288459262 338.325475341512 411.71925393129 432.717624228595 401.320586233428 317.528139945788 181.340285365676 48.5047272013061 0 0 0 0 0 0 0 12.1944489023346 61.7805279284924 125.775940830613 167.273470756335 186.273117705659 182.774881678584 156.77876267511 108.284760695237 37.2928757389665 0 0 0 0 0 0 0 0 31.5884733755828 64.2396407760941 75.6103801949598 96.2984707349944 131.180901587426 144.882042518029 137.401893526802 108.740454613746 66.8975819763326 47.100210798926 45.6210350623498 18.1080942931986 0 0 0 0 0 0 0 59.5816587790465 230.652348302739 415.425899905758 539.240583833281 590.577039456312 569.435266774851 475.815265788899 309.717036498454 126.052253634224 0 0 0 0 0 0 0 0 0 10.5455197065304 95.027884814567 194.582224456858 268.992840391217 305.658122029338 304.578069371221 265.752682416867 189.181961166275 87.617764417386 6.73598624276111 0 0 0 0 0 0 0 0 34.2775186747659 83.0839139498197 115.811670761286 132.460789109166 133.031268993458 " "117.523110414163 85.9363133712805 38.270877864811 2.03294948764621 0 0 0 0 0 0 0 20.7361541250091 81.5174369900932 154.642954330622 200.954109529793 220.450902587606 213.133333504061 179.001402279158 118.055108912897 44.9286549174702 0 0 0 0 0 0 0 0 0 0 1175.60362883881 3271.92094097715 5387.48495444289 6823.74224682784 7341.90300841412 6941.96723920174 5636.75586620374 3570.57116556907 1421.33291220462 0 0 0 0 0 0 29.8677362117457 86.4321563649567 125.192885000945 146.14992211971 149.303267721252 134.652921805571 102.198884372667 51.9411554225396 5.534518724277 0 0 0 0 0 0 1.1979221797489 35.0771644432228 76.6001009996676 120.550541911092 175.31891704995 202.830915651121 203.086537714605 176.085783240401 121.828652228509 72.7811578070367 33.579322370338 5.68504724747096 0 0 0 0 0 0 4.42587041966007 50.6183175751658 83.8689246188789 104.1776915508 97.624278639858 0 0 0 293.806318767698 1531.72592845997 3113.91667207304 4485.32607118122 5215.02744166946 5290.92615197811 4693.0773122294 3456.66844785464 1881.78746381284 507.838819597151 0 0 0 0 0 0 0 0 0 0 16.6549093606585 826.522035825502 1951.18283984489 2989.31958633814 3672.84738735386 3921.07225779998 3671.40922841603 2918.28798762679 1812.09725724512 728.92954992192 33.9887777119525 0 0 0 0 0 0 0 0 0 0 110.527367367332 616.008396104221 1220.04424607782 1706.55481085077 1974.33393909659 1990.12611869332 1753.93134964096 1265.74963193951 652.991835765351 147.028315048396 0 0 0 0 0 0 0 0 10.3992913163904 53.5146969526243 84.1045300677107 102.16879066165 107.707478734441 100.720594286085 81.2081373165816 49.1701078259306 4.6065058141321 0 0 0 0 0 98.8977144681492 360.265585163535 663.662392356181 889.575583042245 993.066799492827 972.307493160935 827.297664046567 558.037312149725 257.568803267046 32.6369105696957 0 0 0 0 0 0 0 0 0 0 42.4608933597734 170.069903998386 315.626871851497 437.516836455374 500.697514318364 499.846322155221 434.963259965946 306.346736490032 156.92121702252 36.2476489727313 0 0 0 0 0 0 0 0 0 " "43.6224250348853 163.79768311116 288.72156416175 365.728610663425 394.818822616186 375.992200020032 309.248742874964 194.58845118098 70.5408987832236 0 0 0 0 0 0 0 0 86.8159599393121 189.236274025657 256.906277743253 289.8259710921 287.995354072197 251.414426683546 180.083188926145 74.0016407999958 0 0 0 0 0 0 0 3.58734956043303 54.2839598755737 105.717722290324 138.868190952114 153.735365860946 150.319247016818 128.619834419731 88.6371280696843 30.3711279666785 0 0 0 0 0 0 0 6.53100639289909 54.638961898697 89.1233437633738 109.984151986929 117.221386569363 110.835047510676 90.8251348108679 57.1916484699383 9.93458848788743 0 0 0 0 0 0 0 33.0584345819788 89.8032842960668 153.045886842243 211.905966378592 239.720644579623 236.489921445335 202.213796975729 136.892271170805 73.3374977022896 22.7568971504976 0 0 0 0 0 0 0 0 43.5407071413695 105.970289074736 147.912516667293 169.367389919041 170.33490882998 150.815073400111 110.807883629432 50.3133395179445 0 0 0 0 0 0 0 0 0 439.979557206302 1593.18936367079 2864.44089364005 3808.5717510588 4218.42350544963 4095.0809859696 3467.86154526931 2376.6609459368 1130.37587718475 180.175223610618 0 0 2.78281863197032 56.6858717556045 19.5213488598804 0 0 0 0 0 0 0 0 48.8985675731739 116.403459633425 161.595425870313 184.474466283838 185.040580874001 163.2937696408 119.234032584237 52.861369704311 0.982750383568241 0 0 0 0 0 0 0 0 0 572.618193299544 1482.56456253289 2360.8765608068 2888.98916366313 3051.81250579748 2865.50242625405 2306.41330532253 1434.12906310607 559.849272472383 0 0 0 3.82009201227643 0.0351890439475344 23.9372966561839 78.5652297226698 112.290927984775 125.369835415642 123.415201253824 106.427025499321 74.4053081521342 27.3500492122623 0 0 0 0 0 0 0 3.73985980551834 41.9761580176009 90.6421347309103 122.64819634711 137.994342866199 136.680574288179 118.706890613049 84.0732918408088 32.7797779714588 0 0 0 0 0 0 0 0 34.9017970300777 0 0 25.3335784698695 488.467605164001 1185.1892574995 1867.74335716265 " "2236.29618394403 2349.87733601746 2240.18993827624 1872.10920114228 1217.61335921565 572.977511354815 173.248479847585 73.2865812928526 148.958372067183 203.796443805828 120.851101321774 61.7425951479753 27.9106073268365 0 0 0 0 0 0 0 0 0 82.145107313747 491.328872396118 1030.8879131326 1528.11916000971 1825.66690152398 1882.67061919099 1684.03670258067 1273.26038092055 764.558522293341 318.300070880454 50.5069618136172 0 47.7651298540734 103.141921107864 97.1473306153483 60.2800752510836 8.70475573417472 0 0 0 0 0 0 0 0 135.72455047394 373.705488049345 605.551220020215 746.781713668006 790.691992130592 737.282055407972 586.551903500146 351.21649991549 113.944046411759 0 0 0 56.0116909356107 113.78442023573 148.902358759811 164.018024826939 159.131418437113 134.242539590333 89.3513882865995 34.6311245009059 0 0 0 0 0 0 0 1.09717974184829 33.8876750385844 82.443207783021 144.746127717701 182.603932271748 196.016621445165 184.984195237949 141.623164214732 65.6447947397654 14.2843073064629 14.4086759340512 83.5553553654597 200.424144753765 312.000301583386 362.631992509037 367.42833942689 326.389342336944 239.515001239199 126.733025539727 27.9169846114579 0 0 0 0 0 0 0 5.43441178470781 36.2007669657817 88.0934995282226 122.808615090964 140.346113654006 140.705995217348 123.888259780991 89.8929073449337 38.7199379091774 5.41438385934538 0 0 0 0 0 0 0 12.2051578334995 58.4683967003456 116.123161013588 171.554837562543 219.707123905351 264.606686856641 306.959975200378 333.05881637182 333.980071203414 307.091727588005 265.867696090734 214.468648843832 152.384756910773 83.6223921342329 22.9342934134957 0 0 0 0 0 0 0 2.00747534834138 37.0035123669462 85.0002777170746 116.903416133427 132.712927616004 132.428812164805 116.05106977983 83.5797004610788 35.014704208552 1.67665384643838 0 0 0 0 0 0 0 31.9877546617201 89.6903783624823 157.836704280827 212.945307911693 237.737069012124 232.21198758212 196.370063621681 130.211297130807 66.228009239499 15.754650409405 0 0 0 0 0 0 0 " "0 19.4335710930101 77.7787673701217 143.266821161017 184.282042638961 200.824431803954 177.589369020262 129.232415935098 39.1077921051521 0 103.277397529229 403.399420678199 779.05466815086 1058.02409778942 1186.84561438216 1164.63961870242 991.406110750212 705.831767938076 346.862274987992 48.2918126744268 0 0 0 0 0 0 0 0 0 0 0 111.694128823448 478.956572099167 965.545141153404 1395.27832241103 1630.84791237713 1649.73058452473 1483.09285709408 1132.82607271066 652.912126163224 201.674341873133 0 0 0 0 0 0 0 0 0 58.2692925157521 326.163037991468 648.937007166011 923.369327714115 1087.33221168785 1125.05208834846 1037.2384348338 827.047219087471 527.668778781846 259.675303710368 105.296841067867 57.4812887409631 50.2044671332086 33.8363268303149 5.83775109066549 0 0 0 0 0 0 0 0 20.7610042189663 160.111334456153 365.708504025475 582.877028885421 750.612373654381 828.934899568002 796.694322812808 659.553058864354 454.625751628743 237.582098936423 68.3212800992953 0 0 0 0 0 0 0 0 0 0 72.4361492592694 210.604772394354 371.857622195513 501.792503196877 571.7057313719 566.310499747039 485.606808322293 346.468812778002 188.414271570308 57.1387147347688 0 0 0 0 0 33.8347077269653 115.724736282598 211.518525806063 276.303507771525 303.451049662415 292.96115147873 244.833813220471 159.069034887638 71.9798505378491 3.57355803376301 0 0 0 0 0 0 0 8.88527001867766 52.1853731595553 82.9961748812305 101.317675183703 107.149874066973 100.492771531041 81.3463675759055 49.7106622015679 5.58565540802778 0 0 0 0 0 0 0 46.5639350731056 118.0017206152 184.744858001496 223.133591409608 233.167920839537 210.202434939938 152.603542905865 79.7044675600279 37.2742177256337 49.482688957161 105.424342193248 152.039699954586 177.630247991958 172.252105143798 145.26517481237 96.6694569976735 38.2075192822721 0 0 0 0 0 0 0 0 0 47.3773529479554 149.003386028441 280.008940049818 394.866506189733 450.797308683951 447.801347532473 385.878622735297 284.323781509221 160.371151228329 46.6382443087917 0 0 " "0 0 0 0 0 0 32.1853336432041 137.235301055552 249.065328175649 318.93877661645 346.855646377955 332.815937460164 276.819649863076 178.866783586693 64.4540293233378 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.175211624109881 36.808372301933 94.9106612483383 134.141732098062 154.501584851103 155.990219507462 138.607636067139 102.353834530135 47.2288148964481 5.60245344966724 0 0 0 0 0 0 16.4139954893738 66.1098476312098 101.073073593887 121.303673377404 126.801646981762 117.56699440696 93.5997156529993 54.8998107198791 1.46727960759947 0 0 0 0 0 0 0 20.9757988847497 68.7749943233036 121.414741711739 153.883093418219 166.180049442745 158.305609785316 130.259774445932 82.0425434245931 27.3536630554911 0 0 0 0 0 0 0 9.94722930979337 53.5163274733893 84.4565742332619 102.767969589411 108.450513541837 101.50420609054 81.9290472355201 49.7250369767765 4.89217531430972 0 0 0 0 0 0 0.377568705098561 34.3604172571 82.2648068941557 145.42450587844 220.847678124488 290.617175620197 316.74618889513 299.234717949287 238.082762782668 172.353093891988 104.303450720015 41.8205796532975 0 0 0 0 0 0 0 0 35.5342825153769 84.0008679369946 116.430232370372 132.822375815509 133.177298272406 117.494999741063 85.7754802214793 38.0187397136554 0 0 0 0 0 0 0 0 38.9181557324105 114.448235963052 172.316959087665 204.780573811565 211.83908013475 193.492478057221 149.740767578979 80.5839487000223 13.4373319043424 0 0 0 0 0 0 0 4.86540343100099 44.0732968915036 91.9156244451349 123.163177347961 137.815955599983 135.873959201199 117.337188151611 82.2056424512174 30.4793221000191 0 0 0 0 0 0 0 4.22522666237575 45.396380871326 74.9973363276129 93.0280930312364 99.4886509821966 94.3790101804934 77.6991706261268 49.4491323190969 9.62889525940363 0 0 0 0 0 0 0 40.5989118811689 70.6051973285097 89.3582179640835 96.8579737878902 93.10446479993 78.0976910002027 51.8376523887084 14.3243489654471 0 0 0 0 8.29099005141177 53.3153146597055 85.4326674454695 104.643048408704 110.946457549409 104.342894867584 " "84.8323603632288 52.4148540363445 7.09037588693046 0 0 0 0 0 0 0 36.7837149880149 110.515281837303 197.405697518017 280.228906769297 321.327862897397 320.702565902319 278.353015784061 194.279212542625 107.633946131993 35.0922806390793 0 0 0 0 0 0 0 0 11.181934561207 66.5535750311293 132.926311181698 193.598643305141 225.454097827831 228.49267474977 202.714374070957 148.119195791391 79.8519263989999 20.0969424659001 0 0 0 0 0 0 0 0 26.8832586328465 82.2074864883244 150.792332326893 216.506510416667 271.510048321633 308.951690567123 301.589426747569 249.423256862969 182.937186465675 115.717427713888 59.510684460193 20.2191065363672 0 0 0 0 0 0 0 0 33.3414653786969 88.5367014069103 125.962790180198 145.619731698559 147.507525961994 131.626172970503 97.9756727240859 46.5560252227427 4.23358150740044 0 0 0 0 0 0 3.42657886851917 49.2175829338304 82.2248101579003 102.448260540729 109.887934082316 104.543830782661 86.4159506417653 55.5042936596281 11.8088598362493 0 0 0 0 0 0 0 41.4243658105811 115.63928578339 195.435300031186 248.845515964748 268.815589175636 255.345519663849 208.435307429387 128.084952472251 54.1913456060947 0.875803914103443 0 0 0 0 0 0 0 0 24.761390668251 74.4035534980969 123.045459204898 152.032808601717 161.365601688554 151.043838465408 121.06751893228 71.43664308917 23.6194370509861 0 0 0 0 0 0 0 0 22.684071467473 64.11917398804 119.834146103937 184.603234030984 220.044432135451 226.157740417338 202.943158876646 150.400687513374 88.758111380197 39.9298217346618 2.92701546906874 0 0 0 0 0 0 0 41.5713966209572 97.8711381392045 135.46978176446 154.367327496722 154.563775335992 136.05912528227 98.8533773355551 42.9465314958479 1.35647984929293 0 0 0 0 0 0 0 32.0626013340093 108.388358447379 200.436403110033 291.819774280895 369.480541771664 419.080530446726 425.607973467776 367.363782940489 279.528182272033 189.263289622771 112.669824240091 54.5868527783657 13.7881280147667 0 0 0 0 0 0 0 0 30.1614983832086 65.1483249619847 99.1833115868914 " "144.374720148829 207.260092817542 275.048872941024 329.039319445203 328.940659458543 300.835668212606 257.118857537116 197.292504584039 119.454253652435 42.4089856625714 0 0 0 0 0 0 0 0 29.1680765218669 78.4953168677839 111.985978631151 129.640061811967 131.457566410234 117.43849242595 87.5828398591154 41.8906087097309 3.86938721983576 0 0 0 0 0 0 0.733101122307076 37.8550097770069 86.428971368394 118.700183077014 134.668644902867 134.334356845954 117.697318906273 84.757531083825 35.5149933786102 1.52220203604172 0 0 0 0 0 0 8.45292350573416 57.6043649953562 92.7026826373902 113.747876431836 120.739946378694 113.678892477965 92.5647147296469 57.3974131337412 8.17698769024754 0 0 0 0 2.88802385663652 47.6229379649484 79.9122747319005 99.7560341574927 107.154216241725 102.106820984598 84.6138483861108 54.6752984462639 12.2911711650572 0 0 0 0 0 0 0 27.1472777964629 78.1575689071263 152.04203028112 235.461428342165 288.063381239528 300.96931055598 274.179216291521 207.69309844615 138.90055413235 67.1743435448421 8.97549975557477 0 0 0 0 0 0 0 0.490160499697275 39.383944424716 99.3751896500311 139.780186366368 160.598934573727 161.831434272108 143.477685461511 105.537688141936 48.0114423133832 4.88861130223127 0 0 0 0 0 0 0 43.2303805762515 112.882085342229 186.096194891941 229.470023770988 238.730800744259 208.196183389161 159.905899403534 116.345568143404 119.021454995607 144.759078481536 174.434771273242 200.157532912035 205.807727911534 172.670081967796 113.958844271573 40.4746310005099 0 0 0 0 0 0 0 4.06773141714247 50.091531606821 83.2273392043748 103.475154209804 110.834976623108 105.306806444288 86.8906436733433 55.5864883102737 11.3943403550794 0 0 0 0 0 0 0 36.5373672094101 99.7522864708534 169.776291391511 239.747220410612 300.184570348069 341.12941018129 355.282575451689 336.62260287625 310.935578424058 295.540268833543 268.401703058701 226.387737852154 174.909043638856 122.462230051036 72.734347221179 29.9801699765079 0 0 0 0 0 0 0 0.828471968501871 " "42.9976859637352 69.5927338500124 76.9957351862412 86.8404873223294 99.4744415994569 118.87400985042 154.355532025958 200.103215499914 255.699726202549 311.510108645424 345.340151735675 337.403262265079 323.865469161169 333.398563731801 355.556257519133 382.298637052238 397.818908229019 388.252807759461 341.887449571303 256.354957384941 151.610405128319 58.3127978842853 0 0 0 0 0 0 0 0 0 10.4152255113864 58.9387213789222 123.947577452048 174.638978437944 200.231006648991 200.723662085189 176.116944746538 126.410854633038 48.0447526055894 0 0 9.17944005152552 101.584808420746 219.497905846798 340.809218044325 408.92100656505 422.895657199246 382.733169946915 288.433544808057 176.096600619229 70.4678693295636 0 0 0 0 0 0 0 0 0 81.0412529365167 199.116906937464 335.935875241295 460.614439068419 517.985780089052 508.049898303195 430.806793710847 286.256466312009 156.341014088451 52.1927834535257 0 0 0 0 0 0 0 2.98129105290054 39.1958800273619 90.367176687245 124.39129780945 141.268243393976 140.998013440823 123.580607949993 89.0160269214835 37.3042703552957 1.76990887835313 0 0 0 0 0 0 8.45487029958158 52.7493535110723 84.3351914554765 103.212384132794 109.380931543026 102.840833686171 83.5920905622291 51.6347021712012 6.96866851308684 0 0 0 0 0 0 0" } }; const size_t testDataSize = sizeof(testData) / sizeof(TestData); vector parseDoubleArray(const string& doubleArray) { vector doubleVector; vector tokens; bal::split(tokens, doubleArray, bal::is_space(), bal::token_compress_on); if (!tokens.empty() && !tokens[0].empty()) for (size_t i=0; i < tokens.size(); ++i) doubleVector.push_back(max(0.0, lexical_cast(tokens[i]))); return doubleVector; } void test() { // test that invalid value exceptions are thrown // order too low /*unit_assert_throws_what(SavitzkyGolaySmoother(1, 15), runtime_error, \ "[SavitzkyGolaySmoother::ctor()] Invalid value for polynomial order; valid range is [2, 20]"); // order too high unit_assert_throws_what(SavitzkyGolaySmoother(21, 15), runtime_error, \ "[SavitzkyGolaySmoother::ctor()] Invalid value for polynomial order; valid range is [2, 20]"); // window size too small unit_assert_throws_what(SavitzkyGolaySmoother(2, 3), runtime_error, \ "[SavitzkyGolaySmoother::ctor()] Invalid value for window size; value must be odd and in range [5, infinity)"); // window size isn't odd unit_assert_throws_what(SavitzkyGolaySmoother(2, 6), runtime_error, \ "[SavitzkyGolaySmoother::ctor()] Invalid value for window size; value must be odd and in range [5, infinity)"); */ SavitzkyGolaySmoother(2, 100001); // window size is valid up to numeric limits /*if (os_) { *os_ << "Unsmoothed data (" << testY.size() << "):\t"; copy(testY.begin(), testY.end(), ostream_iterator(*os_, "\t")); *os_ << endl; }*/ /*if (os_) { *os_ << "Smoothed data (" << smoothData.size() << "):\t"; copy(smoothData.begin(), smoothData.end(), ostream_iterator(*os_, "\t")); *os_ << endl; }*/ for (size_t i=0; i < testDataSize; ++i) { const TestData& data = testData[i]; vector xRaw = parseDoubleArray(data.xRaw); vector yRaw = parseDoubleArray(data.yRaw); vector targetSmoothedX = parseDoubleArray(data.xSmoothed); vector targetSmoothedY = parseDoubleArray(data.ySmoothed); // sanity checks unit_assert(xRaw.size() == yRaw.size()); unit_assert(targetSmoothedX.size() == targetSmoothedY.size()); SavitzkyGolaySmoother smoother(data.polynomialOrder, data.windowSize); vector smoothedX, smoothedY; smoother.smooth(xRaw, yRaw, smoothedX, smoothedY); unit_assert(smoothedX.size() == targetSmoothedX.size()); unit_assert(smoothedY.size() == targetSmoothedY.size()); for (size_t j=0; j < smoothedY.size(); ++j) unit_assert_equal(smoothedY[j], targetSmoothedY[j], 1e-5); } } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/common/ZeroSampleFiller.cpp0000664000175100017510000001177212664775613023613 0ustar teamcityteamcity00000000000000// // $Id: ZeroSampleFiller.cpp 3550 2012-04-18 16:23:06Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "pwiz/utility/misc/Std.hpp" #include "ZeroSampleFiller.hpp" #include namespace pwiz { namespace analysis { void ZeroSampleFiller::fill(const vector& x, const vector& y, vector& xFilled, vector& yFilled, size_t zeroSampleCount) { if (x.size() != y.size()) throw runtime_error("[ZeroSampleFiller::fill()] x and y arrays must be the same size"); // adjacent samples are expected to be within this tolerance const static double EPSILON = 1e-5; // start with the original data xFilled.assign(x.begin(), x.end()); yFilled.assign(y.begin(), y.end()); // insert flanking zeros around non-zero data points bool wasInData = false; bool nowInData = false; for (int i=y.size()-1; i >= 0; --i) { nowInData = yFilled[i] > 0.0; if (nowInData && !wasInData) { // step forward to check for missing samples // at i==0, fudge the first order delta double firstOrderDelta = i < 1 ? xFilled[i+1] - xFilled[i] : xFilled[i] - xFilled[i-1]; // at i==1 or when possibly between signals, assume no second order delta double secondOrderDelta = i < 2 || yFilled[i-1] == 0 ? 0 : firstOrderDelta - (xFilled[i-1] - xFilled[i-2]); double totalDelta = 0; for (int j=1; j <= (int) zeroSampleCount; ++j) { totalDelta += secondOrderDelta; double newX = xFilled[i+j-1] + firstOrderDelta + totalDelta; bool oob = i+j >= (int) y.size(); // sampleDelta should never be less than negative firstOrderDelta double sampleDelta = oob ? 0 : xFilled[i+j] - newX; if (sampleDelta < -firstOrderDelta) break; //throw std::runtime_error("[ZeroSampleFiller::fill()] miscalculated sample rate"); // if out of bounds or newX is a valid missing sample, insert a new zero point if (oob || sampleDelta > firstOrderDelta) { xFilled.insert(xFilled.begin()+(i+j), newX); yFilled.insert(yFilled.begin()+(i+j), 0.0); } } } wasInData = nowInData; } wasInData = false; for (int i=0, end=yFilled.size(); i < end; ++i, end=yFilled.size()) { nowInData = yFilled[i] > 0.0; if (nowInData && !wasInData) { // step backward to check for missing samples // at i==end-1, fudge the first order delta double firstOrderDelta = i == end-1 ? xFilled[i] - xFilled[i-1] : xFilled[i+1] - xFilled[i]; // at i==end-2 or when possibly between signals, assume no second order delta double secondOrderDelta = i == end-2 || yFilled[i+1] == 0 ? 0 : (xFilled[i+2] - xFilled[i+1]) - firstOrderDelta; double totalDelta = 0; for (int j=1; j <= (int) zeroSampleCount; ++j) { totalDelta += secondOrderDelta; double newX = (xFilled[i-j+1] - firstOrderDelta) - totalDelta; bool oob = i-j < 0; // xFilled[i-j] and newX should be nearly equal if they are the same sample // sampleDelta should never be greater than firstOrderDelta double sampleDelta = oob ? 0 : xFilled[i-j] - newX; if (sampleDelta > firstOrderDelta) break; //throw std::runtime_error("[ZeroSampleFiller::fill()] miscalculated sample rate"); // if out of bounds or newX is a valid missing sample, insert a new zero point if (oob || sampleDelta <= -firstOrderDelta ) { xFilled.insert(xFilled.begin()+(i-j+1), newX); yFilled.insert(yFilled.begin()+(i-j+1), 0.0); ++i; } } } wasInData = nowInData; } } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/common/CwtPeakDetector.cpp0000664000175100017510000005316412664775613023425 0ustar teamcityteamcity00000000000000// // $Id: CwtPeakDetector.cpp 6994 2014-12-12 22:57:50Z chambm $ // // // Original author: William French vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "CwtPeakDetector.hpp" #include "pwiz/utility/misc/Std.hpp" // Predicate for sorting vectors of ridgeLines bool sortFinalCol (ridgeLine i, ridgeLine j) { return (i.Col& x, const vector& y, vector& xPeakValues, vector& yPeakValues, vector* peaks) { if (x.size() != y.size()) throw runtime_error("[CwtPeakDetector::detect()] x and y arrays must be the same size"); //cout << "peakPicking on " << x.size() << " points" << endl; int mzLength = x.size(); // number of data points in spectrum if ( mzLength <= 2 ) return; int corrMatrixLength = 2*mzLength-1; // number of data points in a row of the correlation matrix // Data arrays vector < vector > corrMatrix(nScales, vector(corrMatrixLength,0.0)); // correlation matrix vector < vector > locMaxs(nScales, vector(corrMatrixLength,false)); // local maxima matrix vector widths(mzLength,0.0); vector < vector< vector > > waveletPoints(2, vector >(nScales,vector(mzLength,0))); getScales( x, y, waveletPoints, widths ); calcCorrelation( x, y, waveletPoints, widths, corrMatrix ); // calculate the correlation matrix // step 1: find maxima in each column // step 2: apply sliding window with fixed width to generate list of (row,col) maxima (i.e., "lines") // step 3: filter the list of maxima with SNR vector allLines; // identified/filtered lines vector snrs; // snr associated with each line getPeakLines( corrMatrix, x, allLines, snrs ); // refine the peak positions and remove peaks using fixedPeaksKeep_, if needed. xPeakValues.resize(allLines.size()), yPeakValues.resize(allLines.size()); refinePeaks( x, y, allLines, widths, xPeakValues, yPeakValues, snrs ); } // Function for determining the scales we want to sample for the CWT calculation // // This function assumes the profile data is approximately (locally) equally spaced. If the spacing // is much different then issues may arise. If exceptions are being thrown this would be the place to // start looking. Check the Xspacing. For instance, if you pass a peak list to this function you'll // get some unpredictable behavior. void CwtPeakDetector::getScales( const vector & mzData, const vector & intensityData, vector < vector< vector > > & nPoints, vector & widths ) const { int mzLength = mzData.size(); vector Xspacing(mzLength,0.0); double lastXspacing = 0; // get the sampling rate as a function of m/z // this assumes that zero-intensity points flank the "islands" of data for (int i=1; i mzLength) window_size = mzLength / 2; int hf_window = window_size / 2; window_size = 2 * hf_window; // ensures consistency since original window_size could be odd for (int i=1; imzLength-1) windowHigh = mzLength - 1; // need to recalculate the window size in case we are at one of the edges int nTot = windowHigh - windowLow; // recall that windowHigh is not inclusive, so leave off the +1 // get average double sum = accumulate( Xspacing.begin() + windowLow, Xspacing.begin() + windowHigh, 0.0); widths[i] = sum / double(nTot); // figure out the number of wavelet points you'll need to sample for each m/z point for (int j=0; j= 0 ) { if ( mzData[i] - mzData[counter] > maxMZwindow ) break; nPointsLeft++; } int nPointsRight = 0; counter = i; while ( ++counter < mzLength ) { if ( mzData[counter] - mzData[i] > maxMZwindow ) break; nPointsRight++; } nPoints[0][j][i] = nPointsLeft; nPoints[1][j][i] = nPointsRight; } } } // end of function definition getScales // Function for calculating the correlation matrix. // void CwtPeakDetector::calcCorrelation( const vector & mz, const vector & intensity, const vector < vector< vector > > & waveletPoints, const vector & widths, vector < vector > & matrix) const { int mzLength = mz.size(); // setup padded arrays for facilitating the wavelet computation int paddingPoints = 500; // should be more than sufficient vector PadMz(mzLength+2*paddingPoints,0.0); // x array with padding on the front and back vector PadIntensity(mzLength+2*paddingPoints,0.0); // y array with padding on the front and back for (int j = paddingPoints; j < mzLength + paddingPoints; j++) { PadMz[j] = mz[j-paddingPoints]; PadIntensity[j] = intensity[j-paddingPoints]; } vector waveletData(paddingPoints,0.0); // calculate correlation between wavelet and spectrum data, populate correlation matrix for (int i = 0; i 0 ) // calculate first row no matter what, as this is important for the noise calculation { if ( intensity[j] < 0.75*intensity[j-1] || intensity[j] < 0.75*intensity[j+1] ) { matrixIndex += 2; continue; } } int nPointsLeft = waveletPoints[0][i][j]; int nPointsRight = waveletPoints[1][i][j]; int paddedCol = j + paddingPoints; double width = widths[j]*currentScaling; double param1 = 2.0 / ( sqrt(3.0 * width) * (sqrt( sqrt(3.141519) ) ) ); // ricker wavelet parameter double param2 = width * width; // ricker wavelet parameter ricker2d(PadMz, paddedCol, nPointsLeft, nPointsRight, param1, param2, PadMz[paddedCol], waveletData); int startPoint = paddedCol - nPointsLeft; for (int k = 0; k < nPointsLeft+nPointsRight+1 ; k++) matrix[i][matrixIndex] += waveletData[k] * PadIntensity[startPoint+k]; matrixIndex++; if ( j == mzLength-1 ) break; // jump out before final iteration double moverzShift = ( PadMz[ paddedCol ] + PadMz[ paddedCol + 1 ] ) / 2.0; // calculate the correlation at the midpoint between two m/z points, as well. This is why // the length of the correlation matrix is (almost) twice that of the number of m/z points. ricker2d(PadMz, paddedCol, nPointsLeft, nPointsRight, param1, param2, moverzShift, waveletData); for (int k = 0; k < nPointsLeft+nPointsRight+1 ; k++) matrix[i][matrixIndex] += waveletData[k] * PadIntensity[startPoint+k]; matrixIndex++; } // end for over mzPoints } // end for over 10 scales } // end of function calcCorrelation void CwtPeakDetector::getPeakLines(const vector < vector > & corrMatrix, const vector & x, vector & allLines, vector & snrs) const { int corrMatrixLength = corrMatrix[0].size(); // step 1 vector < int > colMaxes(corrMatrixLength,0); for (int i=0; i corrMax ) { corrMax = corrMatrix[j][i]; colMaxes[i] = j; } } } // step 2, setup bins of 300 points and calculate noise threshold within each bin double noise_per = 95.0; int window_size = 300; if (window_size > corrMatrixLength) window_size = corrMatrixLength / 2; int hf_window = window_size / 2; window_size = 2 * hf_window; // ensures consistency since original window_size could be odd int nNoiseBins = corrMatrixLength / window_size + 1; vector noises(nNoiseBins,0.0); for (int i=0; i < nNoiseBins; ++i) { int windowLow = i * window_size; // inclusive int windowHigh = windowLow + window_size; // not inclusive if ( i == nNoiseBins - 1 ) windowHigh = corrMatrixLength; int nTot = windowHigh - windowLow; // don't need +1 because windowHigh is not inclusive vector sortedData(nTot,0.0); for (int j = 0; j < nTot; j++) sortedData[j] = corrMatrix[0][windowLow + j]; // first row of correlation matrix // sort correlation data on first row within window using STL sort function sort(sortedData.begin(),sortedData.end()); double noise = scoreAtPercentile( noise_per, sortedData, nTot ); if ( noise < 1.0 ) noise = 1.0; noises[i] = noise; } vector interpolatedXpoints(corrMatrixLength,0.0); for (int i=0; i maxCorr ) { maxCorr = corrMatrix[row][j]; maxCol = j; } } int noiseBin = maxCol / window_size; if ( noiseBin > nNoiseBins - 1 ) noiseBin = nNoiseBins - 1; double snr = maxCorr / noises[noiseBin]; if ( snr < minSnr_ ) continue; int nLines = allLines.size(); if ( nLines > 0 ) { double mzNewLine = convertColToMZ(x,maxCol); double mzPrevLine = convertColToMZ(x,allLines[nLines-1].Col); double mzDiff = mzNewLine - mzPrevLine; double corrPrev = corrMatrix[allLines[nLines-1].Row][allLines[nLines-1].Col]; if ( mzDiff > mzTol_ ) { ridgeLine newLine; newLine.Col = maxCol; newLine.Row = colMaxes[maxCol]; allLines.push_back(newLine); snrs.push_back(snr); } else if ( maxCorr > corrPrev ) { // remove last ridge line allLines.pop_back(); snrs.pop_back(); // add new ridge line ridgeLine newLine; newLine.Col = maxCol; newLine.Row = colMaxes[maxCol]; allLines.push_back(newLine); snrs.push_back(snr); } } else { ridgeLine newLine; newLine.Col = maxCol; newLine.Row = colMaxes[maxCol]; allLines.push_back(newLine); snrs.push_back(snr); } } } void CwtPeakDetector::refinePeaks( const vector & noisyX, const vector & noisyY, const vector & lines, const vector & widths, vector & smoothX, vector & smoothY, vector & snrs ) const { if ( lines.size() == 0 ) return; for (int i=0, iend=lines.size(); i < iend; ++i) { double mzCol = convertColToMZ(noisyX,lines[i].Col); int row = lines[i].Row; double currentScaling = scalings[row]; double offset = currentScaling * widths[lines[i].Col / 2]; // get the indices for the lower and upper bounds that encapsulate the peak int startFittingPoint = getColLowBound(noisyX,mzCol-offset); int endFittingPoint = getColHighBound(noisyX,mzCol+offset); // sum up the intensity and find the highest point. If there are multiple // points with the maxIntensity value, take the one with the highest m/z. double maxIntensity = 0.0; double intensityAccumulator = 0.0; double maxIntensityMZ = 0.0; for (int j = startFittingPoint; j <= endFittingPoint; ++j) { intensityAccumulator += noisyY[j]; if ( noisyY[j] >= maxIntensity ) { maxIntensity = noisyY[j]; maxIntensityMZ = noisyX[j]; } } smoothX[i] = maxIntensityMZ; smoothY[i] = maxIntensity; } // This is an intensity threshold filter for removing peaks with intensity of 1 // and the best matched wavelet at the lowest scale (indicitive of noise) for (int k = smoothX.size()-1; k > 0; --k) { if ( smoothY[k] < 2.0 && lines[k].Row < 1 ) { smoothX.erase(smoothX.begin()+k); smoothY.erase(smoothY.begin()+k); snrs.erase(snrs.begin()+k); } } // possible to list the same peak if two lines are drawn on the same peak // and fall back to the same max intensity value (or a very similar max intensity value) for (int k = smoothX.size()-1; k > 0; --k) { if ( smoothX[k] - smoothX[k-1] < mzTol_ ) { int removePeakIndex = smoothY[k] > smoothY[k-1] ? k-1 : k; smoothX.erase(smoothX.begin()+removePeakIndex); smoothY.erase(smoothY.begin()+removePeakIndex); snrs.erase(snrs.begin()+removePeakIndex); } } // If required, trim number of peaks to requested size. // This is used by Turbocharger. // it's important to do this after peak refinement, since replicated peaks may be removed at that point. if ( fixedPeaksKeep_ > 0 ) { int sizeSNR = snrs.size(); if ( sizeSNR > fixedPeaksKeep_ ) { double updatedPercentLinesToFilter = 100.0*( 1.0 - ( (double)fixedPeaksKeep_ / (double)snrs.size() ) ); vector sortedSnrs = snrs; sort( sortedSnrs.begin(), sortedSnrs.end() ); double cutoff = scoreAtPercentile(updatedPercentLinesToFilter,sortedSnrs,sortedSnrs.size()); for (vector::iterator it = snrs.begin(); it != snrs.end(); ) { if ( *it < cutoff ) { int index1 = it - snrs.begin(); smoothX.erase(smoothX.begin()+index1); smoothY.erase(smoothY.begin()+index1); snrs.erase(it); } else { ++it; } } } } } } // namespace analysis } // namespace msdata // helper function that calculates the ricker (mexican hat) wavelet. // Designed to handle irregularly spaced data. void ricker2d(const vector & Pad_mz, const int col, const int rickerPointsLeft, const int rickerPointsRight, const double A, const double wsq, const double centralMZ, vector & total) { if (rickerPointsRight - rickerPointsLeft >= (int) total.size()) throw runtime_error("[CwtPeakDetector::ricker2d] invalid input parameters"); for (int i = col-rickerPointsLeft, cnt=0, end = col+rickerPointsRight; i <= end; i++, cnt++) { double vec = Pad_mz[i] - centralMZ; double tsq = vec * vec; double mod = 1.0 - tsq / wsq; double gauss = exp( -1.0 * tsq / (2.0 * wsq) ); total[cnt] = A * mod * gauss; } } // end of function ricker2d // want first point to the right of target int getColLowBound(const vector & mzs,const double target) { const vector::const_iterator it = lower_bound(mzs.begin(),mzs.end(),target); return it - mzs.begin(); } // want first point the the left of target int getColHighBound(const vector & mzs,const double target) { const vector::const_iterator it = upper_bound(mzs.begin(),mzs.end(),target); const vector::const_iterator decrementedIt = it - 1; // decrement by one to get the value that is less than target return decrementedIt - mzs.begin(); } // function for determining the score in a (sorted) vector at a given percentile // end of getScoreAtPercentile. Allow passing of length of vector in case you only // want a slice of the first portion of a vector; // // perc should not be a fraction (e.g. 5th percentile = 5.0) double scoreAtPercentile( const double perc, const vector < double > & dataSorted, const int nTot ) { //using nTot - 1, which is what's done in scipy.scoreatpercentile double nBelow = (double)(nTot-1) * perc / 100.0; if (ceil(nBelow) == nBelow) // whole number { return dataSorted[(int)nBelow]; // consistent with scipy.scoreatpercentile } else { // fraction method used in scipy.scoreatpercentile // linear interpolation between two points double loInd = floor(nBelow); double hiInd = ceil(nBelow); double fraction = nBelow - loInd; double lo = dataSorted[(int)loInd]; double hi = dataSorted[(int)hiInd]; return lo + (hi - lo) * fraction; } } // end function scoreAtPercentile double convertColToMZ( const vector & mzs, const int Col ) { int mapIndex = Col / 2; if ( Col % 2 == 1 ) return (mzs[ mapIndex ]+mzs[mapIndex+1]) / 2.0; else return mzs[ mapIndex ]; } pwiz/pwiz/analysis/common/DataFilter.hpp0000664000175100017510000000313712664775613022414 0ustar teamcityteamcity00000000000000// // $Id: DataFilter.hpp 2242 2010-09-13 15:10:18Z chambm $ // // // Original author: Chris Paulse systemsbiology.org> // // Copyright 2009 Institute for Systems Biology, Seattle, WA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _DATAFILTER_HPP_ #define _DATAFILTER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/MSData.hpp" namespace pwiz { namespace analysis { struct PWIZ_API_DECL SpectrumDataFilter { virtual void operator () (const pwiz::msdata::SpectrumPtr) const = 0; virtual void describe(pwiz::msdata::ProcessingMethod&) const = 0; virtual ~SpectrumDataFilter() {} }; typedef boost::shared_ptr SpectrumDataFilterPtr; struct PWIZ_API_DECL ChromatogramDataFilter { virtual void operator () (const pwiz::msdata::ChromatogramPtr) const = 0; virtual void describe(pwiz::msdata::ProcessingMethod&) const = 0; virtual ~ChromatogramDataFilter() {} }; typedef boost::shared_ptr ChromatogramDataFilterPtr; } // namespace analysis } // namespace pwiz #endif // _DATAFILTER_HPP_ pwiz/pwiz/analysis/common/ExtraZeroSamplesFilterTest.cpp0000664000175100017510000023427712664775613025661 0ustar teamcityteamcity00000000000000// // $Id: ExtraZeroSamplesFilterTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Brian Pratt insilicos.com> // cribbing heavily from Matt Chambers' work in ZeroSampleFillerTest.cpp // // Copyright 2012 Spielberg Family Center for Applied Proteomics // University of Southern California, Los Angeles, California 90033 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "ExtraZeroSamplesFilter.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Exception.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::analysis; ostream* os_ = 0; // test a full spectrum const char* fullSpectrumRawX = "300.000066203793 300.000611626572 300.001157051333 300.001702478078 300.058437690186 300.058983325233 300.059528962264 300.06007460128 300.06062024228 300.061165885264 300.061711530233 300.062257177186 300.062802826123 300.063348477046 300.063894129952 300.064439784843 300.064985441719 300.065531100579 300.066076761424 301.055887660805 301.056436929468 301.056986200136 301.057535472809 301.058084747485 301.058634024166 301.059183302851 301.059732583541 301.060281866235 301.060831150933 301.061380437635 301.061929726342 301.062479017053 301.063028309769 301.063577604489 311.869088211176 311.869677645283 311.870267081618 311.870856520182 311.871445960974 311.872035403993 311.872624849241 311.873214296717 311.873803746421 311.874393198353 311.874982652514 311.875572108902 311.876161567519 311.876751028364 311.877340491437 311.877929956739 311.878519424268 311.879108894026 311.879698366013 311.880287840227 311.88087731667 311.881466795341 311.882056276241 315.73174362051 315.732347745926 315.732951873654 315.733556003694 315.734160136047 315.734764270711 315.735368407687 315.735972546974 315.736576688574 315.737180832486 315.73778497871 315.738389127246 316.901416544052 316.902025153901 316.902633766087 316.90324238061 316.903850997471 316.90445961667 316.905068238207 316.905676862081 316.906285488293 316.906894116843 316.907502747731 316.908111380957 316.90872001652 316.909328654421 326.293591849569 326.294237069432 326.294882291847 326.295527516814 326.296172744332 326.296817974402 326.297463207024 326.298108442198 326.298753679923 326.299398920201 326.30004416303 327.074882186811 327.075530500256 327.076178816272 327.076827134858 327.077475456014 327.07812377974 327.078772106036 327.079420434903 327.080068766339 327.080717100346 327.081365436923 327.082013776071 327.082662117789 327.083310462077 327.083958808935 341.007109159311 341.007813880848 341.008518605298 341.00922333266 341.009928062936 341.010632796124 341.011337532225 341.012042271238 341.012747013165 " "341.013451758004 341.014156505757 341.014861256422 341.01556601 341.016270766491 341.016975525895 341.017680288212 341.018385053442 341.019089821585 341.019794592642 341.020499366611 341.021204143493 341.021908923288 341.022613705997 341.023318491618 341.024023280153 341.024728071601 342.01359244987 342.014301337525 342.015010228119 342.015719121651 342.016428018122 342.017136917532 342.01784581988 342.018554725167 342.019263633392 342.019972544557 342.02068145866 342.021390375702 342.022099295682 342.022808218602 342.02351714446 342.873501341248 342.874213798035 342.874926257782 342.87563872049 342.876351186159 342.877063654789 342.87777612638 342.878488600932 342.879201078445 342.879913558918 342.880626042353 342.881338528749 344.97306118134 344.9737823902 344.974503602076 344.975224816967 344.975946034874 344.976667255797 344.977388479735 344.978109706689 344.978830936658 344.979552169644 344.980273405644 344.980994644661 344.981715886693 355.063935356091 355.064699374529 355.065463396255 355.066227421269 355.066991449572 355.067755481162 355.06851951604 355.069283554207 355.070047595661 355.070811640404 355.071575688435 355.072339739754 355.073103794361 355.073867852257 355.074631913441 355.075395977913 355.076160045673 355.076924116722 355.077688191059 355.078452268685 356.064553240471 356.065321571195 356.066089905234 356.06685824259 356.067626583261 356.068394927249 356.069163274552 356.069931625172 356.070699979107 356.071468336359 356.072236696926 356.07300506081 356.073773428009 356.074541798525 356.075310172357 356.076078549505 356.076846929969 356.07761531375 356.078383700846 356.079152091259 356.079920484988 356.080688882034 357.062327559534 357.063100202372 357.063872848555 357.064645498081 357.065418150951 357.066190807165 357.066963466723 357.067736129625 357.068508795871 357.069281465461 357.070054138395 357.070826814673 357.071599494295 357.072372177261 357.073144863571 357.073917553225 357.074690246224 357.075462942566 357.076235642253 " "357.077008345284 357.077781051659 357.078553761379 357.079326474442 357.08009919085 359.023183355092 359.023964507385 359.024745663078 359.02552682217 359.026307984661 359.027089150551 359.027870319841 359.028651492531 359.029432668619 359.030213848107 359.030995030994 359.031776217281 359.032557406967 359.033338600053 359.034119796538 359.034900996422 359.035682199706 360.023491974674 360.024277485921 360.025063000597 360.0258485187 360.02663404023 360.027419565189 360.028205093575 360.028990625389 360.029776160632 360.030561699301 360.031347241399 360.032132786925 360.032918335879 360.03370388826 360.03448944407 361.021491400285 361.02228127251 361.023071148191 361.023861027329 361.024650909923 361.025440795974 361.026230685481 361.027020578444 361.027810474864 361.02860037474 361.029390278072 361.030180184861 361.030970095107 361.031760008809 371.095690561049 371.096525130684 371.097359704072 371.098194281215 371.099028862111 371.099863446762 371.100698035166 371.101532627324 371.102367223236 371.103201822902 371.104036426322 371.104871033497 371.105705644425 371.106540259107 371.107374877543 371.108209499734 371.109044125678 371.109878755377 371.11071338883 372.078066820464 372.078905814551 372.079744812421 372.080583814075 372.081422819513 372.082261828735 372.083100841741 372.08393985853 372.084778879103 372.08561790346 372.086456931601 372.087295963526 372.095686490895 372.096525564444 372.097364641778 372.098203722896 372.099042807799 372.099881896485 372.100720988956 372.101560085211 372.102399185251 372.103238289075 372.104077396683 372.104916508076 372.105755623254 372.106594742216 372.107433864962 372.108272991493 373.076623237254 373.077466740653 373.078310247866 373.079153758894 373.079997273735 373.080840792391 373.081684314862 373.082527841147 373.083371371246 373.084214905159 373.085058442887 373.08590198443 373.086745529787 373.101086384495 373.101929998517 373.102773616354 373.103617238007 373.104460863474 373.105304492756 373.106148125853 " "373.106991762765 373.107835403493 373.108679048035 373.109522696393 373.110366348566 373.111210004555 415.030543316388 415.031587197383 415.032631083628 415.033674975125 415.034718871873 415.035762773872 415.036806681123 415.037850593625 415.038894511378 415.039938434383 415.040982362639 415.042026296147 415.043070234906 415.044114178917 415.045158128179 415.046202082693 415.047246042459 416.004675140758 416.005723927765 416.006772720059 416.007821517642 416.008870320513 416.009919128672 416.01096794212 416.012016760856 416.01306558488 416.014114414193 416.015163248794 416.016212088684 416.030896402465 416.031945321688 416.032994246201 416.034043176002 416.035092111093 416.036141051473 416.037189997143 416.038238948102 416.03928790435 416.040336865888 416.041385832715 416.042434804832 416.043483782239 416.044532764935 416.04558175292 416.046630746196 416.047679744761 417.027651705639 417.028705657034 417.029759613757 417.030813575807 417.031867543184 417.032921515889 417.033975493922 417.035029477282 417.036083465969 417.037137459984 417.038191459327 417.039245463997 417.040299473995 417.041353489321 426.357976566382 426.359078206359 426.360179852029 426.361281503392 426.362383160449 426.363484823198 426.36458649164 426.365688165776 426.366789845604 426.367891531126 426.368993222341 428.935877697296 428.936992699323 428.938107707146 428.939222720767 428.940337740184 428.941452765398 428.94256779641 428.943682833218 428.944797875823 428.945912924226 428.947027978426 429.083108101101 429.0842238687 429.085339642101 429.086455421305 429.087571206312 429.088686997122 429.089802793735 429.090918596151 429.09203440437 429.093150218392 429.094266038217 429.095381863845 429.096497695277 429.097613532512 429.09872937555 429.099845224392 429.100961079037 429.102076939486 429.134439417209 429.135555451783 429.136671492162 429.137787538345 429.138903590334 429.140019648128 429.141135711726 429.14225178113 429.143367856339 429.144483937353 429.145600024173 429.146716116797 " "429.85101025753 429.852130022341 429.853249792985 429.854369569464 429.855489351777 429.856609139924 429.857728933905 429.858848733721 429.859968539371 429.861088350855 429.862208168173 429.863327991326 429.864447820313 429.865567655135 429.866687495792 429.867807342283 429.868927194608 429.870047052768 429.871166916764 429.872286786593 429.873406662258 429.874526543758 429.875646431092 429.876766324261 429.877886223266 430.081805059062 430.082926026641 430.084047000064 430.08516797933 430.086288964439 430.087409955392 430.088530952189 430.089651954829 430.090772963313 430.091893977641 430.093014997813 430.094136023828 430.095257055687 430.09637809339 430.097499136937 430.098620186328 430.099741241563 430.100862302643 430.101983369566 431.078404724764 431.079530893455 431.08065706803 431.081783248489 431.082909434832 431.08403562706 431.085161825172 431.086288029168 431.087414239049 431.088540454814 431.089666676463 431.090792903997 431.091919137416 431.093045376719 431.094171621907 431.09529787298 431.096424129938 431.09755039278 431.098676661507 431.099802936119 432.079633824813 432.080765230898 432.081896642908 432.083028060844 432.084159484704 432.085290914491 432.086422350202 432.087553791839 432.088685239402 432.08981669289 432.090948152304 432.092079617643 432.093211088908 444.61606065115 444.617258663358 444.618456682022 444.619654707142 444.620852738719 444.622050776751 444.62324882124 444.624446872186 444.625644929587 444.626842993445 444.62804106376 444.629239140531 444.630437223759 445.111389571898 445.112590254911 445.113790944402 445.114991640371 445.116192342817 445.117393051741 445.118593767143 445.119794489023 445.120995217382 445.122195952218 445.123396693532 445.124597441324 445.125798195595 445.126998956343 445.128199723571 445.129400497276 445.13060127746 446.092099627601 446.093305607359 446.094511593638 446.095717586437 446.096923585757 446.098129591598 446.099335603959 446.100541622841 446.101747648245 446.102953680169 446.104159718614 " "446.10536576358 446.106571815068 446.107777873076 446.108983937606 446.110190008657 446.111396086229 446.112602170323 446.113808260938 446.115014358075 446.116220461733 446.117426571913 446.118632688614 446.119838811837 446.121044941582 446.122251077849 446.123457220638 446.124663369948 446.12586952578 446.127075688135 446.128281857011 446.12948803241 446.130694214331 446.131900402774 446.133106597739 447.092888369096 447.09409976606 447.095311169589 447.096522579682 447.09773399634 447.098945419563 447.100156849351 447.101368285703 447.10257972862 447.103791178103 447.10500263415 447.106214096762 447.10742556594 447.108637041682 447.10984852399 447.111060012863 447.112271508302 447.113483010306 447.114694518875 447.115906034009 447.11711755571 447.118329083975 447.119540618807 447.120752160204 447.121963708167 447.123175262696 447.12438682379 447.125598391451 447.126809965677 447.128021546469 447.129233133828 447.130444727752 447.131656328243 449.794778250235 449.796004332987 449.797230422424 449.798456518544 449.799682621349 449.800908730839 449.802134847013 449.803360969872 449.804587099415 449.805813235643 449.807039378556 449.808265528153 476.291926493584 476.293301287096 476.294676088545 476.296050897931 476.297425715253 476.298800540512 476.300175373707 476.30155021484 476.30292506391 476.304299920917 476.305674785861 476.307049658742 487.815419569054 487.81686169142 487.818303822312 487.819745961732 487.821188109678 487.822630266151 487.824072431152 487.825514604679 487.826956786733 487.828398977315 487.829841176424 489.047206755368 489.048656169973 489.050105593169 489.051555024957 489.053004465336 489.054453914307 489.05590337187 489.057352838025 489.058802312771 489.06025179611 489.06170128804 489.063150788563 489.064600297678 489.066049815385 489.067499341685 494.497639238354 494.499121140501 494.500603051529 494.50208497144 494.503566900233 494.505048837908 494.506530784465 494.508012739904 494.509494704226 494.510976677431 494.512458659517 " "503.097384350016 503.098918243574 503.100452146485 503.10198605875 503.103519980368 503.10505391134 503.106587851665 503.108121801345 503.109655760378 503.111189728765 503.112723706507 503.114257693603 503.115791690052 503.117325695857 503.118859711015 503.120393735528 503.121927769396 503.123461812619 503.124995865196 504.057895208494 504.059434964655 504.060974730222 504.062514505197 504.064054289579 504.065594083369 504.067133886566 504.06867369917 504.070213521182 504.071753352602 504.073293193429 504.097931926196 504.099471926969 504.101011937151 504.102551956742 504.104091985743 504.105632024154 504.107172071974 504.108712129204 504.110252195844 504.111792271893 504.113332357353 504.114872452223 504.116412556503 504.117952670193 504.119492793294 504.121032925805 504.122573067726 504.124113219059 504.136434768509 504.137975004541 504.139515249984 504.141055504838 504.142595769105 504.144136042783 504.145676325873 504.147216618374 504.148756920288 504.150297231614 504.151837552352 504.153377882502 505.094736580555 505.096282677762 505.097828784435 505.099374900573 505.100921026176 505.102467161245 505.104013305779 505.105559459779 505.107105623245 505.108651796177 505.110197978574 505.111744170438 505.113290371768 505.114836582564 505.116382802826 505.117929032555 505.11947527175 505.121021520412 505.12256777854 506.095491214212 506.097043444127 506.098595683563 506.100147932522 506.101700191001 506.103252459003 506.104804736527 506.106357023573 506.107909320141 506.109461626231 506.111013941844 506.112566266978 506.114118601636 517.627784100423 517.62940787711 517.631031663984 517.632655461045 517.634279268294 517.635903085731 517.637526913356 517.639150751169 517.64077459917 517.642398457359 517.644022325736 519.117811946194 519.11944508466 519.121078233402 519.122711392419 519.124344561713 519.125977741282 519.127610931128 519.129244131249 519.130877341647 519.132510562322 519.134143793272 519.1357770345 519.137410286004 519.139043547785 519.140676819843 " "519.142310102177 519.143943394789 519.145576697678 519.147210010844 519.148843334287 519.150476668008 519.152110012007 519.153743366283 520.107741759837 520.109381132867 520.111020516231 520.11265990993 520.114299313963 520.115938728332 520.117578153035 520.119217588074 520.120857033448 520.122496489157 520.124135955201 520.125775431581 520.130693922735 520.132333440458 520.133972968517 520.135612506911 520.137252055643 520.13889161471 520.140531184113 520.142170763854 520.14381035393 520.145449954343 520.147089565093 520.14872918618 520.150368817604 520.152008459365 520.153648111463 520.155287773898 521.127785814089 521.129431623767 521.131077443839 521.132723274308 521.134369115172 521.136014966432 521.137660828088 521.13930670014 521.140952582588 521.142598475432 521.144244378673 521.14589029231 521.147536216343 531.114696350534 531.11640584546 531.118115351391 531.119824868327 531.121534396267 531.123243935212 531.124953485163 531.126663046119 531.12837261808 531.130082201046 531.131791795019 531.179664894929 531.181374808109 531.183084732298 531.184794667495 531.186504613701 531.188214570917 531.189924539141 531.191634518375 531.193344508618 531.195054509871 531.196764522133 531.198474545405 539.793121824335 539.79488764215 539.796653471517 539.798419312438 539.800185164913 539.80195102894 539.803716904521 539.805482791656 539.807248690344 539.809014600586 539.810780522383 544.657227988968 544.659025773986 544.660823570872 544.662621379626 544.664419200249 544.66621703274 544.6680148771 544.669812733329 544.671610601426 544.673408481392 544.675206373228 544.677004276933 544.678802192507 544.68060011995 544.682398059264 544.684196010447 544.685993973499 544.687791948422 544.689589935214 544.691387933877 564.063114662872 564.065042838848 564.066971028006 564.068899230347 564.07082744587 564.072755674577 564.074683916467 564.076612171539 564.078540439795 564.080468721235 564.082397015858 564.084325323664 564.086253644655 577.113045862246 577.115064289413 " "577.1170827307 577.119101186105 577.12111965563 577.123138139273 577.125156637036 577.127175148919 577.129193674921 577.131212215043 577.133230769285 577.135249337647 577.137267920129 577.139286516732 577.141305127455 577.143323752299 578.095668254573 578.09769356096 578.099718881538 578.101744216308 578.103769565269 578.105794928421 578.107820305765 578.1098456973 578.111871103028 578.113896522947 578.115921957059 578.117947405363 578.119972867859 578.121998344549 578.124023835431 578.126049340506 578.128074859774 578.130100393235 578.13212594089 578.134151502738 578.13617707878 578.138202669016 578.140228273445 578.142253892069 578.144279524888 578.1463051719 579.112127291178 579.114159725986 579.116192175059 579.118224638399 579.120257116005 579.122289607877 579.124322114016 579.126354634422 579.128387169095 579.130419718034 579.132452281241 579.134484858716 579.136517450457 579.138550056467 579.140582676744 579.142615311289 593.146836106552 593.148968246848 593.151100402472 593.153232573424 593.155364759706 593.157496961317 593.159629178256 593.161761410526 593.163893658125 593.166025921053 593.168158199311 593.1702904929 593.172422801818 593.174555126067 594.334675871054 594.336816559592 594.338957263551 594.341097982931 594.343238717732 594.345379467954 594.347520233598 594.349661014664 594.351801811151 594.35394262306 594.356083450392 594.358224293146 602.991717202929 602.993920708033 602.996124229242 602.998327766555 603.000531319973 603.002734889497 603.004938475125 603.007142076859 603.009345694699 603.011549328644 603.013752978696 603.015956644853 603.018160327117 603.020364025487 603.022567739964 603.024771470548 603.026975217238 647.653798614949 647.656340625328 647.65888265566 647.661424705948 647.66396677619 647.666508866388 647.669050976542 647.671593106651 647.674135256716 647.676677426738 647.679219616716 647.681761826651 647.684304056543 647.686846306392 647.689388576198 647.691930865962 647.694473175684 647.697015505364 647.699557855003 " "651.129472007141 651.132041374488 651.134610762114 651.137180170017 651.139749598198 651.142319046658 651.144888515396 651.147458004413 651.150027513709 651.152597043284 651.155166593139 651.157736163274 651.160305753689 651.162875364383 651.165444995359 651.168014646615 652.130488515969 652.133065789459 652.135643083321 652.138220397554 652.140797732159 652.143375087136 652.145952462485 652.148529858207 652.151107274301 652.153684710768 652.156262167609 652.158839644823 652.16141714241 652.163994660372 652.166572198708 652.169149757418 652.594726156514 652.597307100729 652.599888065358 652.602469050403 652.605050055862 652.607631081738 652.610212128029 652.612793194736 652.615374281859 652.617955389399 652.620536517356 653.126832071549 653.129417226335 653.132002401586 653.134587597302 653.137172813482 653.139758050129 653.142343307241 653.14492858482 653.147513882864 653.150099201375 653.152684540353 653.155269899798 653.157855279709 653.160440680089 653.163026100936 660.922514101737 660.925161337446 660.927808594361 660.930455872483 660.933103171812 660.935750492348 660.938397834091 660.941045197042 660.943692581201 660.946339986568 660.948987413144 660.951634860928 660.954282329921 660.983405888706 660.986053612226 660.988701356959 660.991349122903 660.993996910061 660.996644718431 660.999292548015 661.001940398812 661.004588270823 661.007236164048 661.009884078488 661.012532014142 664.411346114577 664.414021372197 664.41669665136 664.419371952069 664.422047274321 664.424722618119 664.427397983461 664.430073370349 664.432748778782 664.435424208761 664.438099660286 664.440775133357 664.443450627975 664.44612614414 664.448801681852 664.451477241112 664.454152821919 664.456828424273 664.459504048176 664.462179693628 664.464855360628 667.159443330433 667.162140764336 667.164838220052 667.16753569758 667.170233196922 667.172930718076 667.175628261044 667.178325825826 667.181023412421 667.183721020831 667.186418651055 667.189116303095 667.191813976949 " "667.194511672619 667.197209390104 667.199907129405 668.145457833561 668.148163246605 668.150868681559 668.153574138422 668.156279617196 668.158985117879 668.161690640472 668.164396184977 668.167101751392 668.169807339718 668.172512949956 668.175218582105 668.177924236166 668.180629912139 668.183335610025 668.186041329824 668.188747071536 668.19145283516 668.194158620699 668.196864428151 668.199570257517 670.158915513485 670.161637256666 670.164359021956 670.167080809353 670.16980261886 670.172524450475 670.175246304198 670.177968180032 670.180690077974 670.183411998027 670.186133940189 670.188855904462 670.191577890846 677.272020770102 677.274800597507 677.277580447732 677.280360320776 677.283140216641 677.285920135325 677.28870007683 677.291480041156 677.294260028303 677.297040038272 677.299820071062 677.302600126674 677.305380205108 677.308160306364 677.310940430444 677.313720577346 677.316500747072 677.319280939622 677.322061154995 677.324841393193 677.327621654214 677.330401938061 677.333182244733 677.33596257423 684.185792158615 684.188629030244 684.191465925398 684.194302844078 684.197139786283 684.199976752015 684.202813741274 684.205650754059 684.208487790372 684.211324850212 684.21416193358 684.216999040475 684.2198361709 684.222673324852 684.225510502334 685.302497766186 685.305343905889 685.308190069232 685.311036256217 685.313882466843 685.316728701111 685.319574959021 685.322421240572 685.325267545767 685.328113874604 685.330960227085 685.333806603209 685.336653002977 685.339499426388 685.345192344145 685.34803883849 685.350885356481 685.353731898117 685.356578463399 685.359425052328 685.362271664902 685.365118301123 685.367964960991 685.370811644507 685.37365835167 685.376505082481 686.165961086862 686.168814403222 686.171667743312 686.174521107133 686.177374494685 686.180227905968 686.183081340982 686.185934799728 686.188788282207 686.191641788417 686.19449531836 686.197348872036 699.464091765658 699.467056750447 699.470021760373 699.472986795436 " "699.475951855637 699.478916940975 699.481882051452 699.484847187067 699.487812347821 699.490777533714 699.493742744746 699.496707980919 699.499673242231 699.502638528684 699.505603840277 699.508569177012 699.511534538887 699.514499925905 707.540962759248 707.54399661424 707.54703049525 707.550064402278 707.553098335324 707.556132294389 707.559166279473 707.562200290576 707.565234327699 707.568268390842 707.571302480006 707.574336595191 707.577370736396 707.580404903623 707.583439096872 707.586473316143 707.589507561437 707.592541832753 707.595576130092 712.253358999635 712.256433401729 712.259507830364 712.26258228554 712.265656767258 712.268731275519 712.271805810321 712.274880371667 712.277954959555 712.281029573987 712.284104214963 714.637817537752 714.640912559113 714.644007607282 714.647102682261 714.650197784048 714.653292912646 714.656388068053 714.65948325027 714.662578459298 714.665673695137 714.668768957787 714.671864247249 725.142802571441 725.145989253758 725.149175964084 725.152362702418 725.155549468761 725.158736263113 725.161923085476 725.165109935848 725.168296814231 725.171483720624 725.174670655029 725.177857617445 725.181044607873 725.184231626314 725.187418672767 725.190605747233 725.193792849713 725.196979980206 726.144799061961 726.147994557046 726.151190080255 726.15438563159 726.15758121105 726.160776818635 726.163972454346 726.167168118184 726.170363810149 726.17355953024 726.176755278459 726.179951054806 726.183146859281 726.186342691885 726.189538552617 727.133547186777 727.136751390037 727.139955621536 727.143159881275 727.146364169255 727.149568485475 727.152772829936 727.155977202638 727.159181603583 727.162386032769 727.165590490198 727.16879497587 727.171999489785 727.175204031944 727.178408602347 727.181613200995 727.184817827887 727.188022483024 728.144269729676 728.147482846893 728.150695992466 728.153909166398 728.157122368687 728.160335599336 728.163548858343 728.16676214571 728.169975461436 728.173188805523 728.17640217797 " "728.179615578778 728.182829007947 728.623337067404 728.626554414027 728.629771789064 728.632989192515 728.63620662438 728.639424084659 728.642641573354 728.645859090464 728.64907663599 728.652294209931 728.65551181229 728.658729443065 739.579801260267 739.583116094462 739.586430958371 739.589745851995 739.593060775335 739.596375728391 739.599690711162 739.603005723651 739.606320765856 739.609635837779 739.61295093942 741.174345003278 741.177674146565 741.18100331976 741.184332522862 741.187661755872 741.190991018791 741.194320311618 741.197649634355 741.200978987002 741.204308369558 741.207637782025 741.210967224403 741.214296696693 741.217626198894 741.220955731007 741.224285293032 742.067626706004 742.070963878878 742.074301081766 742.077638314671 742.080975577592 742.08431287053 742.087650193485 742.090987546457 742.094324929448 742.097662342457 742.100999785484 742.104337258531 742.107674761597 742.111012294683 742.11434985779 742.117687450917 742.121025074066 742.124362727236 742.127700410428 742.131038123643 742.13437586688 742.137713640141 742.141051443425 742.174431127655 742.177769261226 742.181107424826 742.184445618454 742.187783842111 742.191122095798 742.194460379515 742.197798693263 742.201137037042 742.204475410852 742.207813814694 742.211152248568 742.214490712474 742.217829206413 742.221167730386 742.224506284392 742.227844868433 743.1470966977 743.150443586686 743.153790505819 743.157137455098 743.160484434525 743.1638314441 743.167178483823 743.170525553695 743.173872653716 743.177219783887 743.180566944208 743.183914134679 743.187261355301 743.190608606074 743.193955886998 743.197303198075 743.200650539304 743.203997910686 743.20734531222 743.210692743909 743.214040205752 743.217387697749 743.220735219901 743.224082772208 743.227430354671 743.23077796729 744.176009584717 744.179365747906 744.182721941368 744.186078165103 744.18943441911 744.192790703391 744.196147017945 744.199503362773 744.202859737876 744.206216143254 744.209572578908 " "744.212929044837 744.216285541042 744.219642067524 744.222998624283 758.202410978174 758.205894849435 758.209378752713 758.212862688007 758.216346655318 758.219830654647 758.223314685994 758.226798749359 758.230282844744 758.233766972148 758.237251131571 758.240735323015 758.24421954648 758.247703801965 758.251188089473 758.254672409002 759.203597733713 759.207090811794 759.210583922019 759.214077064387 759.2175702389 759.221063445557 759.22455668436 759.228049955308 759.231543258401 759.235036593642 759.238529961029 759.242023360563 759.245516792245 759.249010256075 760.200427521877 760.203929778783 760.207432067959 760.210934389405 760.214436743123 760.217939129111 760.221441547372 760.224943997905 760.228446480711 760.231948995789 760.235451543142 760.238954122768 760.24245673467 760.316019040799 760.319522362853 760.323025717192 760.326529103815 760.330032522725 760.33353597392 760.337039457402 760.340542973171 760.344046521228 760.347550101572 760.351053714205 760.354557359126 760.358061036338 760.361564745838 777.189954415057 777.193614963706 777.197275546837 777.200936164451 777.204596816548 777.208257503129 777.211918224194 777.215578979744 777.219239769779 777.2229005943 777.226561453308 777.230222346802 777.233883274784 777.237544237253 799.160490663856 799.164361099883 799.1682315734 799.172102084408 799.175972632907 799.179843218898 799.183713842382 799.187584503358 799.191455201828 799.195325937792 799.19919671125 799.203067522204 799.206938370653 799.210809256599 799.214680180041 799.21855114098 800.16418774129 800.168067905512 800.171948107365 800.175828346849 800.179708623967 800.183588938718 800.187469291103 800.191349681123 800.195230108777 800.199110574067 800.202991076993 800.206871617555 800.210752195754 801.158739593593 801.162629409414 801.166519263006 801.170409154372 801.174299083511 801.178189050424 801.182079055111 801.185969097572 801.18985917781 801.193749295823 801.197639451613 801.20152964518 801.205419876525 801.209310145647 " "801.213200452549 810.055165196855 810.059141881054 810.063118604297 810.067095366586 810.07107216792 810.0750490083 810.079025887728 810.083002806202 810.086979763725 810.090956760296 810.094933795916 810.098910870585 810.102887984305 810.106865137076 815.189564537267 815.19359179245 815.197619087424 815.20164642219 815.205673796749 815.209701211101 815.213728665248 815.217756159189 815.221783692925 815.225811266457 815.229838879786 815.233866532911 815.237894225833 815.241921958555 815.245949731074 815.249977543393 815.395005298192 815.3990345835 815.40306390863 815.407093273582 815.411122678358 815.415152122956 815.419181607379 815.423211131626 815.427240695699 815.431270299597 815.435299943322 815.439329626874 816.169358934812 816.17339587673 816.177432858584 816.181469880374 816.1855069421 816.189544043764 816.193581185365 816.197618366904 816.201655588382 816.2056928498 816.209730151157 816.213767492455 816.217804873695 816.221842294876 816.225879756 816.229917257066 816.233954798077 816.237992379031 816.24202999993 816.246067660775 816.250105361565 816.254143102302 817.183885871236 817.187932855536 817.19197987992 817.196026944389 817.200074048944 817.204121193585 817.208168378313 817.212215603128 817.216262868032 817.220310173024 817.224357518104 817.228404903275 817.232452328536 817.236499793888 817.240547299332 817.244594844868 817.248642430496 817.252690056218 818.164426363991 818.16848306611 818.172539808458 818.176596591035 818.180653413842 818.18471027688 818.18876718015 818.192824123651 818.196881107384 818.200938131351 818.204995195551 818.209052299986 818.213109444656 818.21716662956 818.221223854701 818.225281120079 818.229338425694 818.233395771546 818.237453157638 818.241510583968 818.245568050537 818.249625557347 819.18392233678 819.18798915515 819.1920560139 819.19612291303 819.200189852541 819.204256832432 819.208323852706 819.212390913362 819.216458014401 819.220525155824 819.224592337631 819.228659559823 819.2327268224 819.236794125363 " "819.240861468713 819.24492885245 820.193731546341 820.197808397262 820.201885288712 820.205962220691 820.210039193201 820.214116206241 820.218193259813 820.222270353916 820.226347488553 820.230424663722 820.234501879425 820.238579135663 832.21883436359 832.223031634984 832.227228948716 832.231426304787 832.235623703196 832.239821143946 832.244018627035 832.248216152466 832.252413720239 832.256611330353 832.260808982811 832.265006677613 832.269204414758 832.273402194249 832.277600016085 832.281797880267 832.285995786796 832.290193735673 832.294391726897 832.298589760471 833.218980432568 833.223187798465 833.227395206852 833.231602657731 833.235810151102 833.240017686965 833.244225265321 833.248432886172 833.252640549516 833.256848255356 833.261056003692 833.265263794525 833.269471627854 833.273679503681 834.221533310184 834.225750807043 834.229968346546 834.234185928695 834.238403553488 834.242621220928 834.246838931015 834.251056683749 834.255274479132 834.259492317163 834.263710197844 834.267928121174 835.218046494203 835.222274073065 835.226501694725 835.230729359182 835.234957066438 835.239184816494 835.243412609349 835.247640445004 835.251868323461 835.256096244719 835.26032420878 835.264552215644 835.268780265312 835.273008357784 835.277236493061 873.174235302306 873.178855854748 873.18347645609 873.188097106335 873.192717805482 873.197338553533 873.201959350488 873.206580196348 873.211201091114 873.215822034786 873.220443027366 873.225064068854 873.229685159251 873.234306298558 873.238927486775 874.17804253512 874.182673717335 874.18730494862 874.191936228976 874.196567558404 874.201198936904 874.205830364477 874.210461841124 874.215093366845 874.219724941642 874.224356565516 874.228988238466 874.233619960494 874.238251731601 874.303101680785 874.307734188164 874.312366744634 874.316999350196 874.321632004851 874.3262647086 874.330897461442 874.335530263379 874.340163114412 874.344796014542 874.349428963769 874.354061962094 875.174876842222 875.179518592457 " "875.184160391931 875.188802240643 875.193444138596 875.198086085788 875.202728082222 875.207370127898 875.212012222817 875.216654366978 875.221296560385 875.225938803036 875.230581094934 889.200602342844 889.205394064883 889.210185838565 889.214977663891 889.219769540862 889.224561469479 889.229353449744 889.234145481656 889.238937565216 889.243729700426 889.248521887286 889.253314125797 889.25810641596 889.262898757776 889.267691151245 889.272483596368 889.277276093147 889.282068641582 889.286861241673 889.291653893423 889.296446596831 889.301239351898 889.306032158626 889.310825017014 889.315617927065 889.320410888778 889.325203902155 889.329996967196 889.334790083902 890.02073813417 890.0255386994 890.030339316416 890.03513998522 890.039940705812 890.044741478193 890.049542302364 890.054343178326 890.059144106079 890.063945085625 890.068746116964 890.073547200097 890.078348335025 890.083149521749 890.174381911812 890.179184134627 890.183986409256 890.188788735699 890.193591113957 890.198393544031 890.203196025921 890.207998559629 890.212801145155 890.217603782501 890.222406471667 890.227209212653 890.232012005462 890.236814850093 890.241617746547 890.246420694826 890.25122369493 890.25602674686 890.260829850616 890.2656330062 890.270436213613 890.275239472855 890.280042783927 891.198426546905 891.203239824931 891.208053154948 891.212866536959 891.217679970964 891.222493456964 891.22730699496 891.232120584952 891.236934226942 891.24174792093 891.246561666917 891.251375464905 891.256189314893 891.261003216882 891.265817170875 891.27063117687 891.27544523487 891.280259344875 892.200708915166 892.205533025772 892.210357188546 892.21518140349 892.220005670603 892.224829989886 892.229654361341 892.234478784968 892.239303260768 892.244127788742 892.248952368891 892.253777001215 892.258601685716 892.263426422395 892.268251211251 892.273076052286 893.142398272161 893.147232571559 893.15206692329 893.156901327355 893.161735783755 893.166570292491 893.171404853563 " "893.176239466974 893.181074132723 893.185908850811 893.190743621239 893.20041331912 893.205248246574 893.210083226371 893.214918258513 893.219753343 893.224588479834 893.229423669014 893.234258910542 893.239094204419 893.243929550645 893.248764949222 893.25360040015 893.25843590343 893.263271459063 893.26810706705 893.272942727391 894.197514830975 894.202360559179 894.207206339903 894.212052173146 894.21689805891 894.221743997196 894.226589988005 894.231436031336 894.236282127192 894.241128275573 894.24597447648 894.250820729913 894.255667035874 894.260513394364 894.265359805383 894.270206268932 906.234202718878 906.239179781027 906.244156897845 906.249134069332 906.25411129549 906.259088576319 906.26406591182 906.269043301994 906.274020746843 906.278998246366 906.283975800565 906.288953409441 906.293931072995 906.298908791226 907.235692252254 907.240680320926 907.245668444448 907.250656622821 907.255644856045 907.260633144123 907.265621487054 907.270609884839 907.27559833748 907.280586844978 907.285575407332 907.290564024546 907.295552696618 907.30054142355 908.234398692328 908.239397749042 908.244396860787 908.249396027565 908.254395249375 908.25939452622 908.2643938581 908.269393245016 908.274392686968 908.279392183959 908.284391735988 908.289391343056 922.842856257044 922.84801742175 922.853178644185 922.858339924351 922.86350126225 922.86866265788 922.873824111245 922.878985622344 922.884147191179 922.88930881775 922.894470502059 934.042623867136 934.0479110658 934.053198324322 934.058485642702 934.063773020941 934.069060459041 934.074347957002 934.079635514825 934.084923132512 934.090210810063 934.09549854748 934.100786344763 934.106074201913 934.111362118932 962.94815872668 962.953778232548 962.959397804004 962.96501744105 962.970637143686 962.976256911914 962.981876745735 962.987496645149 962.993116610159 962.998736640765 963.004356736968 963.00997689877 963.217969011729 963.223591667127 963.229214388169 963.234837174856 963.240460027188 963.246082945167 " "963.251705928794 963.257328978069 963.262952092996 963.268575273574 963.274198519804 963.279821831688 963.285445209227 963.291068652422 963.296692161274 963.302315735784 963.307939375954 963.313563081784 963.319186853277 963.324810690432 963.420425969611 963.426050988895 963.431676073865 963.43730122452 963.442926440862 963.448551722892 963.454177070612 963.459802484022 963.465427963124 963.471053507919 963.476679118408 963.482304794592 964.21420252401 964.219836816216 964.225471174269 964.23110559817 964.236740087921 964.242374643523 964.248009264976 964.253643952283 964.259278705443 964.26491352446 964.270548409332 964.276183360063 964.281818376652 964.287453459101 964.293088607411 964.298723821583 964.304359101619 964.309994447519 964.315629859286 964.321265336919 964.32690088042 964.33253648979 964.338172165031 964.343807906143 964.349443713128 964.355079585987 964.36071552472 964.36635152933 964.467810878442 964.473448134917 964.479085457292 964.484722845568 964.490360299745 964.495997819824 964.501635405808 964.507273057696 964.512910775491 964.518548559193 964.524186408804 964.529824324324 965.201207199106 965.206853032182 965.212498931307 965.218144896483 965.223790927711 965.229437024992 965.235083188328 965.240729417718 965.246375713166 965.252022074672 965.257668502236 965.26331499586 965.268961555546 965.274608181294 965.280254873106 965.285901630983 965.291548454925 965.297195344935 965.302842301012 965.308489323159 965.314136411377 965.319783565667 965.325430786029 965.331078072465 966.212864647697 966.218522322157 966.224180062874 966.22983786985 966.235495743085 966.241153682582 966.246811688342 966.252469760364 966.258127898651 966.263786103204 966.269444374024 966.275102711111 966.280761114469 966.286419584096 966.292078119995 966.297736722167 966.303395390612 966.309054125333 966.31471292633 966.320371793604 966.326030727157 967.215306113877 967.220975534084 967.226645020755 967.232314573891 967.237984193494 967.243653879564 967.249323632103 " "967.254993451112 967.260663336592 967.266333288544 967.272003306969 967.277673391869 967.283343543245 967.289013761098 967.294684045428 967.300354396238 967.306024813528 967.3116952973 967.317365847555 967.323036464293 967.328707147517 967.334377897227 967.340048713424 967.345719596109 967.351390545285 980.194309595126 980.200132191883 980.205954857816 980.211777592926 980.217600397214 980.223423270681 980.229246213329 980.235069225159 980.240892306172 980.24671545637 980.252538675753 980.258361964323 980.264185322081 980.270008749028 980.275832245166 980.281655810496 980.287479445018 980.293303148735 980.299126921648 980.304950763757 980.310774675063 980.31659865557 980.322422705276 989.849128120579 989.855065986618 989.861003923897 989.866941932417 989.872880012179 989.878818163186 989.884756385438 989.890694678936 989.896633043682 989.902571479677 989.908509986923 989.91444856542 1024.22504311064 1024.23140056509 1024.23775809846 1024.24411571076 1024.25047340198 1024.25683117213 1024.26318902121 1024.26954694921 1024.27590495616 1024.28226304203 1024.28862120684 1024.29497945058 1024.30133777326 1024.30769617489 1024.31405465545 1024.32041321495 1024.3267718534 1024.3331305708 1024.33948936714 1024.62571693597 1024.63207936544 1024.63844187393 1024.64480446143 1024.65116712796 1024.6575298735 1024.66389269807 1024.67025560165 1024.67661858427 1024.6829816459 1024.68934478657 1024.69570800627 1024.80389483394 1024.8102594764 1024.81662419793 1024.82298899851 1024.82935387816 1024.83571883686 1024.84208387463 1024.84844899146 1024.85481418736 1024.86117946232 1024.86754481635 1024.87391024946 1024.88027576163 1024.88664135288 1037.17792520177 1037.18444447285 1037.19096382588 1037.19748326088 1037.20400277783 1037.21052237674 1037.21704205761 1037.22356182045 1037.23008166525 1037.23660159202 1037.24312160075 1037.24964169146 1037.25616186413 1037.26268211878 1037.2692024554 1037.275722874 1037.28224337457 1037.28876395712 1037.29528462166 1037.30180536817 " "1037.30832619667 1037.31484710715 1037.32136809962 1037.32788917408 1038.22205208364 1038.22858448726 1038.2351169731 1038.24164954113 1038.24818219137 1038.25471492382 1038.26124773848 1038.26778063535 1038.27431361443 1038.28084667573 1038.28737981924 1038.29391304497 1038.30044635292 1038.30697974309 1038.31351321548 1038.32004677009 1038.32658040693 1039.22901160479 1039.235556686 1039.24210184966 1039.24864709577 1039.25519242432 1039.26173783531 1039.26828332876 1039.27482890466 1039.28137456301 1039.28792030381 1039.29446612706 1039.30101203278 1039.30755802095 1039.31410409158 1039.32065024467 1039.32719648023 1039.33374279825 1039.34028919873 1039.34683568169 1040.22481095549 1040.23136858588 1040.23792629894 1040.24448409469 1040.25104197312 1040.25759993424 1040.26415797804 1040.27071610453 1040.27727431371 1040.28383260558 1040.29039098014 1040.2969494374 1040.30350797735 1040.3100666 1040.31662530535 1040.32318409339 1040.32974296414 1041.2290907215 1041.2356610201 1041.24223140163 1041.24880186607 1041.25537241343 1041.26194304372 1041.26851375694 1041.27508455308 1041.28165543215 1041.28822639415 1041.29479743909 1041.30136856695 1041.30793977776 1041.3145110715 1041.32108244817 1041.32765390779 1041.33422545035 1041.34079707585 1041.3473687843 1041.35394057569 1041.36051245003 1041.36708440732 1041.37365644756 1041.38022857076 1041.3868007769 1041.39337306601 1041.39994543807 1041.40651789309 1041.41309043107 1041.41966305201 1088.79279195134 1088.79997622919 1088.80716060185 1088.81434506932 1088.82152963161 1088.82871428871 1088.83589904063 1088.84308388737 1088.85026882893 1088.85745386531 1088.86463899652 1098.12539546821 1098.13270343459 1098.14001149825 1098.14731965918 1098.15462791738 1098.16193627285 1098.1692447256 1098.17655327563 1098.18386192294 1098.19117066753 1098.19847950941 1098.20578844857 1098.21309748502 1098.22040661877 1098.2277158498 1098.23502517813 1098.24233460375 1098.24964412667 1098.2569537469 1098.26426346442 " "1098.27157327925 1111.23703980607 1111.2445233295 1111.25200695373 1111.25949067876 1111.26697450458 1111.27445843121 1111.28194245863 1111.28942658687 1111.29691081591 1111.30439514576 1111.31187957642 1111.31936410789 1111.32684874018 1111.33433347329 1111.34181830722 1111.34930324196 1112.25572512581 1112.26322237607 1112.27071972739 1112.27821717979 1112.28571473327 1112.29321238783 1112.30071014346 1112.30820800018 1112.31570595798 1112.32320401687 1112.33070217685 1112.33820043792 1112.34569880008 1112.41318860905 1112.42068798226 1112.42818745657 1112.43568703201 1112.44318670856 1112.45068648624 1112.45818636504 1112.46568634496 1112.47318642601 1112.48068660819 1112.48818689151 1112.49568727595 1112.50318776154 1112.57819818028 1112.58569977849 1112.59320147786 1112.60070327839 1112.60820518009 1112.61570718295 1112.62320928699 1112.63071149219 1112.63821379856 1112.64571620611 1112.65321871484 1112.66072132475 1114.26108654592 1114.26861085524 1114.27613526618 1114.28365977874 1114.29118439293 1114.29870910874 1114.30623392618 1114.31375884525 1114.32128386596 1114.32880898829 1114.33633421227 1115.25517475482 1115.2627124958 1115.27025033867 1115.27778828344 1115.28532633011 1115.29286447867 1115.30040272913 1115.3079410815 1115.31547953577 1115.32301809195 1115.33055675004 1115.33809551004 1115.34563437195 1130.2815779083 1130.28932013803 1130.29706247383 1130.30480491569 1130.31254746363 1130.32029011764 1130.32803287773 1130.33577574389 1130.34351871613 1130.35126179446 1130.35900497886 1147.66276619636 1147.67074837394 1147.67873066254 1147.68671306219 1147.69469557288 1147.70267819461 1147.71066092738 1147.7186437712 1147.72662672607 1147.73460979199 1147.74259296897 1147.750576257 1147.75855965609 1147.76654316625 1147.77452678746 1182.98466783959 1182.99314891893 1183.00163011987 1183.01011144242 1183.01859288659 1183.02707445237 1183.03555613976 1183.04403794878 1183.05251987942 1183.06100193168 1183.06948410557 1183.07796640108 1183.1712796801 " "1183.17976343539 1183.18824731234 1183.19673131095 1183.20521543123 1183.21369967318 1183.22218403681 1183.23066852212 1183.2391531291 1183.24763785777 1183.25612270812 1183.26460768015 1183.27309277388 1183.68052043171 1183.68901149146 1183.69750267303 1183.70599397643 1183.71448540165 1183.7229769487 1183.73146861758 1183.7399604083 1183.74845232085 1183.75694435525 1183.76543651148 1183.77392878956 1188.27493289966 1188.28349000304 1188.29204722968 1188.30060457956 1188.30916205269 1188.31771964907 1188.32627736871 1188.3348352116 1188.34339317776 1188.35195126718 1188.36050947987 1209.74923184622 1209.75810103042 1209.76697034466 1209.77583978896 1209.78470936331 1209.79357906772 1209.80244890218 1209.81131886671 1209.82018896131 1209.82905918597 1209.83792954071 1209.87341226042 1209.88228326555 1209.89115440077 1209.90002566609 1209.9088970615 1209.917768587 1209.92664024261 1209.93551202832 1209.94438394413 1209.95325599005 1209.96212816609 1214.99579864251 1215.00474492341 1215.01369133607 1215.02263788047 1215.03158455663 1215.04053136455 1215.04947830422 1215.05842537566 1215.06737257887 1215.07631991384 1215.08526738058 1215.0942149791 1215.10316270939 1215.11211057146 1240.4233010027 1240.43262565993 1240.44195045736 1240.45127539499 1240.46060047282 1240.46992569085 1240.47925104909 1240.48857654754 1240.4979021862 1240.50722796507 1240.51655388417 1240.52587994349 1240.53520614303 1240.5445324828 1243.04905650569 1243.05842068214 1243.06778499968 1243.0771494583 1243.08651405802 1243.09587879883 1243.10524368075 1243.11460870376 1243.12397386788 1243.13333917311 1243.14270461945 1243.15207020691 1243.16143593548 1243.17080180517 1243.18016781599 1243.18953396794 1250.94602927114 1250.95551280543 1250.96499648351 1250.97448030538 1250.98396427106 1250.99344838053 1251.00293263381 1251.0124170309 1251.0219015718 1251.03138625652 1251.04087108505 1251.05035605741 1261.31128248752 1261.32092383336 1261.33056532659 1261.34020696722 1261.34984875525 " "1261.35949069069 1261.36913277353 1261.37877500379 1261.38841738147 1261.39805990657 1261.40770257909 1261.94792763215 1261.95757871339 1261.96722994224 1261.97688131873 1261.98653284283 1261.99618451457 1262.00583633394 1262.01548830095 1262.02514041559 1262.03479267788 1262.04444508782 1262.05409764541 1262.06375035065 1262.07340320354 1262.32442921749 1262.33408605841 1262.34374304707 1262.35340018349 1262.36305746766 1262.3727148996 1262.3823724793 1262.39203020678 1262.40168808202 1262.41134610504 1262.42100427584 1262.43066259442 1262.44032106079 1263.28117374346 1263.29084522825 1263.30051686113 1263.31018864211 1263.31986057118 1263.32953264835 1263.33920487361 1263.34887724699 1263.35854976847 1263.36822243806 1263.37789525577 1263.3875682216 1263.39724133555 1263.40691459763 1265.31544052296 1265.32514318102 1265.33484598788 1265.34454894355 1265.35425204803 1265.36395530132 1265.37365870343 1265.38336225437 1265.39306595413 1265.40276980271 1265.41247380013 1265.42217794639 1273.46930606141 1273.47913417338 1273.48896243705 1273.49879085242 1273.5086194195 1273.51844813829 1273.5282770088 1273.53810603102 1273.54793520496 1273.55776453063 1273.56759400803 1273.57742363715 1273.58725341802 1273.59708335062 1273.60691343496 1273.61674367105 1273.62657405888 1281.32087896611 1281.33082864257 1281.34077847355 1281.35072845906 1281.3606785991 1281.37062889368 1281.38057934279 1281.39052994644 1281.40048070464 1281.41043161738 1281.42038268468 1281.43033390653 1281.44028528294 1281.45023681392 1281.46018849946 1281.47014033957 1281.48009233426 1293.16997731079 1293.18011185941 1293.19024656688 1293.2003814332 1293.21051645839 1293.22065164243 1293.23078698534 1293.24092248711 1293.25105814776 1293.26119396729 1293.27132994569 1293.28146608298 1409.30396671911 1409.31600329167 1409.32804006984 1409.34007705362 1409.35211424301 1409.36415163802 1409.37618923866 1409.38822704493 1409.40026505684 1409.4123032744 1409.4243416976 1409.43638032645 1439.81291838247 " "1439.82548173949 1439.83804531576 1439.85060911129 1439.86317312607 1439.87573736013 1439.88830181346 1439.90086648606 1439.91343137795 1439.92599648913 1439.93856181961 1439.97625912687 1439.98882533458 1440.00139176163 1440.013958408 1440.0265252737 1440.03909235875 1440.05165966315 1440.0642271869 1440.07679493 1440.08936289247 1440.10193107432 1456.39679555874 1456.40964999523 1456.42250465864 1456.43535954896 1456.44821466621 1456.46107001039 1456.47392558151 1456.48678137957 1456.49963740459 1456.51249365655 1456.52535013548 1456.53820684138 1456.55106377425 1456.5639209341 1456.57677832093 1469.49643693345 1469.5095236508 1469.52261060125 1469.5356977848 1469.54878520145 1469.56187285121 1469.57496073409 1469.58804885009 1469.60113719922 1469.61422578149 1469.6273145969 1469.64040364545 1477.46994793765 1477.48317705841 1477.49640641608 1477.50963601066 1477.52286584217 1477.53609591059 1477.54932621596 1477.56255675826 1477.5757875375 1477.58901855369 1477.60224980685 1477.61548129696 1477.62871302405 1477.64194498811 1477.65517718916 1477.6684096272 1477.68164230223 1477.69487521426 1477.7081083633 1477.72134174936 1478.91331787051 1478.9265728516 1478.93982807029 1478.9530835266 1478.96633922051 1478.97959515204 1478.99285132121 1479.006107728 1479.01936437244 1479.03262125452 1479.04587837426 1480.17360285036 1480.18688043216 1480.20015825217 1480.2134363104 1480.22671460685 1480.23999314153 1480.25327191444 1480.2665509256 1480.279830175 1480.29310966266 1480.30638938858 1480.31966935276 1480.33294955522 1480.34622999596 1480.35951067499 1480.37279159231 1480.38607274793 1480.39935414185 1480.41263577409 1480.42591764464 1480.73146645809 1480.74475405022 1480.75804188082 1480.77132994991 1480.78461825749 1480.79790680357 1480.81119558816 1480.82448461126 1480.83777387287 1480.85106337301 1480.86435311168 1480.87764308888 1480.89093330463 1480.90422375893 1480.91751445178 1480.9308053832 1480.94409655318 1480.95738796174 1480.97067960888 1480.983971494 " "1480.99726361894 1481.01055598187 1481.0238485834 1481.03714142355 1481.05043450231 1481.06372781971 1481.07702137574 1481.34294261915 1481.35624118796 1481.36953999554 1481.38283904191 1481.39613832706 1481.409437851 1481.42273761375 1481.4360376153 1481.44933785567 1481.46263833486 1481.47593905287 1481.48924000971 1481.50254120539 1481.51584263992 1481.5291443133 1481.54244622554 1481.55574837664 1481.56905076662 1481.58235339547 1481.5956562632 1481.60895936983 1481.62226271535 1481.63556629978 1481.64887012311 1481.66217418536 1481.67547848654 1482.36763154258 1482.38094851586 1482.39426572841 1482.40758318025 1482.42090087136 1482.43421880177 1482.44753697147 1482.46085538047 1482.47417402879 1482.48749291642 1482.50081204337 1482.51413140965 1482.52745101526 1482.54077086022 1493.62532276273 1493.63884277381 1493.65236302966 1493.66588353027 1493.67940427566 1493.69292526583 1493.70644650079 1493.71996798055 1493.73348970511 1493.74701167448 1493.76053388867 1493.77405634768 1511.59045068974 1511.60429789207 1511.6181453481 1511.63199305785 1511.64584102131 1511.65968923849 1511.6735377094 1511.68738643405 1511.70123541244 1511.71508464459 1511.72893413049 1599.95476419777 1599.97027768381 1599.98579147069 1600.00130555844"; const char* fullSpectrumRawY = "0 0 0 0 0 0 0 0 0 193.855026245117 641.106506347656 877.26220703125 700.196716308594 274.883911132813 0 0 0 0 0 0 0 0 0 0 224.89469909668 511.670349121094 595.136657714844 452.148010253906 234.596389770508 74.6820220947266 0 0 0 0 0 0 0 0 119.225784301758 185.543075561523 200.134750366211 188.900192260742 160.073196411133 0 0 0 0 0 0 0 172.296859741211 200.144027709961 165.512985229492 0 0 0 0 0 0 0 0 83.4415893554688 208.525405883789 177.816024780273 100.466018676758 0 0 0 0 0 0 0 0 93.3426513671875 177.81330871582 221.383926391602 233.153823852539 185.899673461914 84.1839904785156 0 0 0 0 0 0 0 0 126.048049926758 184.371139526367 97.8295288085938 0 0 0 0 0 0 0 0 25.8681793212891 261.258850097656 531.637878417969 574.53076171875 413.904724121094 218.982650756836 112.732650756836 0 0 0 0 0 0 0 0 94.0497131347656 191.148391723633 161.991897583008 0 0 0 0 0 0 0 402.995788574219 1600.27600097656 3017.67749023438 3685.970703125 3078.0078125 1699.85888671875 531.254028320313 44.9793395996094 0 0 0 0 0 0 0 0 3.05120849609375 326.982971191406 918.194396972656 1295.37927246094 1141.49755859375 577.818969726563 26.3272705078125 0 0 0 0 0 0 0 0 125.907791137695 264.531921386719 266.280029296875 158.506088256836 0 0 0 0 0 0 0 0 45.1534271240234 245.012252807617 337.062133789063 230.558639526367 35.3934326171875 0 0 0 0 0 0 0 0 21.4011077880859 269.609924316406 302.905334472656 3843.85766601563 9906.61328125 14627.65625 14086.5751953125 8667.4873046875 2666.59497070313 152.549850463867 452.571411132813 21.2885437011719 0 0 0 0 0 0 0 0 0 242.630386352539 1476.34033203125 2982.52856445313 3656.2958984375 2926.99194335938 1440.77648925781 378.651611328125 617.814758300781 1036.13317871094 1038.09765625 677.166748046875 273.266662597656 106.01123046875 0 0 0 0 0 0 0 0 0 644.765441894531 1669.39282226563 2428.14697265625 2279.11108398438 1350.7001953125 456.782958984375 195.992416381836 144.774459838867 138.42707824707 203.370742797852 302.340209960938 350.181884765625 " "314.466613769531 225.259658813477 125.442489624023 0 0 0 0 0 0 0 0 0 229.676986694336 1286.525390625 3076.466796875 4448.58984375 4288.94775390625 2695.29956054688 856.980102539063 0 0 0 0 0 0 0 0 0 0 297.09423828125 790.947937011719 1078.3701171875 895.997009277344 377.297119140625 0 0 0 0 0 0 0 0 0 54.2761840820313 380.800170898438 604.678894042969 530.256896972656 239.020004272461 14.5890960693359 0 0 0 0 0 0 0 0 0 315.951721191406 1584.78002929688 3584.27490234375 4964.8896484375 4550.10595703125 2648.34790039063 761.737854003906 336.893249511719 327.000427246094 103.404342651367 0 0 0 0 0 0 0 0 137.308151245117 232.669479370117 225.336959838867 131.02082824707 0 0 0 0 0 0 0 0 0 309.901550292969 806.588073730469 1159.07531738281 1105.30993652344 695.416931152344 245.27473449707 13.4951171875 0 0 0 0 0 0 0 0 114.433959960938 215.006851196289 272.628845214844 187.665817260742 12.0498352050781 0 0 0 0 0 0 0 0 127.550247192383 182.018173217773 211.423233032227 191.385147094727 141.782333374023 0 0 0 0 0 0 0 0 0 745.767456054688 2422.9541015625 3720.92529296875 3568.47998046875 2088.86743164063 510.764953613281 183.886978149414 136.265151977539 0 0 0 0 0 0 0 0 171.257888793945 188.640060424805 192.395614624023 154.632247924805 0 0 0 0 0 0 0 0 130.887710571289 642.11865234375 1160.51184082031 1294.43505859375 977.964050292969 544.39794921875 308.192199707031 211.437362670898 76.1909332275391 0 0 0 0 0 0 0 0 0 229.855178833008 543.525207519531 586.220275878906 314.952575683594 0 0 0 0 0 0 0 0 0 154.422073364258 196.758010864258 149.831283569336 0 0 0 0 0 0 0 0 123.318832397461 188.429489135742 169.386795043945 0 0 0 0 0 0 0 0 2959.08642578125 8616.0419921875 13691.96484375 14140.76953125 9577.6708984375 3752.03759765625 393.419616699219 324.138061523438 232.52278137207 0 0 0 0 0 0 0 0 0 133.11164855957 205.964584350586 199.730422973633 139.437789916992 0 0 0 0 0 0 0 0 101.496200561523 185.133193969727 259.655029296875 244.710922241211 160.866897583 0 0 0 0 0 0 0 0 " "171.158157348633 209.737930297852 216.904006958008 153.206130981445 0 0 0 0 0 0 0 0 0 1064.01928710938 2744.22631835938 3925.62744140625 3728.50854492188 2484.57104492188 1484.09924316406 1184.474609375 801.294799804688 276.304870605469 0 0 0 0 0 0 0 0 0 0 300.0966796875 1263.98876953125 2300.80615234375 2527.240234375 1658.1162109375 416.934509277344 362.052856445313 510.349609375 422.890075683594 293.749877929688 96.1615142822266 0 0 0 0 0 0 0 0 277.112182617188 552.278137207031 634.911743164063 465.758728027344 230.118118286133 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 338.728454589844 100.444885253906 1113.40734863281 4002.13525390625 6734.62841796875 7179.69189453125 4943.12939453125 1888.85778808594 87.8339996337891 0 0 0 0 0 0 0 0 166.607498168945 203.203231811523 88.5599517822266 0 0 134.797103881836 252.799118041992 321.236206054688 317.407653808594 177.626174926758 0 0 0 0 0 0 0 0 420.235168457031 1400.63110351563 2127.62890625 2036.72399902344 1375.9619140625 1018.35345458984 909.901550292969 528.322021484375 118.658309936523 0 0 0 0 0 0 0 0 6.52516174316406 184.584854125977 399.570495605469 472.823852539063 311.700012207031 67.0648040771484 0 0 0 0 0 0 0 0 4.97833251953125 518.760131835938 1195.45788574219 1522.00109863281 1192.40087890625 457.996826171875 236.555740356445 455.735107421875 494.134094238281 419.947204589844 169.757431030273 0 0 0 0 0 0 0 0 158.202651977539 249.356582641602 255.182876586914 181.06364440918 0 0 0 0 0 0 0 0 173.365737915039 243.861038208008 222.755081176758 104.503341674805 0 0 0 0 0 0 0 0 127.732864379883 184.066452026367 159.648910522461 0 0 0 0 0 0 0 0 0 216.264389038086 564.540100097656 758.490661621094 593.172241210938 186.406509399414 0 0 0 0 0 0 0 0 0 57.8870544433594 189.093154907227 180.032363891602 0 0 0 0 0 0 0 0 107.181259155273 588.624389648438 3296.2294921875 6859.40966796875 8629.48046875 6954.76904296875 3204.29370117188 530.406066894531 701.101257324219 446.318359375 172.379989624023 0 0 0 0 0 0 0 0 " "106.025817871094 219.603103637695 171.653244018555 0 0 0 0 0 0 0 0 66.6060028076172 816.289489746094 2058.00170898438 2839.88916015625 2264.32885742188 887.272766113281 1098.07897949219 1184.8994140625 515.840759277344 0 0 0 0 0 0 0 0 0 107.923675537109 213.511978149414 238.096145629883 157.005569458008 0 0 0 0 0 0 0 0 84.7611541748047 279.91943359375 997.471740722656 1668.52087402344 1678.548828125 1062.6884765625 456.879150390625 261.066772460938 414.542724609375 400.814636230469 181.47590637207 0 0 0 0 0 0 0 0 162.703384399414 402.678283691406 606.938415527344 584.632751464844 322.495727539063 0 0 0 0 0 0 0 0 203.609512329102 221.824447631836 103.749816894531 0 0 0 0 0 0 0 0 139.273239135742 246.041458129883 237.826309204102 138.225112915039 0 0 0 102.917053222656 540.358703613281 1507.14807128906 2255.67041015625 2121.10278320313 1207.01428222656 254.796005249023 0 0 0 0 0 0 0 0 0 180.893783569336 216.125747680664 186.408401489258 92.5867767333984 0 0 0 0 0 0 0 0 67.1141357421875 314.660339355469 430.744506835938 249.505142211914 110.873168945313 311.952087402344 298.573059082031 158.444198608398 0 0 0 0 0 0 0 0 0 203.841903686523 330.667297363281 305.950500488281 171.00895690918 0 0 0 0 0 0 0 0 150.461807250977 187.074295043945 122.066360473633 0 0 0 0 0 0 0 0 128.328475952148 228.142013549805 224.649185180664 115.597442626953 0 0 0 0 0 0 0 0 121.621292114258 209.864395141602 180.903396606445 0 0 0 0 0 0 0 0 180.190689086914 221.191635131836 230.223587036133 203.161819458008 163.631942749023 0 0 0 103.920654296875 254.635330200195 239.919662475586 117.75276184082 0 0 0 0 0 0 0 0 127.274429321289 277.754516601563 418.050842285156 364.745910644531 108.102828979492 0 0 0 0 0 0 0 0 122.235366821289 204.649490356445 1283.6416015625 2732.66333007813 3403.52026367188 2677.83666992188 1189.97729492188 91.4230346679688 0 0 0 0 0 0 0 0 179.184860229492 218.383316040039 188.207290649414 103.431289672852 0 0 0 0 0 19.3411254882813 320.543273925781 708.724914550781 " "746.338012695313 324.464965820313 498.983642578125 805.302062988281 584.451416015625 150.821365356445 0 0 0 0 0 0 0 0 18.6659393310547 273.791931152344 556.722961425781 580.784423828125 324.137634277344 118.86296081543 192.937911987305 133.19303894043 0 0 0 0 0 0 0 0 156.306106567383 528.205383300781 857.985168457031 865.72802734375 528.765258789063 126.998458862305 0 0 0 0 0 0 0 0 141.282363891602 213.537307739258 188.727676391602 83.9633941650391 0 0 0 0 0 0 0 0 53.5650329589844 300.0869140625 496.208679199219 543.627502441406 469.730163574219 370.066101074219 289.648376464844 183.115615844727 57.3272399902344 0 0 0 0 0 0 0 0 128.359512329102 282.553894042969 428.125305175781 518.781311035156 625.49609375 722.9619140625 704.251159667969 596.822631835938 501.902587890625 382.079040527344 159.27229309082 0 0 0 0 0 0 0 0 65.7273559570313 820.538696289063 2162.48120117188 3311.76513671875 3299.95263671875 2090.16650390625 672.241455078125 0 0 0 0 0 0 0 0 0 0 308.417297363281 836.372497558594 1054.75146484375 828.995056152344 520.746643066406 281.113220214844 0 0 0 0 0 0 0 0 0 135.923385620117 224.629806518555 176.55793762207 0 0 0 0 0 0 0 0 0 243.977737426758 679.087585449219 930.161682128906 790.303100585938 379.179931640625 152.314804077148 0 0 0 0 0 0 0 0 136.929214477539 317.641784667969 361.6630859375 256.365356445313 53.1949462890625 0 0 0 0 0 0 0 0 79.8312377929688 199.234237670898 225.433242797852 110.191116333008 0 0 0 0 0 0 0 0 88.5470733642578 328.809631347656 486.254577636719 566.095397949219 679.935241699219 807.850219726563 851.315795898438 785.165161132813 654.703979492188 527.893920898438 423.899841308594 256.051086425781 0 0 0 0 0 0 0 0 0 0 325.090454101563 1122.31469726563 1884.14013671875 2005.18811035156 1370.16577148438 511.172485351563 0 0 0 0 0 0 0 0 0 144.137466430664 222.952560424805 139.711410522461 0 0 0 31.4209136962891 456.088439941406 906.362609863281 992.082092285156 640.056396484375 191.88249206543 0 0 0 0 0 0 0 0 0 142.481643676758 " "248.23698425293 361.091796875 321.38818359375 84.5967559814453 0 0 0 0 0 0 0 0 68.5481414794922 229.667556762695 342.556030273438 233.595016479492 12.875 284.913818359375 586.492919921875 765.540771484375 846.076843261719 837.908752441406 736.949829101563 570.628051757813 422.32958984375 338.351196289063 265.928649902344 102.936645507813 0 0 0 0 0 0 0 0 111.217437744141 194.165725708008 498.359680175781 810.423156738281 786.201354980469 424.384338378906 32.8225250244141 0 0 0 0 0 0 0 0 126.047775268555 188.677780151367 216.424392700195 207.760787963867 193.143905639648 173.67204284668 0 0 0 0 0 0 0 0 230.711318969727 263.243713378906 218.297134399414 121.326461791992 0 0 0 0 0 0 0 0 85.8698425292969 222.64518737793 225.071212768555 111.491928100586 0 0 0 0 0 0 0 0 158.272689819336 319.939025878906 405.672607421875 543.889831542969 709.350402832031 762.2890625 669.657836914063 464.710327148438 230.338363647461 135.231704711914 0 0 0 0 0 0 0 0 112.85188293457 340.410949707031 556.054382324219 649.1904296875 642.006286621094 595.709777832031 552.84423828125 532.100952148438 509.958984375 393.80126953125 147.021102905273 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 163.031021118164 257.087280273438 222.833755493164 69.1905975341797 0 0 0 0 0 0 0 0 0 193.01008605957 1283.4189453125 2651.75854492188 3263.72827148438 2533.265625 1061.58337402344 237.298934936523 292.41845703125 36.6092681884766 0 0 0 0 0 0 0 0 0 412.251708984375 1201.08520507813 1691.83618164063 1483.95202636719 787.549011230469 140.731460571289 0 0 0 0 0 0 0 0 155.059463500977 197.582107543945 226.128463745117 389.715087890625 812.975402832031 1328.24084472656 1494.00390625 1091.52282714844 416.5791015625 13.3121490478516 0 0 0 0 0 0 0 0 30.8641204833984 259.902893066406 398.201293945313 307.794982910156 89.9954833984375 0 0 0 0 0 0 0 0 250.239639282227 294.914489746094 240.247360229492 36.3681182861328 0 0 0 0 0 0 0 0 168.141342163086 211.644943237305 185.341293334961 0 0 0 0 0 0 0 0 0 1255.41430664063 " "4270.45751953125 7186.3505859375 7656.57861328125 5270.84912109375 2048.24633789063 131.94660949707 0 0 0 0 0 0 0 0 171.324295043945 234.151138305664 188.494430541992 85.8521118164063 0 0 0 0 0 0 0 177.790451049805 196.738876342773 191.143508911133 173.924301147461 0 0 0 0 0 0 0 0 27.4716339111328 870.664428710938 2696.56469726563 4313.33056640625 4373.56005859375 2848.65014648438 1105.826171875 363.445678710938 95.8519592285156 0 0 0 0 0 0 0 0 165.054183959961 190.630477905273 212.371444702148 119.549850463867 0 0 0 0 144.282302856445 1497.27661132813 3014.11791992188 3372.33959960938 2141.125 440.955444335938 486.9052734375 473.754028320313 237.800888061523 10.4761962890625 0 0 0 0 0 0 0 0 187.649795532227 717.752685546875 1004.04693603516 895.356262207031 611.759887695313 231.517959594727 0 0 0 0 0 0 0 0 0 0 380.191772460938 1166.65649414063 1580.28991699219 1321.69921875 695.5244140625 219.708572387695 60.3770294189453 0 0 0 0 0 0 0 0 168.744674682617 496.461608886719 797.966979980469 819.004150390625 524.868408203125 148.768051147461 0 0 0 0 0 0 0 0 114.591278076172 230.604568481445 404.740417480469 400.008056640625 149.154037475586 0 0 0 0 0 0 0 0 102.017929077148 332.576171875 431.327087402344 395.180480957031 291.81103515625 179.464797973633 0 0 0 0 0 0 0 0 328.818298339844 432.372192382813 513.603515625 524.003845214844 455.190307617188 323.07763671875 0 0 0 0 0 0 0 0 0 500.822875976563 1250.17626953125 1691.61279296875 1446.947265625 741.710021972656 242.135177612305 131.856307983398 0 0 0 0 0 0 0 0 106.934600830078 416.481811523438 591.3037109375 471.31884765625 154.692947387695 0 0 0 0 0 0 0 0 58.2242736816406 451.217834472656 867.215209960938 952.283020019531 683.782348632813 327.990234375 53.9348297119141 0 0 0 0 0 0 0 0 112.282455444336 194.305465698242 247.864517211914 283.480651855469 251.062362670898 154.861434936523 0 0 0 0 0 0 0 0 0 2550.76782226563 7417.4248046875 11472.3154296875 11331.73046875 7126.333984375 2372.173828125 154.968887329 0 0 " "0 0 0 0 0 0 171.941879272461 235.122146606445 189.759658813477 86.6224975585938 0 0 0 0 0 0 0 0 161.515548706055 191.835342407227 263.086181640625 280.552551269531 146.46711730957 354.734191894531 1819.36071777344 4197.60791015625 5904.71484375 5515.97998046875 3378.09521484375 1216.07165527344 240.816360473633 160.06672668457 0 0 0 0 0 0 0 0 168.925979614258 417.149658203125 1732.84704589844 3627.1572265625 4610.03076171875 3790.7890625 1980.00671386719 757.338623046875 314.47314453125 0 0 0 0 0 0 0 0 0 151.324813842773 253.94270324707 329.051940917969 266.352722167969 111.870147705078 0 196.40153503418 1169.40258789063 2201.71215820313 2499.97778320313 1842.07995605469 847.819702148438 294.143676757813 154.02375793457 0 0 0 0 0 0 0 0 0 263.716003417969 663.424133300781 945.621276855469 900.181091308594 586.183349609375 242.737838745117 0 0 0 0 0 0 0 0 0 87.7988586425781 273.416259765625 275.446044921875 122.881698608398 0 0 0 0 0 0 0 0 139.006607055664 632.857299804688 1046.19299316406 1076.18725585938 721.538818359375 282.741760253906 33.4364013671875 0 92.9069519042969 201.903335571289 216.809951782227 66.0712280273438 0 0 0 0 0 0 0 0 0 262.810607910156 583.060974121094 697.79833984375 522.555419921875 181.537673950195 0 0 0 0 0 0 0 0 258.55615234375 289.532775878906 243.079086303711 173.991165161133 0 0 0 0 0 0 0 0 37.7136077880859 214.55876159668 243.370010375977 18.9360961914063 35.8999176025391 191.428115844727 166.77082824707 0 0 0 0 0 0 0 0 0 258.869323730469 651.99658203125 911.448181152344 810.898193359375 421.798156738281 54.3055572509766 0 0 0 0 0 0 0 0 60.1159057617188 292.62109375 475.166442871094 465.994323730469 265.969482421875 59.4075927734375 0 0 0 0 0 0 0 0 129.671829223633 203.134628295898 214.902053833008 142.065078735352 0 0 0 0 0 0 0 0 68.9898071289063 258.451477050781 349.82421875 288.4658203125 184.60481262207 0 0 0 0 0 0 0 0 60.4415130615234 757.99267578125 4146.55859375 8593.078125 10882.390625 9079.6171875 4740.5390625 1125.72338867 " "0 0 0 0 0 0 0 0 0 102.086837768555 209.562088012695 285.004333496094 167.125106811523 0 0 0 0 0 0 0 0 153.054061889648 218.63932800293 227.450668334961 199.439254760742 191.222061157227 179.493179321289 0 0 0 0 0 0 0 0 136.84049987793 243.085250854492 175.279190063477 0 0 0 165.884048461914 1627.97961425781 4570.39892578125 7233.904296875 7538.84521484375 5242.4697265625 2183.01293945313 247.249221801758 94.0259094238281 0 0 0 0 0 0 0 0 0 708.975402832031 2684.54736328125 4892.7626953125 5664.70263671875 4346.48974609375 2153.0361328125 792.776916503906 328.806335449219 26.2600402832031 0 0 0 0 0 0 0 0 0 600.651245117188 1863.01184082031 2856.58935546875 2825.29223632813 1829.23559570313 678.683837890625 156.775985717773 0 0 0 0 0 0 0 0 177.269912719727 213.871047973633 146.206100463867 0 0 0 0 0 0 0 0 0 438.628295898438 1067.17602539063 1423.88037109375 1322.46948242188 846.637451171875 222.935501098633 8.62030029296875 0 0 0 0 0 0 0 0 1.40678405761719 204.166915893555 495.588256835938 711.029602050781 672.086486816406 440.136291503906 197.460708618164 25.0921783447266 0 0 0 0 0 0 0 0 181.639419555664 454.123840332031 630.59228515625 540.996643066406 248.280014038086 0 0 0 0 0 0 0 0 0 0 272.537475585938 507.36669921875 482.3701171875 228.514022827148 0 0 0 0 0 0 0 0 0 173.016799926758 282.362365722656 239.30632019043 89.6678161621094 0 0 0 0 0 0 0 0 163.693313598633 238.812973022461 181.945022583008 0 0 0 0 0 0 0 0 154.68586730957 251.716812133789 301.325927734375 285.520263671875 212.902420043945 125.696426391602 0 0 0 0 0 0 0 0 144.465744018555 280.485534667969 282.486389160156 171.469833374023 0 0 0 0 0 0 0 0 168.80158996582 1852.96484375 4451.087890625 6223.240234375 5698.3251953125 3317.40869140625 947.944641113281 0 72.4445648193359 222.517288208008 190.692306518555 8.54414367675781 0 0 0 0 0 0 0 0 173.518569946289 287.66455078125 315.665649414063 180.375747680664 0 0 0 0 0 0 0 0 22.9653015136719 377.313659667969 1943.11608886719 3810.626464843 4614.140625 " "3648.7470703125 1708.49145507813 216.385025024414 180.797805786133 220.440505981445 66.8912200927734 0 0 0 0 0 143.90119934082 216.902420043945 185.753768920898 98.3815460205078 0 0 0 0 0 0 0 0 162.759536743164 215.904861450195 208.337875366211 127.708084106445 0 0 0 0 0 0 0 0 105.314514160156 217.56315612793 204.984756469727 103.096450805664 1431.53564453125 2977.5546875 3651.64916992188 2931.84326171875 1398.70080566406 87.1452484130859 320.6357421875 384.557983398438 269.201110839844 237.787063598633 238.22102355957 131.059158325195 0 0 0 0 0 0 0 0 82.7467803955078 540.114013671875 1467.232421875 2395.43090820313 2641.54028320313 2010.16149902344 989.484558105469 192.628158569336 0 0 179.865524291992 275.410278320313 175.700149536133 0 0 0 0 0 0 0 0 59.9419708251953 485.762634277344 988.358093261719 1207.15466308594 963.307312011719 438.903381347656 31.6091766357422 0 0 0 0 0 47.9591827392578 196.635208129883 252.011154174805 211.016983032227 150.474960327148 0 0 0 0 0 0 0 0 168.648544311523 212.75212097168 246.239303588867 241.005111694336 180.050369262695 0 0 0 0 93.9449157714844 308.76171875 510.256713867188 547.370849609375 379.794067382813 126.207992553711 0 0 0 0 0 0 0 0 165.212295532227 203.172348022461 187.95915222168 180.575973510742 0 0 0 0 0 0 0 0 75.0355987548828 196.667404174805 286.693542480469 310.418090820313 283.288269042969 260.312194824219 292.165649414063 351.78125 356.774780273438 261.874694824219 112.601119995117 0 0 0 0 0 0 0 0 147.65412902832 199.247695922852 206.355667114258 137.159103393555 0 0 0 0 0 0 0 0 153.178085327148 250.377090454102 305.382019042969 294.765869140625 215.430770874023 81.4587097167969 0 0 0 0 0 0 0 0 89.8516693115234 217.64045715332 309.367736816406 283.979248046875 149.045394897461 0 0 0 182.38005065918 418.089721679688 1096.13757324219 1732.892578125 1712.91027832031 1019.67010498047 253.890274047852 63.1096954345703 0 0 0 0 0 0 0 0 146.927871704102 197.823593139648 450.705383300781 1247.59985351563 " "2147.16479492188 2419.29248046875 1796.34436035156 783.829040527344 106.181396484375 0 0 0 0 0 0 0 0 0 334.013916015625 997.858215332031 1538.47912597656 1550.04187011719 1073.02502441406 532.429992675781 248.089309692383 200.781692504883 213.394241333008 177.545181274414 0 0 0 0 0 0 0 0 26.6942443847656 209.29020690918 520.969909667969 869.404174804688 1070.1162109375 975.004333496094 655.297485351563 316.672058105469 99.7084808349609 0 0 0 0 0 0 0 0 79.5495910644531 288.576049804688 554.977966308594 746.154174804688 740.367309570313 521.067321777344 227.974136352539 72.0663757324219 0 0 0 0 0 0 0 0 171.190017700195 314.421569824219 429.333374023438 416.543640136719 251.908309936523 31.249267578125 0 0 0 0 0 0 0 0 180.657669067383 192.169876098633 162.963485717773 0 0 0 0 0 0 0 0 155.606674194336 333.596923828125 371.658142089844 244.003341674805 111.538848876953 0 0 0 55.3578186035156 199.379867553711 277.664733886719 246.347457885742 148.267105102539 0 0 0 0 0 0 0 0 90.9604797363281 198.196731567383 372.608276367188 566.121337890625 624.478515625 473.921447753906 201.671371459961 0 0 0 0 0 0 0 0 0 120.198684692383 400.147033691406 571.140441894531 478.692626953125 229.758438110352 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 152.600845336914 225.899429321289 240.899063110352 190.175918579102 0 0 0 0 0 0 0 0 225.349227905273 261.482971191406 145.197463989258 0 0 0 0 0 0 0 0 64.5845184326172 213.417953491211 267.813903808594 201.623031616211 117.913467407227 0 0 0 0 0 0 0 0 182.848587036133 203.188278198242 155.740859985352 0 0 0 0 0 0 0 0 184.153060913086 247.411849975586 282.429565429688 316.498046875 347.890441894531 314.713134765625 179.080673217773 0 0 0 0 0 0 0 0 115.904327392578 226.538375854492 215.979263305664 129.574813842773 0 0 0 0 0 0 0 0 129.243606567383 308.855651855469 363.072937011719 252.200698852539 36.5062561035156 0 0 0 0 0 0 0 0 168.485580444336 221.236099243164 203.256454467773 118.937698364258 0 0 0 0 0 0 0 0 135.065872192383 197.25260925293 " "164.043045043945 0 0 0 0 0 0 0 0 101.22346496582 199.961135864258 181.580459594727 0 0 0 0 0 0 0 0 171.627029418945 216.893325805664 165.188735961914 0 0 0 0 0 0 0 0 184.577438354492 315.924865722656 400.736938476563 401.748779296875 309.456359863281 177.526077270508 0 0 0 0 0 0 0 0 71.3968505859375 196.379440307617 317.622741699219 323.017578125 218.84977722168 108.977661132813 0 0 0 0 0 0 0 0 143.710311889648 248.819686889648 318.435913085938 338.807861328125 306.490661621094 239.977798461914 197.418716430664 128.426620483398 0 0 0 0 0 0 0 0 126.655654907227 226.479202270508 229.53288269043 179.628677368164 0 0 0 0 0 0 0 0 144.30647277832 214.861099243164 189.256454467773 0 0 0 0 0 0 0 0 188.085342407227 308.395935058594 374.08056640625 337.305053710938 193.459030151367 33.2561950683594 0 0 0 0 0 0 0 0 101.20735168457 200.764785766602 247.183944702148 206.08268737793 87.9416961669922 0 0 0 0 0 0 0 0 95.3595581054688 225.91584777832 248.077072143555 250.59260559082 257.277648925781 180.943740844727 0 0 0 0 0 0 0 0 155.655776977539 238.868362426758 250.283981323242 157.468978881836 0 0 0 0 0 0 0 0 165.849624633789 341.285217285156 449.087829589844 465.197448730469 414.669006347656 350.80908203125 287.216369628906 202.29280090332 102.295700073242 0 0 0 0 0 0 0 0 122.961654663086 216.524826049805 227.398483276367 197.743057250977 252.932815551758 368.044921875 412.497924804688 332.376770019531 189.94221496582 0 0 0 0 0 0 0 0 110.821487426758 205.431838989258 197.784744262695 165.351150512695 0 0 0 0 0 0 0 0 148.747482299805 197.384048461914 222.412368774414 130.84407043457 0 0 0 0 0 0 0 0 186.619369506836 231.119979858398 185.139663696289 0 0 0 0 0 0 0 0 129.717819213867 224.055252075195 180.142196655273 0 0 0 0 0 0 0 0 176.265243530273 223.66975402832 295.446105957031 361.572326660156 360.102111816406 244.047714233398 41.8561553955078 0 0 0 0 0 0 0 0 160.23698425293 238.57145690918 249.646987915039 191.794631958008 0 0 0 0 0 0 0 0 177.559341430664 308.058898925781 " "348.306823730469 288.753173828125 157.469802856445 0 0 50.9171905517578 233.195449829102 366.537780761719 333.827880859375 112.628784179688 0 0 0 0 0 0 0 0 146.29948425293 221.006973266602 185.588424682617 0 0 0 0 0 0 0 0 169.829788208008 298.886840820313 375.022705078125 349.165283203125 326.073608398438 321.16162109375 301.307739257813 280.400939941406 268.34130859375 250.299697875977 206.922592163086 161.804183959961 0 0 0 0 0 0 0 0 106.515991210938 216.509872436523 174.441055297852 0 47.4068908691406 197.185470581055 263.215942382813 352.870300292969 434.091491699219 407.799926757813 297.367797851563 209.839736938477 246.22785949707 378.100463867188 491.783874511719 505.840270996094 403.557006835938 229.298934936523 54.6394348144531 0 0 0 0 0 0 0 0 50.5400085449219 198.851058959961 280.1474609375 285.830627441406 210.564895629883 50.8290405273438 0 0 0 0 0 170.184860229492 335.466613769531 475.362731933594 547.797119140625 496.642517089844 292.609191894531 4.42018127441406 0 0 0 0 0 0 0 0 386.298461914063 549.150512695313 612.910278320313 599.075317382813 479.97314453125 260.072143554688 0 0 0 0 0 0 0 0 157.101547241211 216.543563842773 210.621841430664 151.346878051758 0 0 0 0 0 0 0 0 163.830764770508 225.50910949707 155.86100769043 0 0 0 0 0 0 0 0"; vector parseDoubleArray(const string& doubleArray) { vector doubleVector; vector tokens; bal::split(tokens, doubleArray, bal::is_space(), bal::token_compress_on); if (!tokens.empty() && !tokens[0].empty()) for (size_t i=0; i < tokens.size(); ++i) doubleVector.push_back(lexical_cast(tokens[i])); return doubleVector; } void test() { vector xRaw = parseDoubleArray(fullSpectrumRawX); vector yRaw = parseDoubleArray(fullSpectrumRawY); // sanity check unit_assert(xRaw.size() == yRaw.size()); try { vector xProcessed, yProcessed; ExtraZeroSamplesFilter::remove_zeros(xRaw, yRaw, xProcessed, yProcessed,true); unit_assert(xProcessed.size() == yProcessed.size()); unit_assert(yProcessed[0]==0); unit_assert(yProcessed[1]!=0); unit_assert(yProcessed[yProcessed.size()-1]==0); unit_assert(yProcessed[yProcessed.size()-2]!=0); unit_assert(xProcessed[1] == xRaw[9]); // now verify that an already processed set doesn't change vector xRaw2(xProcessed), yRaw2(yProcessed); ExtraZeroSamplesFilter::remove_zeros(xRaw2, yRaw2, xProcessed, yProcessed,true); unit_assert(xProcessed == xRaw2); unit_assert(yProcessed == yRaw2); // now verify removal of all zeros ExtraZeroSamplesFilter::remove_zeros(xRaw, yRaw, xProcessed, yProcessed,false); unit_assert(xProcessed.size() == yProcessed.size()); unit_assert(yProcessed[0]!=0); unit_assert(yProcessed[1]!=0); unit_assert(yProcessed[yProcessed.size()-1]!=0); unit_assert(yProcessed[yProcessed.size()-2]!=0); unit_assert(xProcessed[0] == xRaw[9]); } catch (exception& e) { throw runtime_error(std::string("ExtraZeroSamplesFilter test case failed: ") + e.what()); } } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/common/ZeroSampleFiller.hpp0000664000175100017510000000323412664775613023612 0ustar teamcityteamcity00000000000000// // $Id: ZeroSampleFiller.hpp 3116 2011-11-11 23:02:31Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _ZEROSAMPLEFILLER_HPP_ #define _ZEROSAMPLEFILLER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include #include #include namespace pwiz { namespace analysis { /// fills in missing zero samples around signal profiles struct PWIZ_API_DECL ZeroSampleFiller { /// fills in missing zero samples (and won't overwrite existing samples); /// zeroSampleCount controls how many zero samples to add to each signal profile; /// preconditions: /// - sample rate can change, but it must change gradually /// - at least one zero sample on each side of every signal profile static void fill(const std::vector& x, const std::vector& y, std::vector& xFilled, std::vector& yFilled, std::size_t zeroSampleCount); }; } // namespace analysis } // namespace pwiz #endif // _ZEROSAMPLEFILLER_HPP_ pwiz/pwiz/analysis/common/ZeroSampleFillerTest.cpp0000664000175100017510000024223612664775613024454 0ustar teamcityteamcity00000000000000// // $Id: ZeroSampleFillerTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "ZeroSampleFiller.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Exception.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::analysis; ostream* os_ = 0; struct TestData { size_t zeroSampleCount; const char* xRaw; const char* yRaw; const char* xFilled; const char* yFilled; }; const TestData testData[] = { // test that raw data are preserved { 1, "20 21 22 23 24 25 26 27 28 29 30", "00 10 20 30 40 50 40 30 20 10 00", "20 21 22 23 24 25 26 27 28 29 30", "00 10 20 30 40 50 40 30 20 10 00" }, // test that array termini are filled and data with no missing samples are preserved { 5, "20 21 22 23 24 25 26 27 28 29 30", "00 10 20 30 40 50 40 30 20 10 00", "16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34", "00 00 00 00 00 10 20 30 40 50 40 30 20 10 00 00 00 00 00" }, // test that array termini and missing samples are filled { 2, "20 21 22 23 24 27 28 29 30", "00 10 20 10 00 00 10 10 00", "19 20 21 22 23 24 25 26 27 28 29 30 31", "00 00 10 20 10 00 00 00 00 10 10 00 00" }, // test that overlapping missing samples are filled only once { 2, "20 21 22 23 24 26 27 28 29", "00 10 20 10 00 00 10 10 00", "19 20 21 22 23 24 25 26 27 28 29 30", "00 00 10 20 10 00 00 00 10 10 00 00" }, // test that isolated raw zero samples don't cause trouble { 2, "20 21 22 23 24 25 26 27", "00 10 20 10 00 10 10 00", "19 20 21 22 23 24 25 26 27 28", "00 00 10 20 10 00 10 10 00 00" }, // test against profiles with different global sample rates { 2, "1.000001 1.000002 1.000003 1000.001 1000.002 1000.003", "0 1 0 0 1 0", "1.000000 1.000001 1.000002 1.000003 1.000004 1000.000 1000.001 1000.002 1000.003 1000.004", "0 0 1 0 0 0 0 1 0 0" }, // test against profiles with different local and global sample rates { 2, // inferred inferred inferred inferred // -.000001 +.000001 +.0000015 +.0000015 -.001 +.00001 +.000015 +.000015 "1.000001 1.000002 1.0000035 1000.00001 1000.00002 1000.000035", "0 1 0 0 1 0", "1.000000 1.000001 1.000002 1.0000035 1.0000050 1000.000 1000.00001 1000.00002 1000.000035 1000.000050", "0 0 1 0 0 0 0 1 0 0" } }; const size_t testDataSize = sizeof(testData) / sizeof(TestData); // test a full spectrum (at multiple zeroSampleCounts) const char* fullSpectrumRawX = "300.000066203793 300.000611626572 300.001157051333 300.001702478078 300.058437690186 300.058983325233 300.059528962264 300.06007460128 300.06062024228 300.061165885264 300.061711530233 300.062257177186 300.062802826123 300.063348477046 300.063894129952 300.064439784843 300.064985441719 300.065531100579 300.066076761424 301.055887660805 301.056436929468 301.056986200136 301.057535472809 301.058084747485 301.058634024166 301.059183302851 301.059732583541 301.060281866235 301.060831150933 301.061380437635 301.061929726342 301.062479017053 301.063028309769 301.063577604489 311.869088211176 311.869677645283 311.870267081618 311.870856520182 311.871445960974 311.872035403993 311.872624849241 311.873214296717 311.873803746421 311.874393198353 311.874982652514 311.875572108902 311.876161567519 311.876751028364 311.877340491437 311.877929956739 311.878519424268 311.879108894026 311.879698366013 311.880287840227 311.88087731667 311.881466795341 311.882056276241 315.73174362051 315.732347745926 315.732951873654 315.733556003694 315.734160136047 315.734764270711 315.735368407687 315.735972546974 315.736576688574 315.737180832486 315.73778497871 315.738389127246 316.901416544052 316.902025153901 316.902633766087 316.90324238061 316.903850997471 316.90445961667 316.905068238207 316.905676862081 316.906285488293 316.906894116843 316.907502747731 316.908111380957 316.90872001652 316.909328654421 326.293591849569 326.294237069432 326.294882291847 326.295527516814 326.296172744332 326.296817974402 326.297463207024 326.298108442198 326.298753679923 326.299398920201 326.30004416303 327.074882186811 327.075530500256 327.076178816272 327.076827134858 327.077475456014 327.07812377974 327.078772106036 327.079420434903 327.080068766339 327.080717100346 327.081365436923 327.082013776071 327.082662117789 327.083310462077 327.083958808935 341.007109159311 341.007813880848 341.008518605298 341.00922333266 341.009928062936 341.010632796124 341.011337532225 341.012042271238 341.012747013165 " "341.013451758004 341.014156505757 341.014861256422 341.01556601 341.016270766491 341.016975525895 341.017680288212 341.018385053442 341.019089821585 341.019794592642 341.020499366611 341.021204143493 341.021908923288 341.022613705997 341.023318491618 341.024023280153 341.024728071601 342.01359244987 342.014301337525 342.015010228119 342.015719121651 342.016428018122 342.017136917532 342.01784581988 342.018554725167 342.019263633392 342.019972544557 342.02068145866 342.021390375702 342.022099295682 342.022808218602 342.02351714446 342.873501341248 342.874213798035 342.874926257782 342.87563872049 342.876351186159 342.877063654789 342.87777612638 342.878488600932 342.879201078445 342.879913558918 342.880626042353 342.881338528749 344.97306118134 344.9737823902 344.974503602076 344.975224816967 344.975946034874 344.976667255797 344.977388479735 344.978109706689 344.978830936658 344.979552169644 344.980273405644 344.980994644661 344.981715886693 355.063935356091 355.064699374529 355.065463396255 355.066227421269 355.066991449572 355.067755481162 355.06851951604 355.069283554207 355.070047595661 355.070811640404 355.071575688435 355.072339739754 355.073103794361 355.073867852257 355.074631913441 355.075395977913 355.076160045673 355.076924116722 355.077688191059 355.078452268685 356.064553240471 356.065321571195 356.066089905234 356.06685824259 356.067626583261 356.068394927249 356.069163274552 356.069931625172 356.070699979107 356.071468336359 356.072236696926 356.07300506081 356.073773428009 356.074541798525 356.075310172357 356.076078549505 356.076846929969 356.07761531375 356.078383700846 356.079152091259 356.079920484988 356.080688882034 357.062327559534 357.063100202372 357.063872848555 357.064645498081 357.065418150951 357.066190807165 357.066963466723 357.067736129625 357.068508795871 357.069281465461 357.070054138395 357.070826814673 357.071599494295 357.072372177261 357.073144863571 357.073917553225 357.074690246224 357.075462942566 357.076235642253 " "357.077008345284 357.077781051659 357.078553761379 357.079326474442 357.08009919085 359.023183355092 359.023964507385 359.024745663078 359.02552682217 359.026307984661 359.027089150551 359.027870319841 359.028651492531 359.029432668619 359.030213848107 359.030995030994 359.031776217281 359.032557406967 359.033338600053 359.034119796538 359.034900996422 359.035682199706 360.023491974674 360.024277485921 360.025063000597 360.0258485187 360.02663404023 360.027419565189 360.028205093575 360.028990625389 360.029776160632 360.030561699301 360.031347241399 360.032132786925 360.032918335879 360.03370388826 360.03448944407 361.021491400285 361.02228127251 361.023071148191 361.023861027329 361.024650909923 361.025440795974 361.026230685481 361.027020578444 361.027810474864 361.02860037474 361.029390278072 361.030180184861 361.030970095107 361.031760008809 371.095690561049 371.096525130684 371.097359704072 371.098194281215 371.099028862111 371.099863446762 371.100698035166 371.101532627324 371.102367223236 371.103201822902 371.104036426322 371.104871033497 371.105705644425 371.106540259107 371.107374877543 371.108209499734 371.109044125678 371.109878755377 371.11071338883 372.078066820464 372.078905814551 372.079744812421 372.080583814075 372.081422819513 372.082261828735 372.083100841741 372.08393985853 372.084778879103 372.08561790346 372.086456931601 372.087295963526 372.095686490895 372.096525564444 372.097364641778 372.098203722896 372.099042807799 372.099881896485 372.100720988956 372.101560085211 372.102399185251 372.103238289075 372.104077396683 372.104916508076 372.105755623254 372.106594742216 372.107433864962 372.108272991493 373.076623237254 373.077466740653 373.078310247866 373.079153758894 373.079997273735 373.080840792391 373.081684314862 373.082527841147 373.083371371246 373.084214905159 373.085058442887 373.08590198443 373.086745529787 373.101086384495 373.101929998517 373.102773616354 373.103617238007 373.104460863474 373.105304492756 373.106148125853 " "373.106991762765 373.107835403493 373.108679048035 373.109522696393 373.110366348566 373.111210004555 415.030543316388 415.031587197383 415.032631083628 415.033674975125 415.034718871873 415.035762773872 415.036806681123 415.037850593625 415.038894511378 415.039938434383 415.040982362639 415.042026296147 415.043070234906 415.044114178917 415.045158128179 415.046202082693 415.047246042459 416.004675140758 416.005723927765 416.006772720059 416.007821517642 416.008870320513 416.009919128672 416.01096794212 416.012016760856 416.01306558488 416.014114414193 416.015163248794 416.016212088684 416.030896402465 416.031945321688 416.032994246201 416.034043176002 416.035092111093 416.036141051473 416.037189997143 416.038238948102 416.03928790435 416.040336865888 416.041385832715 416.042434804832 416.043483782239 416.044532764935 416.04558175292 416.046630746196 416.047679744761 417.027651705639 417.028705657034 417.029759613757 417.030813575807 417.031867543184 417.032921515889 417.033975493922 417.035029477282 417.036083465969 417.037137459984 417.038191459327 417.039245463997 417.040299473995 417.041353489321 426.357976566382 426.359078206359 426.360179852029 426.361281503392 426.362383160449 426.363484823198 426.36458649164 426.365688165776 426.366789845604 426.367891531126 426.368993222341 428.935877697296 428.936992699323 428.938107707146 428.939222720767 428.940337740184 428.941452765398 428.94256779641 428.943682833218 428.944797875823 428.945912924226 428.947027978426 429.083108101101 429.0842238687 429.085339642101 429.086455421305 429.087571206312 429.088686997122 429.089802793735 429.090918596151 429.09203440437 429.093150218392 429.094266038217 429.095381863845 429.096497695277 429.097613532512 429.09872937555 429.099845224392 429.100961079037 429.102076939486 429.134439417209 429.135555451783 429.136671492162 429.137787538345 429.138903590334 429.140019648128 429.141135711726 429.14225178113 429.143367856339 429.144483937353 429.145600024173 429.146716116797 " "429.85101025753 429.852130022341 429.853249792985 429.854369569464 429.855489351777 429.856609139924 429.857728933905 429.858848733721 429.859968539371 429.861088350855 429.862208168173 429.863327991326 429.864447820313 429.865567655135 429.866687495792 429.867807342283 429.868927194608 429.870047052768 429.871166916764 429.872286786593 429.873406662258 429.874526543758 429.875646431092 429.876766324261 429.877886223266 430.081805059062 430.082926026641 430.084047000064 430.08516797933 430.086288964439 430.087409955392 430.088530952189 430.089651954829 430.090772963313 430.091893977641 430.093014997813 430.094136023828 430.095257055687 430.09637809339 430.097499136937 430.098620186328 430.099741241563 430.100862302643 430.101983369566 431.078404724764 431.079530893455 431.08065706803 431.081783248489 431.082909434832 431.08403562706 431.085161825172 431.086288029168 431.087414239049 431.088540454814 431.089666676463 431.090792903997 431.091919137416 431.093045376719 431.094171621907 431.09529787298 431.096424129938 431.09755039278 431.098676661507 431.099802936119 432.079633824813 432.080765230898 432.081896642908 432.083028060844 432.084159484704 432.085290914491 432.086422350202 432.087553791839 432.088685239402 432.08981669289 432.090948152304 432.092079617643 432.093211088908 444.61606065115 444.617258663358 444.618456682022 444.619654707142 444.620852738719 444.622050776751 444.62324882124 444.624446872186 444.625644929587 444.626842993445 444.62804106376 444.629239140531 444.630437223759 445.111389571898 445.112590254911 445.113790944402 445.114991640371 445.116192342817 445.117393051741 445.118593767143 445.119794489023 445.120995217382 445.122195952218 445.123396693532 445.124597441324 445.125798195595 445.126998956343 445.128199723571 445.129400497276 445.13060127746 446.092099627601 446.093305607359 446.094511593638 446.095717586437 446.096923585757 446.098129591598 446.099335603959 446.100541622841 446.101747648245 446.102953680169 446.104159718614 " "446.10536576358 446.106571815068 446.107777873076 446.108983937606 446.110190008657 446.111396086229 446.112602170323 446.113808260938 446.115014358075 446.116220461733 446.117426571913 446.118632688614 446.119838811837 446.121044941582 446.122251077849 446.123457220638 446.124663369948 446.12586952578 446.127075688135 446.128281857011 446.12948803241 446.130694214331 446.131900402774 446.133106597739 447.092888369096 447.09409976606 447.095311169589 447.096522579682 447.09773399634 447.098945419563 447.100156849351 447.101368285703 447.10257972862 447.103791178103 447.10500263415 447.106214096762 447.10742556594 447.108637041682 447.10984852399 447.111060012863 447.112271508302 447.113483010306 447.114694518875 447.115906034009 447.11711755571 447.118329083975 447.119540618807 447.120752160204 447.121963708167 447.123175262696 447.12438682379 447.125598391451 447.126809965677 447.128021546469 447.129233133828 447.130444727752 447.131656328243 449.794778250235 449.796004332987 449.797230422424 449.798456518544 449.799682621349 449.800908730839 449.802134847013 449.803360969872 449.804587099415 449.805813235643 449.807039378556 449.808265528153 476.291926493584 476.293301287096 476.294676088545 476.296050897931 476.297425715253 476.298800540512 476.300175373707 476.30155021484 476.30292506391 476.304299920917 476.305674785861 476.307049658742 487.815419569054 487.81686169142 487.818303822312 487.819745961732 487.821188109678 487.822630266151 487.824072431152 487.825514604679 487.826956786733 487.828398977315 487.829841176424 489.047206755368 489.048656169973 489.050105593169 489.051555024957 489.053004465336 489.054453914307 489.05590337187 489.057352838025 489.058802312771 489.06025179611 489.06170128804 489.063150788563 489.064600297678 489.066049815385 489.067499341685 494.497639238354 494.499121140501 494.500603051529 494.50208497144 494.503566900233 494.505048837908 494.506530784465 494.508012739904 494.509494704226 494.510976677431 494.512458659517 " "503.097384350016 503.098918243574 503.100452146485 503.10198605875 503.103519980368 503.10505391134 503.106587851665 503.108121801345 503.109655760378 503.111189728765 503.112723706507 503.114257693603 503.115791690052 503.117325695857 503.118859711015 503.120393735528 503.121927769396 503.123461812619 503.124995865196 504.057895208494 504.059434964655 504.060974730222 504.062514505197 504.064054289579 504.065594083369 504.067133886566 504.06867369917 504.070213521182 504.071753352602 504.073293193429 504.097931926196 504.099471926969 504.101011937151 504.102551956742 504.104091985743 504.105632024154 504.107172071974 504.108712129204 504.110252195844 504.111792271893 504.113332357353 504.114872452223 504.116412556503 504.117952670193 504.119492793294 504.121032925805 504.122573067726 504.124113219059 504.136434768509 504.137975004541 504.139515249984 504.141055504838 504.142595769105 504.144136042783 504.145676325873 504.147216618374 504.148756920288 504.150297231614 504.151837552352 504.153377882502 505.094736580555 505.096282677762 505.097828784435 505.099374900573 505.100921026176 505.102467161245 505.104013305779 505.105559459779 505.107105623245 505.108651796177 505.110197978574 505.111744170438 505.113290371768 505.114836582564 505.116382802826 505.117929032555 505.11947527175 505.121021520412 505.12256777854 506.095491214212 506.097043444127 506.098595683563 506.100147932522 506.101700191001 506.103252459003 506.104804736527 506.106357023573 506.107909320141 506.109461626231 506.111013941844 506.112566266978 506.114118601636 517.627784100423 517.62940787711 517.631031663984 517.632655461045 517.634279268294 517.635903085731 517.637526913356 517.639150751169 517.64077459917 517.642398457359 517.644022325736 519.117811946194 519.11944508466 519.121078233402 519.122711392419 519.124344561713 519.125977741282 519.127610931128 519.129244131249 519.130877341647 519.132510562322 519.134143793272 519.1357770345 519.137410286004 519.139043547785 519.140676819843 " "519.142310102177 519.143943394789 519.145576697678 519.147210010844 519.148843334287 519.150476668008 519.152110012007 519.153743366283 520.107741759837 520.109381132867 520.111020516231 520.11265990993 520.114299313963 520.115938728332 520.117578153035 520.119217588074 520.120857033448 520.122496489157 520.124135955201 520.125775431581 520.130693922735 520.132333440458 520.133972968517 520.135612506911 520.137252055643 520.13889161471 520.140531184113 520.142170763854 520.14381035393 520.145449954343 520.147089565093 520.14872918618 520.150368817604 520.152008459365 520.153648111463 520.155287773898 521.127785814089 521.129431623767 521.131077443839 521.132723274308 521.134369115172 521.136014966432 521.137660828088 521.13930670014 521.140952582588 521.142598475432 521.144244378673 521.14589029231 521.147536216343 531.114696350534 531.11640584546 531.118115351391 531.119824868327 531.121534396267 531.123243935212 531.124953485163 531.126663046119 531.12837261808 531.130082201046 531.131791795019 531.179664894929 531.181374808109 531.183084732298 531.184794667495 531.186504613701 531.188214570917 531.189924539141 531.191634518375 531.193344508618 531.195054509871 531.196764522133 531.198474545405 539.793121824335 539.79488764215 539.796653471517 539.798419312438 539.800185164913 539.80195102894 539.803716904521 539.805482791656 539.807248690344 539.809014600586 539.810780522383 544.657227988968 544.659025773986 544.660823570872 544.662621379626 544.664419200249 544.66621703274 544.6680148771 544.669812733329 544.671610601426 544.673408481392 544.675206373228 544.677004276933 544.678802192507 544.68060011995 544.682398059264 544.684196010447 544.685993973499 544.687791948422 544.689589935214 544.691387933877 564.063114662872 564.065042838848 564.066971028006 564.068899230347 564.07082744587 564.072755674577 564.074683916467 564.076612171539 564.078540439795 564.080468721235 564.082397015858 564.084325323664 564.086253644655 577.113045862246 577.115064289413 " "577.1170827307 577.119101186105 577.12111965563 577.123138139273 577.125156637036 577.127175148919 577.129193674921 577.131212215043 577.133230769285 577.135249337647 577.137267920129 577.139286516732 577.141305127455 577.143323752299 578.095668254573 578.09769356096 578.099718881538 578.101744216308 578.103769565269 578.105794928421 578.107820305765 578.1098456973 578.111871103028 578.113896522947 578.115921957059 578.117947405363 578.119972867859 578.121998344549 578.124023835431 578.126049340506 578.128074859774 578.130100393235 578.13212594089 578.134151502738 578.13617707878 578.138202669016 578.140228273445 578.142253892069 578.144279524888 578.1463051719 579.112127291178 579.114159725986 579.116192175059 579.118224638399 579.120257116005 579.122289607877 579.124322114016 579.126354634422 579.128387169095 579.130419718034 579.132452281241 579.134484858716 579.136517450457 579.138550056467 579.140582676744 579.142615311289 593.146836106552 593.148968246848 593.151100402472 593.153232573424 593.155364759706 593.157496961317 593.159629178256 593.161761410526 593.163893658125 593.166025921053 593.168158199311 593.1702904929 593.172422801818 593.174555126067 594.334675871054 594.336816559592 594.338957263551 594.341097982931 594.343238717732 594.345379467954 594.347520233598 594.349661014664 594.351801811151 594.35394262306 594.356083450392 594.358224293146 602.991717202929 602.993920708033 602.996124229242 602.998327766555 603.000531319973 603.002734889497 603.004938475125 603.007142076859 603.009345694699 603.011549328644 603.013752978696 603.015956644853 603.018160327117 603.020364025487 603.022567739964 603.024771470548 603.026975217238 647.653798614949 647.656340625328 647.65888265566 647.661424705948 647.66396677619 647.666508866388 647.669050976542 647.671593106651 647.674135256716 647.676677426738 647.679219616716 647.681761826651 647.684304056543 647.686846306392 647.689388576198 647.691930865962 647.694473175684 647.697015505364 647.699557855003 " "651.129472007141 651.132041374488 651.134610762114 651.137180170017 651.139749598198 651.142319046658 651.144888515396 651.147458004413 651.150027513709 651.152597043284 651.155166593139 651.157736163274 651.160305753689 651.162875364383 651.165444995359 651.168014646615 652.130488515969 652.133065789459 652.135643083321 652.138220397554 652.140797732159 652.143375087136 652.145952462485 652.148529858207 652.151107274301 652.153684710768 652.156262167609 652.158839644823 652.16141714241 652.163994660372 652.166572198708 652.169149757418 652.594726156514 652.597307100729 652.599888065358 652.602469050403 652.605050055862 652.607631081738 652.610212128029 652.612793194736 652.615374281859 652.617955389399 652.620536517356 653.126832071549 653.129417226335 653.132002401586 653.134587597302 653.137172813482 653.139758050129 653.142343307241 653.14492858482 653.147513882864 653.150099201375 653.152684540353 653.155269899798 653.157855279709 653.160440680089 653.163026100936 660.922514101737 660.925161337446 660.927808594361 660.930455872483 660.933103171812 660.935750492348 660.938397834091 660.941045197042 660.943692581201 660.946339986568 660.948987413144 660.951634860928 660.954282329921 660.983405888706 660.986053612226 660.988701356959 660.991349122903 660.993996910061 660.996644718431 660.999292548015 661.001940398812 661.004588270823 661.007236164048 661.009884078488 661.012532014142 664.411346114577 664.414021372197 664.41669665136 664.419371952069 664.422047274321 664.424722618119 664.427397983461 664.430073370349 664.432748778782 664.435424208761 664.438099660286 664.440775133357 664.443450627975 664.44612614414 664.448801681852 664.451477241112 664.454152821919 664.456828424273 664.459504048176 664.462179693628 664.464855360628 667.159443330433 667.162140764336 667.164838220052 667.16753569758 667.170233196922 667.172930718076 667.175628261044 667.178325825826 667.181023412421 667.183721020831 667.186418651055 667.189116303095 667.191813976949 " "667.194511672619 667.197209390104 667.199907129405 668.145457833561 668.148163246605 668.150868681559 668.153574138422 668.156279617196 668.158985117879 668.161690640472 668.164396184977 668.167101751392 668.169807339718 668.172512949956 668.175218582105 668.177924236166 668.180629912139 668.183335610025 668.186041329824 668.188747071536 668.19145283516 668.194158620699 668.196864428151 668.199570257517 670.158915513485 670.161637256666 670.164359021956 670.167080809353 670.16980261886 670.172524450475 670.175246304198 670.177968180032 670.180690077974 670.183411998027 670.186133940189 670.188855904462 670.191577890846 677.272020770102 677.274800597507 677.277580447732 677.280360320776 677.283140216641 677.285920135325 677.28870007683 677.291480041156 677.294260028303 677.297040038272 677.299820071062 677.302600126674 677.305380205108 677.308160306364 677.310940430444 677.313720577346 677.316500747072 677.319280939622 677.322061154995 677.324841393193 677.327621654214 677.330401938061 677.333182244733 677.33596257423 684.185792158615 684.188629030244 684.191465925398 684.194302844078 684.197139786283 684.199976752015 684.202813741274 684.205650754059 684.208487790372 684.211324850212 684.21416193358 684.216999040475 684.2198361709 684.222673324852 684.225510502334 685.302497766186 685.305343905889 685.308190069232 685.311036256217 685.313882466843 685.316728701111 685.319574959021 685.322421240572 685.325267545767 685.328113874604 685.330960227085 685.333806603209 685.336653002977 685.339499426388 685.345192344145 685.34803883849 685.350885356481 685.353731898117 685.356578463399 685.359425052328 685.362271664902 685.365118301123 685.367964960991 685.370811644507 685.37365835167 685.376505082481 686.165961086862 686.168814403222 686.171667743312 686.174521107133 686.177374494685 686.180227905968 686.183081340982 686.185934799728 686.188788282207 686.191641788417 686.19449531836 686.197348872036 699.464091765658 699.467056750447 699.470021760373 699.472986795436 " "699.475951855637 699.478916940975 699.481882051452 699.484847187067 699.487812347821 699.490777533714 699.493742744746 699.496707980919 699.499673242231 699.502638528684 699.505603840277 699.508569177012 699.511534538887 699.514499925905 707.540962759248 707.54399661424 707.54703049525 707.550064402278 707.553098335324 707.556132294389 707.559166279473 707.562200290576 707.565234327699 707.568268390842 707.571302480006 707.574336595191 707.577370736396 707.580404903623 707.583439096872 707.586473316143 707.589507561437 707.592541832753 707.595576130092 712.253358999635 712.256433401729 712.259507830364 712.26258228554 712.265656767258 712.268731275519 712.271805810321 712.274880371667 712.277954959555 712.281029573987 712.284104214963 714.637817537752 714.640912559113 714.644007607282 714.647102682261 714.650197784048 714.653292912646 714.656388068053 714.65948325027 714.662578459298 714.665673695137 714.668768957787 714.671864247249 725.142802571441 725.145989253758 725.149175964084 725.152362702418 725.155549468761 725.158736263113 725.161923085476 725.165109935848 725.168296814231 725.171483720624 725.174670655029 725.177857617445 725.181044607873 725.184231626314 725.187418672767 725.190605747233 725.193792849713 725.196979980206 726.144799061961 726.147994557046 726.151190080255 726.15438563159 726.15758121105 726.160776818635 726.163972454346 726.167168118184 726.170363810149 726.17355953024 726.176755278459 726.179951054806 726.183146859281 726.186342691885 726.189538552617 727.133547186777 727.136751390037 727.139955621536 727.143159881275 727.146364169255 727.149568485475 727.152772829936 727.155977202638 727.159181603583 727.162386032769 727.165590490198 727.16879497587 727.171999489785 727.175204031944 727.178408602347 727.181613200995 727.184817827887 727.188022483024 728.144269729676 728.147482846893 728.150695992466 728.153909166398 728.157122368687 728.160335599336 728.163548858343 728.16676214571 728.169975461436 728.173188805523 728.17640217797 " "728.179615578778 728.182829007947 728.623337067404 728.626554414027 728.629771789064 728.632989192515 728.63620662438 728.639424084659 728.642641573354 728.645859090464 728.64907663599 728.652294209931 728.65551181229 728.658729443065 739.579801260267 739.583116094462 739.586430958371 739.589745851995 739.593060775335 739.596375728391 739.599690711162 739.603005723651 739.606320765856 739.609635837779 739.61295093942 741.174345003278 741.177674146565 741.18100331976 741.184332522862 741.187661755872 741.190991018791 741.194320311618 741.197649634355 741.200978987002 741.204308369558 741.207637782025 741.210967224403 741.214296696693 741.217626198894 741.220955731007 741.224285293032 742.067626706004 742.070963878878 742.074301081766 742.077638314671 742.080975577592 742.08431287053 742.087650193485 742.090987546457 742.094324929448 742.097662342457 742.100999785484 742.104337258531 742.107674761597 742.111012294683 742.11434985779 742.117687450917 742.121025074066 742.124362727236 742.127700410428 742.131038123643 742.13437586688 742.137713640141 742.141051443425 742.174431127655 742.177769261226 742.181107424826 742.184445618454 742.187783842111 742.191122095798 742.194460379515 742.197798693263 742.201137037042 742.204475410852 742.207813814694 742.211152248568 742.214490712474 742.217829206413 742.221167730386 742.224506284392 742.227844868433 743.1470966977 743.150443586686 743.153790505819 743.157137455098 743.160484434525 743.1638314441 743.167178483823 743.170525553695 743.173872653716 743.177219783887 743.180566944208 743.183914134679 743.187261355301 743.190608606074 743.193955886998 743.197303198075 743.200650539304 743.203997910686 743.20734531222 743.210692743909 743.214040205752 743.217387697749 743.220735219901 743.224082772208 743.227430354671 743.23077796729 744.176009584717 744.179365747906 744.182721941368 744.186078165103 744.18943441911 744.192790703391 744.196147017945 744.199503362773 744.202859737876 744.206216143254 744.209572578908 " "744.212929044837 744.216285541042 744.219642067524 744.222998624283 758.202410978174 758.205894849435 758.209378752713 758.212862688007 758.216346655318 758.219830654647 758.223314685994 758.226798749359 758.230282844744 758.233766972148 758.237251131571 758.240735323015 758.24421954648 758.247703801965 758.251188089473 758.254672409002 759.203597733713 759.207090811794 759.210583922019 759.214077064387 759.2175702389 759.221063445557 759.22455668436 759.228049955308 759.231543258401 759.235036593642 759.238529961029 759.242023360563 759.245516792245 759.249010256075 760.200427521877 760.203929778783 760.207432067959 760.210934389405 760.214436743123 760.217939129111 760.221441547372 760.224943997905 760.228446480711 760.231948995789 760.235451543142 760.238954122768 760.24245673467 760.316019040799 760.319522362853 760.323025717192 760.326529103815 760.330032522725 760.33353597392 760.337039457402 760.340542973171 760.344046521228 760.347550101572 760.351053714205 760.354557359126 760.358061036338 760.361564745838 777.189954415057 777.193614963706 777.197275546837 777.200936164451 777.204596816548 777.208257503129 777.211918224194 777.215578979744 777.219239769779 777.2229005943 777.226561453308 777.230222346802 777.233883274784 777.237544237253 799.160490663856 799.164361099883 799.1682315734 799.172102084408 799.175972632907 799.179843218898 799.183713842382 799.187584503358 799.191455201828 799.195325937792 799.19919671125 799.203067522204 799.206938370653 799.210809256599 799.214680180041 799.21855114098 800.16418774129 800.168067905512 800.171948107365 800.175828346849 800.179708623967 800.183588938718 800.187469291103 800.191349681123 800.195230108777 800.199110574067 800.202991076993 800.206871617555 800.210752195754 801.158739593593 801.162629409414 801.166519263006 801.170409154372 801.174299083511 801.178189050424 801.182079055111 801.185969097572 801.18985917781 801.193749295823 801.197639451613 801.20152964518 801.205419876525 801.209310145647 " "801.213200452549 810.055165196855 810.059141881054 810.063118604297 810.067095366586 810.07107216792 810.0750490083 810.079025887728 810.083002806202 810.086979763725 810.090956760296 810.094933795916 810.098910870585 810.102887984305 810.106865137076 815.189564537267 815.19359179245 815.197619087424 815.20164642219 815.205673796749 815.209701211101 815.213728665248 815.217756159189 815.221783692925 815.225811266457 815.229838879786 815.233866532911 815.237894225833 815.241921958555 815.245949731074 815.249977543393 815.395005298192 815.3990345835 815.40306390863 815.407093273582 815.411122678358 815.415152122956 815.419181607379 815.423211131626 815.427240695699 815.431270299597 815.435299943322 815.439329626874 816.169358934812 816.17339587673 816.177432858584 816.181469880374 816.1855069421 816.189544043764 816.193581185365 816.197618366904 816.201655588382 816.2056928498 816.209730151157 816.213767492455 816.217804873695 816.221842294876 816.225879756 816.229917257066 816.233954798077 816.237992379031 816.24202999993 816.246067660775 816.250105361565 816.254143102302 817.183885871236 817.187932855536 817.19197987992 817.196026944389 817.200074048944 817.204121193585 817.208168378313 817.212215603128 817.216262868032 817.220310173024 817.224357518104 817.228404903275 817.232452328536 817.236499793888 817.240547299332 817.244594844868 817.248642430496 817.252690056218 818.164426363991 818.16848306611 818.172539808458 818.176596591035 818.180653413842 818.18471027688 818.18876718015 818.192824123651 818.196881107384 818.200938131351 818.204995195551 818.209052299986 818.213109444656 818.21716662956 818.221223854701 818.225281120079 818.229338425694 818.233395771546 818.237453157638 818.241510583968 818.245568050537 818.249625557347 819.18392233678 819.18798915515 819.1920560139 819.19612291303 819.200189852541 819.204256832432 819.208323852706 819.212390913362 819.216458014401 819.220525155824 819.224592337631 819.228659559823 819.2327268224 819.236794125363 " "819.240861468713 819.24492885245 820.193731546341 820.197808397262 820.201885288712 820.205962220691 820.210039193201 820.214116206241 820.218193259813 820.222270353916 820.226347488553 820.230424663722 820.234501879425 820.238579135663 832.21883436359 832.223031634984 832.227228948716 832.231426304787 832.235623703196 832.239821143946 832.244018627035 832.248216152466 832.252413720239 832.256611330353 832.260808982811 832.265006677613 832.269204414758 832.273402194249 832.277600016085 832.281797880267 832.285995786796 832.290193735673 832.294391726897 832.298589760471 833.218980432568 833.223187798465 833.227395206852 833.231602657731 833.235810151102 833.240017686965 833.244225265321 833.248432886172 833.252640549516 833.256848255356 833.261056003692 833.265263794525 833.269471627854 833.273679503681 834.221533310184 834.225750807043 834.229968346546 834.234185928695 834.238403553488 834.242621220928 834.246838931015 834.251056683749 834.255274479132 834.259492317163 834.263710197844 834.267928121174 835.218046494203 835.222274073065 835.226501694725 835.230729359182 835.234957066438 835.239184816494 835.243412609349 835.247640445004 835.251868323461 835.256096244719 835.26032420878 835.264552215644 835.268780265312 835.273008357784 835.277236493061 873.174235302306 873.178855854748 873.18347645609 873.188097106335 873.192717805482 873.197338553533 873.201959350488 873.206580196348 873.211201091114 873.215822034786 873.220443027366 873.225064068854 873.229685159251 873.234306298558 873.238927486775 874.17804253512 874.182673717335 874.18730494862 874.191936228976 874.196567558404 874.201198936904 874.205830364477 874.210461841124 874.215093366845 874.219724941642 874.224356565516 874.228988238466 874.233619960494 874.238251731601 874.303101680785 874.307734188164 874.312366744634 874.316999350196 874.321632004851 874.3262647086 874.330897461442 874.335530263379 874.340163114412 874.344796014542 874.349428963769 874.354061962094 875.174876842222 875.179518592457 " "875.184160391931 875.188802240643 875.193444138596 875.198086085788 875.202728082222 875.207370127898 875.212012222817 875.216654366978 875.221296560385 875.225938803036 875.230581094934 889.200602342844 889.205394064883 889.210185838565 889.214977663891 889.219769540862 889.224561469479 889.229353449744 889.234145481656 889.238937565216 889.243729700426 889.248521887286 889.253314125797 889.25810641596 889.262898757776 889.267691151245 889.272483596368 889.277276093147 889.282068641582 889.286861241673 889.291653893423 889.296446596831 889.301239351898 889.306032158626 889.310825017014 889.315617927065 889.320410888778 889.325203902155 889.329996967196 889.334790083902 890.02073813417 890.0255386994 890.030339316416 890.03513998522 890.039940705812 890.044741478193 890.049542302364 890.054343178326 890.059144106079 890.063945085625 890.068746116964 890.073547200097 890.078348335025 890.083149521749 890.174381911812 890.179184134627 890.183986409256 890.188788735699 890.193591113957 890.198393544031 890.203196025921 890.207998559629 890.212801145155 890.217603782501 890.222406471667 890.227209212653 890.232012005462 890.236814850093 890.241617746547 890.246420694826 890.25122369493 890.25602674686 890.260829850616 890.2656330062 890.270436213613 890.275239472855 890.280042783927 891.198426546905 891.203239824931 891.208053154948 891.212866536959 891.217679970964 891.222493456964 891.22730699496 891.232120584952 891.236934226942 891.24174792093 891.246561666917 891.251375464905 891.256189314893 891.261003216882 891.265817170875 891.27063117687 891.27544523487 891.280259344875 892.200708915166 892.205533025772 892.210357188546 892.21518140349 892.220005670603 892.224829989886 892.229654361341 892.234478784968 892.239303260768 892.244127788742 892.248952368891 892.253777001215 892.258601685716 892.263426422395 892.268251211251 892.273076052286 893.142398272161 893.147232571559 893.15206692329 893.156901327355 893.161735783755 893.166570292491 893.171404853563 " "893.176239466974 893.181074132723 893.185908850811 893.190743621239 893.20041331912 893.205248246574 893.210083226371 893.214918258513 893.219753343 893.224588479834 893.229423669014 893.234258910542 893.239094204419 893.243929550645 893.248764949222 893.25360040015 893.25843590343 893.263271459063 893.26810706705 893.272942727391 894.197514830975 894.202360559179 894.207206339903 894.212052173146 894.21689805891 894.221743997196 894.226589988005 894.231436031336 894.236282127192 894.241128275573 894.24597447648 894.250820729913 894.255667035874 894.260513394364 894.265359805383 894.270206268932 906.234202718878 906.239179781027 906.244156897845 906.249134069332 906.25411129549 906.259088576319 906.26406591182 906.269043301994 906.274020746843 906.278998246366 906.283975800565 906.288953409441 906.293931072995 906.298908791226 907.235692252254 907.240680320926 907.245668444448 907.250656622821 907.255644856045 907.260633144123 907.265621487054 907.270609884839 907.27559833748 907.280586844978 907.285575407332 907.290564024546 907.295552696618 907.30054142355 908.234398692328 908.239397749042 908.244396860787 908.249396027565 908.254395249375 908.25939452622 908.2643938581 908.269393245016 908.274392686968 908.279392183959 908.284391735988 908.289391343056 922.842856257044 922.84801742175 922.853178644185 922.858339924351 922.86350126225 922.86866265788 922.873824111245 922.878985622344 922.884147191179 922.88930881775 922.894470502059 934.042623867136 934.0479110658 934.053198324322 934.058485642702 934.063773020941 934.069060459041 934.074347957002 934.079635514825 934.084923132512 934.090210810063 934.09549854748 934.100786344763 934.106074201913 934.111362118932 962.94815872668 962.953778232548 962.959397804004 962.96501744105 962.970637143686 962.976256911914 962.981876745735 962.987496645149 962.993116610159 962.998736640765 963.004356736968 963.00997689877 963.217969011729 963.223591667127 963.229214388169 963.234837174856 963.240460027188 963.246082945167 " "963.251705928794 963.257328978069 963.262952092996 963.268575273574 963.274198519804 963.279821831688 963.285445209227 963.291068652422 963.296692161274 963.302315735784 963.307939375954 963.313563081784 963.319186853277 963.324810690432 963.420425969611 963.426050988895 963.431676073865 963.43730122452 963.442926440862 963.448551722892 963.454177070612 963.459802484022 963.465427963124 963.471053507919 963.476679118408 963.482304794592 964.21420252401 964.219836816216 964.225471174269 964.23110559817 964.236740087921 964.242374643523 964.248009264976 964.253643952283 964.259278705443 964.26491352446 964.270548409332 964.276183360063 964.281818376652 964.287453459101 964.293088607411 964.298723821583 964.304359101619 964.309994447519 964.315629859286 964.321265336919 964.32690088042 964.33253648979 964.338172165031 964.343807906143 964.349443713128 964.355079585987 964.36071552472 964.36635152933 964.467810878442 964.473448134917 964.479085457292 964.484722845568 964.490360299745 964.495997819824 964.501635405808 964.507273057696 964.512910775491 964.518548559193 964.524186408804 964.529824324324 965.201207199106 965.206853032182 965.212498931307 965.218144896483 965.223790927711 965.229437024992 965.235083188328 965.240729417718 965.246375713166 965.252022074672 965.257668502236 965.26331499586 965.268961555546 965.274608181294 965.280254873106 965.285901630983 965.291548454925 965.297195344935 965.302842301012 965.308489323159 965.314136411377 965.319783565667 965.325430786029 965.331078072465 966.212864647697 966.218522322157 966.224180062874 966.22983786985 966.235495743085 966.241153682582 966.246811688342 966.252469760364 966.258127898651 966.263786103204 966.269444374024 966.275102711111 966.280761114469 966.286419584096 966.292078119995 966.297736722167 966.303395390612 966.309054125333 966.31471292633 966.320371793604 966.326030727157 967.215306113877 967.220975534084 967.226645020755 967.232314573891 967.237984193494 967.243653879564 967.249323632103 " "967.254993451112 967.260663336592 967.266333288544 967.272003306969 967.277673391869 967.283343543245 967.289013761098 967.294684045428 967.300354396238 967.306024813528 967.3116952973 967.317365847555 967.323036464293 967.328707147517 967.334377897227 967.340048713424 967.345719596109 967.351390545285 980.194309595126 980.200132191883 980.205954857816 980.211777592926 980.217600397214 980.223423270681 980.229246213329 980.235069225159 980.240892306172 980.24671545637 980.252538675753 980.258361964323 980.264185322081 980.270008749028 980.275832245166 980.281655810496 980.287479445018 980.293303148735 980.299126921648 980.304950763757 980.310774675063 980.31659865557 980.322422705276 989.849128120579 989.855065986618 989.861003923897 989.866941932417 989.872880012179 989.878818163186 989.884756385438 989.890694678936 989.896633043682 989.902571479677 989.908509986923 989.91444856542 1024.22504311064 1024.23140056509 1024.23775809846 1024.24411571076 1024.25047340198 1024.25683117213 1024.26318902121 1024.26954694921 1024.27590495616 1024.28226304203 1024.28862120684 1024.29497945058 1024.30133777326 1024.30769617489 1024.31405465545 1024.32041321495 1024.3267718534 1024.3331305708 1024.33948936714 1024.62571693597 1024.63207936544 1024.63844187393 1024.64480446143 1024.65116712796 1024.6575298735 1024.66389269807 1024.67025560165 1024.67661858427 1024.6829816459 1024.68934478657 1024.69570800627 1024.80389483394 1024.8102594764 1024.81662419793 1024.82298899851 1024.82935387816 1024.83571883686 1024.84208387463 1024.84844899146 1024.85481418736 1024.86117946232 1024.86754481635 1024.87391024946 1024.88027576163 1024.88664135288 1037.17792520177 1037.18444447285 1037.19096382588 1037.19748326088 1037.20400277783 1037.21052237674 1037.21704205761 1037.22356182045 1037.23008166525 1037.23660159202 1037.24312160075 1037.24964169146 1037.25616186413 1037.26268211878 1037.2692024554 1037.275722874 1037.28224337457 1037.28876395712 1037.29528462166 1037.30180536817 " "1037.30832619667 1037.31484710715 1037.32136809962 1037.32788917408 1038.22205208364 1038.22858448726 1038.2351169731 1038.24164954113 1038.24818219137 1038.25471492382 1038.26124773848 1038.26778063535 1038.27431361443 1038.28084667573 1038.28737981924 1038.29391304497 1038.30044635292 1038.30697974309 1038.31351321548 1038.32004677009 1038.32658040693 1039.22901160479 1039.235556686 1039.24210184966 1039.24864709577 1039.25519242432 1039.26173783531 1039.26828332876 1039.27482890466 1039.28137456301 1039.28792030381 1039.29446612706 1039.30101203278 1039.30755802095 1039.31410409158 1039.32065024467 1039.32719648023 1039.33374279825 1039.34028919873 1039.34683568169 1040.22481095549 1040.23136858588 1040.23792629894 1040.24448409469 1040.25104197312 1040.25759993424 1040.26415797804 1040.27071610453 1040.27727431371 1040.28383260558 1040.29039098014 1040.2969494374 1040.30350797735 1040.3100666 1040.31662530535 1040.32318409339 1040.32974296414 1041.2290907215 1041.2356610201 1041.24223140163 1041.24880186607 1041.25537241343 1041.26194304372 1041.26851375694 1041.27508455308 1041.28165543215 1041.28822639415 1041.29479743909 1041.30136856695 1041.30793977776 1041.3145110715 1041.32108244817 1041.32765390779 1041.33422545035 1041.34079707585 1041.3473687843 1041.35394057569 1041.36051245003 1041.36708440732 1041.37365644756 1041.38022857076 1041.3868007769 1041.39337306601 1041.39994543807 1041.40651789309 1041.41309043107 1041.41966305201 1088.79279195134 1088.79997622919 1088.80716060185 1088.81434506932 1088.82152963161 1088.82871428871 1088.83589904063 1088.84308388737 1088.85026882893 1088.85745386531 1088.86463899652 1098.12539546821 1098.13270343459 1098.14001149825 1098.14731965918 1098.15462791738 1098.16193627285 1098.1692447256 1098.17655327563 1098.18386192294 1098.19117066753 1098.19847950941 1098.20578844857 1098.21309748502 1098.22040661877 1098.2277158498 1098.23502517813 1098.24233460375 1098.24964412667 1098.2569537469 1098.26426346442 " "1098.27157327925 1111.23703980607 1111.2445233295 1111.25200695373 1111.25949067876 1111.26697450458 1111.27445843121 1111.28194245863 1111.28942658687 1111.29691081591 1111.30439514576 1111.31187957642 1111.31936410789 1111.32684874018 1111.33433347329 1111.34181830722 1111.34930324196 1112.25572512581 1112.26322237607 1112.27071972739 1112.27821717979 1112.28571473327 1112.29321238783 1112.30071014346 1112.30820800018 1112.31570595798 1112.32320401687 1112.33070217685 1112.33820043792 1112.34569880008 1112.41318860905 1112.42068798226 1112.42818745657 1112.43568703201 1112.44318670856 1112.45068648624 1112.45818636504 1112.46568634496 1112.47318642601 1112.48068660819 1112.48818689151 1112.49568727595 1112.50318776154 1112.57819818028 1112.58569977849 1112.59320147786 1112.60070327839 1112.60820518009 1112.61570718295 1112.62320928699 1112.63071149219 1112.63821379856 1112.64571620611 1112.65321871484 1112.66072132475 1114.26108654592 1114.26861085524 1114.27613526618 1114.28365977874 1114.29118439293 1114.29870910874 1114.30623392618 1114.31375884525 1114.32128386596 1114.32880898829 1114.33633421227 1115.25517475482 1115.2627124958 1115.27025033867 1115.27778828344 1115.28532633011 1115.29286447867 1115.30040272913 1115.3079410815 1115.31547953577 1115.32301809195 1115.33055675004 1115.33809551004 1115.34563437195 1130.2815779083 1130.28932013803 1130.29706247383 1130.30480491569 1130.31254746363 1130.32029011764 1130.32803287773 1130.33577574389 1130.34351871613 1130.35126179446 1130.35900497886 1147.66276619636 1147.67074837394 1147.67873066254 1147.68671306219 1147.69469557288 1147.70267819461 1147.71066092738 1147.7186437712 1147.72662672607 1147.73460979199 1147.74259296897 1147.750576257 1147.75855965609 1147.76654316625 1147.77452678746 1182.98466783959 1182.99314891893 1183.00163011987 1183.01011144242 1183.01859288659 1183.02707445237 1183.03555613976 1183.04403794878 1183.05251987942 1183.06100193168 1183.06948410557 1183.07796640108 1183.1712796801 " "1183.17976343539 1183.18824731234 1183.19673131095 1183.20521543123 1183.21369967318 1183.22218403681 1183.23066852212 1183.2391531291 1183.24763785777 1183.25612270812 1183.26460768015 1183.27309277388 1183.68052043171 1183.68901149146 1183.69750267303 1183.70599397643 1183.71448540165 1183.7229769487 1183.73146861758 1183.7399604083 1183.74845232085 1183.75694435525 1183.76543651148 1183.77392878956 1188.27493289966 1188.28349000304 1188.29204722968 1188.30060457956 1188.30916205269 1188.31771964907 1188.32627736871 1188.3348352116 1188.34339317776 1188.35195126718 1188.36050947987 1209.74923184622 1209.75810103042 1209.76697034466 1209.77583978896 1209.78470936331 1209.79357906772 1209.80244890218 1209.81131886671 1209.82018896131 1209.82905918597 1209.83792954071 1209.87341226042 1209.88228326555 1209.89115440077 1209.90002566609 1209.9088970615 1209.917768587 1209.92664024261 1209.93551202832 1209.94438394413 1209.95325599005 1209.96212816609 1214.99579864251 1215.00474492341 1215.01369133607 1215.02263788047 1215.03158455663 1215.04053136455 1215.04947830422 1215.05842537566 1215.06737257887 1215.07631991384 1215.08526738058 1215.0942149791 1215.10316270939 1215.11211057146 1240.4233010027 1240.43262565993 1240.44195045736 1240.45127539499 1240.46060047282 1240.46992569085 1240.47925104909 1240.48857654754 1240.4979021862 1240.50722796507 1240.51655388417 1240.52587994349 1240.53520614303 1240.5445324828 1243.04905650569 1243.05842068214 1243.06778499968 1243.0771494583 1243.08651405802 1243.09587879883 1243.10524368075 1243.11460870376 1243.12397386788 1243.13333917311 1243.14270461945 1243.15207020691 1243.16143593548 1243.17080180517 1243.18016781599 1243.18953396794 1250.94602927114 1250.95551280543 1250.96499648351 1250.97448030538 1250.98396427106 1250.99344838053 1251.00293263381 1251.0124170309 1251.0219015718 1251.03138625652 1251.04087108505 1251.05035605741 1261.31128248752 1261.32092383336 1261.33056532659 1261.34020696722 1261.34984875525 " "1261.35949069069 1261.36913277353 1261.37877500379 1261.38841738147 1261.39805990657 1261.40770257909 1261.94792763215 1261.95757871339 1261.96722994224 1261.97688131873 1261.98653284283 1261.99618451457 1262.00583633394 1262.01548830095 1262.02514041559 1262.03479267788 1262.04444508782 1262.05409764541 1262.06375035065 1262.07340320354 1262.32442921749 1262.33408605841 1262.34374304707 1262.35340018349 1262.36305746766 1262.3727148996 1262.3823724793 1262.39203020678 1262.40168808202 1262.41134610504 1262.42100427584 1262.43066259442 1262.44032106079 1263.28117374346 1263.29084522825 1263.30051686113 1263.31018864211 1263.31986057118 1263.32953264835 1263.33920487361 1263.34887724699 1263.35854976847 1263.36822243806 1263.37789525577 1263.3875682216 1263.39724133555 1263.40691459763 1265.31544052296 1265.32514318102 1265.33484598788 1265.34454894355 1265.35425204803 1265.36395530132 1265.37365870343 1265.38336225437 1265.39306595413 1265.40276980271 1265.41247380013 1265.42217794639 1273.46930606141 1273.47913417338 1273.48896243705 1273.49879085242 1273.5086194195 1273.51844813829 1273.5282770088 1273.53810603102 1273.54793520496 1273.55776453063 1273.56759400803 1273.57742363715 1273.58725341802 1273.59708335062 1273.60691343496 1273.61674367105 1273.62657405888 1281.32087896611 1281.33082864257 1281.34077847355 1281.35072845906 1281.3606785991 1281.37062889368 1281.38057934279 1281.39052994644 1281.40048070464 1281.41043161738 1281.42038268468 1281.43033390653 1281.44028528294 1281.45023681392 1281.46018849946 1281.47014033957 1281.48009233426 1293.16997731079 1293.18011185941 1293.19024656688 1293.2003814332 1293.21051645839 1293.22065164243 1293.23078698534 1293.24092248711 1293.25105814776 1293.26119396729 1293.27132994569 1293.28146608298 1409.30396671911 1409.31600329167 1409.32804006984 1409.34007705362 1409.35211424301 1409.36415163802 1409.37618923866 1409.38822704493 1409.40026505684 1409.4123032744 1409.4243416976 1409.43638032645 1439.81291838247 " "1439.82548173949 1439.83804531576 1439.85060911129 1439.86317312607 1439.87573736013 1439.88830181346 1439.90086648606 1439.91343137795 1439.92599648913 1439.93856181961 1439.97625912687 1439.98882533458 1440.00139176163 1440.013958408 1440.0265252737 1440.03909235875 1440.05165966315 1440.0642271869 1440.07679493 1440.08936289247 1440.10193107432 1456.39679555874 1456.40964999523 1456.42250465864 1456.43535954896 1456.44821466621 1456.46107001039 1456.47392558151 1456.48678137957 1456.49963740459 1456.51249365655 1456.52535013548 1456.53820684138 1456.55106377425 1456.5639209341 1456.57677832093 1469.49643693345 1469.5095236508 1469.52261060125 1469.5356977848 1469.54878520145 1469.56187285121 1469.57496073409 1469.58804885009 1469.60113719922 1469.61422578149 1469.6273145969 1469.64040364545 1477.46994793765 1477.48317705841 1477.49640641608 1477.50963601066 1477.52286584217 1477.53609591059 1477.54932621596 1477.56255675826 1477.5757875375 1477.58901855369 1477.60224980685 1477.61548129696 1477.62871302405 1477.64194498811 1477.65517718916 1477.6684096272 1477.68164230223 1477.69487521426 1477.7081083633 1477.72134174936 1478.91331787051 1478.9265728516 1478.93982807029 1478.9530835266 1478.96633922051 1478.97959515204 1478.99285132121 1479.006107728 1479.01936437244 1479.03262125452 1479.04587837426 1480.17360285036 1480.18688043216 1480.20015825217 1480.2134363104 1480.22671460685 1480.23999314153 1480.25327191444 1480.2665509256 1480.279830175 1480.29310966266 1480.30638938858 1480.31966935276 1480.33294955522 1480.34622999596 1480.35951067499 1480.37279159231 1480.38607274793 1480.39935414185 1480.41263577409 1480.42591764464 1480.73146645809 1480.74475405022 1480.75804188082 1480.77132994991 1480.78461825749 1480.79790680357 1480.81119558816 1480.82448461126 1480.83777387287 1480.85106337301 1480.86435311168 1480.87764308888 1480.89093330463 1480.90422375893 1480.91751445178 1480.9308053832 1480.94409655318 1480.95738796174 1480.97067960888 1480.983971494 " "1480.99726361894 1481.01055598187 1481.0238485834 1481.03714142355 1481.05043450231 1481.06372781971 1481.07702137574 1481.34294261915 1481.35624118796 1481.36953999554 1481.38283904191 1481.39613832706 1481.409437851 1481.42273761375 1481.4360376153 1481.44933785567 1481.46263833486 1481.47593905287 1481.48924000971 1481.50254120539 1481.51584263992 1481.5291443133 1481.54244622554 1481.55574837664 1481.56905076662 1481.58235339547 1481.5956562632 1481.60895936983 1481.62226271535 1481.63556629978 1481.64887012311 1481.66217418536 1481.67547848654 1482.36763154258 1482.38094851586 1482.39426572841 1482.40758318025 1482.42090087136 1482.43421880177 1482.44753697147 1482.46085538047 1482.47417402879 1482.48749291642 1482.50081204337 1482.51413140965 1482.52745101526 1482.54077086022 1493.62532276273 1493.63884277381 1493.65236302966 1493.66588353027 1493.67940427566 1493.69292526583 1493.70644650079 1493.71996798055 1493.73348970511 1493.74701167448 1493.76053388867 1493.77405634768 1511.59045068974 1511.60429789207 1511.6181453481 1511.63199305785 1511.64584102131 1511.65968923849 1511.6735377094 1511.68738643405 1511.70123541244 1511.71508464459 1511.72893413049 1599.95476419777 1599.97027768381 1599.98579147069 1600.00130555844"; const char* fullSpectrumRawY = "0 0 0 0 0 0 0 0 0 193.855026245117 641.106506347656 877.26220703125 700.196716308594 274.883911132813 0 0 0 0 0 0 0 0 0 0 224.89469909668 511.670349121094 595.136657714844 452.148010253906 234.596389770508 74.6820220947266 0 0 0 0 0 0 0 0 119.225784301758 185.543075561523 200.134750366211 188.900192260742 160.073196411133 0 0 0 0 0 0 0 172.296859741211 200.144027709961 165.512985229492 0 0 0 0 0 0 0 0 83.4415893554688 208.525405883789 177.816024780273 100.466018676758 0 0 0 0 0 0 0 0 93.3426513671875 177.81330871582 221.383926391602 233.153823852539 185.899673461914 84.1839904785156 0 0 0 0 0 0 0 0 126.048049926758 184.371139526367 97.8295288085938 0 0 0 0 0 0 0 0 25.8681793212891 261.258850097656 531.637878417969 574.53076171875 413.904724121094 218.982650756836 112.732650756836 0 0 0 0 0 0 0 0 94.0497131347656 191.148391723633 161.991897583008 0 0 0 0 0 0 0 402.995788574219 1600.27600097656 3017.67749023438 3685.970703125 3078.0078125 1699.85888671875 531.254028320313 44.9793395996094 0 0 0 0 0 0 0 0 3.05120849609375 326.982971191406 918.194396972656 1295.37927246094 1141.49755859375 577.818969726563 26.3272705078125 0 0 0 0 0 0 0 0 125.907791137695 264.531921386719 266.280029296875 158.506088256836 0 0 0 0 0 0 0 0 45.1534271240234 245.012252807617 337.062133789063 230.558639526367 35.3934326171875 0 0 0 0 0 0 0 0 21.4011077880859 269.609924316406 302.905334472656 3843.85766601563 9906.61328125 14627.65625 14086.5751953125 8667.4873046875 2666.59497070313 152.549850463867 452.571411132813 21.2885437011719 0 0 0 0 0 0 0 0 0 242.630386352539 1476.34033203125 2982.52856445313 3656.2958984375 2926.99194335938 1440.77648925781 378.651611328125 617.814758300781 1036.13317871094 1038.09765625 677.166748046875 273.266662597656 106.01123046875 0 0 0 0 0 0 0 0 0 644.765441894531 1669.39282226563 2428.14697265625 2279.11108398438 1350.7001953125 456.782958984375 195.992416381836 144.774459838867 138.42707824707 203.370742797852 302.340209960938 350.181884765625 " "314.466613769531 225.259658813477 125.442489624023 0 0 0 0 0 0 0 0 0 229.676986694336 1286.525390625 3076.466796875 4448.58984375 4288.94775390625 2695.29956054688 856.980102539063 0 0 0 0 0 0 0 0 0 0 297.09423828125 790.947937011719 1078.3701171875 895.997009277344 377.297119140625 0 0 0 0 0 0 0 0 0 54.2761840820313 380.800170898438 604.678894042969 530.256896972656 239.020004272461 14.5890960693359 0 0 0 0 0 0 0 0 0 315.951721191406 1584.78002929688 3584.27490234375 4964.8896484375 4550.10595703125 2648.34790039063 761.737854003906 336.893249511719 327.000427246094 103.404342651367 0 0 0 0 0 0 0 0 137.308151245117 232.669479370117 225.336959838867 131.02082824707 0 0 0 0 0 0 0 0 0 309.901550292969 806.588073730469 1159.07531738281 1105.30993652344 695.416931152344 245.27473449707 13.4951171875 0 0 0 0 0 0 0 0 114.433959960938 215.006851196289 272.628845214844 187.665817260742 12.0498352050781 0 0 0 0 0 0 0 0 127.550247192383 182.018173217773 211.423233032227 191.385147094727 141.782333374023 0 0 0 0 0 0 0 0 0 745.767456054688 2422.9541015625 3720.92529296875 3568.47998046875 2088.86743164063 510.764953613281 183.886978149414 136.265151977539 0 0 0 0 0 0 0 0 171.257888793945 188.640060424805 192.395614624023 154.632247924805 0 0 0 0 0 0 0 0 130.887710571289 642.11865234375 1160.51184082031 1294.43505859375 977.964050292969 544.39794921875 308.192199707031 211.437362670898 76.1909332275391 0 0 0 0 0 0 0 0 0 229.855178833008 543.525207519531 586.220275878906 314.952575683594 0 0 0 0 0 0 0 0 0 154.422073364258 196.758010864258 149.831283569336 0 0 0 0 0 0 0 0 123.318832397461 188.429489135742 169.386795043945 0 0 0 0 0 0 0 0 2959.08642578125 8616.0419921875 13691.96484375 14140.76953125 9577.6708984375 3752.03759765625 393.419616699219 324.138061523438 232.52278137207 0 0 0 0 0 0 0 0 0 133.11164855957 205.964584350586 199.730422973633 139.437789916992 0 0 0 0 0 0 0 0 101.496200561523 185.133193969727 259.655029296875 244.710922241211 160.866897583 0 0 0 0 0 0 0 0 " "171.158157348633 209.737930297852 216.904006958008 153.206130981445 0 0 0 0 0 0 0 0 0 1064.01928710938 2744.22631835938 3925.62744140625 3728.50854492188 2484.57104492188 1484.09924316406 1184.474609375 801.294799804688 276.304870605469 0 0 0 0 0 0 0 0 0 0 300.0966796875 1263.98876953125 2300.80615234375 2527.240234375 1658.1162109375 416.934509277344 362.052856445313 510.349609375 422.890075683594 293.749877929688 96.1615142822266 0 0 0 0 0 0 0 0 277.112182617188 552.278137207031 634.911743164063 465.758728027344 230.118118286133 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 338.728454589844 100.444885253906 1113.40734863281 4002.13525390625 6734.62841796875 7179.69189453125 4943.12939453125 1888.85778808594 87.8339996337891 0 0 0 0 0 0 0 0 166.607498168945 203.203231811523 88.5599517822266 0 0 134.797103881836 252.799118041992 321.236206054688 317.407653808594 177.626174926758 0 0 0 0 0 0 0 0 420.235168457031 1400.63110351563 2127.62890625 2036.72399902344 1375.9619140625 1018.35345458984 909.901550292969 528.322021484375 118.658309936523 0 0 0 0 0 0 0 0 6.52516174316406 184.584854125977 399.570495605469 472.823852539063 311.700012207031 67.0648040771484 0 0 0 0 0 0 0 0 4.97833251953125 518.760131835938 1195.45788574219 1522.00109863281 1192.40087890625 457.996826171875 236.555740356445 455.735107421875 494.134094238281 419.947204589844 169.757431030273 0 0 0 0 0 0 0 0 158.202651977539 249.356582641602 255.182876586914 181.06364440918 0 0 0 0 0 0 0 0 173.365737915039 243.861038208008 222.755081176758 104.503341674805 0 0 0 0 0 0 0 0 127.732864379883 184.066452026367 159.648910522461 0 0 0 0 0 0 0 0 0 216.264389038086 564.540100097656 758.490661621094 593.172241210938 186.406509399414 0 0 0 0 0 0 0 0 0 57.8870544433594 189.093154907227 180.032363891602 0 0 0 0 0 0 0 0 107.181259155273 588.624389648438 3296.2294921875 6859.40966796875 8629.48046875 6954.76904296875 3204.29370117188 530.406066894531 701.101257324219 446.318359375 172.379989624023 0 0 0 0 0 0 0 0 " "106.025817871094 219.603103637695 171.653244018555 0 0 0 0 0 0 0 0 66.6060028076172 816.289489746094 2058.00170898438 2839.88916015625 2264.32885742188 887.272766113281 1098.07897949219 1184.8994140625 515.840759277344 0 0 0 0 0 0 0 0 0 107.923675537109 213.511978149414 238.096145629883 157.005569458008 0 0 0 0 0 0 0 0 84.7611541748047 279.91943359375 997.471740722656 1668.52087402344 1678.548828125 1062.6884765625 456.879150390625 261.066772460938 414.542724609375 400.814636230469 181.47590637207 0 0 0 0 0 0 0 0 162.703384399414 402.678283691406 606.938415527344 584.632751464844 322.495727539063 0 0 0 0 0 0 0 0 203.609512329102 221.824447631836 103.749816894531 0 0 0 0 0 0 0 0 139.273239135742 246.041458129883 237.826309204102 138.225112915039 0 0 0 102.917053222656 540.358703613281 1507.14807128906 2255.67041015625 2121.10278320313 1207.01428222656 254.796005249023 0 0 0 0 0 0 0 0 0 180.893783569336 216.125747680664 186.408401489258 92.5867767333984 0 0 0 0 0 0 0 0 67.1141357421875 314.660339355469 430.744506835938 249.505142211914 110.873168945313 311.952087402344 298.573059082031 158.444198608398 0 0 0 0 0 0 0 0 0 203.841903686523 330.667297363281 305.950500488281 171.00895690918 0 0 0 0 0 0 0 0 150.461807250977 187.074295043945 122.066360473633 0 0 0 0 0 0 0 0 128.328475952148 228.142013549805 224.649185180664 115.597442626953 0 0 0 0 0 0 0 0 121.621292114258 209.864395141602 180.903396606445 0 0 0 0 0 0 0 0 180.190689086914 221.191635131836 230.223587036133 203.161819458008 163.631942749023 0 0 0 103.920654296875 254.635330200195 239.919662475586 117.75276184082 0 0 0 0 0 0 0 0 127.274429321289 277.754516601563 418.050842285156 364.745910644531 108.102828979492 0 0 0 0 0 0 0 0 122.235366821289 204.649490356445 1283.6416015625 2732.66333007813 3403.52026367188 2677.83666992188 1189.97729492188 91.4230346679688 0 0 0 0 0 0 0 0 179.184860229492 218.383316040039 188.207290649414 103.431289672852 0 0 0 0 0 19.3411254882813 320.543273925781 708.724914550781 " "746.338012695313 324.464965820313 498.983642578125 805.302062988281 584.451416015625 150.821365356445 0 0 0 0 0 0 0 0 18.6659393310547 273.791931152344 556.722961425781 580.784423828125 324.137634277344 118.86296081543 192.937911987305 133.19303894043 0 0 0 0 0 0 0 0 156.306106567383 528.205383300781 857.985168457031 865.72802734375 528.765258789063 126.998458862305 0 0 0 0 0 0 0 0 141.282363891602 213.537307739258 188.727676391602 83.9633941650391 0 0 0 0 0 0 0 0 53.5650329589844 300.0869140625 496.208679199219 543.627502441406 469.730163574219 370.066101074219 289.648376464844 183.115615844727 57.3272399902344 0 0 0 0 0 0 0 0 128.359512329102 282.553894042969 428.125305175781 518.781311035156 625.49609375 722.9619140625 704.251159667969 596.822631835938 501.902587890625 382.079040527344 159.27229309082 0 0 0 0 0 0 0 0 65.7273559570313 820.538696289063 2162.48120117188 3311.76513671875 3299.95263671875 2090.16650390625 672.241455078125 0 0 0 0 0 0 0 0 0 0 308.417297363281 836.372497558594 1054.75146484375 828.995056152344 520.746643066406 281.113220214844 0 0 0 0 0 0 0 0 0 135.923385620117 224.629806518555 176.55793762207 0 0 0 0 0 0 0 0 0 243.977737426758 679.087585449219 930.161682128906 790.303100585938 379.179931640625 152.314804077148 0 0 0 0 0 0 0 0 136.929214477539 317.641784667969 361.6630859375 256.365356445313 53.1949462890625 0 0 0 0 0 0 0 0 79.8312377929688 199.234237670898 225.433242797852 110.191116333008 0 0 0 0 0 0 0 0 88.5470733642578 328.809631347656 486.254577636719 566.095397949219 679.935241699219 807.850219726563 851.315795898438 785.165161132813 654.703979492188 527.893920898438 423.899841308594 256.051086425781 0 0 0 0 0 0 0 0 0 0 325.090454101563 1122.31469726563 1884.14013671875 2005.18811035156 1370.16577148438 511.172485351563 0 0 0 0 0 0 0 0 0 144.137466430664 222.952560424805 139.711410522461 0 0 0 31.4209136962891 456.088439941406 906.362609863281 992.082092285156 640.056396484375 191.88249206543 0 0 0 0 0 0 0 0 0 142.481643676758 " "248.23698425293 361.091796875 321.38818359375 84.5967559814453 0 0 0 0 0 0 0 0 68.5481414794922 229.667556762695 342.556030273438 233.595016479492 12.875 284.913818359375 586.492919921875 765.540771484375 846.076843261719 837.908752441406 736.949829101563 570.628051757813 422.32958984375 338.351196289063 265.928649902344 102.936645507813 0 0 0 0 0 0 0 0 111.217437744141 194.165725708008 498.359680175781 810.423156738281 786.201354980469 424.384338378906 32.8225250244141 0 0 0 0 0 0 0 0 126.047775268555 188.677780151367 216.424392700195 207.760787963867 193.143905639648 173.67204284668 0 0 0 0 0 0 0 0 230.711318969727 263.243713378906 218.297134399414 121.326461791992 0 0 0 0 0 0 0 0 85.8698425292969 222.64518737793 225.071212768555 111.491928100586 0 0 0 0 0 0 0 0 158.272689819336 319.939025878906 405.672607421875 543.889831542969 709.350402832031 762.2890625 669.657836914063 464.710327148438 230.338363647461 135.231704711914 0 0 0 0 0 0 0 0 112.85188293457 340.410949707031 556.054382324219 649.1904296875 642.006286621094 595.709777832031 552.84423828125 532.100952148438 509.958984375 393.80126953125 147.021102905273 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 163.031021118164 257.087280273438 222.833755493164 69.1905975341797 0 0 0 0 0 0 0 0 0 193.01008605957 1283.4189453125 2651.75854492188 3263.72827148438 2533.265625 1061.58337402344 237.298934936523 292.41845703125 36.6092681884766 0 0 0 0 0 0 0 0 0 412.251708984375 1201.08520507813 1691.83618164063 1483.95202636719 787.549011230469 140.731460571289 0 0 0 0 0 0 0 0 155.059463500977 197.582107543945 226.128463745117 389.715087890625 812.975402832031 1328.24084472656 1494.00390625 1091.52282714844 416.5791015625 13.3121490478516 0 0 0 0 0 0 0 0 30.8641204833984 259.902893066406 398.201293945313 307.794982910156 89.9954833984375 0 0 0 0 0 0 0 0 250.239639282227 294.914489746094 240.247360229492 36.3681182861328 0 0 0 0 0 0 0 0 168.141342163086 211.644943237305 185.341293334961 0 0 0 0 0 0 0 0 0 1255.41430664063 " "4270.45751953125 7186.3505859375 7656.57861328125 5270.84912109375 2048.24633789063 131.94660949707 0 0 0 0 0 0 0 0 171.324295043945 234.151138305664 188.494430541992 85.8521118164063 0 0 0 0 0 0 0 177.790451049805 196.738876342773 191.143508911133 173.924301147461 0 0 0 0 0 0 0 0 27.4716339111328 870.664428710938 2696.56469726563 4313.33056640625 4373.56005859375 2848.65014648438 1105.826171875 363.445678710938 95.8519592285156 0 0 0 0 0 0 0 0 165.054183959961 190.630477905273 212.371444702148 119.549850463867 0 0 0 0 144.282302856445 1497.27661132813 3014.11791992188 3372.33959960938 2141.125 440.955444335938 486.9052734375 473.754028320313 237.800888061523 10.4761962890625 0 0 0 0 0 0 0 0 187.649795532227 717.752685546875 1004.04693603516 895.356262207031 611.759887695313 231.517959594727 0 0 0 0 0 0 0 0 0 0 380.191772460938 1166.65649414063 1580.28991699219 1321.69921875 695.5244140625 219.708572387695 60.3770294189453 0 0 0 0 0 0 0 0 168.744674682617 496.461608886719 797.966979980469 819.004150390625 524.868408203125 148.768051147461 0 0 0 0 0 0 0 0 114.591278076172 230.604568481445 404.740417480469 400.008056640625 149.154037475586 0 0 0 0 0 0 0 0 102.017929077148 332.576171875 431.327087402344 395.180480957031 291.81103515625 179.464797973633 0 0 0 0 0 0 0 0 328.818298339844 432.372192382813 513.603515625 524.003845214844 455.190307617188 323.07763671875 0 0 0 0 0 0 0 0 0 500.822875976563 1250.17626953125 1691.61279296875 1446.947265625 741.710021972656 242.135177612305 131.856307983398 0 0 0 0 0 0 0 0 106.934600830078 416.481811523438 591.3037109375 471.31884765625 154.692947387695 0 0 0 0 0 0 0 0 58.2242736816406 451.217834472656 867.215209960938 952.283020019531 683.782348632813 327.990234375 53.9348297119141 0 0 0 0 0 0 0 0 112.282455444336 194.305465698242 247.864517211914 283.480651855469 251.062362670898 154.861434936523 0 0 0 0 0 0 0 0 0 2550.76782226563 7417.4248046875 11472.3154296875 11331.73046875 7126.333984375 2372.173828125 154.968887329 0 0 " "0 0 0 0 0 0 171.941879272461 235.122146606445 189.759658813477 86.6224975585938 0 0 0 0 0 0 0 0 161.515548706055 191.835342407227 263.086181640625 280.552551269531 146.46711730957 354.734191894531 1819.36071777344 4197.60791015625 5904.71484375 5515.97998046875 3378.09521484375 1216.07165527344 240.816360473633 160.06672668457 0 0 0 0 0 0 0 0 168.925979614258 417.149658203125 1732.84704589844 3627.1572265625 4610.03076171875 3790.7890625 1980.00671386719 757.338623046875 314.47314453125 0 0 0 0 0 0 0 0 0 151.324813842773 253.94270324707 329.051940917969 266.352722167969 111.870147705078 0 196.40153503418 1169.40258789063 2201.71215820313 2499.97778320313 1842.07995605469 847.819702148438 294.143676757813 154.02375793457 0 0 0 0 0 0 0 0 0 263.716003417969 663.424133300781 945.621276855469 900.181091308594 586.183349609375 242.737838745117 0 0 0 0 0 0 0 0 0 87.7988586425781 273.416259765625 275.446044921875 122.881698608398 0 0 0 0 0 0 0 0 139.006607055664 632.857299804688 1046.19299316406 1076.18725585938 721.538818359375 282.741760253906 33.4364013671875 0 92.9069519042969 201.903335571289 216.809951782227 66.0712280273438 0 0 0 0 0 0 0 0 0 262.810607910156 583.060974121094 697.79833984375 522.555419921875 181.537673950195 0 0 0 0 0 0 0 0 258.55615234375 289.532775878906 243.079086303711 173.991165161133 0 0 0 0 0 0 0 0 37.7136077880859 214.55876159668 243.370010375977 18.9360961914063 35.8999176025391 191.428115844727 166.77082824707 0 0 0 0 0 0 0 0 0 258.869323730469 651.99658203125 911.448181152344 810.898193359375 421.798156738281 54.3055572509766 0 0 0 0 0 0 0 0 60.1159057617188 292.62109375 475.166442871094 465.994323730469 265.969482421875 59.4075927734375 0 0 0 0 0 0 0 0 129.671829223633 203.134628295898 214.902053833008 142.065078735352 0 0 0 0 0 0 0 0 68.9898071289063 258.451477050781 349.82421875 288.4658203125 184.60481262207 0 0 0 0 0 0 0 0 60.4415130615234 757.99267578125 4146.55859375 8593.078125 10882.390625 9079.6171875 4740.5390625 1125.72338867 " "0 0 0 0 0 0 0 0 0 102.086837768555 209.562088012695 285.004333496094 167.125106811523 0 0 0 0 0 0 0 0 153.054061889648 218.63932800293 227.450668334961 199.439254760742 191.222061157227 179.493179321289 0 0 0 0 0 0 0 0 136.84049987793 243.085250854492 175.279190063477 0 0 0 165.884048461914 1627.97961425781 4570.39892578125 7233.904296875 7538.84521484375 5242.4697265625 2183.01293945313 247.249221801758 94.0259094238281 0 0 0 0 0 0 0 0 0 708.975402832031 2684.54736328125 4892.7626953125 5664.70263671875 4346.48974609375 2153.0361328125 792.776916503906 328.806335449219 26.2600402832031 0 0 0 0 0 0 0 0 0 600.651245117188 1863.01184082031 2856.58935546875 2825.29223632813 1829.23559570313 678.683837890625 156.775985717773 0 0 0 0 0 0 0 0 177.269912719727 213.871047973633 146.206100463867 0 0 0 0 0 0 0 0 0 438.628295898438 1067.17602539063 1423.88037109375 1322.46948242188 846.637451171875 222.935501098633 8.62030029296875 0 0 0 0 0 0 0 0 1.40678405761719 204.166915893555 495.588256835938 711.029602050781 672.086486816406 440.136291503906 197.460708618164 25.0921783447266 0 0 0 0 0 0 0 0 181.639419555664 454.123840332031 630.59228515625 540.996643066406 248.280014038086 0 0 0 0 0 0 0 0 0 0 272.537475585938 507.36669921875 482.3701171875 228.514022827148 0 0 0 0 0 0 0 0 0 173.016799926758 282.362365722656 239.30632019043 89.6678161621094 0 0 0 0 0 0 0 0 163.693313598633 238.812973022461 181.945022583008 0 0 0 0 0 0 0 0 154.68586730957 251.716812133789 301.325927734375 285.520263671875 212.902420043945 125.696426391602 0 0 0 0 0 0 0 0 144.465744018555 280.485534667969 282.486389160156 171.469833374023 0 0 0 0 0 0 0 0 168.80158996582 1852.96484375 4451.087890625 6223.240234375 5698.3251953125 3317.40869140625 947.944641113281 0 72.4445648193359 222.517288208008 190.692306518555 8.54414367675781 0 0 0 0 0 0 0 0 173.518569946289 287.66455078125 315.665649414063 180.375747680664 0 0 0 0 0 0 0 0 22.9653015136719 377.313659667969 1943.11608886719 3810.626464843 4614.140625 " "3648.7470703125 1708.49145507813 216.385025024414 180.797805786133 220.440505981445 66.8912200927734 0 0 0 0 0 143.90119934082 216.902420043945 185.753768920898 98.3815460205078 0 0 0 0 0 0 0 0 162.759536743164 215.904861450195 208.337875366211 127.708084106445 0 0 0 0 0 0 0 0 105.314514160156 217.56315612793 204.984756469727 103.096450805664 1431.53564453125 2977.5546875 3651.64916992188 2931.84326171875 1398.70080566406 87.1452484130859 320.6357421875 384.557983398438 269.201110839844 237.787063598633 238.22102355957 131.059158325195 0 0 0 0 0 0 0 0 82.7467803955078 540.114013671875 1467.232421875 2395.43090820313 2641.54028320313 2010.16149902344 989.484558105469 192.628158569336 0 0 179.865524291992 275.410278320313 175.700149536133 0 0 0 0 0 0 0 0 59.9419708251953 485.762634277344 988.358093261719 1207.15466308594 963.307312011719 438.903381347656 31.6091766357422 0 0 0 0 0 47.9591827392578 196.635208129883 252.011154174805 211.016983032227 150.474960327148 0 0 0 0 0 0 0 0 168.648544311523 212.75212097168 246.239303588867 241.005111694336 180.050369262695 0 0 0 0 93.9449157714844 308.76171875 510.256713867188 547.370849609375 379.794067382813 126.207992553711 0 0 0 0 0 0 0 0 165.212295532227 203.172348022461 187.95915222168 180.575973510742 0 0 0 0 0 0 0 0 75.0355987548828 196.667404174805 286.693542480469 310.418090820313 283.288269042969 260.312194824219 292.165649414063 351.78125 356.774780273438 261.874694824219 112.601119995117 0 0 0 0 0 0 0 0 147.65412902832 199.247695922852 206.355667114258 137.159103393555 0 0 0 0 0 0 0 0 153.178085327148 250.377090454102 305.382019042969 294.765869140625 215.430770874023 81.4587097167969 0 0 0 0 0 0 0 0 89.8516693115234 217.64045715332 309.367736816406 283.979248046875 149.045394897461 0 0 0 182.38005065918 418.089721679688 1096.13757324219 1732.892578125 1712.91027832031 1019.67010498047 253.890274047852 63.1096954345703 0 0 0 0 0 0 0 0 146.927871704102 197.823593139648 450.705383300781 1247.59985351563 " "2147.16479492188 2419.29248046875 1796.34436035156 783.829040527344 106.181396484375 0 0 0 0 0 0 0 0 0 334.013916015625 997.858215332031 1538.47912597656 1550.04187011719 1073.02502441406 532.429992675781 248.089309692383 200.781692504883 213.394241333008 177.545181274414 0 0 0 0 0 0 0 0 26.6942443847656 209.29020690918 520.969909667969 869.404174804688 1070.1162109375 975.004333496094 655.297485351563 316.672058105469 99.7084808349609 0 0 0 0 0 0 0 0 79.5495910644531 288.576049804688 554.977966308594 746.154174804688 740.367309570313 521.067321777344 227.974136352539 72.0663757324219 0 0 0 0 0 0 0 0 171.190017700195 314.421569824219 429.333374023438 416.543640136719 251.908309936523 31.249267578125 0 0 0 0 0 0 0 0 180.657669067383 192.169876098633 162.963485717773 0 0 0 0 0 0 0 0 155.606674194336 333.596923828125 371.658142089844 244.003341674805 111.538848876953 0 0 0 55.3578186035156 199.379867553711 277.664733886719 246.347457885742 148.267105102539 0 0 0 0 0 0 0 0 90.9604797363281 198.196731567383 372.608276367188 566.121337890625 624.478515625 473.921447753906 201.671371459961 0 0 0 0 0 0 0 0 0 120.198684692383 400.147033691406 571.140441894531 478.692626953125 229.758438110352 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 152.600845336914 225.899429321289 240.899063110352 190.175918579102 0 0 0 0 0 0 0 0 225.349227905273 261.482971191406 145.197463989258 0 0 0 0 0 0 0 0 64.5845184326172 213.417953491211 267.813903808594 201.623031616211 117.913467407227 0 0 0 0 0 0 0 0 182.848587036133 203.188278198242 155.740859985352 0 0 0 0 0 0 0 0 184.153060913086 247.411849975586 282.429565429688 316.498046875 347.890441894531 314.713134765625 179.080673217773 0 0 0 0 0 0 0 0 115.904327392578 226.538375854492 215.979263305664 129.574813842773 0 0 0 0 0 0 0 0 129.243606567383 308.855651855469 363.072937011719 252.200698852539 36.5062561035156 0 0 0 0 0 0 0 0 168.485580444336 221.236099243164 203.256454467773 118.937698364258 0 0 0 0 0 0 0 0 135.065872192383 197.25260925293 " "164.043045043945 0 0 0 0 0 0 0 0 101.22346496582 199.961135864258 181.580459594727 0 0 0 0 0 0 0 0 171.627029418945 216.893325805664 165.188735961914 0 0 0 0 0 0 0 0 184.577438354492 315.924865722656 400.736938476563 401.748779296875 309.456359863281 177.526077270508 0 0 0 0 0 0 0 0 71.3968505859375 196.379440307617 317.622741699219 323.017578125 218.84977722168 108.977661132813 0 0 0 0 0 0 0 0 143.710311889648 248.819686889648 318.435913085938 338.807861328125 306.490661621094 239.977798461914 197.418716430664 128.426620483398 0 0 0 0 0 0 0 0 126.655654907227 226.479202270508 229.53288269043 179.628677368164 0 0 0 0 0 0 0 0 144.30647277832 214.861099243164 189.256454467773 0 0 0 0 0 0 0 0 188.085342407227 308.395935058594 374.08056640625 337.305053710938 193.459030151367 33.2561950683594 0 0 0 0 0 0 0 0 101.20735168457 200.764785766602 247.183944702148 206.08268737793 87.9416961669922 0 0 0 0 0 0 0 0 95.3595581054688 225.91584777832 248.077072143555 250.59260559082 257.277648925781 180.943740844727 0 0 0 0 0 0 0 0 155.655776977539 238.868362426758 250.283981323242 157.468978881836 0 0 0 0 0 0 0 0 165.849624633789 341.285217285156 449.087829589844 465.197448730469 414.669006347656 350.80908203125 287.216369628906 202.29280090332 102.295700073242 0 0 0 0 0 0 0 0 122.961654663086 216.524826049805 227.398483276367 197.743057250977 252.932815551758 368.044921875 412.497924804688 332.376770019531 189.94221496582 0 0 0 0 0 0 0 0 110.821487426758 205.431838989258 197.784744262695 165.351150512695 0 0 0 0 0 0 0 0 148.747482299805 197.384048461914 222.412368774414 130.84407043457 0 0 0 0 0 0 0 0 186.619369506836 231.119979858398 185.139663696289 0 0 0 0 0 0 0 0 129.717819213867 224.055252075195 180.142196655273 0 0 0 0 0 0 0 0 176.265243530273 223.66975402832 295.446105957031 361.572326660156 360.102111816406 244.047714233398 41.8561553955078 0 0 0 0 0 0 0 0 160.23698425293 238.57145690918 249.646987915039 191.794631958008 0 0 0 0 0 0 0 0 177.559341430664 308.058898925781 " "348.306823730469 288.753173828125 157.469802856445 0 0 50.9171905517578 233.195449829102 366.537780761719 333.827880859375 112.628784179688 0 0 0 0 0 0 0 0 146.29948425293 221.006973266602 185.588424682617 0 0 0 0 0 0 0 0 169.829788208008 298.886840820313 375.022705078125 349.165283203125 326.073608398438 321.16162109375 301.307739257813 280.400939941406 268.34130859375 250.299697875977 206.922592163086 161.804183959961 0 0 0 0 0 0 0 0 106.515991210938 216.509872436523 174.441055297852 0 47.4068908691406 197.185470581055 263.215942382813 352.870300292969 434.091491699219 407.799926757813 297.367797851563 209.839736938477 246.22785949707 378.100463867188 491.783874511719 505.840270996094 403.557006835938 229.298934936523 54.6394348144531 0 0 0 0 0 0 0 0 50.5400085449219 198.851058959961 280.1474609375 285.830627441406 210.564895629883 50.8290405273438 0 0 0 0 0 170.184860229492 335.466613769531 475.362731933594 547.797119140625 496.642517089844 292.609191894531 4.42018127441406 0 0 0 0 0 0 0 0 386.298461914063 549.150512695313 612.910278320313 599.075317382813 479.97314453125 260.072143554688 0 0 0 0 0 0 0 0 157.101547241211 216.543563842773 210.621841430664 151.346878051758 0 0 0 0 0 0 0 0 163.830764770508 225.50910949707 155.86100769043 0 0 0 0 0 0 0 0"; vector parseDoubleArray(const string& doubleArray) { vector doubleVector; vector tokens; bal::split(tokens, doubleArray, bal::is_space(), bal::token_compress_on); if (!tokens.empty() && !tokens[0].empty()) for (size_t i=0; i < tokens.size(); ++i) doubleVector.push_back(lexical_cast(tokens[i])); return doubleVector; } void test() { for (size_t i=0; i < testDataSize; ++i) { try { const TestData& data = testData[i]; vector xRaw = parseDoubleArray(data.xRaw); vector yRaw = parseDoubleArray(data.yRaw); vector targetFilledX = parseDoubleArray(data.xFilled); vector targetFilledY = parseDoubleArray(data.yFilled); // sanity checks unit_assert(xRaw.size() == yRaw.size()); unit_assert(targetFilledX.size() == targetFilledY.size()); vector xFilled, yFilled; ZeroSampleFiller::fill(xRaw, yRaw, xFilled, yFilled, data.zeroSampleCount); unit_assert(xFilled.size() == targetFilledX.size()); unit_assert(xFilled.size() == yFilled.size()); for (size_t j=0; j < xFilled.size(); ++j) { unit_assert_equal(xFilled[j], targetFilledX[j], 1e-5); unit_assert_equal(yFilled[j], targetFilledY[j], 1e-5); } } catch (exception& e) { throw runtime_error("ZeroSampleFiller test case " + lexical_cast(i+1) + " failed: " + e.what()); } } vector xRaw = parseDoubleArray(fullSpectrumRawX); vector yRaw = parseDoubleArray(fullSpectrumRawY); // sanity check unit_assert(xRaw.size() == yRaw.size()); for (size_t zeroSampleCount=1; zeroSampleCount < 100; ++zeroSampleCount) { try { vector xFilled, yFilled; ZeroSampleFiller::fill(xRaw, yRaw, xFilled, yFilled, zeroSampleCount); } catch (exception& e) { throw runtime_error("ZeroSampleFiller full spectrum test case failed at zeroSampleCount=" + lexical_cast(zeroSampleCount) + ": " + e.what()); } } } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/proteome_processing/ProteinList_DecoyGenerator.cpp0000664000175100017510000001057012664775613030433 0ustar teamcityteamcity00000000000000// // $Id: ProteinList_DecoyGenerator.cpp 4010 2012-10-17 20:22:16Z chambm $ // // // Original author: Matt Chambers // // Copyright 2010 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "ProteinList_DecoyGenerator.hpp" #include #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace analysis { using namespace pwiz::util; using namespace pwiz::proteome; // // ProteinList_DecoyGenerator::Impl // struct ProteinList_DecoyGenerator::Impl { const ProteinListPtr original; const PredicatePtr predicate; Impl(ProteinListPtr original, PredicatePtr predicate) : original(original), predicate(predicate) { if (!original.get()) throw runtime_error("[ProteinList_DecoyGenerator] Null pointer"); } }; // // ProteinList_DecoyGenerator // PWIZ_API_DECL ProteinList_DecoyGenerator::ProteinList_DecoyGenerator(const ProteinListPtr& original, const PredicatePtr& predicate) : ProteinListWrapper(original), impl_(new Impl(original, predicate)) {} PWIZ_API_DECL size_t ProteinList_DecoyGenerator::size() const { // a decoy is generated for every protein in the original list return impl_->original->size() * 2; } PWIZ_API_DECL size_t ProteinList_DecoyGenerator::find(const string& id) const { if (bal::starts_with(id, impl_->predicate->decoyPrefix())) { // a decoy protein's index is the original protein's index plus the original size string originalId(id.begin() + impl_->predicate->decoyPrefix().length(), id.end()); size_t originalIndex = impl_->original->find(originalId); return originalIndex + impl_->original->size(); } return impl_->original->find(id); } PWIZ_API_DECL ProteinPtr ProteinList_DecoyGenerator::protein(size_t index, bool getSequence) const { if (index > size()) throw out_of_range("[ProteinList_DecoyGenerator::protein] Index out of range"); size_t originalIndex = index % impl_->original->size(); ProteinPtr protein = impl_->original->protein(originalIndex, getSequence); // the second half of the database is decoys if (index >= impl_->original->size()) { protein = impl_->predicate->generate(*protein); protein->index = index; } return protein; } // // ProteinList_DecoyGeneratorPredicate_Reversed // PWIZ_API_DECL ProteinList_DecoyGeneratorPredicate_Reversed::ProteinList_DecoyGeneratorPredicate_Reversed(const std::string& decoyPrefix) { decoyPrefix_ = decoyPrefix; } PWIZ_API_DECL ProteinPtr ProteinList_DecoyGeneratorPredicate_Reversed::generate(const Protein& protein) const { string reversedSequence(protein.sequence().rbegin(), protein.sequence().rend()); return ProteinPtr(new Protein(decoyPrefix_ + protein.id, protein.index, "", reversedSequence)); } // // ProteinList_DecoyGeneratorPredicate_Shuffled::Impl // struct ProteinList_DecoyGeneratorPredicate_Shuffled::Impl { Impl(boost::uint32_t randomSeed) : engine(randomSeed), rng(engine, distribution) { } boost::mt19937 engine; boost::uniform_int<> distribution; boost::variate_generator > rng; }; // // ProteinList_DecoyGeneratorPredicate_Shuffled // PWIZ_API_DECL ProteinList_DecoyGeneratorPredicate_Shuffled::ProteinList_DecoyGeneratorPredicate_Shuffled(const std::string& decoyPrefix, boost::uint32_t randomSeed) : impl_(new Impl(randomSeed)) { decoyPrefix_ = decoyPrefix; } PWIZ_API_DECL ProteinPtr ProteinList_DecoyGeneratorPredicate_Shuffled::generate(const Protein& protein) const { string shuffledSequence = protein.sequence(); std::random_shuffle(shuffledSequence.begin(), shuffledSequence.end(), impl_->rng); return ProteinPtr(new Protein(decoyPrefix_ + protein.id, protein.index, "", shuffledSequence)); } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/proteome_processing/ProteinListFactoryTest.cpp0000664000175100017510000000413612664775613027632 0ustar teamcityteamcity00000000000000// // $Id: ProteinListFactoryTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2012 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "ProteinListFactory.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/data/proteome/examples.hpp" #include using namespace pwiz::analysis; using namespace pwiz::util; using namespace pwiz::proteome; ostream* os_ = 0; void testUsage() { if (os_) *os_ << "ProteinListFactory::usage():\n" << ProteinListFactory::usage() << endl; } void testWrap() { ProteomeData pd; examples::initializeTiny(pd); ProteinListPtr& pl = pd.proteinListPtr; unit_assert(pl.get()); unit_assert_operator_equal(3, pl->size()); ProteinListFactory::wrap(pd, "id DEFCON42;ZEBRA"); unit_assert_operator_equal(2, pl->size()); unit_assert_operator_equal("ZEBRA", pl->protein(0)->id); unit_assert_operator_equal("DEFCON42", pl->protein(1)->id); ProteinListFactory::wrap(pd, "index 1"); unit_assert_operator_equal(1, pl->size()); unit_assert_operator_equal("DEFCON42", pl->protein(0)->id); } void test() { testUsage(); testWrap(); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/proteome_processing/ProteinList_Filter.cpp0000664000175100017510000001014112664775613026740 0ustar teamcityteamcity00000000000000// // $Id: ProteinList_Filter.cpp 4010 2012-10-17 20:22:16Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2012 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "pwiz/data/common/cv.hpp" #include "ProteinList_Filter.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace analysis { using namespace pwiz::cv; using namespace pwiz::util; using namespace pwiz::proteome; using boost::logic::tribool; // // ProteinList_Filter::Impl // struct ProteinList_Filter::Impl { const ProteinListPtr original; vector indexMap; // maps index -> original index bool getSequence; // true if sequence is needed for a non-indeterminate result Impl(ProteinListPtr original, const Predicate& predicate); void pushProtein(const Protein& protein); }; ProteinList_Filter::Impl::Impl(ProteinListPtr _original, const Predicate& predicate) : original(_original), getSequence(false) { if (!original.get()) throw runtime_error("[ProteinList_Filter] Null pointer"); // iterate through the proteins, using predicate to build the sub-list for (size_t i=1, end=original->size(); i<=end; ++i) { if (predicate.done()) break; ProteinPtr protein = original->protein(i-1, getSequence); tribool accepted = predicate.accept(*protein); if (accepted || getSequence) // if still indeterminate with getSequence = true, it passes the filter by default { pushProtein(*protein); } else if (!accepted) { // do nothing } else // indeterminate and !getSequence { // try again with getSequence = true getSequence = true; --i; } } } void ProteinList_Filter::Impl::pushProtein(const Protein& protein) { indexMap.push_back(protein.index); } // // ProteinList_Filter // PWIZ_API_DECL ProteinList_Filter::ProteinList_Filter(const ProteinListPtr original, const Predicate& predicate) : ProteinListWrapper(original), impl_(new Impl(original, predicate)) {} PWIZ_API_DECL size_t ProteinList_Filter::size() const { return impl_->indexMap.size(); } PWIZ_API_DECL ProteinPtr ProteinList_Filter::protein(size_t index, bool getSequence) const { size_t originalIndex = impl_->indexMap.at(index); ProteinPtr originalProtein = impl_->original->protein(originalIndex, getSequence); ProteinPtr newProtein(new Protein(*originalProtein)); newProtein->index = index; return newProtein; } // // ProteinList_FilterPredicate_IndexSet // PWIZ_API_DECL ProteinList_FilterPredicate_IndexSet::ProteinList_FilterPredicate_IndexSet(const IntegerSet& indexSet) : indexSet_(indexSet), eos_(false) {} PWIZ_API_DECL tribool ProteinList_FilterPredicate_IndexSet::accept(const Protein& protein) const { if (indexSet_.hasUpperBound((int)protein.index)) eos_ = true; bool result = indexSet_.contains((int)protein.index); return result; } PWIZ_API_DECL bool ProteinList_FilterPredicate_IndexSet::done() const { return eos_; // end of set } // // ProteinList_FilterPredicate_IdSet // PWIZ_API_DECL ProteinList_FilterPredicate_IdSet::ProteinList_FilterPredicate_IdSet(const set& idSet) : idSet_(idSet) {} PWIZ_API_DECL tribool ProteinList_FilterPredicate_IdSet::accept(const Protein& protein) const { return idSet_.erase(protein.id) > 0; } PWIZ_API_DECL bool ProteinList_FilterPredicate_IdSet::done() const { return idSet_.empty(); // end of set } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/proteome_processing/ProteinList_DecoyGeneratorTest.cpp0000664000175100017510000000654012664775613031275 0ustar teamcityteamcity00000000000000// // $Id: ProteinList_DecoyGeneratorTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Matt Chambers // // Copyright 2010 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/unit.hpp" #include "ProteinList_DecoyGenerator.hpp" #include "pwiz/data/proteome/examples.hpp" #include "boost/random.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::proteome; using namespace pwiz::analysis; using namespace pwiz::util; ostream* os_ = 0; void testReversedList(ProteinListPtr pl) { unit_assert(pl->size() == 3); ProteinList_DecoyGenerator decoyList(pl, ProteinList_DecoyGenerator::PredicatePtr(new ProteinList_DecoyGeneratorPredicate_Reversed("reversed_"))); unit_assert(decoyList.size() == 6); for (size_t i=0; i < pl->size(); ++i) { ProteinPtr target = decoyList.protein(i); ProteinPtr decoy = decoyList.protein(i + pl->size()); if (os_) *os_ << target->id << " " << target->sequence() << endl; if (os_) *os_ << decoy->id << " " << decoy->sequence() << endl; unit_assert("reversed_" + target->id == decoy->id); unit_assert(decoy->description.empty()); unit_assert(string(target->sequence().rbegin(), target->sequence().rend()) == decoy->sequence()); } } void testShuffledList(ProteinListPtr pl) { unit_assert(pl->size() == 3); ProteinList_DecoyGenerator decoyList(pl, ProteinList_DecoyGenerator::PredicatePtr(new ProteinList_DecoyGeneratorPredicate_Shuffled("shuffled_"))); unit_assert(decoyList.size() == 6); boost::mt19937 engine(0); boost::uniform_int<> distribution; boost::variate_generator > rng(engine, distribution); for (size_t i=0; i < pl->size(); ++i) { ProteinPtr target = decoyList.protein(i); ProteinPtr decoy = decoyList.protein(i + pl->size()); if (os_) *os_ << target->id << " " << target->sequence() << endl; if (os_) *os_ << decoy->id << " " << decoy->sequence() << endl; unit_assert("shuffled_" + target->id == decoy->id); unit_assert(decoy->description.empty()); string sequence = target->sequence(); random_shuffle(sequence.begin(), sequence.end(), rng); unit_assert(sequence == decoy->sequence()); } } void test() { ProteomeData pd; examples::initializeTiny(pd); ProteinListPtr pl = pd.proteinListPtr; testReversedList(pl); testShuffledList(pl); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/proteome_processing/ProteinList_DecoyGenerator.hpp0000664000175100017510000000663212664775613030444 0ustar teamcityteamcity00000000000000// // $Id: ProteinList_DecoyGenerator.hpp 4010 2012-10-17 20:22:16Z chambm $ // // // Original author: Matt Chambers // // Copyright 2010 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PROTEINLIST_DECOYGENERATOR_HPP_ #define _PROTEINLIST_DECOYGENERATOR_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/proteome/ProteinListWrapper.hpp" #include namespace pwiz { namespace analysis { using namespace pwiz::proteome; /// ProteinList decoy generator for creating decoy proteins on the fly class PWIZ_API_DECL ProteinList_DecoyGenerator : public proteome::ProteinListWrapper { public: /// client-implemented generator predicate -- called during construction of /// ProteinList_DecoyGenerator to create a decoy protein from a target protein struct PWIZ_API_DECL Predicate { /// return a decoy protein based on an input target protein virtual ProteinPtr generate(const Protein& protein) const = 0; /// return the string prefixed to a protein id to indicate it is a decoy virtual const std::string& decoyPrefix() const {return decoyPrefix_;} virtual ~Predicate() {} protected: std::string decoyPrefix_; }; typedef boost::shared_ptr PredicatePtr; ProteinList_DecoyGenerator(const ProteinListPtr& original, const PredicatePtr& predicate); /// \name ProteinList interface //@{ virtual size_t size() const; virtual size_t find(const std::string& id) const; virtual ProteinPtr protein(size_t index, bool getSequence = true) const; //@} private: struct Impl; boost::shared_ptr impl_; ProteinList_DecoyGenerator(const ProteinList_DecoyGenerator&); ProteinList_DecoyGenerator& operator=(const ProteinList_DecoyGenerator&); }; /// creates a reversed copy of every target protein with the specified decoy string prefixed to the id class PWIZ_API_DECL ProteinList_DecoyGeneratorPredicate_Reversed : public ProteinList_DecoyGenerator::Predicate { public: ProteinList_DecoyGeneratorPredicate_Reversed(const std::string& decoyPrefix); virtual ProteinPtr generate(const Protein& protein) const; }; /// creates a randomly shuffled copy of every target protein with the specified decoy string prefixed to the id class PWIZ_API_DECL ProteinList_DecoyGeneratorPredicate_Shuffled : public ProteinList_DecoyGenerator::Predicate { public: ProteinList_DecoyGeneratorPredicate_Shuffled(const std::string& decoyPrefix, boost::uint32_t randomSeed = 0u); virtual ProteinPtr generate(const Protein& protein) const; private: struct Impl; boost::shared_ptr impl_; }; } // namespace analysis } // namespace pwiz #endif // _PROTEINLIST_DECOYGENERATOR_HPP_ pwiz/pwiz/analysis/proteome_processing/ProteinListFactory.hpp0000664000175100017510000000276412664775613027004 0ustar teamcityteamcity00000000000000// // $Id: ProteinListFactory.hpp 4010 2012-10-17 20:22:16Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2012 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PROTEINLISTFACTORY_HPP_ #define _PROTEINLISTFACTORY_HPP_ #include "pwiz/data/proteome/ProteomeData.hpp" #include #include namespace pwiz { namespace analysis { /// Factory for instantiating and wrapping ProteinLists class PWIZ_API_DECL ProteinListFactory { public: /// instantiate the ProteinListWrapper indicated by wrapper static void wrap(proteome::ProteomeData& pd, const std::string& wrapper); /// instantiate a list of ProteinListWrappers static void wrap(proteome::ProteomeData& pd, const std::vector& wrappers); /// user-friendly documentation static std::string usage(); }; } // namespace analysis } // namespace pwiz #endif // _PROTEINLISTFACTORY_HPP_ pwiz/pwiz/analysis/proteome_processing/ProteinList_FilterTest.cpp0000664000175100017510000001106012664775613027601 0ustar teamcityteamcity00000000000000// // $Id: ProteinList_FilterTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2012 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "ProteinList_Filter.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/IntegerSet.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz; using namespace pwiz::proteome; using namespace pwiz::analysis; using namespace pwiz::util; using namespace boost::assign; using boost::logic::tribool; ostream* os_ = 0; void printProteinList(const ProteinList& pl, ostream& os) { os << "size: " << pl.size() << endl; for (size_t i=0, end=pl.size(); iindex << " " << protein->id << " " << endl; } } ProteinListPtr createProteinList() { shared_ptr pl(new ProteinListSimple); for (size_t i=0; i<10; ++i) { ProteinPtr protein(new Protein("Pro" + lexical_cast(i+1), i, "", string(16, 'A'+i))); pl->proteins.push_back(protein); } if (os_) { *os_ << "original protein list:\n"; printProteinList(*pl, *os_); *os_ << endl; } return pl; } struct SelectedIndexPredicate : public ProteinList_Filter::Predicate { mutable bool pastMaxIndex; SelectedIndexPredicate() : pastMaxIndex(false) {} virtual tribool accept(const Protein& protein) const { if (protein.index>5) pastMaxIndex = true; return (protein.index==1 || protein.index==3 || protein.index==5); } virtual bool done() const { return pastMaxIndex; } }; void testSelectedIndices(ProteinListPtr pl) { if (os_) *os_ << "testSelectedIndices:\n"; ProteinList_Filter filter(pl, SelectedIndexPredicate()); if (os_) { printProteinList(filter, *os_); *os_ << endl; } unit_assert_operator_equal(3, filter.size()); unit_assert_operator_equal("Pro2", filter.protein(0)->id); unit_assert_operator_equal("Pro4", filter.protein(1)->id); unit_assert_operator_equal("Pro6", filter.protein(2)->id); } void testIndexSet(ProteinListPtr pl) { if (os_) *os_ << "testIndexSet:\n"; IntegerSet indexSet; indexSet.insert(3,5); indexSet.insert(7); indexSet.insert(9); ProteinList_Filter filter(pl, ProteinList_FilterPredicate_IndexSet(indexSet)); if (os_) { printProteinList(filter, *os_); *os_ << endl; } unit_assert_operator_equal(5, filter.size()); unit_assert_operator_equal("Pro4", filter.protein(0)->id); unit_assert_operator_equal("Pro5", filter.protein(1)->id); unit_assert_operator_equal("Pro6", filter.protein(2)->id); unit_assert_operator_equal("Pro8", filter.protein(3)->id); unit_assert_operator_equal("Pro10", filter.protein(4)->id); } void testIdSet(ProteinListPtr pl) { if (os_) *os_ << "testIdSet:\n"; set idSet; idSet += "Pro2", "Pro3", "Pro4", "Pro7"; ProteinList_Filter filter(pl, ProteinList_FilterPredicate_IdSet(idSet)); if (os_) { printProteinList(filter, *os_); *os_ << endl; } unit_assert_operator_equal(4, filter.size()); unit_assert_operator_equal("Pro2", filter.protein(0)->id); unit_assert_operator_equal("Pro3", filter.protein(1)->id); unit_assert_operator_equal("Pro4", filter.protein(2)->id); unit_assert_operator_equal("Pro7", filter.protein(3)->id); } void test() { ProteinListPtr pl = createProteinList(); testSelectedIndices(pl); testIndexSet(pl); testIdSet(pl); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/proteome_processing/ProteinListFactory.cpp0000664000175100017510000001273312664775613026774 0ustar teamcityteamcity00000000000000// // $Id: ProteinListFactory.cpp 4010 2012-10-17 20:22:16Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2012 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "ProteinListFactory.hpp" #include "ProteinList_Filter.hpp" #include "ProteinList_DecoyGenerator.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/Filesystem.hpp" namespace pwiz { namespace analysis { using namespace pwiz::proteome; using namespace pwiz::util; namespace { // // each ProteinListWrapper has a filterCreator_* function, // and an entry in the jump table below // typedef ProteinListPtr (*FilterCreator)(const ProteomeData& pd, const string& arg); ProteinListPtr filterCreator_index(const ProteomeData& pd, const string& arg) { IntegerSet indexSet; indexSet.parse(arg); return ProteinListPtr(new ProteinList_Filter(pd.proteinListPtr, ProteinList_FilterPredicate_IndexSet(indexSet))); } ProteinListPtr filterCreator_id(const ProteomeData& pd, const string& arg) { vector tokens; bal::split(tokens, arg, bal::is_any_of(";")); if (tokens.size() == 1 && bfs::exists(tokens[0])) { ifstream idListFile(tokens[0].c_str()); string token; tokens.clear(); while(idListFile >> token) tokens.push_back(token); } return ProteinListPtr(new ProteinList_Filter(pd.proteinListPtr, ProteinList_FilterPredicate_IdSet(tokens.begin(), tokens.end()))); } ProteinListPtr filterCreator_decoyGenerator(const ProteomeData& pd, const string& arg) { istringstream argStream(arg); string mode, prefix; argStream >> mode >> prefix; if (prefix.empty()) throw user_error("[ProteinListFactory::filterCreator_decoyGenerator] no decoy prefix provided"); ProteinList_DecoyGenerator::PredicatePtr predicate; if (bal::iequals(mode, "reverse")) predicate.reset(new ProteinList_DecoyGeneratorPredicate_Reversed(prefix)); else if (bal::istarts_with(mode, "shuffle")) { boost::uint32_t randomSeed; vector tokens; bal::split(tokens, mode, bal::is_any_of("=")); if (tokens.size() == 2) try {randomSeed = lexical_cast(tokens[1]);} catch(bad_lexical_cast&) {randomSeed = 0;} predicate.reset(new ProteinList_DecoyGeneratorPredicate_Shuffled(prefix, randomSeed)); } else throw user_error("[ProteinListFactory::filterCreator_decoyGenerator] invalid decoy mode '" + mode + "' (expected 'reverse' or 'shuffle')"); return ProteinListPtr(new ProteinList_DecoyGenerator(pd.proteinListPtr, predicate)); } struct JumpTableEntry { const char* command; const char* usage; FilterCreator creator; }; JumpTableEntry jumpTable_[] = { {"index", "int_set", filterCreator_index}, {"id", "filepath to a line-by-line list OR semicolon-delimited list of protein ids (unique accession strings)", filterCreator_id}, {"decoyGenerator", " ", filterCreator_decoyGenerator}, }; size_t jumpTableSize_ = sizeof(jumpTable_)/sizeof(JumpTableEntry); JumpTableEntry* jumpTableEnd_ = jumpTable_ + jumpTableSize_; struct HasCommand { HasCommand(const string& command) : command_(command) {} bool operator()(const JumpTableEntry& entry) {return command_ == entry.command;} string command_; }; } // namespace PWIZ_API_DECL void ProteinListFactory::wrap(ProteomeData& pd, const string& wrapper) { // split wrapper string into command + arg istringstream iss(wrapper); string command; iss >> command; string arg = wrapper.substr(command.size() + 1); // switch on command, instantiate the filter JumpTableEntry* entry = find_if(jumpTable_, jumpTableEnd_, HasCommand(command)); if (entry == jumpTableEnd_) { cerr << "[ProteinListFactory] Ignoring wrapper: " << wrapper << endl; return; } ProteinListPtr filter = entry->creator(pd, arg); if (!filter.get()) { cerr << "command: " << command << endl; cerr << "arg: " << arg << endl; throw runtime_error("[ProteinListFactory::wrap()] Error creating filter."); } // replace existing ProteinList with the new one pd.proteinListPtr = filter; } PWIZ_API_DECL void ProteinListFactory::wrap(proteome::ProteomeData& pd, const vector& wrappers) { for (vector::const_iterator it=wrappers.begin(); it!=wrappers.end(); ++it) wrap(pd, *it); } PWIZ_API_DECL string ProteinListFactory::usage() { ostringstream oss; oss << "\nFilter options:\n\n"; for (JumpTableEntry* it=jumpTable_; it!=jumpTableEnd_; ++it) oss << it->command << " " << it->usage << endl; oss << endl; oss << "\'int_set\' means that a set of integers must be specified, as a list of intervals of the form [a,b] or a[-][b]\n"; oss << endl; return oss.str(); } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/proteome_processing/ProteinList_Filter.hpp0000664000175100017510000000652012664775613026753 0ustar teamcityteamcity00000000000000// // $Id: ProteinList_Filter.hpp 4010 2012-10-17 20:22:16Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2012 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PROTEINLIST_FILTER_HPP_ #define _PROTEINLIST_FILTER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/proteome/ProteinListWrapper.hpp" #include "pwiz/utility/misc/IntegerSet.hpp" #include "boost/logic/tribool.hpp" #include namespace pwiz { namespace analysis { /// ProteinList filter, for creating Protein sub-lists class PWIZ_API_DECL ProteinList_Filter : public proteome::ProteinListWrapper { public: /// client-implemented filter predicate -- called during construction of /// ProteinList_Filter to create the filtered list of proteins struct PWIZ_API_DECL Predicate { /// return true iff Protein is accepted virtual boost::logic::tribool accept(const proteome::Protein& protein) const {return false;} /// return true iff done accepting proteins; /// this allows early termination of the iteration through the original /// ProteinList, possibly using assumptions about the order of the /// iteration (e.g. index is increasing) virtual bool done() const {return false;} virtual ~Predicate() {} }; ProteinList_Filter(const proteome::ProteinListPtr original, const Predicate& predicate); /// \name ProteinList interface //@{ virtual size_t size() const; virtual proteome::ProteinPtr protein(size_t index, bool getSequence = true) const; //@} private: struct Impl; boost::shared_ptr impl_; ProteinList_Filter(ProteinList_Filter&); ProteinList_Filter& operator=(ProteinList_Filter&); }; class PWIZ_API_DECL ProteinList_FilterPredicate_IndexSet : public ProteinList_Filter::Predicate { public: ProteinList_FilterPredicate_IndexSet(const util::IntegerSet& indexSet); virtual boost::logic::tribool accept(const proteome::Protein& protein) const; virtual bool done() const; private: util::IntegerSet indexSet_; mutable bool eos_; }; class PWIZ_API_DECL ProteinList_FilterPredicate_IdSet : public ProteinList_Filter::Predicate { public: ProteinList_FilterPredicate_IdSet(const std::set& idSet); template ProteinList_FilterPredicate_IdSet(const InputIterator& begin, const InputIterator& end) : idSet_(begin, end) {} virtual boost::logic::tribool accept(const proteome::Protein& protein) const; virtual bool done() const; private: mutable std::set idSet_; }; } // namespace analysis } // namespace pwiz #endif // _PROTEINLIST_FILTER_HPP_ pwiz/pwiz/utility/minimxml/SAXParser.cpp0000664000175100017510000004451212664775616022427 0ustar teamcityteamcity00000000000000// // $Id: SAXParser.cpp 6909 2014-11-19 17:18:29Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Reworked for zero-copy performance by Brian Pratt, Insilicos LLC // those changes Copyright 2011 Insilicos LLC All Rights Reserved // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SAXParser.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/random_access_compressed_ifstream.hpp" #include "boost/xpressive/xpressive_dynamic.hpp" namespace bxp = boost::xpressive; const string CDATA_begin("![CDATA["), CDATA_end("]]"); const string comment_begin("!--"), comment_end("--"); const string DOCTYPE_begin("!DOCTYPE"); #ifdef _DEBUG_READCOUNT // in case you want to verify that you aren't doing excessive reads static boost::iostreams::stream_offset bytesin = 0; void note_read_count(size_t n) { // collect some stats bytesin += n; } #endif namespace pwiz { namespace minimxml { namespace SAXParser { const char* ws = " \n\r\t"; size_t count_trail_ws(const char *data,size_t len) { // remove trailing whitespace if any size_t n=len; while (n && strchr(ws,data[n-1])) n--; return len-n; } namespace { inline bool unbalanced_quotes(const saxstring & buffer) { // find next single or double quote for (const char *c=buffer.c_str();(c=strpbrk(c,"\"'"))!=NULL;c++) { c = strchr(c+1,*c); // find matching quote if (!c) return true; // unmatched quote } return false; } // returns number of ws chars it had to eat on front end // returns -1 if nothing read static int eat_whitespace(istream& is) { char c; int lead_ws=0; while (is.good()) { // loop while extraction from file is possible c = is.get(); // get character from file if (is.good()) { if (strchr(ws,c)) lead_ws++; // eat the whitespace else { is.unget(); break; // no more whitespace } } else break; } #ifdef _DEBUG_READCOUNT note_read_count(lead_ws); // collect some stats #endif if (is.good()) return lead_ws; else return -1; } struct ProcessingInstruction { string name; string value; ProcessingInstruction(const string& buffer) { istringstream iss(buffer); char questionMark = '\0'; iss >> questionMark >> name; if (questionMark != '?') throw runtime_error("[SAXParser::ProcessingInstruction] Error."); eat_whitespace(iss); getline(iss, value, '?'); value.resize(value.length()-count_trail_ws(value.c_str(),value.length())); } }; const char * quote_ = "\"\'"; // // zero-copy StartTag - it hacks up the // saxparser string into name-value pairs // instead of making lots of little std::strings // do that a few bazillion times and it makes // a big difference in performance - bpratt // struct StartTag { bool end; Handler::Attributes attributes; StartTag(saxstring &str, bool unescapeAttributes) : end(str.length() && str[str.length()-1]=='/'), // evaluate str before attributes hacks it up attributes(str,unescapeAttributes) { if (!str.length()) throw runtime_error("[SAXParser::StartTag] Empty buffer."); } const char *getName() { return attributes.getTagName(); // reads from hacked-up input str } }; struct HandlerInfo { Handler& handler; stack names; HandlerInfo(Handler& _handler) : handler(_handler) {} }; // HandlerWrangler responsibilities: // - maintain a Handler stack // - validate return Status from Handler calls // - validate element start/end tag matching class HandlerWrangler : public SAXParser::Handler { public: HandlerWrangler(Handler& root) { handlers_.push(root); } void verifyNoDelegate(const Status& status) { if (status.flag==Status::Delegate || status.delegate) throw runtime_error("[SAXParser] Illegal return of Status::Delegate."); } virtual Status processingInstruction(const string& name, const string& data, stream_offset position) { Status status = handlers_.top().handler.processingInstruction(name, data, position); verifyNoDelegate(status); return status; } virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { HandlerInfo& top = handlers_.top(); // element start/end validation top.names.push(name); // call handler Handler::Status status = top.handler.startElement(name, attributes, position); if (status.flag != Handler::Status::Delegate) return status; // Status::Delegate: let status.delegate handle this message if (!status.delegate) throw runtime_error("[SAXParser] Null delegate."); top.names.pop(); handlers_.push(*status.delegate); return startElement(name, attributes, position); } virtual Status endElement(const string& name, stream_offset position) { HandlerInfo& top = handlers_.top(); // element start/end validation if (top.names.empty() || top.names.top()!=name) throw runtime_error("[SAXParser::ParserWrangler::elementEnd()] Illegal end tag \"" + name + "\" at offset " + lexical_cast(position) + "."); top.names.pop(); // call handler Status status = top.handler.endElement(name, position); verifyNoDelegate(status); // delete handler if we're done with it if (top.names.empty()) { handlers_.pop(); if (handlers_.empty()) return Status::Done; } return status; } virtual Status characters(const SAXParser::saxstring& text, stream_offset position) { Status status = topHandler().characters(text, position); verifyNoDelegate(status); return status; } const Handler& topHandler() const {return handlers_.top().handler;} Handler& topHandler() {return handlers_.top().handler;} private: stack handlers_; }; } // namespace void Handler::Attributes::parseAttributes(string::size_type& index) const { if (!attrs.size()) { // first access // avoid lots of reallocs int n_equals=0; for (const char *p=textbuff+index;(p=strchr(p,'='))!=NULL;p++) n_equals++; attrs.resize(n_equals); // might be more than we need, but we'll correct int nattrs = 0; while (index < index_end) { string::size_type indexNameBegin = index; string::size_type indexNameEnd = indexNameBegin; string::size_type indexQuoteOpen; string::size_type indexQuoteClose; const char *eq=strchr(textbuff+indexNameBegin,'='); if (eq) { indexNameEnd = eq-textbuff; const char *c=textbuff+indexNameEnd+1; while (*c && !strchr(quote_,*c)) c++; indexQuoteOpen = (c-textbuff); char quoteChar = *c; const char *q = strchr(textbuff+indexQuoteOpen+1,quoteChar); indexQuoteClose = q?(q-textbuff):string::npos; } else indexQuoteClose = string::npos; if (indexQuoteClose == string::npos) { // this index can only be OK if the others are too if ('/'==textbuff[indexNameBegin]) { // end of tag index++; break; } else if ('\0'==textbuff[indexNameBegin]) { break; } throw runtime_error("[SAXParser::parseAttribute()] Error at index " + lexical_cast(index) + ":\n" + textbuff); } while (strchr(ws,textbuff[indexNameEnd-1])) indexNameEnd--; // work back from = to end of name textbuff[indexNameEnd]=0; // null terminate in-place textbuff[indexQuoteClose]=0; // null terminate in-place attrs[nattrs++].set(textbuff+indexNameBegin,textbuff+indexQuoteOpen+1,autoUnescape); index = indexQuoteClose+1; // ready for next round while (textbuff[index] && strchr(ws,textbuff[index])) // eat whitespace index++; } attrs.resize(nattrs); } } void unescapeXML(std::string &str) { if (std::string::npos != str.find('&')) { SAXParser::saxstring s(str); s.unescapeXML(); str = s.c_str(); } } void unescapeXML(char *str) { char *amp; size_t end=strlen(str); for (size_t i=0 ; (amp=strchr(str+i,'&'))!=NULL ; i++) { i = (amp-str); // there must be at least three characters after '&' (< or >) if (i+3 >= end) throw runtime_error("[SAXParser::unescapeXML] Invalid escape sequence \"" + string(str) + "\"."); int adjustlen=0; if (str[i+1] == 'l' && str[i+2] == 't' && str[i+3] == ';') { *amp = '<'; adjustlen=3; } else if (str[i+1] == 'g' && str[i+2] == 't' && str[i+3] == ';') { *amp = '>'; adjustlen = 3; } else if (i+4 < end && str[i+1] == 'a' && str[i+2] == 'm' && str[i+3] == 'p' && str[i+4] == ';') { *amp = '&'; adjustlen = 4; } else if (i+5 < end && str[i+1] == 'q' && str[i+2] == 'u' && str[i+3] == 'o' && str[i+4] == 't' && str[i+5] == ';') { *amp = '"'; adjustlen = 5; } else if (i+5 < end && str[i+1] == 'a' && str[i+2] == 'p' && str[i+3] == 'o' && str[i+4] == 's' && str[i+5] == ';') { *amp = '\''; adjustlen = 5; } else throw runtime_error("[SAXParser::unescapeXML] Invalid escape sequence."); memmove(amp+1,amp+adjustlen+1,(end-(i+adjustlen))); end -= adjustlen; } } // (nearly)zero-copy getline static bool getline(istream& is, saxstring &vec, char delim, bool append = false) { const size_t minbuf = 1024; size_t begin = append?vec.length():0; size_t end = begin; while (is.good()) { if (vec.capacity() < minbuf + (begin+3)) { size_t newsize = 2* ( vec.capacity() ? vec.capacity() : minbuf ); vec.resize(newsize); } char *buffer = &vec[0]; // always guarantee room for readahead and nullterm at end of buffer is.get(buffer+begin, vec.capacity()-(begin+3), delim); // keeps delim if read size_t nread = (size_t)is.gcount(); if (!nread && !is.eof()) // empty line? is.clear(); // clear the failbit end += nread; #ifdef _DEBUG_READCOUNT note_read_count(nread+1); // collect some stats #endif // did we stop reading because we hit delimiter? char c=0; is.get(c); if (delim == c) { // full read vec.resize(end); // so we don't copy more than we need return true; } else if (c) { // ran out of room buffer[end++] = c; buffer[end] = 0; begin = end; } } return false; } // // parse() responsibilities: // - stream parsing // - initiation of events // - events are routed through a HandlerWrangler // - HandlerWrangler handles any XML/Handler validation // - return on Handler::Status::Done // PWIZ_API_DECL void parse(istream& is, Handler& handler) { using boost::iostreams::position_to_offset; HandlerWrangler wrangler(handler); Handler::stream_offset position = position_to_offset(is.tellg()); saxstring buffer(16384); // hopefully big enough to avoid realloc while (is) { // read text up to next tag (may be empty) buffer.clear(); if (!getline(is, buffer, '<')) break; size_t lead_ws = buffer.trim_lead_ws(); // remove trailing ws buffer.trim_trail_ws(); // position == beginning of characters position += lead_ws; // TODO: is it possible to detect when Handler::characters() has been overridden? const Handler& topHandler = wrangler.topHandler(); if (buffer.length() && topHandler.parseCharacters) { if (topHandler.autoUnescapeCharacters) buffer.unescapeXML(); Handler::Status status = wrangler.characters(buffer, position); if (status.flag == Handler::Status::Done) return; } // position == beginning of tag position = position_to_offset(is.tellg()); if (position > 0) position--; // read tag bool inCDATA; buffer.clear(); while (true) { bool firstpass = (!buffer.length()); if (!getline(is,buffer, '>',true)) // append break; if (firstpass) buffer.trim_lead_ws(); inCDATA = buffer.starts_with(CDATA_begin.c_str()); // If in CDATA, fetch more until the section is ended; // else deal with the unlikely but still legal case // // You're a monster, Zorg.>I know. // if (inCDATA ? !buffer.ends_with(CDATA_end.c_str()) : unbalanced_quotes(buffer)) buffer += ">"; // put back that char we ate, go for more else break; } // remove trailing ws buffer.trim_trail_ws(); if (!buffer.length()) throw runtime_error("[SAXParser::parse()] Empty tag at offset " + lexical_cast(position) + "."); // switch on tag type switch (buffer[0]) { case '?': { ProcessingInstruction pi(buffer.c_str()); Handler::Status status = wrangler.processingInstruction(pi.name, pi.value, position); if (status.flag == Handler::Status::Done) return; break; } case '/': { Handler::Status status = wrangler.endElement(buffer.c_str()+1, position); if (status.flag == Handler::Status::Done) return; break; } case '!': { if (inCDATA) { std::string buf(buffer.c_str()); Handler::Status status = wrangler.characters(buf.substr(CDATA_begin.length(), buffer.length()-CDATA_begin.length()-CDATA_end.length()), position); if (status.flag == Handler::Status::Done) return; } else if (!buffer.starts_with(DOCTYPE_begin.c_str()) && (!buffer.starts_with("!--") || !buffer.ends_with("--"))) throw runtime_error("[SAXParser::parse()] Illegal comment \"" + string(buffer.c_str()) + "\" at offset " + lexical_cast(position) + "."); break; } default: { StartTag tag(buffer, handler.autoUnescapeAttributes); Handler::Status status = wrangler.startElement(tag.getName(), tag.attributes, position); if (status.flag == Handler::Status::Done) return; if (tag.end) { status = wrangler.endElement(tag.getName(), position); if (status.flag == Handler::Status::Done) return; } } } // position == after tag end position = position_to_offset(is.tellg()); } } } // namespace SAXParser string xml_root_element(const string& fileheader) { const static bxp::sregex e = bxp::sregex::compile("<\\?xml.*?>.*?<([^?!]\\S+?)[\\s>]"); // convert Unicode to ASCII string asciiheader; asciiheader.reserve(fileheader.size()); BOOST_FOREACH(char c, fileheader) { if(c > 0) asciiheader.push_back(c); } bxp::smatch m; if (bxp::regex_search(asciiheader, m, e)) return m[1]; throw runtime_error("[xml_root_element] Root element not found (header is not well-formed XML)"); } string xml_root_element(istream& is) { char buf[513]; is.read(buf, 512); buf[512] = 0; return xml_root_element(buf); } string xml_root_element_from_file(const string& filepath) { pwiz::util::random_access_compressed_ifstream file(filepath.c_str()); if (!file) throw runtime_error("[xml_root_element_from_file] Error opening file"); return xml_root_element(file); } namespace { bool isalnum(char& c) {return std::isalnum(c, std::locale::classic());} } PWIZ_API_DECL string& decode_xml_id(string& str) { std::istringstream parser; for (size_t i=0; i < str.length(); ++i) { size_t found = str.find("_x00"); if (found != string::npos && found+6 < str.length() && isalnum(str[found+4]) && isalnum(str[found+5]) && str[found+6] == '_') { parser.clear(); // reset state parser.str(str.substr(found+4, 2)); int value; parser >> std::hex >> value; char decoded = (char) value; str.replace(found, 7, &decoded, 1); } else break; } return str; } PWIZ_API_DECL string decode_xml_id_copy(const string& str) { string copy(str); return decode_xml_id(copy); } } // namespace minimxml } // namespace pwiz pwiz/pwiz/utility/minimxml/SAXParser.hpp0000664000175100017510000005501312664775616022432 0ustar teamcityteamcity00000000000000// // $Id: SAXParser.hpp 3703 2012-06-15 18:23:36Z pcbrefugee $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Reworked for zero-copy performance by Brian Pratt, Insilicos LLC // those changes Copyright 2011 Insilicos LLC All Rights Reserved // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SAXPARSER_HPP_ #define _SAXPARSER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/utility/misc/optimized_lexical_cast.hpp" #include "pwiz/utility/misc/shared_map.hpp" #include "boost/iostreams/positioning.hpp" #include #include #include #include #include #include namespace pwiz { namespace minimxml { /// /// An extended SAX interface for custom XML stream parsing. /// /// Use cases: /// - read a single element /// - read a single element, aborting on a specified tag /// - delegate handling of a sub-element to another handler /// namespace SAXParser { PWIZ_API_DECL size_t count_trail_ws(const char *data,size_t len); // count whitespace chars at end of data PWIZ_API_DECL void unescapeXML(char *str); PWIZ_API_DECL void unescapeXML(std::string &str); class saxstring { // simple string management for zero-copy saxparser // // not using std::string due to overhead with: // reference counts // exception unwinding // etc etc // // provides for zero-copy trimming of whitespace // public: saxstring(size_t size = 0) { init(size); } saxstring(const SAXParser::saxstring &rhs) { *this = rhs; } saxstring(const std::string &rhs) { init(rhs.length()); memcpy(data(),rhs.c_str(),rhs.length()); (*this)[rhs.length()] = 0; // nullterm } void unescapeXML() { if (strchr(c_str(),'&')) { SAXParser::unescapeXML(data()); resize(strlen(c_str())); } } ~saxstring() { free(_data); } saxstring & operator = (const SAXParser::saxstring &rhs) { init(rhs.length()); if (length()) { memcpy(data(),rhs.c_str(),length()+1); } return *this; } saxstring & operator = (const char *rhs) { init(rhs ? strlen(rhs) : 0); if (length()) { memcpy(data(),rhs,length()+1); } return *this; } saxstring & operator += (const SAXParser::saxstring &rhs) { if (rhs.length()) { size_t oldsize = length(); resize(rhs.length()+oldsize); memcpy(data()+oldsize,rhs.c_str(),rhs.length()+1); } return *this; } saxstring & operator += (const char *rhs) { size_t rhslen = rhs?strlen(rhs):0; if (rhslen) { size_t oldsize = length(); resize(rhslen+oldsize); strcpy(data()+oldsize,rhs); } return *this; } bool operator == (const char *c) const { return c && !strcmp(c,c_str()); } bool operator == (const std::string &s) const { return !strcmp(c_str(),s.c_str()); } bool operator == (const saxstring &s) const { return !strcmp(c_str(),s.c_str()); } char *resize(size_t size) { if (!size) { _lead = 0; // empty, reclaim the start of buffer } size_t new_used = size + _lead; // translate to "used" space if (new_used >= _capacity) { _data = (char *)realloc(_data, (_used = new_used)+1); if (_used && !_data) { throw std::runtime_error("SAXParser: cannot allocate memory"); } _capacity = _used; } else { _used = new_used; } _data[_used] = 0; return _data; } void clear() { resize(0); } inline const char *c_str() const { return _data?_data+_lead:""; } inline char & operator [](size_t n) { return *(data()+n); } inline size_t length() const { return _used-_lead; } inline size_t capacity() const { return _capacity; } void trim_trail_ws() { // remove trailing whitespace if any size_t n = count_trail_ws(c_str(),length()); resize(length()-n); } // returns number of ws chars it had to eat on front end int trim_lead_ws() { size_t n=0; for (const char *c=c_str(); *c && strchr(" \n\r\t",*c); c++) { n++; } _lead += n; return n; } bool starts_with(const char *txt) const { return !strncmp(c_str(),txt,strlen(txt)); } bool ends_with(const char *txt) const { size_t len = strlen(txt); return (len <= length()) ? (!strcmp(c_str()+length()-len,txt)) : false; } char *data() { // direct access to data buffer if (!_data) { resize(0); } return _data+_lead; } private: void init(size_t size) { _used = 0; _lead = 0; _capacity = 0; _data = NULL; if (size) { resize(size); } } char * _data; // char buf size_t _used; // characters used size_t _lead; // for skipping whitespace size_t _capacity; // max characters (always >_used) }; inline std::ostream& operator<<(std::ostream& os, const saxstring& s) { os << s.c_str(); return os; } // fast string-to-value conversions // not very boost-y, or even very c++, but lexical_cast and istringstreams are // just too slow for our parsing performance needs. template< typename Target > inline Target textToValue(const char *txt); // template prototype template<> inline float textToValue(const char *txt) { return (float) ATOF( txt ) ; } template<> inline double textToValue(const char *txt) { return ATOF( txt ); } template<> inline int textToValue(const char *txt) { return atoi(txt); } template<> inline char textToValue(const char *txt) { return *(txt); } template<> inline long textToValue(const char *txt) { return atol(txt); } template<> inline unsigned int textToValue(const char *txt) { return (unsigned int) strtoul( txt, NULL, 10 ); } template<> inline unsigned long textToValue(const char *txt) { return strtoul( txt, NULL, 10 ); } #if defined(BOOST_HAS_LONG_LONG) template<> inline long long textToValue(const char *txt) { #if defined(BOOST_HAS_MS_INT64) return _atoi64(txt); #else return atoll(txt); #endif } template<> inline unsigned long long textToValue(const char *txt) { #if defined(BOOST_HAS_MS_INT64) return _strtoui64(txt,NULL,10); #else return strtoull( txt, NULL, 10 ); #endif } #endif // has long long inline bool istrue(const char *t) { return strcmp(t, "0") && strcmp(t,"false"); // as in optimized_lexical_cast.h } template<> inline bool textToValue(const char *txt) { return istrue(txt); } template<> inline boost::logic::tribool textToValue(const char *txt) { using namespace boost::logic; if (!*txt) return tribool(indeterminate); else { bool b = istrue(txt); return tribool(b); } } template<> inline std::string textToValue(const char *txt) { return std::string( txt ); } /// SAX event handler interface. class Handler { public: /// When false, no calls to characters() will be made bool parseCharacters; /// Setting these to false will disable the auto-unescaping feature of the parser; /// this is useful for handlers which deal with large amounts of data bool autoUnescapeAttributes, autoUnescapeCharacters; /// contextual version available to control handler logic which support multiple versions of a schema; /// the default value 0 indicates handler should ignore the version; /// the handler determines the meaning of any non-zero value int version; /// Handler returns the Status struct as a means of changing the parser's behavior. struct Status { enum Flag { Ok, // ok, continue parsing the stream Done, // abort immediately Delegate // delegate this element to the specified Handler [startElement() only] }; Flag flag; Handler* delegate; // valid iff (flag == Delegate) Status(Flag _flag = Ok, Handler* _delegate = 0) : flag(_flag), delegate(_delegate) {} }; enum XMLUnescapeBehavior_t {XMLUnescapeDefault,NoXMLUnescape}; class Attributes { // lazy evaluation - doesn't process text until asked // near-zero copy - copies the source text just once, // instead of a bunch of little std::string operations public: Attributes(const char * _source_text, size_t _source_text_len, bool _autoUnescape) : index(0),index_end(0),autoUnescape(_autoUnescape),firstread(true),attrs() { size=_source_text_len; textbuff = (char *)malloc(size+1); managemem = true; memcpy(textbuff,_source_text,size); textbuff[size] = 0; setParserIndex(); // ready for eventual parsing test_invariant(); // everything correct? }; Attributes() : index(0),index_end(0),autoUnescape(false),firstread(true),attrs() { size=0; textbuff = NULL; managemem = true; test_invariant(); // everything correct? }; Attributes(saxstring &str, bool _autoUnescape) : index(0),index_end(0),autoUnescape(_autoUnescape),firstread(true),attrs() { textbuff = str.data(); size=str.length(); managemem = false; // we don't have to free this setParserIndex(); // ready for eventual parsing test_invariant(); // everything correct? }; ~Attributes() { if (managemem) free(textbuff); } Attributes(const Attributes &rhs) { textbuff = NULL; *this = rhs; } Attributes & operator = (const Attributes &rhs) { size = rhs.size; index = rhs.index; index_end = rhs.index_end; // string bounds for attribute parsing autoUnescape = rhs.autoUnescape; // do XML escape of attribute? firstread = rhs.firstread; // may change during const access if (managemem) textbuff = (char *)realloc(textbuff,size+1); else textbuff = (char *)malloc(size+1); managemem = true; // we need to free textbuff at dtor memcpy(textbuff,rhs.textbuff,size+1); attrs.resize(rhs.attrs.size()); // now fix up the char ptrs to point to our copy of attribute list for (size_t n=attrs.size();n--;) { attrs[n].name = ((char *)textbuff)+(rhs.attrs[n].getName()-rhs.getTextBuffer()); attrs[n].value = ((char *)textbuff)+(rhs.attrs[n].getValuePtr()-rhs.getTextBuffer()); } test_invariant(); // everything correct? return *this; } inline void test_invariant() const { #ifdef _DEBUG for (size_t n=attrs.size();n--;) { assert(textbuff != NULL); assert(attrs[n].name>textbuff); assert(attrs[n].value>attrs[n].name); assert(attrs[n].valueattrs[n-1].value); } #endif } const char *getTagName() const { // work area contains tag name test_invariant(); // everything correct? return textbuff+('/'==*textbuff); } const char *getTextBuffer() const { // return pointer to our work area test_invariant(); // everything correct? return textbuff; } size_t getSize() const { return size; } protected: mutable char *textbuff; // we'll operate on this copy of string size_t size; mutable size_t index,index_end; // string bounds for attribute parsing bool autoUnescape; // do XML escape of attribute? bool managemem; // if true we need to free on exit mutable bool firstread; // may change during const access void setParserIndex() { // on entry, buffer has form "foo bar="baz" or maybe "foo/" const char *c = textbuff; while (*c && !strchr(" \n\r\t/",*c)) c++; size_t indexNameEnd = c-textbuff; while (*c && strchr(" \n\r\t",*c)) c++; textbuff[indexNameEnd] = 0; // nullterm the name index = c-textbuff; // should point to bar index_end = size; test_invariant(); // everything correct? } public: class attribute { // a set of pointers into the main text buffer - going for zero copy, for speed public: attribute() {}; bool matchName(const char *test) const { return !strcmp(test,name); // return true on match } const char *getName() const { return name; } // handle XML escapes on demand const char *getValuePtr(XMLUnescapeBehavior_t Unescape = XMLUnescapeDefault) const { if (Unescape == NoXMLUnescape) needsUnescape = false; else if (needsUnescape) { unescapeXML(value); needsUnescape = false; } return value; } std::string getValue(XMLUnescapeBehavior_t Unescape = XMLUnescapeDefault) const { return std::string(getValuePtr(Unescape)); } // cast-to-type template< typename T > inline T valueAs( XMLUnescapeBehavior_t Unescape ) const { return textToValue(getValuePtr(Unescape)); } inline size_t valueAs( XMLUnescapeBehavior_t Unescape ) const { return (size_t)strtoul(getValuePtr(Unescape),NULL,10); } friend class Attributes; protected: const char *name; // attribute name - a pointer into main text buffer char *value; // also a pointer into main text buffer, content may change during read mutable bool needsUnescape; // may change during read void set(const char *_name, char *_value, bool _needsUnescape) { name = _name; value = _value; needsUnescape = _needsUnescape; } }; // class attribute public: typedef std::vector attribute_list; protected: mutable attribute_list attrs; // may change even in a const function due to lazy evaluation public: attribute_list::const_iterator begin() const { access(); // have we actually parsed the attributes text yet? return attrs.begin(); } attribute_list::const_iterator end() const { access(); // have we actually parsed the attributes text yet? return attrs.end(); } attribute_list::const_iterator find(const std::string &name) const { attribute_list::const_iterator it; for (it = begin(); it != end() ; it++ ) { if (it->matchName(name.c_str())) break; // found it } return it; } protected: PWIZ_API_DECL void parseAttributes(std::string::size_type& index) const; void access() const { // don't parse attributes until asked to test_invariant(); // everything correct? if (firstread) { firstread = false; parseAttributes(index); } test_invariant(); // everything correct? } public: const attribute *findAttributeByName(const char *name) const { access(); // parse the buffer if we haven't already for (attribute_list::const_iterator it=attrs.begin();it!=attrs.end();it++) { if (it->matchName(name)) return &(*it); } return NULL; } // return value for name if any, or NULL const char *findValueByName(const char *name,XMLUnescapeBehavior_t Unescape = XMLUnescapeDefault) const { const attribute *attr = findAttributeByName(name); if (attr) return attr->getValuePtr(Unescape); return NULL; } }; typedef boost::iostreams::stream_offset stream_offset; virtual Status processingInstruction(const std::string& name, const std::string& data, stream_offset position) {return Status::Ok;} virtual Status startElement(const std::string& name, const Attributes& attributes, stream_offset position) {return Status::Ok;} virtual Status endElement(const std::string& name, stream_offset position) {return Status::Ok;} virtual Status characters(const SAXParser::saxstring& text, stream_offset position) {return Status::Ok;} Handler() : parseCharacters(false), autoUnescapeAttributes(true), autoUnescapeCharacters(true), version(0) {} virtual ~Handler(){} protected: template inline T& getAttribute(const Attributes& attributes, const char * name, T& result, XMLUnescapeBehavior_t Unescape, T defaultValue = T()) const { const Attributes::attribute *attr = attributes.findAttributeByName(name); if (attr) result = attr->valueAs(Unescape); else result = defaultValue; return result; } const char *getAttribute(const Attributes& attributes, const char * name, XMLUnescapeBehavior_t Unescape, const char * defaultValue = NULL) const { const char *val = attributes.findValueByName(name,Unescape); if (!val) val = defaultValue; return val; } // general case using default unescape behavior template inline T& getAttribute(const Attributes& attributes, const char *name, T& result) const { const Attributes::attribute *attr = attributes.findAttributeByName(name); if (attr) result = attr->valueAs(XMLUnescapeDefault); else result = T(); return result; } inline std::string& getAttribute(const Attributes& attributes, const char *name, std::string& result) const { const Attributes::attribute *attr = attributes.findAttributeByName(name); if (attr) result = attr->getValuePtr(XMLUnescapeDefault); else result = ""; return result; } // general case using default unescape behavior template inline T& getAttribute(const Attributes& attributes, const std::string &name, T& result, T defaultValue = T()) const { const Attributes::attribute *attr = attributes.findAttributeByName(name.c_str()); if (attr) result = attr->valueAs(XMLUnescapeDefault); else result = defaultValue; return result; } }; /// /// Extract a single XML element from the istream, sending SAX events to the handler. /// /// Behavior: /// /// - Parser returns when it completes reading of the first element it encounters. /// /// - Parser returns immediately if the Handler returns Status::Done when handling an event. /// /// - On startElement(), Handler may delegate handling to a sub-Handler, which will receive /// the same startElement() event. The sub-Handler pointer will remain on the parser's /// Handler stack until it handles the corresponding endElement(). Caution: The sub-Handler /// pointer must remain valid while it is on the Handler stack, so it cannot point to /// a local object that goes out of scope when Handler:startElement() returns. /// /// Notes: /// - Start tags with end marker '/' generate two events, e.g.
will generate events /// startElement("br", ...) and endElement("br"). /// PWIZ_API_DECL void parse(std::istream& is, Handler& handler); } // namespace SAXParser /// Returns the root element from an XML buffer; /// throws runtime_error if no element is found. PWIZ_API_DECL std::string xml_root_element(const std::string& fileheader); /// Returns the root element from an XML stream; /// throws runtime_error if no element is found. PWIZ_API_DECL std::string xml_root_element(std::istream& is); /// Returns the root element from an XML file; /// throws runtime_error if no element is found. PWIZ_API_DECL std::string xml_root_element_from_file(const std::string& filepath); /// Decodes any characters encoded with their hexadecimal value, /// e.g. "_x0020_" decodes as " " /// This override modifies the input string in place and returns its reference. PWIZ_API_DECL std::string& decode_xml_id(std::string& str); /// Decodes any characters encoded with their hexadecimal value, /// e.g. "_x0020_" decodes as " " /// This override modifies and returns a copy of the input string. PWIZ_API_DECL std::string decode_xml_id_copy(const std::string& str); } // namespace minimxml } // namespace pwiz #endif // _SAXPARSER_HPP_ pwiz/pwiz/utility/minimxml/XMLWriter.hpp0000664000175100017510000001472012664775616022457 0ustar teamcityteamcity00000000000000// // $Id: XMLWriter.hpp 2763 2011-06-09 19:44:07Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _XMLWRITER_HPP_ #define _XMLWRITER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/utility/misc/optimized_lexical_cast.hpp" #include "boost/shared_ptr.hpp" #include "boost/iostreams/positioning.hpp" #include "boost/iostreams/filter/counter.hpp" #include #include #include namespace pwiz { namespace minimxml { /// /// The XMLWriter class provides simple, tag-level XML syntax writing. /// Internally, XMLWriter keeps a style stack (for client customization /// of the XML style) and an element stack (for element nesting/indentation). /// class PWIZ_API_DECL XMLWriter { public: /// flags to control the XML writing style enum PWIZ_API_DECL StyleFlag { StyleFlag_InlineInner = 0x01, // no whitespace within an element StyleFlag_InlineOuter = 0x02, // no whitespace around an element StyleFlag_Inline = StyleFlag_InlineInner | StyleFlag_InlineOuter, StyleFlag_AttributesOnMultipleLines = 0x04 }; /// interface to allow outside observation of data sent to output stream class PWIZ_API_DECL OutputObserver { public: virtual void update(const std::string& output) = 0; virtual ~OutputObserver(){} }; /// initial configuration of the XMLWriter struct PWIZ_API_DECL Config { unsigned int initialStyle; unsigned int indentationStep; OutputObserver* outputObserver; Config() : initialStyle(0), indentationStep(2), outputObserver(0) {} }; /// vector of name/value pairs to be written as XML attributes class PWIZ_API_DECL Attributes : public std::vector< std::pair > { public: void add(const std::string& name, const double& value); void add(const std::string& name, const int& value); template inline void add(const std::string& name, const T& value) { push_back(make_pair(name, boost::lexical_cast(value))); } }; /// constructor XMLWriter(std::ostream& os, const Config& config = Config()); virtual ~XMLWriter() {} /// pushes style flags onto the internal style stack void pushStyle(unsigned int flags); /// pops the style stack void popStyle(); /// writes a processing instruction void processingInstruction(const std::string& name, const std::string& data); /// tag for indicating an empty element enum EmptyElementTag {NotEmptyElement, EmptyElement}; /// writes element start tag void startElement(const std::string& name, const Attributes& attributes = Attributes(), EmptyElementTag emptyElementTag = NotEmptyElement); /// writes element end tag void endElement(); /// writes character data; /// autoEscape writes reserved XML characters in the input text in their escaped form /// '&', '<', and '>' are '&', '<', '>' respectively void characters(const std::string& text, bool autoEscape = true); typedef boost::iostreams::stream_offset stream_offset; /// returns current stream position stream_offset position() const; /// returns stream position of next element start tag stream_offset positionNext() const; private: class Impl; boost::shared_ptr impl_; XMLWriter(const XMLWriter&); XMLWriter& operator=(const XMLWriter&); }; /// Encodes any characters not suitable in an xml:ID or xml:IDREF /// with their hexadecimal value, e.g. " " encodes as "_x0020_" /// This override modifies the input string in place and returns its reference. PWIZ_API_DECL std::string& encode_xml_id(std::string& str); /// Encodes any characters not suitable in an xml:ID or xml:IDREF /// with their hexadecimal value, e.g. " " encodes as "_x0020_" /// This override modifies and returns a copy of the input string. PWIZ_API_DECL std::string encode_xml_id_copy(const std::string& str); // // Template name: basic_charcounter. // Template paramters: // Ch - The character type. // Description: Filter which counts characters. // Based on boost's basic_counter, but // without the line counting, and couting using // stream_offset instead of int // template class basic_charcounter { public: typedef Ch char_type; struct category : boost::iostreams::dual_use, boost::iostreams::filter_tag, boost::iostreams::multichar_tag, boost::iostreams::optimally_buffered_tag { }; explicit basic_charcounter(int first_char = 0) : chars_(first_char) { } boost::iostreams::stream_offset characters() const { return chars_; } std::streamsize optimal_buffer_size() const { return 0; } template std::streamsize read(Source& src, char_type* s, std::streamsize n) { std::streamsize result = boost::iostreams::read(src, s, n); if (result == -1) return -1; chars_ += result; return result; } template std::streamsize write(Sink& snk, const char_type* s, std::streamsize n) { std::streamsize result = boost::iostreams::write(snk, s, n); chars_ += result; return result; } private: boost::iostreams::stream_offset chars_; }; BOOST_IOSTREAMS_PIPABLE(basic_charcounter, 1) typedef basic_charcounter charcounter; typedef basic_charcounter wcharcounter; } // namespace minimxml } // namespace pwiz #endif // _XMLWRITER_HPP_ pwiz/pwiz/utility/minimxml/XMLWriter.cpp0000664000175100017510000002605712664775616022460 0ustar teamcityteamcity00000000000000// // $Id: XMLWriter.cpp 5091 2013-10-30 20:02:10Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "XMLWriter.hpp" #include "pwiz/utility/misc/Std.hpp" #include "boost/iostreams/filtering_stream.hpp" #include "boost/iostreams/filter/counter.hpp" #include namespace pwiz { namespace minimxml { template struct double12_policy : boost::spirit::karma::real_policies { // we want to generate up to 12 fractional digits static unsigned int precision(T) { return 12; } }; PWIZ_API_DECL void XMLWriter::Attributes::add(const string& name, const double& valueRef) { double value = valueRef; // HACK: karma has a stack overflow on subnormal values, so we clamp to normalized values if (value > 0) value = max(numeric_limits::min(), value); else if (value < 0) value = min(-numeric_limits::min(), value); using namespace boost::spirit::karma; typedef real_generator > double12_type; static const double12_type double12 = double12_type(); char buffer[256]; char* p = buffer; generate(p, double12, value); *p = '\0'; push_back(make_pair(name, std::string(&buffer[0], p))); } PWIZ_API_DECL void XMLWriter::Attributes::add(const string& name, const int& value) { using namespace boost::spirit::karma; static const int_generator intgen = int_generator(); char buffer[256]; char* p = buffer; generate(p, intgen, value); *p = '\0'; push_back(make_pair(name, std::string(&buffer[0], p))); } class XMLWriter::Impl { public: Impl(ostream& os, const Config& config); void pushStyle(unsigned int flags); void popStyle(); void processingInstruction(const string& name, const string& data); void startElement(const string& name, const Attributes& attributes, EmptyElementTag emptyElementTag); void endElement(); void characters(const string& text, bool autoEscape); bio::stream_offset position() const; bio::stream_offset positionNext() const; private: ostream& os_; Config config_; stack elementStack_; stack styleStack_; string indentation() const {return string(elementStack_.size()*config_.indentationStep, ' ');} string indentation(size_t depth) const {return string(depth*config_.indentationStep, ' ');} bool style(StyleFlag styleFlag) const {return styleStack_.top() & styleFlag ? true : false;} }; XMLWriter::Impl::Impl(ostream& os, const Config& config) : os_(os), config_(config) { styleStack_.push(config.initialStyle); } void XMLWriter::Impl::pushStyle(unsigned int flags) { styleStack_.push(flags); } void XMLWriter::Impl::popStyle() { styleStack_.pop(); if (styleStack_.empty()) throw runtime_error("[XMLWriter] Style stack underflow."); } void XMLWriter::Impl::processingInstruction(const string& name, const string& data) { ostream* os = &os_; if (config_.outputObserver) os = new ostringstream; *os << indentation() << "\n"; if (config_.outputObserver) { config_.outputObserver->update(static_cast(os)->str()); os_ << static_cast(os)->str(); delete os; } } void writeEscapedAttributeXML(ostream& os, const string& str) { for (size_t i=0, end=str.size(); i < end; ++i) { const char& c = str[i]; switch (c) { case '&': os << "&"; break; case '"': os << """; break; case '\'': os << "'"; break; case '<': os << "<"; break; case '>': os << ">"; break; default: os << c; break; } } } void writeEscapedTextXML(ostream& os, const string& str) { for (size_t i=0, end=str.size(); i < end; ++i) { const char& c = str[i]; switch (c) { case '&': os << "&"; break; case '<': os << "<"; break; case '>': os << ">"; break; default: os << c; break; } } } void XMLWriter::Impl::startElement(const string& name, const Attributes& attributes, EmptyElementTag emptyElementTag) { ostream* os = &os_; if (config_.outputObserver) os = new ostringstream; if (!style(StyleFlag_InlineOuter)) *os << indentation(); *os << "<" << name; string attributeIndentation(name.size()+1, ' '); for (Attributes::const_iterator it=attributes.begin(); it!=attributes.end(); ++it) { *os << " " << it->first << "=\""; writeEscapedAttributeXML(*os, it->second); *os << "\""; if (style(StyleFlag_AttributesOnMultipleLines) && (it+1)!=attributes.end()) *os << "\n" << indentation() << attributeIndentation; } *os << (emptyElementTag==EmptyElement ? "/>" : ">"); if (!style(StyleFlag_InlineInner) || (!style(StyleFlag_InlineOuter) && emptyElementTag==EmptyElement)) *os << "\n"; if (emptyElementTag == NotEmptyElement) elementStack_.push(name); if (config_.outputObserver) { config_.outputObserver->update(static_cast(os)->str()); os_ << static_cast(os)->str(); delete os; } } void XMLWriter::Impl::endElement() { ostream* os = &os_; if (config_.outputObserver) os = new ostringstream; if (elementStack_.empty()) throw runtime_error("[XMLWriter] Element stack underflow."); if (!style(StyleFlag_InlineInner)) *os << indentation(elementStack_.size()-1); *os << ""; elementStack_.pop(); if (!style(StyleFlag_InlineOuter)) *os << "\n"; if (config_.outputObserver) { config_.outputObserver->update(static_cast(os)->str()); os_ << static_cast(os)->str(); delete os; } } void XMLWriter::Impl::characters(const string& text, bool autoEscape) { ostream* os = &os_; if (config_.outputObserver) os = new ostringstream; if (!style(StyleFlag_InlineInner)) *os << indentation(); if (autoEscape) writeEscapedTextXML(*os, text); else *os << text; if (!style(StyleFlag_InlineInner)) *os << "\n"; if (config_.outputObserver) { config_.outputObserver->update(static_cast(os)->str()); os_ << static_cast(os)->str(); delete os; } } XMLWriter::stream_offset XMLWriter::Impl::position() const { os_ << flush; // check to see if we're actually writing to a gzip file boost::iostreams::filtering_ostream *zipper = dynamic_cast(&os_); if (zipper) { // os_ is actually a boost::iostreams::filtering_ostream with gzip and a counter return zipper->component<0, pwiz::minimxml::charcounter>()->characters(); } else { // OK to do a simple ftellp because seek is implemented, unlike with gzip return boost::iostreams::position_to_offset(os_.tellp()); } } XMLWriter::stream_offset XMLWriter::Impl::positionNext() const { stream_offset offset = position(); if (!style(StyleFlag_InlineOuter)) offset += indentation().size(); return offset; } // // XMLWriter forwarding functions // PWIZ_API_DECL XMLWriter::XMLWriter(ostream& os, const Config& config) : impl_(new Impl(os, config)) {} PWIZ_API_DECL void XMLWriter::pushStyle(unsigned int flags) {impl_->pushStyle(flags);} PWIZ_API_DECL void XMLWriter::popStyle() {impl_->popStyle();} PWIZ_API_DECL void XMLWriter::processingInstruction(const string& name, const string& data) { impl_->processingInstruction(name, data); } PWIZ_API_DECL void XMLWriter::startElement(const string& name, const Attributes& attributes, EmptyElementTag emptyElementTag) { impl_->startElement(name, attributes, emptyElementTag); } PWIZ_API_DECL void XMLWriter::endElement() {impl_->endElement();} PWIZ_API_DECL void XMLWriter::characters(const string& text, bool autoEscape) {impl_->characters(text, autoEscape);} PWIZ_API_DECL XMLWriter::stream_offset XMLWriter::position() const {return impl_->position();} PWIZ_API_DECL XMLWriter::stream_offset XMLWriter::positionNext() const {return impl_->positionNext();} namespace { // NCName ::= NCNameStartChar (NCNameChar)* // NCNameStartChar ::= [A-Z] | '_' | [a-z] // NCNameChar ::= NCNameStartChar | [0-9] | '.' | '-' // // Note: If we were working in Unicode, there's a lot of other valid characters, // but here we'll just encode any non-ASCII value. bool isNCNameStartChar(char& c) { return std::isalpha(c, std::locale::classic()) || c == '_'; } bool isNCNameChar(char& c) { return isNCNameStartChar(c) || std::isdigit(c, std::locale::classic()) || c == '.' || c == '-'; } const char hex[] = "0123456789abcdef"; void insertEncodedChar(string& str, string::iterator& itr) { char c = *itr; *itr = '_'; str.insert(size_t(itr-str.begin()), "_x0000"); itr += 4; *itr = hex[(c & 0xF0) >> 4]; *(++itr) = hex[c & 0x0F]; ++itr; } } // namespace PWIZ_API_DECL string& encode_xml_id(string& str) { if (str.empty()) throw std::invalid_argument("[encode_xml_id] xml:IDs and xml:IDREFs cannot be empty strings"); // reserve size for the worst case scenario (all characters need replacing), // this should be a reasonable guarantee that the iterator won't be invalidated str.reserve(str.length()*7); string::iterator itr = str.begin(); if (!isNCNameStartChar(*itr)) insertEncodedChar(str, itr); for (; itr != str.end(); ++itr) if (!isNCNameChar(*itr)) insertEncodedChar(str, itr); return str; } PWIZ_API_DECL string encode_xml_id_copy(const string& str) { string copy(str); return encode_xml_id(copy); } } // namespace minimxml } // namespace pwiz pwiz/pwiz/utility/minimxml/SAXParserTest.cpp0000664000175100017510000004240012664775616023261 0ustar teamcityteamcity00000000000000// // $Id: SAXParserTest.cpp 4243 2012-12-28 20:24:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/unit.hpp" #include "SAXParser.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include using namespace pwiz::util; using namespace pwiz::minimxml; using namespace pwiz::minimxml::SAXParser; ostream* os_; // note: this tests single-quoted double quotes const char* sampleXML = "\n" "\n" "\n" " \n" " Some Text with Entity References: <&>\n" " \n" " \n" " Pre-Text Inlined text with ]]> Post-text.
\n" "
\n" " \n" " \n" " \n" " \n" " \n" " You're a monster, Zorg.>I know.\n" " \n" "
\n" "The quick brown fox jumps over the lazy dog.\n"; // // demo of event handling // struct PrintAttribute { PrintAttribute(ostream& os) : os_(os) {} ostream& os_; void operator()(const Handler::Attributes::attribute &attr) { os_ << " (" << attr.getName() << "," << attr.getValue() << ")"; } }; class PrintEventHandler : public Handler { public: PrintEventHandler(ostream& os) : os_(os) {} virtual Status processingInstruction(const string& name, const string& value, stream_offset position) { os_ << "[0x" << hex << position << "] processingInstruction: (" << name << "," << value << ")\n"; return Status::Ok; }; virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { os_ << "[0x" << hex << position << "] startElement: " << name; for_each(attributes.begin(), attributes.end(), PrintAttribute(os_)); os_ << endl; return Status::Ok; }; virtual Status endElement(const string& name, stream_offset position) { os_ << "[0x" << hex << position << "] endElement: " << name << endl; return Status::Ok; } virtual Status characters(const SAXParser::saxstring& text, stream_offset position) { os_ << "[0x" << hex << position << "] text: " << text << endl; return Status::Ok; } private: ostream& os_; }; void demo() { if (os_) { *os_ << "sampleXML:\n" << sampleXML << endl; istringstream is(sampleXML); PrintEventHandler handler(*os_); *os_ << "first parse events:\n"; parse(is, handler); *os_ << endl; *os_ << "second parse events:\n"; parse(is, handler); *os_ << endl; } } // // C++ model of the sample XML // struct First { string escaped_attribute; string text; }; struct Second { string param2; string param3; vector text; }; struct Fifth { string leeloo; string mr_zorg; }; struct Root { string param; First first; Second second; Fifth fifth; }; // // // Handlers to connect XML to C++ model // void readAttribute(const Handler::Attributes& attributes, const string& attributeName, string& result) { Handler::Attributes::attribute_list::const_iterator it = attributes.find(attributeName); if (it != attributes.end()) result = it->getValue(); } class FirstHandler : public Handler { public: FirstHandler(First& first, bool autoUnescapeAttributes, bool autoUnescapeCharacters) : object_(first) { parseCharacters = true; this->autoUnescapeAttributes = autoUnescapeAttributes; this->autoUnescapeCharacters = autoUnescapeCharacters; } virtual Status startElement(const string& name, const Handler::Attributes& attributes, stream_offset position) { if (name == "FirstElement") readAttribute(attributes, "escaped_attribute", object_.escaped_attribute); return Status::Ok; } virtual Status characters(const SAXParser::saxstring& text, stream_offset position) { unit_assert_operator_equal(158, position); object_.text = text.c_str(); return Status::Ok; } virtual Status endElement(const string& name, stream_offset position) { unit_assert_operator_equal(210, position); return Status::Ok; } private: First& object_; }; class SecondHandler : public Handler { public: SecondHandler(Second& object, bool autoUnescapeAttributes, bool autoUnescapeCharacters) : object_(object) { parseCharacters = true; this->autoUnescapeAttributes = autoUnescapeAttributes; this->autoUnescapeCharacters = autoUnescapeCharacters; } virtual Status startElement(const string& name, const Handler::Attributes& attributes, stream_offset position) { if (name == "SecondElement") { readAttribute(attributes, "param2", object_.param2); readAttribute(attributes, "param3", object_.param3); // long as we're here, verify copyability of Handler::Attributes Handler::Attributes *copy1 = new Handler::Attributes(attributes); Handler::Attributes copy2(*copy1); delete copy1; std::string str; readAttribute(copy2, "param2", str); unit_assert(str==object_.param2); } return Status::Ok; } virtual Status characters(const SAXParser::saxstring& text, stream_offset position) { object_.text.push_back(text.c_str()); return Status::Ok; } private: Second& object_; }; class FifthHandler : public Handler { public: FifthHandler(Fifth& object, bool autoUnescapeAttributes, bool autoUnescapeCharacters) : object_(object) { parseCharacters = true; this->autoUnescapeAttributes = autoUnescapeAttributes; this->autoUnescapeCharacters = autoUnescapeCharacters; } virtual Status startElement(const string& name, const Handler::Attributes& attributes, stream_offset position) { if (name == "FifthElement") { getAttribute(attributes, "leeloo", object_.leeloo); } return Status::Ok; } virtual Status characters(const SAXParser::saxstring& text, stream_offset position) { object_.mr_zorg = text.c_str(); return Status::Ok; } virtual Status endElement(const string& name, stream_offset position) { unit_assert_operator_equal(625, position); return Status::Ok; } private: Fifth& object_; }; class RootHandler : public Handler { public: RootHandler(Root& root, bool autoUnescapeAttributes = true, bool autoUnescapeCharacters = true) : object_(root), firstHandler_(object_.first, autoUnescapeAttributes, autoUnescapeCharacters), secondHandler_(object_.second, autoUnescapeAttributes, autoUnescapeCharacters), fifthHandler_(object_.fifth, autoUnescapeAttributes, autoUnescapeCharacters) { parseCharacters = true; this->autoUnescapeAttributes = autoUnescapeAttributes; this->autoUnescapeCharacters = autoUnescapeCharacters; } virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "RootElement") { readAttribute(attributes, "param", object_.param); unit_assert_operator_equal(54, position); } else if (name == "FirstElement") { // delegate handling to a FirstHandler unit_assert_operator_equal(86, position); return Status(Status::Delegate, &firstHandler_); } else if (name == "SecondElement") { // delegate handling to a SecondHandler return Status(Status::Delegate, &secondHandler_); } else if (name == "FifthElement") { // delegate handling to a FifthHandler return Status(Status::Delegate, &fifthHandler_); } return Status::Ok; } private: Root& object_; FirstHandler firstHandler_; SecondHandler secondHandler_; FifthHandler fifthHandler_; }; void test() { if (os_) *os_ << "test()\n"; istringstream is(sampleXML); Root root; RootHandler rootHandler(root); parse(is, rootHandler); if (os_) { *os_ << "root.param: " << root.param << endl << "first.escaped_attribute: " << root.first.escaped_attribute << endl << "first.text: " << root.first.text << endl << "second.param2: " << root.second.param2 << endl << "second.param3: " << root.second.param3 << endl << "second.text: "; copy(root.second.text.begin(), root.second.text.end(), ostream_iterator(*os_,"|")); *os_ << "\nfifth.leeloo: " << root.fifth.leeloo << endl << "fifth.mr_zorg: " << root.fifth.mr_zorg << endl << "\n"; } unit_assert_operator_equal("value", root.param); unit_assert_operator_equal("\"<<>\"", root.first.escaped_attribute); unit_assert_operator_equal("Some Text with Entity References: <&>", root.first.text); unit_assert_operator_equal("something", root.second.param2); unit_assert_operator_equal("something.else 1234-56", root.second.param3); unit_assert_operator_equal(4, root.second.text.size()); unit_assert_operator_equal("Pre-Text", root.second.text[0]); unit_assert_operator_equal("Inlined text with", root.second.text[1]); unit_assert_operator_equal("<&\">", root.second.text[2]); unit_assert_operator_equal("Post-text.", root.second.text[3]); unit_assert_operator_equal(">Leeloo > mul-\"tipass", root.fifth.leeloo); unit_assert_operator_equal("You're a monster, Zorg.>I know.", root.fifth.mr_zorg); } void testNoAutoUnescape() { if (os_) *os_ << "testNoAutoUnescape()\n"; istringstream is(sampleXML); Root root; RootHandler rootHandler(root, false, false); parse(is, rootHandler); if (os_) { *os_ << "root.param: " << root.param << endl << "first.escaped_attribute: " << root.first.escaped_attribute << endl << "first.text: " << root.first.text << endl << "second.param2: " << root.second.param2 << endl << "second.param3: " << root.second.param3 << endl << "second.text: "; copy(root.second.text.begin(), root.second.text.end(), ostream_iterator(*os_,"|")); *os_ << "\n\n"; } unit_assert_operator_equal("value", root.param); unit_assert_operator_equal(""<&lt;>"", root.first.escaped_attribute); unit_assert_operator_equal("Some Text with Entity References: <&>", root.first.text); unit_assert_operator_equal("something", root.second.param2); unit_assert_operator_equal("something.else 1234-56", root.second.param3); unit_assert_operator_equal(4, root.second.text.size()); unit_assert_operator_equal("Pre-Text", root.second.text[0]); unit_assert_operator_equal("Inlined text with", root.second.text[1]); unit_assert_operator_equal("<&\">", root.second.text[2]); unit_assert_operator_equal("Post-text.", root.second.text[3]); } class AnotherRootHandler : public Handler { public: virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "AnotherRoot") { unit_assert_operator_equal(656, position); return Status::Done; } return Status::Ok; } }; void testDone() { if (os_) *os_ << "testDone()\n"; istringstream is(sampleXML); AnotherRootHandler handler; parse(is, handler); // parses ... parse(is, handler); // parses and aborts string buffer; getline(is, buffer, '<'); if (os_) *os_ << "buffer: " << buffer << "\n\n"; unit_assert_operator_equal("The quick brown fox jumps over the lazy dog.", buffer); } void testBadXML() { if (os_) *os_ << "testBadXML()\n"; const char* bad = ""; istringstream is(bad); Handler handler; try { parse(is, handler); } catch (exception& e) { if (os_) *os_ << e.what() << "\nOK: Parser caught bad XML.\n\n"; return; } throw runtime_error("Parser failed to catch bad XML."); } struct NestedHandler : public SAXParser::Handler { int count; NestedHandler() : count(0) {} virtual Status endElement(const string& name, stream_offset position) { count++; return Status::Ok; } }; void testNested() { if (os_) *os_ << "testNested()\n"; const char* nested = ""; istringstream is(nested); NestedHandler nestedHandler; parse(is, nestedHandler); if (os_) *os_ << "count: " << nestedHandler.count << "\n\n"; unit_assert_operator_equal(2, nestedHandler.count); } void testRootElement() { if (os_) *os_ << "testRootElement()\n"; string RootElement = "RootElement"; unit_assert_operator_equal(RootElement, xml_root_element(sampleXML)); istringstream sampleXMLStream(sampleXML); unit_assert_operator_equal(RootElement, xml_root_element(sampleXMLStream)); {ofstream sampleXMLFile("testRootElement.xml"); sampleXMLFile << sampleXML;} unit_assert_operator_equal(RootElement, xml_root_element_from_file("testRootElement.xml")); bfs::remove("testRootElement.xml"); unit_assert_operator_equal(RootElement, xml_root_element("")); unit_assert_operator_equal(RootElement, xml_root_element("", decode_xml_id_copy(id2)); unit_assert_operator_equal("_invalid-ID_#2_<3>", decode_xml_id(id2)); string crazyId("_x0021__x0021__x0021_"); unit_assert_operator_equal("!!!", decode_xml_id(crazyId)); } void testSaxParserString() { std::string str = " \t foo \n"; saxstring xstr = str; unit_assert_operator_equal(xstr,str); unit_assert_operator_equal(xstr,str.c_str()); unit_assert_operator_equal(str.length(),xstr.length()); xstr.trim_lead_ws(); unit_assert_operator_equal(xstr.length(),str.length()-3); unit_assert_operator_equal(xstr,str.substr(3)); xstr.trim_trail_ws(); unit_assert_operator_equal(xstr.length(),str.length()-5); unit_assert_operator_equal(xstr,str.substr(3,3)); unit_assert_operator_equal(xstr[1],'o'); xstr[1] = '0'; unit_assert_operator_equal(xstr[1],'0'); std::string str2(xstr.data()); unit_assert_operator_equal(str2,"f0o"); std::string str3(xstr.c_str()); unit_assert_operator_equal(str2,str3); saxstring xstr2(xstr); unit_assert_operator_equal(xstr2,xstr); saxstring xstr3; unit_assert_operator_equal(xstr3.c_str(),std::string()); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; demo(); testSaxParserString(); test(); testNoAutoUnescape(); testDone(); testBadXML(); testNested(); testRootElement(); testDecoding(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/utility/minimxml/XMLWriterTest.cpp0000664000175100017510000001653712664775616023322 0ustar teamcityteamcity00000000000000// // $Id: XMLWriterTest.cpp 6141 2014-05-05 21:03:47Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "XMLWriter.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::minimxml; ostream* os_ = 0; const char* targetXML = "\n" "\n" " \n" " I'm not a crook.\n" " \n" " \n" " \n" " 'Bull<shit!'\n" " \n" " \n" " I did not have sexual relations with that woman.\n" " \n" " \n" " \n" " Mission accomplished.\n" " \n" "\n"; struct TestOutputObserver : public XMLWriter::OutputObserver { virtual void update(const string& output) { cache += output; } string cache; }; void test() { ostringstream oss; TestOutputObserver outputObserver; XMLWriter::Config config; config.indentationStep = 4; config.outputObserver = &outputObserver; XMLWriter writer(oss, config); if (os_) *os_ << "target:\n" << targetXML << endl; unit_assert(writer.position() < 1); // 0 or -1 depending on platform const char* piData = "version=\"1.0\" encoding=\"UTF-8\""; writer.processingInstruction("xml", piData); unit_assert(writer.position() == 39); XMLWriter::Attributes attributes; attributes.push_back(make_pair("name1", "value1")); attributes.push_back(make_pair("name2", "420")); attributes.push_back(make_pair("name3", "0.666")); writer.startElement("root", attributes); unit_assert(writer.position() == 87); unit_assert(writer.positionNext() == 91); attributes.clear(); attributes.push_back(make_pair("name", "nixon")); attributes.push_back(make_pair("color", "red")); attributes.push_back(make_pair("number", "37")); writer.pushStyle(XMLWriter::StyleFlag_AttributesOnMultipleLines); writer.startElement("record", attributes); writer.pushStyle(XMLWriter::StyleFlag_InlineInner); writer.startElement("quote"); writer.characters("I'm not a crook."); writer.endElement(); writer.startElement("resigned", XMLWriter::Attributes(), XMLWriter::EmptyElement); writer.popStyle(); writer.endElement(); writer.popStyle(); attributes.clear(); attributes.push_back(make_pair("name", "\"Penn & Teller\"")); writer.startElement("record", attributes); writer.pushStyle(XMLWriter::StyleFlag_InlineInner); writer.startElement("quote"); writer.characters("'Bull"); unit_assert(encode_xml_id_copy(id2) == "_invalid-ID__x0023_2__x003c_3_x003e_"); unit_assert(encode_xml_id(id2) == "_invalid-ID__x0023_2__x003c_3_x003e_"); string crazyId("!!!"); unit_assert(encode_xml_id(crazyId) == "_x0021__x0021__x0021_"); } void testNormalization() { #ifndef __APPLE__ // TODO: how to test that this works with Darwin's compiler? // test that subnormal values are clamped and provide 12 decimal places XMLWriter::Attributes attributes; attributes.add("1", 2.2250738585072014e-309); attributes.add("2", -2.2250738585072014e-309); unit_assert_operator_equal(2.225073858507e-308, lexical_cast(attributes[0].second)); unit_assert_operator_equal(-2.225073858507e-308, lexical_cast(attributes[1].second)); #endif } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); testNormalization(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/utility/math/Types.hpp0000664000175100017510000000222512664775616021022 0ustar teamcityteamcity00000000000000// // $Id: Types.hpp 1195 2009-08-14 22:12:04Z chambm $ // // // Original author: Robert Burke // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef TYPES_H_ #define TYPES_H_ #include "boost/numeric/ublas/vector.hpp" #include "boost/numeric/ublas/matrix.hpp" namespace pwiz { namespace math { namespace types { typedef boost::numeric::ublas::matrix dmatrix; typedef boost::numeric::ublas::vector dvector; } // namespace types } // namespace math } // namespace pwiz #endif // TYPES_H_ pwiz/pwiz/utility/math/MatchedFilterTest.cpp0000664000175100017510000001471212664775616023270 0ustar teamcityteamcity00000000000000// // $Id: MatchedFilterTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "MatchedFilter.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include #include #include using namespace pwiz::math; using namespace pwiz::util; ostream* os_ = 0; void test_SampledData() { if (os_) *os_ << "test_SampledData()\n"; using namespace MatchedFilter; SampledData sd; sd.domain = make_pair(0.0, 2.0); sd.samples.push_back(10); sd.samples.push_back(11); sd.samples.push_back(12); sd.samples.push_back(13); sd.samples.push_back(14); if (os_) *os_ << sd << endl; if (os_) *os_ << "domainWidth: " << sd.domainWidth() << endl; unit_assert(sd.domainWidth() == 2.0); if (os_) *os_ << "dx: " << sd.dx() << endl; unit_assert(sd.dx() == .5); for (unsigned int i=0; i. struct OneMinusAbs { typedef MatchedFilter::DxD space_type; double operator()(double d) const {return (d>=-1 && d<=1) ? 1 - abs(d) : 0;} }; // KernelTraitsBase<> has default specialization for function pointer types complex OneMinusAbsComplex(double d) { return (d>=-1 && d<=1) ? 1 - abs(d) : 0; } template void test_createFilter(const Kernel& f) { using namespace MatchedFilter; if (os_) *os_ << "test_createFilter() " << typeid(f).name() << endl; int sampleRadius = 4; double dx = .25; double shift = 0; typedef typename KernelTraits::filter_type filter_type; typedef typename KernelTraits::abscissa_type abscissa_type; typedef typename KernelTraits::ordinate_type ordinate_type; filter_type filter = details::createFilter(f, sampleRadius, dx, shift); if (os_) { copy(filter.begin(), filter.end(), ostream_iterator(*os_, " ")); *os_ << endl; } unit_assert((int)filter.size() == sampleRadius*2 + 1); for (int i=-sampleRadius; i<=sampleRadius; ++i) unit_assert(filter[sampleRadius+i] == f(i*dx - shift)); if (os_) *os_ << endl; } template void test_createFilters(const Kernel& f) { using namespace MatchedFilter; if (os_) *os_ << "test_createFilters() " << typeid(f).name() << endl; int sampleRadius = 2; int subsampleFactor = 4; double dx = 1; typedef typename KernelTraits::filter_type filter_type; typedef typename KernelTraits::ordinate_type ordinate_type; vector filters = details::createFilters(f, sampleRadius, subsampleFactor, dx); // verify filter count unit_assert((int)filters.size() == subsampleFactor); for (typename vector::const_iterator it=filters.begin(); it!=filters.end(); ++it) { if (os_) { copy(it->begin(), it->end(), ostream_iterator(*os_, " ")); *os_ << endl; } // verify filter size unit_assert((int)it->size() == sampleRadius*2 + 1); // verify filter normalization double sum = 0; for (typename filter_type::const_iterator jt=it->begin(); jt!=it->end(); ++jt) sum += norm(complex(*jt)); unit_assert_equal(sum, 1, 1e-14); } if (os_) *os_ << endl; } template void test_compute(const Kernel& f) { using namespace MatchedFilter; if (os_) *os_ << "test_compute() " << typeid(f).name() << endl; typename KernelTraits::sampled_data_type data; data.domain = make_pair(0, 10); data.samples.resize(11); data.samples[5] = 1.; if (os_) *os_ << "data: " << data << endl; int sampleRadius = 2; int sampleFactor = 4; typedef typename KernelTraits::correlation_data_type CorrelationData; CorrelationData correlationData = computeCorrelationData(data, f, sampleRadius, sampleFactor); if (os_) *os_ << "correlationData: " << correlationData << endl; unit_assert(correlationData.samples.size() == 41); unit_assert(abs(correlationData.samples[20].dot - 1.) < 1e-12); } template void test_kernel(const Kernel& kernel) { if (os_) *os_ << "***************************************************************\n"; if (os_) *os_ << "test_kernel() " << typeid(kernel).name() << endl; if (os_) *os_ << "***************************************************************\n"; if (os_) *os_ << endl; test_createFilter(kernel); test_createFilters(kernel); test_compute(kernel); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; if (os_) *os_ << "MatchedFilterTest\n"; test_SampledData(); test_kernel(OneMinusAbs()); test_kernel(&OneMinusAbsComplex); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/utility/math/Parabola.cpp0000664000175100017510000001265312664775616021440 0ustar teamcityteamcity00000000000000// // $Id: Parabola.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Parabola.hpp" #include "pwiz/utility/misc/Std.hpp" #ifndef NDEBUG #define NDEBUG #endif // NDEBUG #include #include #include #include #include #include namespace ublas = boost::numeric::ublas; #if BOOST_UBLAS_TYPE_CHECK goo; // need -DNDEBUG in makefile! #endif namespace pwiz { namespace math { PWIZ_API_DECL Parabola::Parabola(double a, double b, double c) : a_(3) { a_[0] = a; a_[1] = b; a_[2] = c; } PWIZ_API_DECL Parabola::Parabola(vector a) : a_(a) { if (a_.size() != 3) throw logic_error("[Parabola::Parabola()] 3 coefficients required."); } namespace { void solve(ublas::matrix& A, ublas::vector& a) { ublas::permutation_matrix pm(3); int singular = lu_factorize(A, pm); if (singular) throw runtime_error("[Parabola.cpp::solve()] Matrix is singular."); lu_substitute(A, pm, a); // may cause assertion without NDEBUG defined for ublas, probably due to roundoff errors } void fitExact(const vector< pair >& samples, vector& coefficients) { if (samples.size() != 3) throw logic_error("[Parabola.cpp::fitExact()] Exactly 3 samples required.\n"); // fit parabola to the 3 samples (xi,yi): // // ( x1^2 x1 1 )( a[0] ) ( y1 ) // ( x2^2 x2 1 )( a[1] ) = ( y2 ) // ( x3^2 x3 1 )( a[2] ) ( y3 ) ublas::matrix A(3,3); ublas::vector a(3); for (int i=0; i<3; i++) { double x = samples[i].first; double y = samples[i].second; A(i,0) = x*x; A(i,1) = x; A(i,2) = 1; a(i) = y; } solve(A, a); copy(a.begin(), a.end(), coefficients.begin()); } void fitWeightedLeastSquares(const vector< pair >& samples, const vector& weights, vector& coefficients) { if (samples.size() != weights.size()) throw logic_error("[Parabola.cpp::fitWeightedLeastSquares] Wrong weight count."); // given samples {(xi,yi)} and weights {wi} // minimize e(a) = sum[wi(p(a,xi)-yi)^2], // where p(a,xi) = a[0](xi)^2 + a[1](xi) + a[0]c // // de/da == 0 => // ( sum_wx4 sum_wx3 sum_wx2 )( a[0] ) ( sum_wyx2 ) // ( sum_wx3 sum_wx2 sum_wx1 )( a[1] ) = ( sum_wyx1 ) // ( sum_wx2 sum_wx1 sum_wx0 )( a[2] ) ( sum_wyx0 ) // // where: // sum_wxn means sum[wi*(xi)^n] // sum_wyxn means sum[wi*yi*(xi)^n] double sum_wx4 = 0; double sum_wx3 = 0; double sum_wx2 = 0; double sum_wx1 = 0; double sum_wx0 = 0; double sum_wyx2 = 0; double sum_wyx1 = 0; double sum_wyx0 = 0; for (unsigned int i=0; i A(3,3); ublas::vector a(3); A(0,0) = sum_wx4; A(1,0) = A(0,1) = sum_wx3; A(2,0) = A(1,1) = A(0,2) = sum_wx2; A(1,2) = A(2,1) = sum_wx1; A(2,2) = sum_wx0; a(0) = sum_wyx2; a(1) = sum_wyx1; a(2) = sum_wyx0; solve(A, a); copy(a.begin(), a.end(), coefficients.begin()); } } // namespace PWIZ_API_DECL Parabola::Parabola(const vector< pair >& samples) : a_(3) { if (samples.size() < 3) throw logic_error("[Parabola::Parabola()] At least 3 samples required."); if (samples.size() == 3) fitExact(samples, a_); else fitWeightedLeastSquares(samples, vector(samples.size(),1), a_); } // construct by weighted least squares PWIZ_API_DECL Parabola::Parabola(const std::vector< std::pair >& samples, const std::vector& weights) : a_(3) { fitWeightedLeastSquares(samples, weights, a_); } PWIZ_API_DECL ostream& operator<<(ostream& os, const Parabola& p) { vector a = p.coefficients(); os << "[Parabola (" << a[0] << ", " << a[1] << ", " << a[2] << ")]"; return os; } } // namespace math } // namespace pwiz pwiz/pwiz/utility/math/Stats.cpp0000664000175100017510000000573612664775616021021 0ustar teamcityteamcity00000000000000// // $Id: Stats.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Stats.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace math { class Stats::Impl { public: Impl(const Stats::data_type& data); Stats::vector_type mean() const; Stats::matrix_type covariance() const; Stats::matrix_type meanOuterProduct() const; private: unsigned int D_; // dimension of the data int N_; // number of data points Stats::vector_type sumData_; Stats::matrix_type sumOuterProducts_; void computeSums(const Stats::data_type& data); }; Stats::Impl::Impl(const Stats::data_type& data) : D_(0), N_(data.size()) { computeSums(data); } Stats::vector_type Stats::Impl::mean() const { return sumData_/N_; } Stats::matrix_type Stats::Impl::meanOuterProduct() const { return sumOuterProducts_/N_; } Stats::matrix_type Stats::Impl::covariance() const { Stats::vector_type m = mean(); return meanOuterProduct() - outer_prod(m, m); } void Stats::Impl::computeSums(const Stats::data_type& data) { if (data.size()>0) D_ = data[0].size(); sumData_ = Stats::vector_type(D_); sumOuterProducts_ = Stats::matrix_type(D_, D_); sumData_.clear(); sumOuterProducts_.clear(); for (Stats::data_type::const_iterator it=data.begin(); it!=data.end(); ++it) { if (it->size() != D_) { ostringstream message; message << "[Stats::Impl::computeSums()] " << D_ << "-dimensional data expected: " << *it; throw runtime_error(message.str()); } sumData_ += *it; sumOuterProducts_ += outer_prod(*it, *it); } } PWIZ_API_DECL Stats::Stats(const Stats::data_type& data) : impl_(new Stats::Impl(data)) {} PWIZ_API_DECL Stats::~Stats() {} // auto destruction of impl_ PWIZ_API_DECL Stats::vector_type Stats::mean() const {return impl_->mean();} PWIZ_API_DECL Stats::matrix_type Stats::meanOuterProduct() const {return impl_->meanOuterProduct();} PWIZ_API_DECL Stats::matrix_type Stats::covariance() const {return impl_->covariance();} } // namespace math } // namespace pwiz pwiz/pwiz/utility/math/LinearLeastSquares.hpp0000664000175100017510000000467112664775616023474 0ustar teamcityteamcity00000000000000// // $Id: LinearLeastSquares.hpp 1195 2009-08-14 22:12:04Z chambm $ // // Original author: Robert Burke // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _LINEARLEASTSQUARES_HPP_ #define _LINEARLEASTSQUARES_HPP_ #include "pwiz/utility/misc/Export.hpp" #include #include "LinearSolver.hpp" #include "Types.hpp" namespace pwiz { namespace math { enum PWIZ_API_DECL LinearLeastSquaresType {LinearLeastSquaresType_LU, LinearLeastSquaresType_QR}; template class LinearLeastSquares; template<> class LinearLeastSquares { public: template boost::numeric::ublas::vector solve(const boost::numeric::ublas::matrix& A, const boost::numeric::ublas::vector& y) { boost::numeric::ublas::permutation_matrix m(A.size1()); boost::numeric::ublas::matrix AtA = prod(trans(A), A); boost::numeric::ublas::vector b = y; boost::numeric::ublas::vector r; // This serves as a sanity check. Note that an exception here // probably indicates a data file error. if (boost::numeric::ublas::lu_factorize(AtA, m) == 0.) { r = prod(trans(A), b); boost::numeric::ublas::lu_substitute(AtA, m, r); } return r; } }; template<> class LinearLeastSquares { public: template boost::numeric::ublas::vector solve( const boost::numeric::ublas::matrix& A, const boost::numeric::ublas::vector& x) { LinearSolver solver; boost::numeric::ublas::vector y = solver.solve(A, x); return y; } }; } } #endif // _LINEARLEASTSQUARES_HPP_ pwiz/pwiz/utility/math/HouseholderQRTest.cpp0000664000175100017510000000235112664775616023275 0ustar teamcityteamcity00000000000000// // $Id: HouseholderQRTest.cpp 6141 2014-05-05 21:03:47Z chambm $ // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "HouseholderQR.hpp" using namespace pwiz::math; int main(int argc, char* argv[]) { using namespace boost::numeric::ublas; using namespace std; matrix A (3,3); A(0,0) = 1; A(0,1) = 1; A(0,2) = 0; A(1,1) = 1; A(1,0) = 0; A(1,2) = 0; A(2,2) = 1; A(2,0) = 1; A(2,1) = 0; cout << "A=" << A << endl; cout << "QR decomposition using Householder" << endl; matrix Q(3,3), R(3,3); HouseholderQR (A,Q,R); matrix Z = prod(Q,R) - A; float f = norm_1 (Z); cout << "Q=" << Q < #include #include #include #include #include #include #include #include #include #include "qr.hpp" namespace pwiz { namespace math { enum PWIZ_API_DECL LinearSolverType {LinearSolverType_LU, LinearSolverType_QR}; template class LinearSolver; template<> class LinearSolver { public: /// solve system of linear equations Ax = y using boost::ublas; /// note: extra copying inefficiencies for ease of client use template vector_type solve(const matrix_type& A, const vector_type& y) { namespace ublas = boost::numeric::ublas; matrix_type A_factorized = A; ublas::permutation_matrix pm(y.size()); int singular = lu_factorize(A_factorized, pm); if (singular) throw std::runtime_error("[LinearSolver::solve()] A is singular."); vector_type result(y); lu_substitute(A_factorized, pm, result); return result; } }; template<> class LinearSolver { public: /// solve system of linear equations Ax = y using boost::ublas; /// note: extra copying inefficiencies for ease of client use template vector_type solve(const matrix_type& A, const vector_type& y) { typedef typename matrix_type::size_type size_type; typedef typename matrix_type::value_type value_type; namespace ublas = boost::numeric::ublas; matrix_type Q(A.size1(), A.size2()), R(A.size1(), A.size2()); qr (A, Q, R); vector_type b = prod(trans(Q), y); vector_type result; if (R.size1() > R.size2()) { size_type min = (R.size1() < R.size2() ? R.size1() : R.size2()); result = ublas::solve(subrange(R, 0, min, 0, min), subrange(b, 0, min), ublas::upper_tag()); } else { result = ublas::solve(R, b, ublas::upper_tag()); } return result; } }; } // namespace math } // namespace pwiz #endif // _LINEARSOLVER_HPP_ pwiz/pwiz/utility/math/Stats.hpp0000664000175100017510000000333512664775616021017 0ustar teamcityteamcity00000000000000// // $Id: Stats.hpp 1195 2009-08-14 22:12:04Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _STATS_HPP_ #define _STATS_HPP_ #include "pwiz/utility/misc/Export.hpp" #include #include #include #include #include namespace pwiz { namespace math { class PWIZ_API_DECL Stats { public: typedef boost::numeric::ublas::vector vector_type; typedef boost::numeric::ublas::matrix matrix_type; typedef std::vector data_type; Stats(const data_type& data); ~Stats(); vector_type mean() const; matrix_type meanOuterProduct() const; matrix_type covariance() const; private: class Impl; std::auto_ptr impl_; // no copying Stats(const Stats& stats); Stats& operator=(const Stats& stats); }; } // namespace math } // namespace pwiz #endif // _STATS_HPP_ pwiz/pwiz/utility/math/ParabolaTest.cpp0000664000175100017510000001167512664775616022303 0ustar teamcityteamcity00000000000000// // $Id: ParabolaTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "Parabola.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include #include #include using namespace pwiz::util; using namespace pwiz::math; ostream* os_ = 0; double epsilon_ = numeric_limits::epsilon(); void testBasic() { if (os_) *os_ << "***************************\n"; if (os_) *os_ << "testBasic()\n"; Parabola p(2, 3, 4); unit_assert_equal(p(5), 69, epsilon_); p.coefficients()[0] = 3; unit_assert_equal(p(5), 94, epsilon_); if (os_) *os_ << "testBasic(): success\n"; } void testExactFit() { if (os_) *os_ << "***************************\n"; if (os_) *os_ << "testExactFit()\n"; vector< pair > samples; samples.push_back(make_pair(1,1)); samples.push_back(make_pair(2,3)); samples.push_back(make_pair(3,9)); const Parabola p(samples); if (os_) *os_ << p << endl; if (os_) *os_ << "center: (" << p.center() << ", " << p(p.center()) << ")\n"; const vector& a = p.coefficients(); unit_assert_equal(a[0], 2, epsilon_*10); unit_assert_equal(a[1], -4, epsilon_*10); unit_assert_equal(a[2], 3, epsilon_*5); unit_assert_equal(p.center(), 1, epsilon_); unit_assert_equal(p(p.center()), 1, epsilon_*10); unit_assert_equal(p(0), 3, epsilon_*5); if (os_) *os_ << "testExactFit(): success\n"; } void testLeastSquares() { if (os_) *os_ << "***************************\n"; if (os_) *os_ << "testLeastSquares()\n"; vector< pair > samples; samples.push_back(make_pair(1,1)); samples.push_back(make_pair(2,3)); samples.push_back(make_pair(3,9)); samples.push_back(make_pair(0,3)); samples.push_back(make_pair(-1,9)); const Parabola p(samples); if (os_) *os_ << p << endl; if (os_) *os_ << "center: (" << p.center() << ", " << p(p.center()) << ")\n"; const vector& a = p.coefficients(); unit_assert_equal(a[0], 2, epsilon_*10); unit_assert_equal(a[1], -4, epsilon_*100); unit_assert_equal(a[2], 3, epsilon_*10); unit_assert_equal(p.center(), 1, epsilon_*10); unit_assert_equal(p(p.center()), 1, epsilon_*100); unit_assert_equal(p(0), 3, epsilon_*10); if (os_) *os_ << "testLeastSquares(): success\n"; } void testWeightedLeastSquares() { if (os_) *os_ << "***************************\n"; if (os_) *os_ << "testWeightedLeastSquares()\n"; // fit to f(x) = 1/sqrt(x*x+1) // samples ( x, 1/(f(x)*f(x)) ), i.e. (x, x*x+1) vector< pair > samples; samples.push_back(make_pair(0,1)); samples.push_back(make_pair(1,2)); samples.push_back(make_pair(2,5)); samples.push_back(make_pair(-3,10)); samples.push_back(make_pair(-4,17)); // weights w = (y^6)/4 => fits data to 1/sqrt(a[0]x^2 + a[1]x + a[2]) vector weights; for (unsigned int i=0; i(*os_, " " )); } const Parabola p(samples, weights); if (os_) *os_ << p << endl; if (os_) *os_ << "center: (" << p.center() << ", " << p(p.center()) << ")\n"; if (os_) { *os_ << "coefficients: " << setprecision(14); copy(p.coefficients().begin(), p.coefficients().end(), ostream_iterator(*os_, " ")); *os_ << endl; } unit_assert_equal(p.coefficients()[0], 1, epsilon_*1000); unit_assert_equal(p.coefficients()[1], 0, epsilon_*10e4); unit_assert_equal(p.coefficients()[2], 1, epsilon_*10e4); if (os_) *os_ << "testWeightedLeastSquares(): success\n"; } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; if (os_) *os_ << "ParabolaTest\n"; testBasic(); testExactFit(); testLeastSquares(); testWeightedLeastSquares(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/utility/math/LinearLeastSquaresTest.cpp0000664000175100017510000001121112664775616024313 0ustar teamcityteamcity00000000000000// // $Id: LinearLeastSquaresTest.cpp 4140 2012-11-22 01:07:16Z pcbrefugee $ // // Original author: Robert Burke // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "LinearLeastSquares.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::math; using namespace pwiz::math::types; namespace ublas = boost::numeric::ublas; const double epsilon = 1e-16; ostream* os_ = 0; void testDouble() { if (os_) *os_ << "testDouble()\n"; LinearLeastSquares<> lls; ublas::matrix A(2, 2); A(0,0) = 1; A(0,1) = 2; A(1,0) = 3; A(1,1) = 4; ublas::vector y(2); y(0) = 5; y(1) = 11; ublas::vector x = lls.solve(A, y); if (os_) *os_ << "A: " << A << endl; if (os_) *os_ << "y: " << y << endl; if (os_) *os_ << "x: " << x << endl; unit_assert_equal(x(0), 1., 1e-13); unit_assert_equal(x(1), 2., 1e-13); } void testDoubleQR() { if (os_) *os_ << "testDoubleQR()\n"; LinearLeastSquares lls; ublas::matrix A(2, 2); A(0,0) = 1; A(0,1) = 2; A(1,0) = 3; A(1,1) = 4; ublas::vector y(2); y(0) = 5; y(1) = 11; ublas::vector x = lls.solve(A, y); if (os_) *os_ << "A: " << A << endl; if (os_) *os_ << "y: " << y << endl; if (os_) *os_ << "x: " << x << endl; if (os_) *os_ << "x(0) = " << x(0) - 1. << ", x(1) = " << x(1) - 2. << endl; unit_assert_equal(x(0), 1., 100*epsilon); unit_assert_equal(x(1), 2., 100*epsilon); } void testExactFitQR() { if (os_) *os_ << "***************************\n"; if (os_) *os_ << "testExactFit()\n"; dmatrix m(2,2); dvector obs(2); m(0, 0) = 1; m(1, 0) = 0; m(0, 1) = 0; m(1, 1) = 1; obs(0) = 1; obs(1) = 1; LinearLeastSquares lls; const dvector result = lls.solve(m,obs); unit_assert_equal(obs(0), 1, epsilon); unit_assert_equal(obs(1), 1, epsilon); if (os_) *os_ << "testExactFit(): success\n"; } void testSimpleRectangleQR() { if (os_) *os_ << "***************************\n"; if (os_) *os_ << "testSimpleRectangleQR()\n"; dmatrix samples(4, 2); samples.clear(); samples(0,0) = 1; samples(0,1) = 0; samples(1,0) = 0; samples(1,1) = 1; samples(2,0) = 1; samples(2,1) = 0; samples(3,0) = 0; samples(3,1) = 1; dvector obs(4); obs(0) = 2; obs(1) = 2; obs(2) = 2; obs(3) = 2; LinearLeastSquares lls; dvector a = lls.solve(samples, obs); unit_assert_equal(a(0), 2, epsilon); unit_assert_equal(a(1), 2, epsilon); if (os_) *os_ << "testSimpleRectangleQR(): success\n"; } void testLeastSquaresQR() { if (os_) *os_ << "***************************\n"; if (os_) *os_ << "testLeastSquaresQR()\n"; dmatrix samples(5, 2); samples.clear(); samples(0,0) = 1; samples(0,1) = 1; samples(1,0) = 2; samples(1,1) = 2; samples(2,0) = 3; samples(2,1) = 3; samples(3,0) = 0; samples(3,1) = 4; samples(4,0) = -1; samples(4,1) = 5; dvector obs(5); obs(0) = 1; obs(1) = 3; obs(2) = 9; obs(3) = 3; obs(4) = -9; LinearLeastSquares lls; dvector a = lls.solve(samples, obs); unit_assert_equal(a(0), 3.16666666666667, epsilon*100); unit_assert_equal(a(1), -0.5, epsilon*100); if (os_) *os_ << "testLeastSquaresQR(): success\n"; } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; if (os_) *os_ << "LinearLeastSquaresTest\n"; testDouble(); testDoubleQR(); testExactFitQR(); testSimpleRectangleQR(); testLeastSquaresQR(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/utility/math/MatrixInverse.hpp0000664000175100017510000001324012664775616022515 0ustar teamcityteamcity00000000000000// // $Id: MatrixInverse.hpp 4146 2012-11-26 23:46:34Z pcbrefugee $ // // // NB: Variations of this file appear in many open source projects, // with no copyright claims or license statements made in any of them. // Assumed to be public domain, or at least as open as the boost license, // since the farthest back we can seem to trace it is the Boost Wiki at // http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Effective_UBLAS/Matrix_Inversion // #ifndef _MATRIXINVERSE_HPP_ #define _MATRIXINVERSE_HPP_ #include #include #include #include #include #include #include #include #include #include #include /* Matrix inversion routine. Uses lu_factorize and lu_substitute in uBLAS to invert a matrix */ template bool InvertMatrix(const M& input, M& inverse) { using namespace boost::numeric::ublas; typedef permutation_matrix pmatrix; // create a working copy of the input M A(input); // create a permutation matrix for the LU-factorization pmatrix pm(A.size1()); // perform LU-factorization int res = lu_factorize(A,pm); if( res != 0 ) return false; // create identity matrix of "inverse" inverse.assign(identity_matrix(A.size1())); // backsubstitute to get the inverse lu_substitute(A, pm, inverse); return true; } /** * Invert a matrix via gauss-jordan algorithm (PARTIAL PIVOT) * * @param m The matrix to invert. Must be square. * @param singular If the matrix was found to be singular, then this * is set to true, else set to false. * @return If singular is false, then the inverted matrix is returned. * Otherwise it contains random values. */ template //#define T double /// for debug boost::numeric::ublas::matrix gjinverse(const boost::numeric::ublas::matrix &m, bool &singular) { using namespace boost::numeric::ublas; const size_t size = m.size1(); // Cannot invert if non-square matrix or 0x0 matrix. // Report it as singular in these cases, and return // a 0x0 matrix. if (size != m.size2() || size == 0) { singular = true; matrix A(0,0); return A; } // Handle 1x1 matrix edge case as general purpose // inverter below requires 2x2 to function properly. if (size == 1) { matrix A(1, 1); if (m(0,0) == 0.0) { singular = true; return A; } singular = false; A(0,0) = 1/m(0,0); return A; } // Create an augmented matrix A to invert. Assign the // matrix to be inverted to the left hand side and an // identity matrix to the right hand side. matrix A(size, 2*size); matrix_range > Aleft(A, range(0, size), range(0, size)); Aleft = m; matrix_range > Aright(A, range(0, size), range(size, 2*size)); Aright = identity_matrix(size); // Doing partial pivot for (size_t k = 0; k < size; k++) { // Swap rows to eliminate zero diagonal elements. for (size_t kk = 0; kk < size; kk++) { if ( A(kk,kk) == 0 ) // XXX: test for "small" instead { // Find a row(l) to swap with row(k) int l = -1; for (size_t i = kk+1; i < size; i++) { if ( A(i,kk) != 0 ) { l = i; break; } } // Swap the rows if found if ( l < 0 ) { std::cerr << "Error:" << __FUNCTION__ << ":" << "Input matrix is singular, because cannot find" << " a row to swap while eliminating zero-diagonal."; singular = true; return Aleft; } else { matrix_row > rowk(A, kk); matrix_row > rowl(A, l); rowk.swap(rowl); /*#if defined(DEBUG) || !defined(NDEBUG) std::cerr << __FUNCTION__ << ":" << "Swapped row " << kk << " with row " << l << ":" << A << "\n"; #endif*/ } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////// // normalize the current row for (size_t j = k+1; j < 2*size; j++) A(k,j) /= A(k,k); A(k,k) = 1; // normalize other rows for (size_t i = 0; i < size; i++) { if ( i != k ) // other rows // FIX: PROBLEM HERE { if ( A(i,k) != 0 ) { for (size_t j = k+1; j < 2*size; j++) A(i,j) -= A(k,j) * A(i,k); A(i,k) = 0; } } } /*#if defined(DEBUG) || !defined(NDEBUG) std::cerr << __FUNCTION__ << ":" << "GJ row " << k << " : " << A << "\n"; #endif*/ } singular = false; return Aright; } #endif // _MATRIXINVERSE_HPP_ pwiz/pwiz/utility/math/Parabola.hpp0000664000175100017510000000363712664775616021447 0ustar teamcityteamcity00000000000000// // $Id: Parabola.hpp 1195 2009-08-14 22:12:04Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PARABOLA_HPP_ #define _PARABOLA_HPP_ #include "pwiz/utility/misc/Export.hpp" #include #include namespace pwiz { namespace math { class PWIZ_API_DECL Parabola { public: // construct by giving 3 coefficients Parabola(double a=0, double b=0, double c=0); Parabola(std::vector a); // construct by giving 3 or more sample points Parabola(const std::vector< std::pair >& samples); // construct by weighted least squares Parabola(const std::vector< std::pair >& samples, const std::vector& weights); std::vector& coefficients() {return a_;} const std::vector& coefficients() const {return a_;} double operator()(double x) const {return a_[0]*x*x + a_[1]*x + a_[2];} double center() const {return -a_[1]/(2*a_[0]);} private: std::vector a_; }; PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const Parabola& p); } // namespace math } // namespace pwiz #endif // _PARABOLA_HPP_ pwiz/pwiz/utility/math/OrderedPairTest.cpp0000664000175100017510000001113512664775616022751 0ustar teamcityteamcity00000000000000// // $Id: OrderedPairTest.cpp 6141 2014-05-05 21:03:47Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "OrderedPair.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/unit.hpp" #include "boost/static_assert.hpp" using namespace pwiz::util; using namespace pwiz::math; ostream* os_ = 0; BOOST_STATIC_ASSERT(sizeof(OrderedPair) == 2*sizeof(double)); void testContainer(const OrderedPairContainerRef& pairs) { // verify that pairs == { (1,2), (3,4), (5,6) } // test size if (os_) { copy(pairs.begin(), pairs.end(), ostream_iterator(*os_, " ")); *os_ << endl; } unit_assert(pairs.size() == 3); // test iteration OrderedPairContainerRef::const_iterator it = pairs.begin(); unit_assert(it->x == 1); unit_assert(it->y == 2); ++it; unit_assert(it->x == 3); unit_assert(it->y == 4); ++it; unit_assert(it->x == 5); unit_assert(it->y == 6); // test random access unit_assert(pairs[0].x == 1); unit_assert(pairs[0].y == 2); unit_assert(pairs[1].x == 3); unit_assert(pairs[1].y == 4); unit_assert(pairs[2].x == 5); unit_assert(pairs[2].y == 6); // test algorithms vector v; copy(pairs.begin(), pairs.end(), back_inserter(v)); unit_assert(v.size() == 3); unit_assert(v[0].x == 1); unit_assert(v[0].y == 2); unit_assert(v[1].x == 3); unit_assert(v[1].y == 4); unit_assert(v[2].x == 5); unit_assert(v[2].y == 6); } void testArray() { if (os_) *os_ << "testArray()\n"; double a[] = {1, 2, 3, 4, 5, 6}; OrderedPairContainerRef pairs(a, a+sizeof(a)/sizeof(double)); testContainer(pairs); } void testVectorDouble() { if (os_) *os_ << "testVectorDouble()\n"; vector v; for (int i=1; i<=6; i++) v.push_back(i); testContainer(v); // note automatic conversion: vector -> OrderedPairContainerRef } void testVectorOrderedPair() { if (os_) *os_ << "testVectorOrderedPair()\n"; vector v; v.push_back(OrderedPair(1,2)); v.push_back(OrderedPair(3,4)); v.push_back(OrderedPair(5,6)); testContainer(v); // note automatic conversion: vector -> OrderedPairContainerRef } #pragma pack(push, 1) struct CustomPair {double a; double b; CustomPair(double _a, double _b) : a(_a), b(_b) {} }; #pragma pack(pop) void testVectorCustomPair() { if (os_) *os_ << "testVectorCustomPair()\n"; vector v; v.push_back(CustomPair(1,2)); v.push_back(CustomPair(3,4)); v.push_back(CustomPair(5,6)); testContainer(v); // note automatic conversion: vector -> OrderedPairContainerRef } void testEquality() { if (os_) *os_ << "testEquality()\n"; vector v; v.push_back(OrderedPair(1,2)); v.push_back(OrderedPair(3,4)); v.push_back(OrderedPair(5,6)); vector w = v; unit_assert(v == w); w.push_back(OrderedPair(7,8)); unit_assert(v != w); v.push_back(OrderedPair(7,9)); unit_assert(v != w); v.back().y = w.back().y; unit_assert(v == w); } void testExtraction() { vector v; istringstream iss("(420,666) (421,667)"); copy(istream_iterator(iss), istream_iterator(), back_inserter(v)); unit_assert(v.size() == 2); unit_assert(v[0].x == 420); unit_assert(v[0].y == 666); unit_assert(v[1].x == 421); unit_assert(v[1].y == 667); } void test() { testArray(); testVectorDouble(); testVectorOrderedPair(); testVectorCustomPair(); testEquality(); testExtraction(); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/utility/math/erf.cpp0000664000175100017510000001737212664775616020476 0ustar teamcityteamcity00000000000000// // $Id: erf.cpp 4151 2012-11-28 18:32:03Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "erf.hpp" #include "pwiz/utility/misc/Std.hpp" #include namespace pwiz { namespace math { // pulled from IT++ Library /*! * \brief Error function for complex argument * \ingroup errorfunc * \author Adam Piatyszek * * This function calculates a well known error function \c erf(z) * for complex \c z. The implementation is based on unofficial * implementation for Octave. Here is a part of the author's note * from original sources: * * Put together by John Smith john at arrows dot demon dot co dot uk, * using ideas by others. * * Calculate \c erf(z) for complex \c z. * Three methods are implemented; which one is used depends on z. * * The code includes some hard coded constants that are intended to * give about 14 decimal places of accuracy. This is appropriate for * 64-bit floating point numbers. */ PWIZ_API_DECL const double pi = 3.14159265358979323846; PWIZ_API_DECL const double eps = std::numeric_limits::epsilon(); /* * Abramowitz and Stegun: Eq. (7.1.14) gives this continued fraction * for erfc(z) * * erfc(z) = sqrt(pi).exp(-z^2). 1 1/2 1 3/2 2 5/2 * --- --- --- --- --- --- ... * z + z + z + z + z + z + * * This is evaluated using Lentz's method, as described in the * narative of Numerical Recipes in C. * * The continued fraction is true providing real(z) > 0. In practice * we like real(z) to be significantly greater than 0, say greater * than 0.5. */ std::complex cerfc_continued_fraction(const std::complex& z) { const double tiny = std::numeric_limits::min(); // first calculate z+ 1/2 1 // --- --- ... // z + z + std::complex f(z); std::complex C(f); std::complex D(0.0); std::complex delta; double a; a = 0.0; do { a += 0.5; D = z + a * D; C = z + a / C; if ((D.real() == 0.0) && (D.imag() == 0.0)) D = tiny; D = 1.0 / D; delta = C * D; f = f * delta; } while (abs(1.0 - delta) > eps); // Do the first term of the continued fraction f = 1.0 / f; // and do the final scaling f = f * exp(-z * z) / sqrt(pi); return f; } std::complex cerf_continued_fraction(const std::complex& z) { if (z.real() > 0) return 1.0 - cerfc_continued_fraction(z); else return -1.0 + cerfc_continued_fraction(-z); } /* * Abramawitz and Stegun: Eq. (7.1.5) gives a series for erf(z) good * for all z, but converges faster for smallish abs(z), say abs(z) < 2. */ std::complex cerf_series(const std::complex& z) { const double tiny = std::numeric_limits::min(); std::complex sum(0.0); std::complex term(z); std::complex z2(z*z); for (int n = 0; (n < 3) || (abs(term) > abs(sum) * tiny); n++) { sum += term / static_cast(2 * n + 1); term *= -z2 / static_cast(n + 1); } return sum * 2.0 / sqrt(pi); } /* * Numerical Recipes quotes a formula due to Rybicki for evaluating * Dawson's Integral: * * exp(-x^2) integral exp(t^2).dt = 1/sqrt(pi) lim sum exp(-(z-n.h)^2) / n * 0 to x h->0 n odd * * This can be adapted to erf(z). */ std::complex cerf_rybicki(const std::complex& z) { double h = 0.2; // numerical experiment suggests this is small enough // choose an even n0, and then shift z->z-n0.h and n->n-h. // n0 is chosen so that real((z-n0.h)^2) is as small as possible. int n0 = 2 * static_cast(z.imag() / (2 * h) + 0.5); std::complex z0(0.0, n0 * h); std::complex zp(z - z0); std::complex sum(0.0, 0.0); // limits of sum chosen so that the end sums of the sum are // fairly small. In this case exp(-(35.h)^2)=5e-22 for (int np = -35; np <= 35; np += 2) { std::complex t(zp.real(), zp.imag() - np * h); std::complex b(exp(t * t) / static_cast(np + n0)); sum += b; } sum *= 2.0 * exp(-z * z) / pi; return std::complex(-sum.imag(), sum.real()); } /* * This function calculates a well known error function erf(z) for * complex z. Three methods are implemented. Which one is used * depends on z. */ PWIZ_API_DECL std::complex erf(const std::complex& z) { // Use the method appropriate to size of z - // there probably ought to be an extra option for NaN z, or infinite z if (abs(z) < 2.0) return cerf_series(z); else { if (std::abs(z.real()) < 0.5) return cerf_rybicki(z); else return cerf_continued_fraction(z); } } // end pulled from IT++ Library #if defined(_MSC_VER) PWIZ_API_DECL double erf(double x) { // call complex implementation return erf(complex(x)).real(); } #else PWIZ_API_DECL double erf(double x) { // call gcc-provided real implementation return ::erf(x); } #endif // defined(_MSC_VER) // Darren's series experimentation /* const double precision_ = numeric_limits::epsilon(); complex erf_series(complex z) { // erf(z) = (2/sqrt(pi)) * sum[ (-1)^n * z^(2n+1) / n!(2n+1) ] complex sum = 0; complex term = z; const int maxTermCount = 100; for (int n=0; n sum = 0; complex term = z; const int maxTermCount = 10000; for (int n=0; n #include #include using namespace pwiz::util; using namespace pwiz::math; using std::numeric_limits; using std::complex; ostream* os_ = 0; const double epsilon_ = numeric_limits::epsilon(); /* void test_series() { cout << "test_series()\n"; // we match real-valued erf within epsilon_*10 in range [-2,2], // using 29 terms at +/-2 for (double x=-2; x<2; x+=.2) { complex resultComplex = erf_series(complex(x)); double resultReal = ((double(*)(double))erf)(x); //cout << resultComplex << " " << resultReal << endl; unit_assert_equal(resultComplex.real(), resultReal, epsilon_*10); } } void test_series2() { cout << "test_series2()\n"; // 1e-12 precision in range [-20,20] using < 1200 terms for (double x=-20; x<20; x+=2) { complex resultComplex = erf_series2(complex(x)); double resultReal = ((double(*)(double))erf)(x); //cout << resultComplex << " " << resultReal << endl; unit_assert_equal(resultComplex.real(), resultReal, 1e-12); } } void test_1vs2() { cout << "test_1vs2()\n"; // erf_series matches erf_series2 in region [-2,2]x[-2,2] within 1e-10 double a = 2; for (double x=-a; x<=a; x+=a/5.) for (double y=-a; y<=a; y+=a/5.) { complex z(x,y); complex result1 = erf_series(z); complex result2 = erf_series2(z); //cout << z << ": " << abs(result1-result2) << endl; unit_assert_equal(result1, result2, 1e-10); } } void test_convergence2() { complex z(100,1); cout << erf_series2(z) << endl; } */ #if defined(_MSC_VER) void test_real() { cerr << "[erfTest] Warning: test_real() not implemented for MSVC.\n"; } #else void test_real() { // tests our complex erf against the not-so-standard gcc-provided double erf(double) if (os_) *os_ << "test_real()\n"; double a = 10; for (double x=-a; x<=a; x+=a/100) { complex resultComplex = erf(complex(x)); double resultReal = ((double(*)(double))::erf)(x); if (os_) *os_ << x << " -> " << resultComplex << " " << resultReal << endl; unit_assert_equal(resultComplex.real(), resultReal, 1e-12); } if (os_) *os_ << endl; } #endif // defined(_MSC_VER) void test_series() { if (os_) *os_ << "test_series()\n"; // erf_series2 matches erf in region [-2,2]x[-2,2] within 1e-10 double a = 2; for (double x=-a; x<=a; x+=a/5.) for (double y=-a; y<=a; y+=a/5.) { complex z(x,y); complex result1 = erf(z); complex result2 = erf_series2(z); if (os_) *os_ << z << ": " << abs(result1-result2) << endl; unit_assert_equal(abs(result1-result2), 0, 1e-10); } if (os_) *os_ << endl; } void test_real_wrapper() { if (os_) *os_ << "test_real_wrapper()\n"; double a = 10; for (double x=-a; x<=a; x+=a/100) { double result_pwiz = pwiz::math::erf(x); double result_std = ::erf(x); if (os_) *os_ << x << " -> " << result_pwiz << " " << result_std << endl; unit_assert_equal(result_pwiz, result_std, 1e-12); } if (os_) *os_ << endl; } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; if (os_) *os_ << "erfTest\n" << setprecision(20); test_real(); test_series(); test_real_wrapper(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/utility/math/HouseholderQR.hpp0000664000175100017510000000667112664775616022453 0ustar teamcityteamcity00000000000000// // $Id: HouseholderQR.hpp 1195 2009-08-14 22:12:04Z chambm $ // // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // // Original author: Robert Burke // // This code taken from the following site: // http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Effective_UBLAS/Matrix_Inversion // #ifndef HOUSEHOLDERQR_HPP #define HOUSEHOLDERQR_HPP #include #include #include #include #include namespace ublas = boost::numeric::ublas; namespace pwiz { namespace math { template void TransposeMultiply (const ublas::vector& vector, ublas::matrix& result, size_t size) { result.resize (size,size); result.clear (); for(unsigned int row=0; row< vector.size(); ++row) { for(unsigned int col=0; col < vector.size(); ++col) result(row,col) = vector(col) * vector(row); } } template void HouseholderCornerSubstraction (ublas::matrix& LeftLarge, const ublas::matrix& RightSmall) { using namespace boost::numeric::ublas; using namespace std; if( !( (LeftLarge.size1() >= RightSmall.size1()) && (LeftLarge.size2() >= RightSmall.size2()) ) ) { cerr << "invalid matrix dimensions" << endl; return; } size_t row_offset = LeftLarge.size2() - RightSmall.size2(); size_t col_offset = LeftLarge.size1() - RightSmall.size1(); for(unsigned int row = 0; row < RightSmall.size2(); ++row ) for(unsigned int col = 0; col < RightSmall.size1(); ++col ) LeftLarge(col_offset+col,row_offset+row) -= RightSmall(col,row); } template void HouseholderQR (const ublas::matrix& M, ublas::matrix& Q, ublas::matrix& R) { using namespace boost::numeric::ublas; using namespace std; if( !( (M.size1() == M.size2()) ) ) { cerr << "invalid matrix dimensions" << endl; return; } size_t size = M.size1(); // init Matrices matrix H, HTemp; HTemp = identity_matrix(size); Q = identity_matrix(size); R = M; // find Householder reflection matrices for(unsigned int col = 0; col < size-1; ++col) { // create X vector ublas::vector RRowView = column(R,col); vector_range< ublas::vector > X2 (RRowView, range (col, size)); ublas::vector X = X2; // X -> U~ if(X(0) >= 0) X(0) += norm_2(X); else X(0) += -1*norm_2(X); HTemp.resize(X.size(),X.size(),true); TransposeMultiply(X, HTemp, X.size()); // HTemp = the 2UUt part of H HTemp *= ( 2 / inner_prod(X,X) ); // H = I - 2UUt H = identity_matrix(size); HouseholderCornerSubstraction(H,HTemp); // add H to Q and R Q = prod(Q,H); R = prod(H,R); } } } } #endif // HOUSEHOLDERQR_HPP pwiz/pwiz/utility/math/MatchedFilter.hpp0000664000175100017510000002345512664775616022441 0ustar teamcityteamcity00000000000000// // $Id: MatchedFilter.hpp 1195 2009-08-14 22:12:04Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _MATCHEDFILTER_HPP_ #define _MATCHEDFILTER_HPP_ #include "pwiz/utility/math/round.hpp" #include #include #include #include #include #include namespace pwiz { namespace math { namespace MatchedFilter { template struct ProductSpace { typedef X abscissa_type; typedef Y ordinate_type; }; typedef ProductSpace< double, double > DxD; typedef ProductSpace< double, std::complex > DxCD; template struct SampledData { typedef typename space_type::abscissa_type abscissa_type; typedef typename space_type::ordinate_type ordinate_type; typedef std::pair domain_type; typedef std::vector samples_type; domain_type domain; samples_type samples; abscissa_type domainWidth() const { return domain.second - domain.first; } abscissa_type dx() const { return samples.empty() ? 0 : domainWidth()/(samples.size()-1); } abscissa_type x(typename samples_type::size_type index) const { return domain.first + domainWidth() * index / (samples.size()-1); } typename samples_type::size_type sampleIndex(const abscissa_type& x) const { typename samples_type::size_type sampleCount = samples.size(); int result = (int)round((sampleCount-1)*(x-domain.first)/domainWidth()); if (result < 0) result = 0; if (result > (int)(sampleCount-1)) result = sampleCount-1; return (typename samples_type::size_type)(result); } const ordinate_type& sample(abscissa_type x) const { return samples[sampleIndex(x)]; } }; template std::ostream& operator<<(std::ostream& os, const SampledData& data) { os << "[" << data.domain.first << "," << data.domain.second << "] " << "(" << data.samples.size() << " samples)\n"; typename SampledData::samples_type::const_iterator it=data.samples.begin(); for (unsigned int index=0; index!=data.samples.size(); ++index, ++it) os << data.x(index) << "\t" << *it << std::endl; return os; } template struct KernelTraitsBase { // When using a kernel function of type Kernel, // KernelTraitsBase must define space_type, // which in turn must define abscissa_type and ordinate_type, e.g: // typedef ProductSpace space_type; // As a shortcut, the following default typedef allows a client to // define space_type in the definition of Kernel: typedef typename Kernel::space_type space_type; }; // partial specialization of KernelTraitsBase for function pointers template struct KernelTraitsBase { typedef ProductSpace space_type; }; namespace { template struct KernelConcept { void check() { y = k(x); } typename KernelTraitsBase::space_type::abscissa_type x; typename KernelTraitsBase::space_type::ordinate_type y; Kernel k; }; } template void checkKernelConcept() { // force compile of KernelConcept::check() void (KernelConcept::*dummy)() = &KernelConcept::check; (void)dummy; } template struct Correlation { Y dot; double e2; double tan2angle; Correlation(Y _dot = 0, double _e2 = 0, double _tan2angle = 0) : dot(_dot), e2(_e2), tan2angle(_tan2angle) {} double angle() const {return atan(sqrt(tan2angle))*180/M_PI;} }; template std::ostream& operator<<(std::ostream& os, const Correlation& c) { os << "<" << c.dot << ", " << c.e2 << ", " << c.angle() << ">"; return os; } template struct KernelTraits { typedef typename KernelTraitsBase::space_type space_type; typedef typename space_type::abscissa_type abscissa_type; typedef typename space_type::ordinate_type ordinate_type; typedef SampledData sampled_data_type; typedef typename sampled_data_type::samples_type samples_type; typedef samples_type filter_type; typedef Correlation correlation_type; typedef ProductSpace correlation_space_type; typedef SampledData correlation_data_type; // verify Kernel concept at compile time template struct Dummy; typedef Dummy< &checkKernelConcept > dummy; }; namespace details { template typename KernelTraits::filter_type createFilter(const Kernel& kernel, int sampleRadius, typename KernelTraits::abscissa_type dx, typename KernelTraits::abscissa_type shift) { checkKernelConcept(); typename KernelTraits::filter_type filter; for (int i=-sampleRadius; i<=sampleRadius; i++) filter.push_back(kernel(i*dx - shift)); return filter; } // mimic complex<> functions inline double norm(double d) {return d*d;} inline double conj(double d) {return d;} template void normalizeFilter(Filter& filter) { double normalization = 0; for (typename Filter::const_iterator it=filter.begin(); it!=filter.end(); ++it) normalization += norm(*it); normalization = sqrt(normalization); for (typename Filter::iterator it=filter.begin(); it!=filter.end(); ++it) *it /= normalization; } template std::vector::filter_type> createFilters(const Kernel& kernel, int sampleRadius, int subsampleFactor, typename KernelTraits::abscissa_type dx) { checkKernelConcept(); typedef typename KernelTraits::filter_type filter_type; std::vector filters; for (int i=0; i); return filters; } template void computeCorrelation(typename KernelTraits::samples_type::const_iterator samples, typename KernelTraits::samples_type::const_iterator samplesEnd, typename KernelTraits::samples_type::const_iterator filter, typename KernelTraits::correlation_type& result) { checkKernelConcept(); result.dot = 0; double normData = 0; for (; samples!=samplesEnd; ++samples, ++filter) { result.dot += (*samples) * conj(*filter); normData += norm(*samples); } double normDot = norm(result.dot); result.e2 = (std::max)(normData - normDot, 0.); result.tan2angle = normDot>0 ? result.e2/normDot : std::numeric_limits::infinity(); } } // namespace details template typename KernelTraits::correlation_data_type computeCorrelationData(const typename KernelTraits::sampled_data_type& data, const Kernel& kernel, int sampleRadius, int subsampleFactor) { checkKernelConcept(); typedef typename KernelTraits::correlation_data_type result_type; result_type result; result.domain = data.domain; if (data.samples.empty()) return result; result.samples.resize((data.samples.size()-1) * subsampleFactor + 1); typedef typename KernelTraits::filter_type filter_type; std::vector filters = details::createFilters(kernel, sampleRadius, subsampleFactor, data.dx()); typedef typename KernelTraits::samples_type samples_type; unsigned int sampleIndex = sampleRadius; for (typename samples_type::const_iterator itData = data.samples.begin() + sampleRadius; itData + sampleRadius != data.samples.end(); ++itData, ++sampleIndex) for (unsigned int filterIndex=0; filterIndex= result.samples.size()) // only when sampleRadius==0, filterIndex>0 break; details::computeCorrelation(itData-sampleRadius, itData+sampleRadius+1, filters[filterIndex].begin(), result.samples[index]); } return result; } } // namespace MatchedFilter } // namespace math } // namespace pwiz #endif // _MATCHEDFILTER_HPP_ pwiz/pwiz/utility/math/OrderedPair.hpp0000664000175100017510000000612412664775616022120 0ustar teamcityteamcity00000000000000// // $Id: OrderedPair.hpp 1832 2010-02-22 22:21:00Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _ORDEREDPAIR_HPP_ #define _ORDEREDPAIR_HPP_ #include "pwiz/utility/misc/Export.hpp" #include #include #include namespace pwiz { namespace math { #pragma pack(push, 1) struct OrderedPair { double x; double y; OrderedPair(double _x = 0, double _y = 0) : x(_x), y(_y) {} }; #pragma pack(pop) inline std::ostream& operator<<(std::ostream& os, const OrderedPair& p) { os << "(" << p.x << "," << p.y << ")"; return os; } inline std::istream& operator>>(std::istream& is, OrderedPair& p) { char open='\0', comma='\0', close='\0'; is >> open >> p.x >> comma >> p.y >> close; if (!is) return is; if (open!='(' || comma!=',' || close!=')') throw std::runtime_error("[OrderedPair::operator>>] Unexpected input."); return is; } inline bool operator==(const OrderedPair& a, const OrderedPair& b) { return a.x==b.x && a.y==b.y; } inline bool operator!=(const OrderedPair& a, const OrderedPair& b) { return !(a == b); } /// /// wrapper class for accessing contiguous data as a container of OrderedPairs; /// note that it does not own the underlying data /// class OrderedPairContainerRef { public: /// constructor for wrapping array of contiguous data OrderedPairContainerRef(const void* begin, const void* end) : begin_(reinterpret_cast(begin)), end_(reinterpret_cast(end)) {} /// template constructor for automatic conversion from vector; /// e.g. vector, vector, vector template OrderedPairContainerRef(const std::vector& v) : begin_(reinterpret_cast(&v[0])), end_(reinterpret_cast(&v[0]+v.size())) {} typedef const OrderedPair* const_iterator; const_iterator begin() const {return begin_;} const_iterator end() const {return end_;} size_t size() const {return end_-begin_;} const OrderedPair& operator[](size_t index) const {return *(begin_+index);} private: const OrderedPair* begin_; const OrderedPair* end_; }; } // namespace math } // namespace pwiz #endif // _ORDEREDPAIR_HPP_ pwiz/pwiz/utility/math/erf.hpp0000664000175100017510000000256712664775616020503 0ustar teamcityteamcity00000000000000// // $Id: erf.hpp 4151 2012-11-28 18:32:03Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _ERF_HPP_ #define _ERF_HPP_ #include "pwiz/utility/misc/Export.hpp" #include namespace pwiz { namespace math { /// real error function; calls gcc-provided erf, complex version (below) on msvc PWIZ_API_DECL double erf(double x); /// complex error function PWIZ_API_DECL std::complex erf(const std::complex& z); /// series implementation for testing PWIZ_API_DECL std::complex erf_series2(const std::complex& z); } // namespace math } // namespace pwiz #endif // _ERF_HPP_ pwiz/pwiz/utility/math/qr.hpp0000664000175100017510000000711212664775616020340 0ustar teamcityteamcity00000000000000// // $Id: qr.hpp 2357 2010-11-09 19:59:54Z broter $ // // Original author: Robert Burke // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _QR_HPP #define _QR_HPP #include #include #include #include namespace pwiz { namespace math { // Constructs a matrix to reflect a vector x onto ||x|| * e1. // // \param x vector to reflect // \param F matrix object to construct reflector with template void Reflector(const vector_type& x, matrix_type& F) { using namespace boost::numeric::ublas; typedef typename matrix_type::value_type value_type; unit_vector e1(x.size(), 0); //v_k = -sgn( x(1) ) * inner_prod(x) * e1 + x; double x_2 = norm_2(x); boost::numeric::ublas::vector v_k((x(0) >= 0 ? x_2 : -1 * x_2) * e1 + x); //v_k = v_k / norm_2(v_k); double norm_vk = norm_2(v_k); if (norm_vk != 0) v_k /= norm_2(v_k); // F = A(k:m,k:n) - 2 * outer_prod(v_k, v_k) * A(k:m,k:n) identity_matrix eye(v_k.size()); F = matrix_type(v_k.size(), v_k.size()); F = eye - 2. * outer_prod(v_k, v_k); } // Returns a matrix to reflect x onto ||x|| * e1. // // \param x vector to reflect // \return Householder reflector for x template matrix_type Reflector(const vector_type& x) { using namespace boost::numeric::ublas; matrix_type F(x.size(), x.size()); Reflector(x, F); return F; } template void qr(const matrix_type& A, matrix_type& Q, matrix_type& R) { using namespace boost::numeric::ublas; typedef typename matrix_type::size_type size_type; typedef typename matrix_type::value_type value_type; // TODO resize Q and R to match the needed size. int m=A.size1(); int n=A.size2(); identity_matrix ident(m); if (Q.size1() != ident.size1() || Q.size2() != ident.size2()) Q = matrix_type(m, m); Q.assign(ident); R.clear(); R = A; for (size_type k=0; k< R.size1() && k e1(m - k, 0); // x = A(k:m, k); matrix_vector_slice x(R, s1, s2); matrix_type F(x.size(), x.size()); Reflector(x, F); matrix_type temp = subrange(R, k, m, k, n); //F = prod(F, temp); subrange(R, k, m, k, n) = prod(F, temp); // <<---------------------------------------------->> // forming Q identity_matrix iqk(A.size1()); matrix_type Q_k(iqk); subrange(Q_k, Q_k.size1() - F.size1(), Q_k.size1(), Q_k.size2() - F.size2(), Q_k.size2()) = F; Q = prod(Q, Q_k); } } } } #endif // _QR_HPP pwiz/pwiz/utility/math/qrTest.cpp0000664000175100017510000000734512664775616021203 0ustar teamcityteamcity00000000000000// // $Id: qrTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include #include #include #include "pwiz/utility/misc/Std.hpp" //#include #include "pwiz/utility/misc/unit.hpp" #include "Types.hpp" #include "qr.hpp" using namespace boost::numeric::ublas; using namespace pwiz::math; using namespace pwiz::math::types; using namespace pwiz::util; ostream* os_ = 0; const double epsilon = 1e-12; template bool isUpperTriangular(const matrix_type& A, double eps) { typedef typename matrix_type::size_type size_type; bool upper = true; for (size_type i=1; i(A, Q, R); unit_assert(isUpperTriangular(R, epsilon)); dmatrix diff = (A - prod(Q, R)); unit_assert_equal(norm_1(diff), 0, epsilon); identity_matrix eye(Q.size1()); diff = prod(Q, herm(Q)) - eye; unit_assert_equal(norm_1(diff), 0, epsilon); } catch (boost::numeric::ublas::bad_argument ba) { if (os_) *os_ << "exception: " << ba.what() << endl; } if (os_) *os_ << "testQR() end" << endl; } void testRectangularQR() { if (os_) *os_ << "testRectangularQR() begin" << endl; dmatrix A(5,3); dmatrix Q; dmatrix R; for (dmatrix::size_type i=0; i< A.size1(); i++) { for (dmatrix::size_type j=0; j(A, Q, R); unit_assert(isUpperTriangular(R, epsilon)); dmatrix diff = (A - prod(Q, R)); unit_assert_equal(norm_1(diff), 0, epsilon); identity_matrix eye(Q.size1()); diff = prod(Q, herm(Q)) - eye; unit_assert_equal(norm_1(diff), 0, epsilon); } catch (boost::numeric::ublas::bad_argument ba) { if (os_) *os_ << "exception: " << ba.what() << endl; } if (os_) *os_ << "testRectangularQR() end" << endl; } int main(int argc, char** argv) { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; if (os_) *os_ << "qrTest\n"; testReflector(); testQR(); testRectangularQR(); return 0; } pwiz/pwiz/utility/math/round.hpp0000664000175100017510000000203312664775616021042 0ustar teamcityteamcity00000000000000// // $Id: round.hpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _ROUND_HPP_ #define _ROUND_HPP_ #include #ifdef _MSC_VER // msvc hack inline double round(double d) {return floor(d + 0.5);} #endif // _MSC_VER #endif // _ROUND_HPP_ pwiz/pwiz/utility/math/StatsTest.cpp0000664000175100017510000000500412664775616021645 0ustar teamcityteamcity00000000000000// // $Id: StatsTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "Stats.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::math; ostream* os_ = 0; void test() { Stats::vector_type a(2); a(0) = 1; a(1) = 2; Stats::vector_type b(2); b(0) = 3; b(1) = 4; Stats::vector_type c(2); c(0) = 5; c(1) = 6; Stats::data_type data; data.push_back(a); data.push_back(b); data.push_back(c); Stats stats(data); if (os_) *os_ << "mean: " << stats.mean() << endl; if (os_) *os_ << "covariance: " << stats.covariance() << endl; // mean & covariance computed using good old-fashioned reckoning Stats::vector_type mean(2); mean(0) = 3; mean(1) = 4; Stats::matrix_type covariance(2,2); covariance(0,0) = covariance(0,1) = covariance(1,0) = covariance(1,1) = 8/3.; // verify results const double epsilon = 1e-12; unit_assert_vectors_equal(stats.mean(), mean, epsilon); unit_assert_matrices_equal(stats.covariance(), covariance, epsilon); double rms0_good = sqrt(35./3); double rms1_good = sqrt(56./3); double rms0_test = sqrt(stats.meanOuterProduct()(0,0)); double rms1_test = sqrt(stats.meanOuterProduct()(1,1)); unit_assert_equal(rms0_test, rms0_good, epsilon); unit_assert_equal(rms1_test, rms1_good, epsilon); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; if (os_) *os_ << "StatsTest\n"; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/utility/math/LinearSolverTest.cpp0000664000175100017510000001400012664775616023150 0ustar teamcityteamcity00000000000000// // $Id: LinearSolverTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "LinearSolver.hpp" #include "pwiz/utility/misc/unit.hpp" #include #include #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::math; namespace ublas = boost::numeric::ublas; ostream* os_ = 0; void testDouble() { if (os_) *os_ << "testDouble()\n"; LinearSolver<> solver; ublas::matrix A(2,2); A(0,0) = 1; A(0,1) = 2; A(1,0) = 3; A(1,1) = 4; ublas::vector y(2); y(0) = 5; y(1) = 11; ublas::vector x = solver.solve(A, y); if (os_) *os_ << "A: " << A << endl; if (os_) *os_ << "y: " << y << endl; if (os_) *os_ << "x: " << x << endl; unit_assert(x(0) == 1.); unit_assert(x(1) == 2.); } void testComplex() { if (os_) *os_ << "testComplex()\n"; LinearSolver<> solver; ublas::matrix< complex > A(2,2); A(0,0) = 1; A(0,1) = 2; A(1,0) = 3; A(1,1) = 4; ublas::vector< complex > y(2); y(0) = 5; y(1) = 11; ublas::vector< complex > x = solver.solve(A, y); if (os_) *os_ << "A: " << A << endl; if (os_) *os_ << "y: " << y << endl; if (os_) *os_ << "x: " << x << endl; unit_assert(x(0) == 1.); unit_assert(x(1) == 2.); } void testDoubleQR() { if (os_) *os_ << "testDoubleQR()\n"; LinearSolver solver; ublas::matrix A(2,2); A(0,0) = 1.; A(0,1) = 2.; A(1,0) = 3.; A(1,1) = 4.; ublas::vector y(2); y(0) = 5.; y(1) = 11.; ublas::vector x = solver.solve(A, y); if (os_) *os_ << "A: " << A << endl; if (os_) *os_ << "y: " << y << endl; if (os_) *os_ << "x: " << x << endl; if (os_) *os_ << x(0) << " - 1. = " << x(0) - 1. << endl; unit_assert_equal(x(0), 1., 1e-14); unit_assert_equal(x(1), 2., 1e-14); } /* void testComplexQR() { if (os_) *os_ << "testComplex()\n"; LinearSolver solver; ublas::matrix< complex > A(2,2); A(0,0) = 1; A(0,1) = 2; A(1,0) = 3; A(1,1) = 4; ublas::vector< complex > y(2); y(0) = 5; y(1) = 11; ublas::vector< complex > x = solver.solve(A, y); if (os_) *os_ << "A: " << A << endl; if (os_) *os_ << "y: " << y << endl; if (os_) *os_ << "x: " << x << endl; unit_assert(x(0) == 1.); unit_assert(x(1) == 2.); } */ void testSparse() { if (os_) *os_ << "testSparse()\n"; LinearSolver<> solver; ublas::mapped_matrix A(2,2,4); A(0,0) = 1.; A(0,1) = 2.; A(1,0) = 3.; A(1,1) = 4.; ublas::vector y(2); y(0) = 5.; y(1) = 11.; ublas::vector x = solver.solve(A, y); if (os_) *os_ << "A: " << A << endl; if (os_) *os_ << "y: " << y << endl; if (os_) *os_ << "x: " << x << endl; unit_assert_equal(x(0), 1., 1e-14); unit_assert_equal(x(1), 2., 1e-14); } /* void testSparseComplex() { if (os_) *os_ << "testSparseComplex()\n"; LinearSolver<> solver; ublas::mapped_matrix< complex > A(2,2,4); A(0,0) = 1.; A(0,1) = 2.; A(1,0) = 3.; A(1,1) = 4.; ublas::vector< complex > y(2); y(0) = 5.; y(1) = 11.; ublas::vector< complex > x = solver.solve(A, y); if (os_) *os_ << "A: " << A << endl; if (os_) *os_ << "y: " << y << endl; if (os_) *os_ << "x: " << x << endl; unit_assert(norm(x(0)-1.) < 1e-14); unit_assert(norm(x(1)-2.) < 1e-14); } */ void testBanded() { if (os_) *os_ << "testBanded()\n"; LinearSolver<> solver; ublas::banded_matrix A(2,2,1,1); A(0,0) = 1.; A(0,1) = 2.; A(1,0) = 3.; A(1,1) = 4.; ublas::vector y(2); y(0) = 5.; y(1) = 11.; ublas::vector x = solver.solve(A, y); if (os_) *os_ << "A: " << A << endl; if (os_) *os_ << "y: " << y << endl; if (os_) *os_ << "x: " << x << endl; unit_assert_equal(x(0), 1., 1e-14); unit_assert_equal(x(1), 2., 1e-14); } void testBandedComplex() { if (os_) *os_ << "testBandedComplex()\n"; LinearSolver<> solver; ublas::banded_matrix< complex > A(2,2,1,1); A(0,0) = 1.; A(0,1) = 2.; A(1,0) = 3.; A(1,1) = 4.; ublas::vector< complex > y(2); y(0) = 5.; y(1) = 11.; ublas::vector< complex > x = solver.solve(A, y); if (os_) *os_ << "A: " << A << endl; if (os_) *os_ << "y: " << y << endl; if (os_) *os_ << "x: " << x << endl; unit_assert(norm(x(0)-1.) < 1e-14); unit_assert(norm(x(1)-2.) < 1e-14); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; if (os_) *os_ << "LinearSolverTest\n"; testDouble(); testComplex(); testDoubleQR(); //testComplexQR(); testSparse(); //testSparseComplex(); // lu_factorize doesn't like mapped_matrix testBanded(); //testBandedComplex(); // FIXME: GCC 4.2 doesn't like this test with link=shared } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/libraries/boost_aux/libs/thread/src/win32/tss_pe.cpp0000664000175100017510000002111012664775723025462 0ustar teamcityteamcity00000000000000// $Id: tss_pe.cpp 72431 2011-06-06 08:28:31Z anthonyw $ // (C) Copyright Aaron W. LaFramboise, Roland Schwarz, Michael Glassford 2004. // (C) Copyright 2007 Roland Schwarz // (C) Copyright 2007 Anthony Williams // (C) Copyright 2007 David Deakins // Use, modification and distribution are subject to the // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include #if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) #if (defined(__MINGW32__) && !defined(_WIN64)) || defined(__MINGW64__) #include #include #include namespace boost { void tss_cleanup_implemented() {} } namespace { void NTAPI on_tls_callback(void* h, DWORD dwReason, PVOID pv) { switch (dwReason) { case DLL_THREAD_DETACH: { boost::on_thread_exit(); break; } } } } #if defined(__MINGW64__) || (__MINGW32_MAJOR_VERSION >3) || \ ((__MINGW32_MAJOR_VERSION==3) && (__MINGW32_MINOR_VERSION>=18)) extern "C" { PIMAGE_TLS_CALLBACK __crt_xl_tls_callback__ __attribute__ ((section(".CRT$XLB"))) = on_tls_callback; } #else extern "C" { void (* after_ctors )() __attribute__((section(".ctors"))) = boost::on_process_enter; void (* before_dtors)() __attribute__((section(".dtors"))) = boost::on_thread_exit; void (* after_dtors )() __attribute__((section(".dtors.zzz"))) = boost::on_process_exit; ULONG __tls_index__ = 0; char __tls_end__ __attribute__((section(".tls$zzz"))) = 0; char __tls_start__ __attribute__((section(".tls"))) = 0; PIMAGE_TLS_CALLBACK __crt_xl_start__ __attribute__ ((section(".CRT$XLA"))) = 0; PIMAGE_TLS_CALLBACK __crt_xl_end__ __attribute__ ((section(".CRT$XLZ"))) = 0; } extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata$T"))) = { (DWORD) &__tls_start__, (DWORD) &__tls_end__, (DWORD) &__tls_index__, (DWORD) (&__crt_xl_start__+1), (DWORD) 0, (DWORD) 0 }; #endif #elif defined(_MSC_VER) && !defined(UNDER_CE) #include #include #define WIN32_LEAN_AND_MEAN #include //Definitions required by implementation #if (_MSC_VER < 1300) // 1300 == VC++ 7.0 typedef void (__cdecl *_PVFV)(); #define INIRETSUCCESS #define PVAPI void __cdecl #else typedef int (__cdecl *_PVFV)(); #define INIRETSUCCESS 0 #define PVAPI int __cdecl #endif typedef void (NTAPI* _TLSCB)(HINSTANCE, DWORD, PVOID); //Symbols for connection to the runtime environment extern "C" { extern DWORD _tls_used; //the tls directory (located in .rdata segment) extern _TLSCB __xl_a[], __xl_z[]; //tls initializers */ } namespace { //Forward declarations static PVAPI on_tls_prepare(); static PVAPI on_process_init(); static PVAPI on_process_term(); static void NTAPI on_tls_callback(HINSTANCE, DWORD, PVOID); //The .CRT$Xxx information is taken from Codeguru: //http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/ #if (_MSC_VER >= 1400) //#pragma section(".CRT$XIU",long,read) #pragma section(".CRT$XCU",long,read) #pragma section(".CRT$XTU",long,read) #pragma section(".CRT$XLC",long,read) __declspec(allocate(".CRT$XLC")) _TLSCB __xl_ca=on_tls_callback; //__declspec(allocate(".CRT$XIU"))_PVFV p_tls_prepare = on_tls_prepare; __declspec(allocate(".CRT$XCU"))_PVFV p_process_init = on_process_init; __declspec(allocate(".CRT$XTU"))_PVFV p_process_term = on_process_term; #else #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0 # pragma data_seg(push, old_seg) #endif //Callback to run tls glue code first. //I don't think it is necessary to run it //at .CRT$XIB level, since we are only //interested in thread detachement. But //this could be changed easily if required. #pragma data_seg(".CRT$XIU") static _PVFV p_tls_prepare = on_tls_prepare; #pragma data_seg() //Callback after all global ctors. #pragma data_seg(".CRT$XCU") static _PVFV p_process_init = on_process_init; #pragma data_seg() //Callback for tls notifications. #pragma data_seg(".CRT$XLB") _TLSCB p_thread_callback = on_tls_callback; #pragma data_seg() //Callback for termination. #pragma data_seg(".CRT$XTU") static _PVFV p_process_term = on_process_term; #pragma data_seg() #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0 # pragma data_seg(pop, old_seg) #endif #endif #ifdef BOOST_MSVC #pragma warning(push) #pragma warning(disable:4189) #endif PVAPI on_tls_prepare() { //The following line has an important side effect: //if the TLS directory is not already there, it will //be created by the linker. In other words, it forces a tls //directory to be generated by the linker even when static tls //(i.e. __declspec(thread)) is not used. //The volatile should prevent the optimizer //from removing the reference. DWORD volatile dw = _tls_used; #if (_MSC_VER < 1300) // 1300 == VC++ 7.0 _TLSCB* pfbegin = __xl_a; _TLSCB* pfend = __xl_z; _TLSCB* pfdst = pfbegin; //pfdst = (_TLSCB*)_tls_used.AddressOfCallBacks; //The following loop will merge the address pointers //into a contiguous area, since the tlssup code seems //to require this (at least on MSVC 6) while (pfbegin < pfend) { if (*pfbegin != 0) { *pfdst = *pfbegin; ++pfdst; } ++pfbegin; } *pfdst = 0; #endif return INIRETSUCCESS; } #ifdef BOOST_MSVC #pragma warning(pop) #endif PVAPI on_process_init() { //Schedule on_thread_exit() to be called for the main //thread before destructors of global objects have been //called. //It will not be run when 'quick' exiting the //library; however, this is the standard behaviour //for destructors of global objects, so that //shouldn't be a problem. atexit(boost::on_thread_exit); //Call Boost process entry callback here boost::on_process_enter(); return INIRETSUCCESS; } PVAPI on_process_term() { boost::on_process_exit(); return INIRETSUCCESS; } void NTAPI on_tls_callback(HINSTANCE /*h*/, DWORD dwReason, PVOID /*pv*/) { switch (dwReason) { case DLL_THREAD_DETACH: boost::on_thread_exit(); break; } } BOOL WINAPI dll_callback(HANDLE, DWORD dwReason, LPVOID) { switch (dwReason) { case DLL_THREAD_DETACH: boost::on_thread_exit(); break; case DLL_PROCESS_DETACH: boost::on_process_exit(); break; } return true; } } //namespace extern "C" { extern BOOL (WINAPI * const _pRawDllMain)(HANDLE, DWORD, LPVOID)=&dll_callback; } namespace boost { void tss_cleanup_implemented() { /* This function's sole purpose is to cause a link error in cases where automatic tss cleanup is not implemented by Boost.Threads as a reminder that user code is responsible for calling the necessary functions at the appropriate times (and for implementing an a tss_cleanup_implemented() function to eliminate the linker's missing symbol error). If Boost.Threads later implements automatic tss cleanup in cases where it currently doesn't (which is the plan), the duplicate symbol error will warn the user that their custom solution is no longer needed and can be removed. */ } } #endif //defined(_MSC_VER) && !defined(UNDER_CE) #endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) pwiz/libraries/boost_aux/libs/thread/src/win32/tss_pe-before_1_44.cpp0000664000175100017510000002030412664775723027455 0ustar teamcityteamcity00000000000000// $Id: tss_pe.cpp 43743 2008-03-21 15:04:10Z anthonyw $ // (C) Copyright Aaron W. LaFramboise, Roland Schwarz, Michael Glassford 2004. // (C) Copyright 2007 Roland Schwarz // (C) Copyright 2007 Anthony Williams // (C) Copyright 2007 David Deakins // Use, modification and distribution are subject to the // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include #if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) #if defined(__MINGW32__) && !defined(_WIN64) #include #include #include extern "C" void tss_cleanup_implemented(void) {} namespace { void NTAPI on_tls_callback(void* h, DWORD dwReason, PVOID pv) { switch (dwReason) { case DLL_THREAD_DETACH: { on_thread_exit(); break; } } } void on_after_ctors(void) { on_process_enter(); } void on_before_dtors(void) { on_thread_exit(); } void on_after_dtors(void) { on_process_exit(); } } extern "C" { void (* after_ctors )(void) __attribute__((section(".ctors"))) = on_after_ctors; void (* before_dtors)(void) __attribute__((section(".dtors"))) = on_before_dtors; void (* after_dtors )(void) __attribute__((section(".dtors.zzz"))) = on_after_dtors; ULONG __tls_index__ = 0; char __tls_end__ __attribute__((section(".tls$zzz"))) = 0; char __tls_start__ __attribute__((section(".tls"))) = 0; PIMAGE_TLS_CALLBACK __crt_xl_start__ __attribute__ ((section(".CRT$XLA"))) = 0; PIMAGE_TLS_CALLBACK __crt_xl_tls_callback__ __attribute__ ((section(".CRT$XLB"))) = on_tls_callback; PIMAGE_TLS_CALLBACK __crt_xl_end__ __attribute__ ((section(".CRT$XLZ"))) = 0; } extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata$T"))) = { (DWORD) &__tls_start__, (DWORD) &__tls_end__, (DWORD) &__tls_index__, (DWORD) (&__crt_xl_start__+1), (DWORD) 0, (DWORD) 0 }; #elif defined(_MSC_VER) && !defined(UNDER_CE) #include #include #define WIN32_LEAN_AND_MEAN #include //Definitions required by implementation #if (_MSC_VER < 1300) // 1300 == VC++ 7.0 typedef void (__cdecl *_PVFV)(void); #define INIRETSUCCESS #define PVAPI void #else typedef int (__cdecl *_PVFV)(void); #define INIRETSUCCESS 0 #define PVAPI int #endif typedef void (NTAPI* _TLSCB)(HINSTANCE, DWORD, PVOID); //Symbols for connection to the runtime environment extern "C" { extern DWORD _tls_used; //the tls directory (located in .rdata segment) extern _TLSCB __xl_a[], __xl_z[]; //tls initializers */ } namespace { //Forward declarations static PVAPI on_tls_prepare(void); static PVAPI on_process_init(void); static PVAPI on_process_term(void); static void NTAPI on_tls_callback(HINSTANCE, DWORD, PVOID); //The .CRT$Xxx information is taken from Codeguru: //http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/ #if (_MSC_VER >= 1400) //#pragma section(".CRT$XIU",long,read) #pragma section(".CRT$XCU",long,read) #pragma section(".CRT$XTU",long,read) #pragma section(".CRT$XLC",long,read) static __declspec(allocate(".CRT$XLC")) _TLSCB __xl_ca=on_tls_callback; //static __declspec(allocate(".CRT$XIU"))_PVFV p_tls_prepare = on_tls_prepare; static __declspec(allocate(".CRT$XCU"))_PVFV p_process_init = on_process_init; static __declspec(allocate(".CRT$XTU"))_PVFV p_process_term = on_process_term; #else #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0 # pragma data_seg(push, old_seg) #endif //Callback to run tls glue code first. //I don't think it is necessary to run it //at .CRT$XIB level, since we are only //interested in thread detachement. But //this could be changed easily if required. #pragma data_seg(".CRT$XIU") static _PVFV p_tls_prepare = on_tls_prepare; #pragma data_seg() //Callback after all global ctors. #pragma data_seg(".CRT$XCU") static _PVFV p_process_init = on_process_init; #pragma data_seg() //Callback for tls notifications. #pragma data_seg(".CRT$XLB") _TLSCB p_thread_callback = on_tls_callback; #pragma data_seg() //Callback for termination. #pragma data_seg(".CRT$XTU") static _PVFV p_process_term = on_process_term; #pragma data_seg() #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0 # pragma data_seg(pop, old_seg) #endif #endif #ifdef BOOST_MSVC #pragma warning(push) #pragma warning(disable:4189) #endif PVAPI on_tls_prepare(void) { //The following line has an important side effect: //if the TLS directory is not already there, it will //be created by the linker. In other words, it forces a tls //directory to be generated by the linker even when static tls //(i.e. __declspec(thread)) is not used. //The volatile should prevent the optimizer //from removing the reference. DWORD volatile dw = _tls_used; #if (_MSC_VER < 1300) // 1300 == VC++ 7.0 _TLSCB* pfbegin = __xl_a; _TLSCB* pfend = __xl_z; _TLSCB* pfdst = pfbegin; //pfdst = (_TLSCB*)_tls_used.AddressOfCallBacks; //The following loop will merge the address pointers //into a contiguous area, since the tlssup code seems //to require this (at least on MSVC 6) while (pfbegin < pfend) { if (*pfbegin != 0) { *pfdst = *pfbegin; ++pfdst; } ++pfbegin; } *pfdst = 0; #endif return INIRETSUCCESS; } #ifdef BOOST_MSVC #pragma warning(pop) #endif PVAPI on_process_init(void) { //Schedule on_thread_exit() to be called for the main //thread before destructors of global objects have been //called. //It will not be run when 'quick' exiting the //library; however, this is the standard behaviour //for destructors of global objects, so that //shouldn't be a problem. atexit(on_thread_exit); //Call Boost process entry callback here on_process_enter(); return INIRETSUCCESS; } PVAPI on_process_term(void) { on_process_exit(); return INIRETSUCCESS; } void NTAPI on_tls_callback(HINSTANCE /*h*/, DWORD dwReason, PVOID /*pv*/) { switch (dwReason) { case DLL_THREAD_DETACH: { on_thread_exit(); break; } } } } //namespace extern "C" void tss_cleanup_implemented(void) { /* This function's sole purpose is to cause a link error in cases where automatic tss cleanup is not implemented by Boost.Threads as a reminder that user code is responsible for calling the necessary functions at the appropriate times (and for implementing an a tss_cleanup_implemented() function to eliminate the linker's missing symbol error). If Boost.Threads later implements automatic tss cleanup in cases where it currently doesn't (which is the plan), the duplicate symbol error will warn the user that their custom solution is no longer needed and can be removed. */ } #endif //defined(_MSC_VER) && !defined(UNDER_CE) #endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) pwiz/LICENSE0000664000175100017510000002613612664775611014567 0ustar teamcityteamcity00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. pwiz/NOTICE0000664000175100017510000000067112664775611014462 0ustar teamcityteamcity00000000000000 ProteoWizard software library for mass spectrometry data analysis http://proteowizard.sourceforge.net Copyright 2005-2008 Spielberg Family Center for Applied Proteomics Cedars Sinai Medical Center, Los Angeles, California 90048 http://sfcap.cshs.org This software makes use of the following libraries: Boost C++ libraries (http://www.boost.org). gd graphics library (http://www.libgd.org). fftw library (http://www.fftw.org) pwiz/pwiz/analysis/spectrum_processing/SpectrumList_MZRefinerTest.cpp0000664000175100017510000002026312664775615030416 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_MZRefinerTest.cpp 8985 2015-10-12 22:38:57Z chambm $ // // // Original author: Bryson Gibbons // // Copyright 2014 Pacific Northwest National Laboratory // Richland, WA 99352 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "SpectrumList_MZRefiner.hpp" #include "pwiz/data/msdata/MSDataFile.hpp" #include "pwiz/data/identdata/IdentDataFile.hpp" #include "pwiz/utility/misc/unit.hpp" #include "boost/filesystem/path.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::cv; using namespace pwiz::msdata; using namespace pwiz::util; using namespace pwiz::analysis; namespace bfs = boost::filesystem; ostream* os_ = 0; // Check scan metadata and a small sample of the m/z data for high-res scans. void verifyScanInfo(const Spectrum& spectrum, const double& epsilon, double basePeakMZ, double lowestObservedMZ, double highestObservedMZ, int mzArrayIndex1, double mzArrayValue1, int mzArrayIndex2, double mzArrayValue2) { unit_assert(spectrum.hasBinaryData()); const BinaryDataArrayPtr binaryData = spectrum.getMZArray(); if (os_) { *os_ << "[verifyScanInfo] " << spectrum.index << " " << spectrum.id << " " << basePeakMZ << " " << lowestObservedMZ << " " << highestObservedMZ << " " << mzArrayValue1 << " " << mzArrayValue2 << ": " << spectrum.cvParam(MS_base_peak_m_z).value << " " << spectrum.cvParam(MS_lowest_observed_m_z).value << " " << spectrum.cvParam(MS_highest_observed_m_z).value << " " << binaryData->data[mzArrayIndex1] << " " << binaryData->data[mzArrayIndex2] << endl; } unit_assert_equal(spectrum.cvParam(MS_base_peak_m_z).valueAs(), basePeakMZ, epsilon); unit_assert_equal(spectrum.cvParam(MS_lowest_observed_m_z).valueAs(), lowestObservedMZ, epsilon); unit_assert_equal(spectrum.cvParam(MS_highest_observed_m_z).valueAs(), highestObservedMZ, epsilon); unit_assert_equal(binaryData->data[mzArrayIndex1], mzArrayValue1, epsilon); unit_assert_equal(binaryData->data[mzArrayIndex2], mzArrayValue2, epsilon); } // Check scan precursor metadata for MS/MS scans void verifyPrecursorInfo(const Spectrum& spectrum, const double& epsilon, double precursorMZ, double isolationWindowTarget) { unit_assert(!spectrum.precursors.empty()); const Precursor& precursor = spectrum.precursors[0]; unit_assert(!precursor.selectedIons.empty()); const SelectedIon& selectedIon = precursor.selectedIons[0]; unit_assert(!precursor.isolationWindow.empty()); const IsolationWindow& isoWindow = precursor.isolationWindow; if (os_) { *os_ << "[verifyPrecursorInfo] " << spectrum.index << " " << spectrum.id << " " << precursorMZ << " " << isolationWindowTarget << ": " << selectedIon.cvParam(MS_selected_ion_m_z).value << " " << isoWindow.cvParam(MS_isolation_window_target_m_z).value << endl; } unit_assert_equal(selectedIon.cvParam(MS_selected_ion_m_z).valueAs(), precursorMZ, epsilon); unit_assert_equal(isoWindow.cvParam(MS_isolation_window_target_m_z).valueAs(), isolationWindowTarget, epsilon); } void testShift(const bfs::path& datadir) { MSDataFile msd((datadir / "JD_06232014_sample4_C.mzML").string()); unit_assert(msd.run.spectrumListPtr.get() && msd.run.spectrumListPtr->size()==610); if (os_) *os_ << "original spectra:\n"; // Provided mzML file is high-res/high-res double epsilon = 1e-4; // MS1 scans 0, 224, 398 (0 and 224 verifyScanInfo(*msd.run.spectrumListPtr->spectrum(0, true), epsilon, 371.09958, 300.14306, 1568.55126, 30, 303.64633, 1200, 416.24838); verifyScanInfo(*msd.run.spectrumListPtr->spectrum(224, true), epsilon, 558.30688, 301.05908, 1522.72473, 200, 407.26425, 1500, 724.32824); verifyScanInfo(*msd.run.spectrumListPtr->spectrum(10, true), epsilon, 530.32782, 74.06039, 887.42852, 41, 188.11117, 93, 442.22839); verifyPrecursorInfo(*msd.run.spectrumListPtr->spectrum(10), epsilon, 530.26684, 530.27); verifyScanInfo(*msd.run.spectrumListPtr->spectrum(173, true), epsilon, 141.10162, 87.05542, 1187.53137, 63, 248.15817, 116, 887.44793); verifyPrecursorInfo(*msd.run.spectrumListPtr->spectrum(173), epsilon, 629.30160, 629.3); verifyScanInfo(*msd.run.spectrumListPtr->spectrum(346, true), epsilon, 848.45895, 116.00368, 1454.73327, 16, 185.16418, 95, 862.43109); verifyPrecursorInfo(*msd.run.spectrumListPtr->spectrum(346), epsilon, 840.45480, 840.45); verifyScanInfo(*msd.run.spectrumListPtr->spectrum(470, true), epsilon, 249.15857, 119.04895, 1402.77331, 23, 217.08113, 102, 1154.59863); verifyPrecursorInfo(*msd.run.spectrumListPtr->spectrum(470), epsilon, 838.96706, 838.97); verifyScanInfo(*msd.run.spectrumListPtr->spectrum(551, true), epsilon, 1048.55047, 155.08105, 1321.67761, 50, 368.19134, 104, 941.96954); verifyPrecursorInfo(*msd.run.spectrumListPtr->spectrum(551), epsilon, 739.69935, 740.03); shared_ptr spectrumListMZRefined( new SpectrumList_MZRefiner(msd, (datadir / "JD_06232014_sample4_C.mzid").string(), "specEValue", "-1e-10", IntegerSet(1, 2))); unit_assert(spectrumListMZRefined->size() == 610); if (os_) *os_ << "refined spectra:\n"; epsilon = 1e-2; // Increase the tolerance a little bit for the refined results (add some forgiveness with algorithm updates...) verifyScanInfo(*msd.run.spectrumListPtr->spectrum(0, true), epsilon, 371.10060, 300.14388, 1568.55631, 30, 303.64715, 1200, 416.24951); verifyScanInfo(*msd.run.spectrumListPtr->spectrum(224, true), epsilon, 558.30841, 301.05990, 1522.72962, 200, 407.26538, 1500, 724.33007); verifyScanInfo(*msd.run.spectrumListPtr->spectrum(10, true), epsilon, 530.32928, 74.06059, 887.43126, 41, 188.11169, 93, 442.22961); verifyPrecursorInfo(*msd.run.spectrumListPtr->spectrum(10), epsilon, 530.26830, 530.27145); verifyScanInfo(*msd.run.spectrumListPtr->spectrum(173, true), epsilon, 141.10200, 87.05566, 1187.53519, 63, 248.15885, 116, 887.45068); verifyPrecursorInfo(*msd.run.spectrumListPtr->spectrum(173), epsilon, 629.30333, 629.30172); verifyScanInfo(*msd.run.spectrumListPtr->spectrum(346, true), epsilon, 848.46155, 116.00400, 1454.73795, 16, 185.16468, 95, 862.43371); verifyPrecursorInfo(*msd.run.spectrumListPtr->spectrum(346), epsilon, 840.45738, 840.45257); verifyScanInfo(*msd.run.spectrumListPtr->spectrum(470, true), epsilon, 249.15926, 119.04927, 1402.77782, 23, 217.08172, 102, 1154.60229); verifyPrecursorInfo(*msd.run.spectrumListPtr->spectrum(470), epsilon, 838.96963, 838.97257); verifyScanInfo(*msd.run.spectrumListPtr->spectrum(551, true), epsilon, 1048.55384, 155.08147, 1321.68186, 50, 368.19235, 104, 941.97253); verifyPrecursorInfo(*msd.run.spectrumListPtr->spectrum(551), epsilon, 739.70141, 740.03206); } void test(const bfs::path& datadir) { testShift(datadir); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { bfs::path datadir = "."; // grab the parent directory for the test files. for (int i=1; i1 && !strcmp(argv[1],"-v")) os_ = &cout; test(datadir); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/spectrum_processing/SpectrumList_TitleMaker.cpp0000664000175100017510000002553312664775615027763 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_TitleMaker.cpp 8981 2015-10-12 20:20:31Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_TitleMaker.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/minimxml/SAXParser.hpp" #include namespace pwiz { namespace analysis { using namespace msdata; using namespace pwiz::util; PWIZ_API_DECL SpectrumList_TitleMaker::SpectrumList_TitleMaker(const msdata::MSData& msd, const string& format) : SpectrumListWrapper(msd.run.spectrumListPtr), msd_(msd), format_(format) { nativeIdFormat_ = id::getDefaultNativeIDFormat(msd); // title adding isn't really worth a processingMethod, is it? } namespace { template void replaceCvParam(ParamContainer& pc, CVID cvid, const value_type& value) { vector::iterator itr; itr = std::find(pc.cvParams.begin(), pc.cvParams.end(), cvid); if (itr == pc.cvParams.end()) pc.set(cvid, value); else itr->value = lexical_cast(value); } // TODO: Make this a public function? It's copied and modified from Serializer_mzXML.cpp; // instead of returning basename, it returns the full file or directory name. string translate_SourceFileTypeToRunID(const SourceFile& sf, CVID sourceFileType) { string nameExtension = bal::to_lower_copy(bfs::extension(sf.name)); string locationExtension = bal::to_lower_copy(bfs::extension(sf.location)); string result; // MSVC10 is happier with a copy before return? switch (sourceFileType) { // location="file://path/to" name="source.RAW" case MS_Thermo_RAW_format: if (nameExtension == ".raw") return sf.name; return ""; // sane: location="file://path/to/source.raw" name="_FUNC001.DAT" // insane: location="file://path/to" name="source.raw" case MS_Waters_raw_format: if (nameExtension == ".dat" && locationExtension == ".raw") return result=BFS_STRING(bfs::path(sf.location).filename()); else if (nameExtension == ".raw") return sf.name; return ""; // location="file://path/to/source.d" name="Analysis.yep" case MS_Bruker_Agilent_YEP_format: if (nameExtension == ".yep" && locationExtension == ".d") return result=BFS_STRING(bfs::path(sf.location).filename()); return ""; // location="file://path/to/source.d" name="Analysis.baf" case MS_Bruker_BAF_format: if (nameExtension == ".baf" && locationExtension == ".d") return result=BFS_STRING(bfs::path(sf.location).filename()); return ""; // location="file://path/to/source.d/AcqData" name="msprofile.bin" case MS_Agilent_MassHunter_format: if (nameExtension == ".bin" && bfs::path(sf.location).filename() == "AcqData") return result=BFS_STRING(bfs::path(sf.location).parent_path().filename()); return ""; // location="file://path/to" name="source.mzXML" // location="file://path/to" name="source.mz.xml" // location="file://path/to" name="source.d" (ambiguous) case MS_ISB_mzXML_format: if (nameExtension == ".mzxml" || nameExtension == ".d") return sf.name; else if (bal::iends_with(sf.name, ".mz.xml")) return sf.name.substr(0, sf.name.length()-7); return ""; // location="file://path/to" name="source.mzData" // location="file://path/to" name="source.mz.data" ??? case MS_PSI_mzData_format: if (nameExtension == ".mzdata") return sf.name; return ""; // location="file://path/to" name="source.mgf" case MS_Mascot_MGF_format: if (nameExtension == ".mgf") return sf.name; return ""; // location="file://path/to" name="source.wiff" case MS_ABI_WIFF_format: if (nameExtension == ".wiff") return sf.name; return ""; // location="file://path/to/source/maldi-spot/1/1SRef" name="fid" // location="file://path/to/source/1/1SRef" name="fid" case MS_Bruker_FID_format: return (bfs::path(sf.location) / sf.name).string().substr(7); // location="file://path/to/source" name="spectrum-id.t2d" // location="file://path/to/source/MS" name="spectrum-id.t2d" // location="file://path/to/source/MSMS" name="spectrum-id.t2d" case MS_SCIEX_TOF_TOF_T2D_format: return (bfs::path(sf.location) / sf.name).string().substr(7); default: return ""; } } struct SourceFilePtrIdEquals { SourceFilePtrIdEquals(const string& id) : id(id) {} bool operator() (const SourceFilePtr& sf) const {return sf->id == id;} private: const string& id; }; SourceFilePtr spectrumSourceFilePtr(const Spectrum& s, const MSData& msd) { if (s.sourceFilePtr.get()) return s.sourceFilePtr; if (bal::starts_with(s.id, "file=")) { string sourceFileId = s.id.substr(5); pwiz::minimxml::decode_xml_id(sourceFileId); vector::const_iterator itr = boost::find_if(msd.fileDescription.sourceFilePtrs, SourceFilePtrIdEquals(sourceFileId)); if (itr == msd.fileDescription.sourceFilePtrs.end()) throw runtime_error("id \"" + s.id + "\" does not match the id of a source file"); return *itr; } return msd.run.defaultSourceFilePtr; } } // namespace PWIZ_API_DECL SpectrumPtr SpectrumList_TitleMaker::spectrum(size_t index, bool getBinaryData) const { SpectrumPtr s = inner_->spectrum(index, getBinaryData); /// - Run::id /// - "Data.d" from "C:/Agilent/Data.d/AcqData/mspeak.bin" /// - SpectrumIdentity::index /// - SpectrumIdentity::id (nativeID) /// - if the nativeID can be represented as a single number, that number, else index /// - for the first precursor, Activation::cvParamChild("dissociation method") /// - for the first precursor, IsolationWindow::cvParam("isolation target m/z") /// - for the first selected ion of the first precursor, SelectedIon::cvParam("selected ion m/z") /// - for the first selected ion of the first precursor, SelectedIon::cvParam("charge state") /// - for the first precursor, Precursor::spectrumID or Precursor::externalSpectrumID /// - Spectrum::cvParamChild("spectrum type") /// - Spectrum::cvParam("ms level") /// - for the first scan, Scan::cvParam("scan start time") /// - Spectrum::cvParam("base peak m/z") /// - Spectrum::cvParam("base peak intensity") /// - Spectrum::cvParam("total ion current") string title = format_; bal::replace_all(title, "", msd_.run.id); bal::replace_all(title, "", lexical_cast(s->index)); bal::replace_all(title, "", s->id); if (bal::contains(title, "")) { string nativeSourcePath; SourceFilePtr sfp = spectrumSourceFilePtr(*s, msd_); if (sfp.get()) { const SourceFile& sf = *sfp; CVID nativeFileFormat = sf.cvParamChild(MS_mass_spectrometer_file_format).cvid; nativeSourcePath = translate_SourceFileTypeToRunID(sf, nativeFileFormat); } bal::replace_all(title, "", nativeSourcePath); } string scanNumberStr = id::translateNativeIDToScanNumber(nativeIdFormat_, s->id); if (scanNumberStr.empty()) scanNumberStr = lexical_cast(s->index+1); // scanNumber is a 1-based index for some nativeID formats bal::replace_all(title, "", scanNumberStr); if (!s->precursors.empty()) { const Precursor& p = s->precursors[0]; vector activationTypes; BOOST_FOREACH(const CVParam& cvParam, p.activation.cvParamChildren(MS_dissociation_method)) activationTypes.push_back(cv::cvTermInfo(cvParam.cvid).shortName()); bal::replace_all(title, "", bal::join(activationTypes, "/")); bal::replace_all(title, "", p.isolationWindow.cvParam(MS_isolation_window_target_m_z).value); if (!p.selectedIons.empty()) { bal::replace_all(title, "", p.selectedIons[0].cvParam(MS_selected_ion_m_z).value); bal::replace_all(title, "", p.selectedIons[0].cvParam(MS_charge_state).value); } else { bal::replace_all(title, "", ""); bal::replace_all(title, "", ""); } if (!p.spectrumID.empty()) bal::replace_all(title, "", p.spectrumID); else if (!p.externalSpectrumID.empty()) bal::replace_all(title, "", p.externalSpectrumID); } else { bal::replace_all(title, "", ""); bal::replace_all(title, "", ""); bal::replace_all(title, "", ""); bal::replace_all(title, "", ""); bal::replace_all(title, "", ""); } double scanStartTimeInSeconds = s->scanList.scans.empty() ? 0 : s->scanList.scans[0].cvParam(MS_scan_start_time).timeInSeconds(); bal::replace_all(title, "", lexical_cast(scanStartTimeInSeconds)); bal::replace_all(title, "", lexical_cast(scanStartTimeInSeconds / 60)); bal::replace_all(title, "", s->cvParamChild(MS_spectrum_type).name()); bal::replace_all(title, "", s->cvParam(MS_ms_level).value); bal::replace_all(title, "", s->cvParam(MS_base_peak_m_z).value); bal::replace_all(title, "", s->cvParam(MS_base_peak_intensity).value); bal::replace_all(title, "", s->cvParam(MS_TIC).value); replaceCvParam(*s, MS_spectrum_title, title); return s; } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/SpectrumList_PrecursorRefineTest.cpp0000664000175100017510000001012212664775615031663 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_PrecursorRefineTest.cpp 4457 2013-03-29 19:33:27Z pcbrefugee $ // // // Original author: Chris Paulse // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "SpectrumList_PrecursorRefine.hpp" #include "pwiz/data/msdata/MSDataFile.hpp" #include "pwiz/utility/misc/unit.hpp" #include "boost/filesystem/path.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::cv; using namespace pwiz::msdata; using namespace pwiz::util; using namespace pwiz::analysis; namespace bfs = boost::filesystem; ostream* os_ = 0; void verifyPrecursorMZ(const Spectrum& spectrum, double precursorMZ) { unit_assert(!spectrum.precursors.empty()); const Precursor& precursor = spectrum.precursors[0]; unit_assert(!precursor.selectedIons.empty()); const SelectedIon& selectedIon = precursor.selectedIons[0]; double foo = selectedIon.cvParam(MS_selected_ion_m_z).valueAs(); foo++; // quiet an "initalized but not used" warning const double epsilon = 1e-4; if (os_) { *os_ << "[verifyPrecursorMZ] " << spectrum.index << " " << spectrum.id << " " << precursorMZ << ": " << selectedIon.cvParam(MS_selected_ion_m_z).value << " " << selectedIon.cvParam(MS_charge_state).value << endl; } unit_assert_equal(selectedIon.cvParam(MS_selected_ion_m_z).valueAs(), precursorMZ, epsilon); } void testPrecursorRefine(const bfs::path& datadir) { MSDataFile msd((datadir / "PrecursorRefineOrbi.mzML").string()); unit_assert(msd.run.spectrumListPtr.get() && msd.run.spectrumListPtr->size()==51); if (os_) *os_ << "original spectra:\n"; verifyPrecursorMZ(*msd.run.spectrumListPtr->spectrum(21), 747.37225); verifyPrecursorMZ(*msd.run.spectrumListPtr->spectrum(22), 614.867065); verifyPrecursorMZ(*msd.run.spectrumListPtr->spectrum(24), 547.2510); verifyPrecursorMZ(*msd.run.spectrumListPtr->spectrum(25), 533.2534); verifyPrecursorMZ(*msd.run.spectrumListPtr->spectrum(26), 401.22787); shared_ptr spectrumListRecalculated( new SpectrumList_PrecursorRefine(msd)); unit_assert(spectrumListRecalculated->size() == 51); if (os_) *os_ << "recalculated spectra:\n"; verifyPrecursorMZ(*spectrumListRecalculated->spectrum(21), 747.37078); verifyPrecursorMZ(*spectrumListRecalculated->spectrum(22), 614.86648); verifyPrecursorMZ(*spectrumListRecalculated->spectrum(24), 547.2507); verifyPrecursorMZ(*spectrumListRecalculated->spectrum(25), 533.2534); verifyPrecursorMZ(*spectrumListRecalculated->spectrum(26), 401.226957); } void test(const bfs::path& datadir) { testPrecursorRefine(datadir); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { bfs::path datadir = "."; for (int i=1; i1 && !strcmp(argv[1],"-v")) os_ = &cout; test(datadir); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/spectrum_processing/ThresholdFilter.hpp0000664000175100017510000001005612664775615026305 0ustar teamcityteamcity00000000000000// // $Id: ThresholdFilter.hpp 2363 2010-11-10 23:19:45Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _THRESHOLDFILTER_HPP_ #define _THRESHOLDFILTER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/utility/misc/IntegerSet.hpp" #include "pwiz/analysis/common/DataFilter.hpp" #include namespace pwiz { namespace analysis { struct PWIZ_API_DECL ThresholdFilter : public SpectrumDataFilter { /// determines the method of thresholding and the meaning of the threshold value PWIZ_API_DECL enum ThresholdingBy_Type { /// keep the [most|least] intense data points /// - is rounded to the nearest integer /// - if the falls within equally intense data points, all data points with that intensity are removed ThresholdingBy_Count, /// keep the [most|least] intense data points /// - is rounded to the nearest integer /// - if the falls within equally intense data points, all data points with that intensity are kept ThresholdingBy_CountAfterTies, /// keep data points ranked [better|worse] than /// - is rounded to the nearest integer /// - rank 1 is the most intense // TODO: By_CompetitionRank, /// keep data points ranked [better|worse] than /// - rank 1 is the most intense // TODO: By_FractionalRank, /// keep data points [more|less] absolutely intense than ThresholdingBy_AbsoluteIntensity, /// keep data points [more|less] relatively intense than /// - is each data point's fraction of the base peak intensity (in the range [0,1]) ThresholdingBy_FractionOfBasePeakIntensity, /// keep data points [more|less] relatively intense than /// - is each data point's fraction of the total intensity, aka total ion current (in the range [0,1]) ThresholdingBy_FractionOfTotalIntensity, /// keep data points that are part of the [most|least] intense fraction /// - is the fraction of TIC to keep, i.e. the TIC of the kept data points is * original TIC ThresholdingBy_FractionOfTotalIntensityCutoff }; /// determines the orientation of the thresholding PWIZ_API_DECL enum ThresholdingOrientation { Orientation_MostIntense, /// thresholder removes the least intense data points Orientation_LeastIntense /// thresholder removes the most intense data points }; ThresholdFilter(ThresholdingBy_Type byType_ = ThresholdingBy_Count, double threshold_ = 1.0, ThresholdingOrientation orientation_ = Orientation_MostIntense, const pwiz::util::IntegerSet& msLevelsToThreshold = pwiz::util::IntegerSet(1, INT_MAX)); virtual void operator () (const pwiz::msdata::SpectrumPtr) const; virtual void describe(pwiz::msdata::ProcessingMethod&) const; const ThresholdingBy_Type byType; const double threshold; const ThresholdingOrientation orientation; const pwiz::util::IntegerSet msLevelsToThreshold; private: static const char* byTypeMostIntenseName[]; static const char* byTypeLeastIntenseName[]; }; } // namespace analysis } // namespace pwiz #endif // _SPECTRUMLIST_PEAKFILTER_HPP_ pwiz/pwiz/analysis/spectrum_processing/SpectrumList_ChargeStateCalculatorTest.cpp0000664000175100017510000050706412664775615032772 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_ChargeStateCalculatorTest.cpp 6827 2014-10-22 17:54:33Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "SpectrumList_ChargeStateCalculator.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/data/msdata/examples.hpp" #include "pwiz/data/msdata/TextWriter.hpp" #include "pwiz/data/common/CVTranslator.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::msdata; using namespace pwiz::analysis; ostream* os_ = 0; ostream& operator<< (ostream& os, const vector& v) { os << "("; for (size_t i=0; i < v.size(); ++i) os << " " << v[i]; os << " )"; return os; } struct TestChargeStateCalculator { // space-delimited doubles const char* inputMZArray; const char* inputIntensityArray; const char* inputChargeStateArray; const char* inputActivationTypeArray; double inputPrecursorMZ; bool overrideExistingChargeState; int minMultipleCharge; int maxMultipleCharge; double singlyChargedFraction; const char* chargeStateArray; int maxKnownCharge; bool useMakeMS2Behavior; }; TestChargeStateCalculator testChargeStateCalculators[] = { { "1 2 3 4 5", "10 20 30 40 50", "1", "CID", 5, true, 2, 3, 0.9, "1", 0, false }, { "1 2 3 4 5", "10 20 30 40 50", "1 2 3", "CID", 5, true, 2, 3, 0.9, "1", 0, false }, { "1 2 3 4 5", "10 20 30 40 50", "2 3", "CID", 5, true, 2, 3, 0.9, "1" }, { "1 2 3 4 5", "10 20 30 40 50", "", "CID", 2.5, true, 2, 3, 0.9, "2 3", 0, false }, // input charge of 0 should be treated like no charge { "1 2 3 4 5", "10 20 30 40 50", "0", "CID", 2.5, true, 2, 3, 0.9, "2 3", 0, false }, { "1 2 3 4 5", "10 20 30 40 50", "2", "CID", 2.5, true, 3, 4, 0.9, "3 4 5", 0, false }, { "1 2 3 4 5", "10 20 30 40 50", "3 4 5", "CID", 2.5, true, 3, 4, 0.9, "3 4 5", 0, false }, { "1 2 3 4 5", "10 20 30 40 50", "3", "CID", 2.5, true, 2, 2, 0.9, "2", 0, false }, { "1 2 3 4 5", "10 20 30 40 50", "", "CID", 5, false, 2, 3, 0.9, "1", 0, false }, { "1 2 3 4 5", "10 20 30 40 50", "", "CID", 2.5, false, 2, 3, 0.9, "2 3", 0, false }, // input charge of 0 should be treated like no charge { "1 2 3 4 5", "10 20 30 40 50", "0", "CID", 2.5, false, 2, 3, 0.9, "2 3", 0, false }, { "1 2 3 4 5", "10 20 30 40 50", "1", "CID", 2.5, false, 2, 3, 0.9, "1", 0, false }, { "1 2 3 4 5", "10 20 30 40 50", "2 3", "CID", 5, false, 2, 3, 0.9, "1 2 3", 0 }, { "1 2 3 4 5", "10 20 30 40 50", "2 3", "CID", 2.5, false, 2, 4, 0.9, "2 3 4", 0, false }, // 20090326_Yest_LysC_1x6ETD_longGrad_01.05864.05864.7.dta { "100.2316 102.1654 114.1007 142.3967 147.1805 148.0554 158.1545 159.1372 204.4804 211.9715 216.0852 217.2059 218.3450 219.1636 230.0421 238.6137 245.4243 246.2292 246.8875 259.0931 260.1801 267.7267 272.4216 273.2703 274.2005 287.1424 288.3069 294.8814 295.7421 296.4242 299.0081 303.5564 305.5432 316.3794 317.2255 326.3209 329.1799 339.1173 341.1064 342.1323 344.3056 345.2133 347.3302 355.1378 356.2534 367.5323 370.0612 371.1212 372.3159 380.9781 383.1261 384.1235 385.7302 386.3345 388.3026 389.2090 390.2366 390.9072 400.0575 404.4477 411.1859 416.4116 419.3402 426.5632 427.2871 428.3036 429.2469 431.1707 432.6296 437.1998 438.0903 445.0817 446.1855 456.3277 457.2303 459.3148 460.3862 461.1172 463.4081 467.3364 472.6896 474.4414 475.2522 476.0383 477.0409 479.3283 480.0349 484.2828 485.2685 487.2802 490.2423 491.2538 492.0312 502.1874 503.1729 504.3073 511.1371 512.5167 513.3364 513.9659 528.2398 529.0281 530.1065 531.5367 533.0511 533.9404 535.1735 536.2697 537.0353 539.3831 542.0954 546.0742 547.6926 552.2240 553.3661 556.2790 557.2021 557.9160 559.4593 562.8941 565.2065 568.3622 569.3952 573.2255 574.2047 575.4551 576.5182 581.0674 583.7980 585.7489 586.8701 587.5425 589.6053 590.2707 591.2530 592.2204 593.2232 597.5678 598.3864 599.1964 600.0155 604.6537 606.2562 607.7433 610.8060 612.3967 613.2997 614.2175 615.4516 617.8012 622.2905 624.6938 626.3412 631.5930 632.6418 633.3755 636.5936 639.9253 640.9366 643.3186 644.1926 645.7126 647.3211 648.4583 649.2852 650.5535 651.3624 654.3332 657.2921 658.3475 659.8166 662.4810 664.3082 665.6356 668.1566 669.6567 670.2629 671.4838 672.3119 675.8893 677.0720 678.0397 680.3560 682.3088 683.4887 684.3668 689.4347 692.5178 693.4395 694.9922 696.2354 698.6488 699.7452 700.6685 701.5429 702.9158 704.6758 705.5378 706.4117 707.9384 708.7421 710.2140 711.4921 713.7796 714.5510 716.2544 717.9063 718.5756 719.7270 723.4227 725.6956 726.4857 727.2152 728.2474 729.0570 729.9482 730.6264 732.6265 733.2515 734.4771 738.3369 739.5363 740.2814 741.5637 749.6926 752.5176 753.2125 754.4744 755.3438 757.0353 758.0003 759.4985 760.3941 761.7000 762.8120 764.7708 765.6356 767.5706 768.6167 769.8208 771.1314 771.8177 773.3740 774.5911 775.1982 775.9609 776.8069 777.4185 778.2676 779.3928 781.2325 783.3708 784.3259 785.1341 786.0793 787.1502 787.9260 789.0554 790.2109 791.4124 792.5274 793.5887 794.5103 795.2405 796.2149 796.9224 799.5650 801.3645 803.8350 804.4755 805.2210 806.4171 807.4406 808.6633 809.6253 811.9946 814.5346 817.0883 818.0493 819.0435 820.9210 821.8782 824.1953 825.4860 826.4271 829.5283 830.4576 832.2156 832.8347 834.4541 836.0142 836.9937 838.1580 839.6205 841.3862 843.0901 843.8099 845.3442 846.6658 847.6355 850.0297 852.0378 853.2718 854.4008 856.4588 857.4885 859.5439 861.4915 862.1750 863.2495 864.8409 867.3325 868.4129 869.3459 870.4559 871.7208 872.5671 873.2695 874.4902 875.4397 877.8188 880.2540 882.8533 883.6810 884.6408 887.3281 889.8179 893.5707 894.5350 898.4689 899.2938 900.3057 901.4645 902.7376 903.6931 904.5297 910.3437 911.3130 912.6046 913.4197 914.2205 916.8642 918.2337 920.0554 921.9939 922.9043 924.7449 925.5725 926.3651 927.3116 928.2539 929.2107 930.2380 932.0637 933.0691 933.6707 935.9348 937.2978 939.5454 940.9717 941.9307 943.8423 944.8279 949.0307 952.2651 953.4227 954.1648 955.2634 956.2859 957.3259 957.9824 959.4771 960.2833 962.5200 963.5037 965.2302 967.8181 968.6046 969.2939 970.3937 971.6548 972.6874 976.8770 978.5676 980.8109 981.4683 982.4684 983.2844 983.9832 986.5053 987.1211 989.2344 993.3611 994.6191 996.0191 997.5510 999.1077 1000.4880 1002.7420 1005.3079 1006.2520 1007.1972 1008.3851 1009.3384 1010.3657 1012.2654 1013.2116 1014.0049 1015.4166 1017.0412 1017.6729 1019.2534 1021.5500 1023.4800 1024.4152 1025.5474 1026.6501 1027.8084 1028.9393 1030.0382 1031.1877 1031.8257 1033.3679 1034.3296 1035.4045 1036.1647 1037.3960 1038.4543 1039.1770 1040.1565 1042.1265 1043.2186 1044.4426 1045.5302 1046.7881 1047.5444 1049.1858 1050.2570 1051.4323 1053.2034 1054.4518 1055.5977 1056.4724 1057.2979 1058.4558 1059.4180 1060.2227 1060.9368 1062.2380 1063.0264 1063.7651 1065.1206 1066.2021 1067.3129 1068.5062 1069.2571 1070.4927 1071.5564 1072.6907 1073.7375 1074.5313 1075.2959 1076.3043 1077.2311 1078.0673 1079.6613 1081.9634 1083.8835 1084.7516 1087.9388 1088.6055 1090.0548 1090.7660 1091.6577 1092.5103 1093.2368 1093.8492 1094.5607 1095.9825 1096.6309 1098.0442 1098.8674 1100.5309 1101.6241 1103.2767 1104.0603 1106.0070 1106.9993 1109.4095 1112.0243 1114.4689 1115.4701 1116.4965 1118.4481 1120.3474 1122.0121 1123.3585 1124.0900 1126.5304 1127.5829 1129.7465 1131.1656 1133.5940 1134.8131 1136.3689 1137.7687 1138.9125 1139.9618 1140.6614 1142.9773 1143.7170 1144.4061 1145.0295 1148.4452 1150.0396 1151.6088 1153.8888 1155.4089 1157.7570 1159.0519 1160.5687 1163.3629 1164.2449 1165.6302 1167.2775 1170.1827 1171.9503 1173.6943 1178.1985 1178.9193 1180.1576 1181.7102 1183.7064 1187.6965 1189.9983 1191.4650 1192.9443 1193.8871 1194.8962 1195.7772 1196.4039 1197.9064 1198.9985 1199.7401 1201.5292 1206.3419 1207.0554 1207.7147 1208.9205 1210.1613 1211.1132 1211.7198 1212.8514 1213.9382 1215.0614 1215.8712 1216.8856 1218.7352 1220.2765 1221.1106 1221.7494 1222.8069 1224.0594 1224.9103 1225.7242 1226.5060 1227.3594 1229.0797 1229.9269 1230.7487 1231.5803 1232.2225 1232.8799 1235.1190 1236.3748 1236.9987 1237.8800 1240.5161 1242.5454 1245.7117 1248.2661 1249.0128 1250.0117 1253.4581 1254.8519 1258.7023 1261.1508 1262.4562 1263.8649 1266.9794 1268.4827 1271.5897 1272.6104 1276.4093 1278.5415 1279.4795 1280.1755 1283.2010 1284.1530 1285.4436 1286.6320 1287.8259 1288.8115 1292.2874 1294.6595 1295.3514 1296.9506 1297.6798 1299.2562 1300.0573 1301.4045 1303.1136 1303.7776 1304.8346 1305.4403 1306.5542 1307.6301 1308.7888 1310.1801 1311.2026 1312.3358 1313.4727 1314.5222 1315.2391 1316.4742 1317.2528 1317.9081 1319.5140 1322.6118 1323.4581 1324.4717 1325.4580 1326.8948 1328.9554 1329.6587 1330.7810 1331.5580 1332.9672 1338.9171 1340.0092 1341.0057 1342.1337 1343.0525 1343.9711 1344.8038 1346.7933 1348.2371 1351.8527 1352.8333 1353.9034 1354.5902 1357.1407 1359.8356 1368.5875 1370.5602 1371.7577 1372.9083 1375.4344 1382.9457 1383.8612 1385.3168 1387.3273 1390.1798 1391.5629 1392.4547 1393.5638 1394.3420 1395.7352 1397.0741 1398.1329 1398.8969 1400.7195 1402.5508 1403.6631 1407.2289 1410.7687 1411.7717 1412.4025 1413.7531 1415.5807 1416.5509 1417.6246 1418.7306 1419.4539 1420.1559 1421.1342 1421.9913 1422.8665 1423.7020 1425.9493 1427.1515 1428.4490 1429.0841 1430.0243 1431.8527 1434.8483 1436.1760 1436.9138 1437.8707 1439.5657 1442.8479 1450.1022 1451.2184 1453.8065 1456.0328 1456.6864 1458.0870 1459.1053 1461.9120 1462.6119 1463.7512 1469.5785 1473.6619 1475.8344 1478.1866 1479.9750 1480.7377 1482.8094 1484.3290 1485.4197 1487.3420 1493.9686 1496.9908 1498.8871 1499.9709 1501.5465 1503.8168 1505.7375 1506.5231 1507.2571 1507.9613 1509.2472 1510.8177 1511.9337 1512.8951 1516.2877 1516.9982 1517.9640 1519.2213 1521.8727 1523.5814 1524.6912 1525.5077 1526.3093 1528.0574 1528.8844 1529.6288 1530.7858 1531.8386 1533.4905 1534.8173 1536.1672 1537.7214 1539.0460 1539.8561 1540.9690 1542.5066 1544.0828 1544.8269 1545.9760 1546.8141 1547.5980 1548.7726 1549.4471 1550.2883 1551.1202 1552.0406 1552.9171 1554.0577 1555.2815 1556.1970 1556.9130 1557.9539 1559.1941 1560.8824 1562.7125 1563.6962 1565.8517 1566.8927 1567.9371 1568.8998 1569.9613 1571.1643 1572.1046 1572.8573 1573.7242 1574.4230 1577.9452 1578.9706 1579.7214 1580.5770 1581.3318 1582.5018 1583.2159 1584.3450 1585.7789 1586.8810 1588.1760 1589.1420 1590.6589 1591.7211 1593.4823 1594.6254 1595.4083 1596.3741 1597.6932 1598.7032", " 3.2418 2.2150 11.0869 2.2778 50.9633 2.2093 19.3287 12.4510 8.9364 3.3966 73.3816 35.4844 17.8207 12.0066 6.4694 15.7834 8.2228 6.0483 8.6328 2.2224 12.6325 17.8730 12.9276 3.4544 11.7616 142.6698 69.7587 11.4609 216.5886 1.8377 6.5047 48.8038 4.3386 46.1475 4.4074 18.6191 4.6289 20.0546 2.9302 11.5797 21.3002 15.2543 7.4326 6.0572 1.9788 6.9874 155.7842 10.7804 11.7532 24.5477 24.2512 9.8384 31.9294 10.7230 80.0561 21.8453 4.2641 7.5264 3.4045 1.9816 6.0726 5.6346 25.9069 18.8623 18.5661 45.0142 16.8058 2.2163 1.7374 25.7332 30.4077 8.3505 26.0232 27.2097 12.4612 2.6889 4.3828 3.8749 25.7056 4.8666 7.9613 26.5360 72.1348 46.1052 6.2061 38.5774 32.5843 121.5198 36.7320 9.0994 9.5700 13.7784 8.6465 3.4076 29.5869 10.2263 38.0570 222.2102 28.3271 36.8888 527.9606 559.1112 1000.0000 42.5538 29.9167 16.2195 9.4391 135.0116 10.7759 7.4709 4.8641 9.6174 8.8924 11.7112 9.1210 2.2504 14.3277 8.8646 2.4484 2.6109 10.5663 31.9595 14.9439 51.2389 9.4340 9.1117 3.9247 2.2127 11.9327 50.3476 40.0407 21.7258 28.2477 195.3547 56.9475 101.0778 18.8569 20.2152 9.4084 12.7033 15.9751 26.1827 25.2666 11.3724 12.1166 228.3339 51.6904 13.8419 19.1409 67.5237 7.0505 20.1022 11.5966 12.5294 29.2311 12.6644 89.0887 42.5493 22.1867 284.1091 75.3782 9.5436 17.6771 10.8152 7.7030 16.7860 15.3062 3.8434 8.9797 33.1646 20.8195 31.6203 42.3290 15.6282 32.7879 13.7429 5.5781 159.8926 49.8017 19.5154 10.0519 8.1359 49.1926 27.8555 12.2163 23.6995 9.8478 6.5212 27.3637 44.8395 12.2819 73.2868 79.3788 47.1691 41.8323 17.7027 47.3262 100.6576 30.6365 89.0225 111.0906 85.2993 47.1381 12.1153 16.9150 76.4411 126.5558 132.3647 17.5699 20.0839 49.8344 41.3531 89.9600 40.7703 4.1909 30.8658 17.8780 14.6302 3.6403 13.5900 26.9555 25.8994 55.4275 7.4319 8.8972 25.1711 10.7609 24.7685 43.4959 95.7611 12.8040 29.0010 32.5526 91.6369 78.5863 153.4670 99.6896 24.0892 46.4224 23.2663 59.5909 20.8479 44.3557 6.2475 21.2062 52.1075 36.3742 22.1843 4.5882 75.2949 8.3783 15.3799 46.0072 22.8688 113.2306 32.0690 18.1297 10.4917 115.5912 111.7756 401.1757 122.0876 279.1254 39.4676 62.1709 7.5180 4.9301 23.2444 25.8239 6.1557 76.0793 62.5210 49.6156 95.2091 36.9798 12.7502 16.5192 39.1498 56.7536 5.8498 34.9025 36.0609 13.3717 10.4189 19.5955 24.5496 11.9503 11.0001 25.1156 33.0185 26.1695 8.0101 25.6687 46.1801 8.8585 79.3093 60.3437 16.0549 128.9062 15.0835 7.2337 43.6132 3.9066 14.3446 15.2733 13.3906 15.3547 13.4817 4.1137 17.9837 37.4059 124.3921 82.3209 49.4677 37.0553 16.6742 10.0291 67.2750 132.8354 59.9224 39.5181 30.8779 21.0157 22.9907 13.9648 7.5204 30.9982 59.8321 82.4379 11.7083 5.0482 69.8900 17.8834 27.8587 27.7243 37.2471 9.1249 133.9667 81.9941 7.9074 10.7635 33.3638 51.3460 28.5408 120.0791 64.7641 130.6045 57.2454 43.0353 76.0876 47.7058 35.8746 93.3957 11.5280 86.3272 48.0687 17.4323 17.9122 32.9358 64.8450 65.4608 237.2285 63.2972 14.5888 12.9763 22.4495 26.9346 20.1092 22.2112 5.2457 26.2077 31.5904 26.9079 3.1633 7.7255 27.5440 55.5476 12.5317 12.2895 29.7237 7.8901 40.7258 29.4631 59.8513 42.8277 33.9833 11.4439 14.0811 27.8080 24.0819 20.2655 5.8329 95.8489 10.7876 27.9724 11.7674 65.8042 17.1769 75.2262 108.2203 54.5236 115.9897 53.0610 64.9889 56.1649 36.3425 43.3307 41.8708 12.8255 39.2026 10.7519 7.9070 28.0647 96.8431 272.0151 40.1899 88.3676 125.8584 48.9294 62.9378 38.2105 32.8664 173.3573 35.0060 12.7923 47.6801 24.0867 316.5758 58.3904 126.7407 50.1308 94.4073 33.2618 30.6582 56.5687 8.3901 227.6603 114.3906 32.3215 35.7905 86.9787 335.9061 253.4367 274.9273 308.5602 370.9917 115.7313 18.8021 110.6610 71.3167 72.6248 31.7910 2.7195 71.2045 11.4435 9.5659 60.2547 146.5376 49.1726 20.5347 26.9450 8.8278 17.1559 50.6427 17.5154 13.8876 35.0394 36.4334 5.2007 58.4728 91.9885 14.8054 51.3077 43.9949 22.6586 16.0143 38.2009 22.9566 16.7180 18.8799 42.6049 27.6320 22.4117 19.5303 15.1561 21.4431 95.0123 64.2030 3.9374 108.4517 37.7694 4.5797 31.8731 10.5401 12.9173 4.3468 100.2101 9.2353 59.5649 18.6624 14.4319 18.9445 41.4509 182.4317 54.1046 68.3520 48.8382 34.0989 36.4116 8.2339 23.0928 40.2105 105.4458 18.0327 14.3393 24.3977 19.6919 26.4091 38.8509 44.9871 2.7207 45.5520 49.5328 4.0999 36.4504 23.1417 65.7151 9.3434 82.1442 30.5353 17.5419 75.2710 13.3796 16.3657 28.0236 38.3099 136.1610 38.2127 13.3162 24.8838 32.5043 37.0730 11.8400 2.3494 104.0438 72.1625 65.9864 50.1828 145.5539 142.2270 95.9832 34.1003 74.0660 37.7689 262.6055 227.1480 37.2455 72.0068 133.5652 70.6917 58.9968 33.5739 136.1320 122.0077 34.4275 15.2904 52.0315 217.4032 294.8655 46.4175 18.8492 18.5775 5.8225 302.8139 33.9352 59.0499 23.7904 30.2314 5.1719 4.8413 27.1069 13.8646 34.0044 28.0126 28.6527 36.1438 16.9803 13.1914 2.2518 11.0453 13.7889 32.1950 18.0757 67.8071 59.1083 74.2689 60.3698 15.0569 9.5843 28.0170 59.0015 96.2570 44.1337 26.6404 115.1966 13.2806 46.2623 28.0777 20.1977 9.5533 14.0957 55.0649 28.3657 6.3383 17.4758 2.2125 66.3089 108.6709 88.2742 15.5212 29.2015 6.0010 31.4612 41.5906 92.0749 48.1478 3.2631 35.9574 17.0619 4.5782 16.4670 10.9796 19.0521 55.7497 18.4859 17.1694 15.7372 65.8272 16.5908 126.2662 340.1746 85.5386 32.7716 7.4511 25.9296 6.2617 18.8992 51.5927 35.4239 14.3629 8.7435 8.3693 14.0242 7.9631 18.5842 57.3299 38.7590 15.9937 21.4731 9.8567 20.5013 40.2602 41.4855 20.7565 8.4145 14.3733 7.0817 6.1302 13.6144 10.1045 12.4565 7.9210 13.6308 17.4817 8.1616 19.0192 26.1957 24.0622 40.4821 244.4002 75.6395 34.6522 69.4252 72.4496 23.6674 27.5617 17.3844 13.2189 11.9606 45.7776 13.5406 13.6217 5.9266 15.7507 23.6746 90.7586 21.9682 16.7471 43.0270 24.2355 12.6997 73.6207 18.9294 6.5011 94.5874 6.4875 18.8324 10.5245 18.8643 11.9761 9.0707 30.2404 14.7942 27.3304 11.0095 5.1887 36.7607 15.8796 35.9323 36.2018 24.5081 61.2506 10.0052 9.1100 27.4192 12.7560 34.0523 21.3068 10.2965 14.9880 29.3413 31.2773 22.6135 150.2002 52.4790 36.1888 23.6843 24.6079 29.6641 40.7802 32.2881 32.5135 23.1299 39.1300 89.2834 101.0283 50.9225 67.8559 13.3802 6.9135 16.0007 84.8277 90.0348 58.0272 54.7518 56.2134 133.9728 46.4745 13.6455 42.5110 82.2220 25.6897 102.5927 83.6057 6.7646 113.5944 43.7605 16.0641 15.1910 46.8437 34.5942 129.2386 301.2840 52.0523 2.2900 23.7619 33.4012 17.4250 31.0673 56.7097 20.9884 18.9671 52.8099 17.3569 19.3719 11.3217 23.9565 22.9341 34.2522 21.1709 4.2498 37.1278 36.2991 7.7404 36.1655 103.5929 51.3723 157.4559 111.6063 28.3911 4.4272 6.7148 55.8945 16.8600 37.5254 25.4733 30.2943", "7", "ETD", 529.7, true, 2, 4, 0.9, "7", 0, false }, // 20090326_Yest_LysC_1x6ETD_longGrad_01.09832.09832.6.dta { "113.9901 131.2311 132.1521 143.1788 146.3371 146.9454 152.4344 159.1886 175.0511 189.9796 202.1302 204.0196 217.2641 218.2109 219.1491 220.0296 229.4176 231.9133 243.0516 245.0983 246.2436 247.2485 259.4018 260.4774 261.3199 262.3853 271.1878 275.3297 284.0590 286.2119 287.1346 302.1248 303.4427 331.2704 334.0960 344.3830 345.0301 346.0869 348.1975 354.3492 357.2001 357.8897 359.1330 362.2360 367.1863 373.1064 374.0351 375.1785 375.9212 382.2288 382.9473 385.1367 388.4153 389.1718 390.3647 400.3410 402.7518 408.0059 414.3023 414.9655 416.0516 417.4536 418.4369 428.2923 429.4773 432.2854 439.2054 444.1362 445.3222 446.1862 447.4139 454.2898 455.2044 457.3239 461.2656 466.1697 470.2955 472.8702 474.5312 478.3126 482.5112 483.7782 487.1635 488.1677 489.2876 490.1572 491.2320 492.2506 495.2077 502.8879 504.5410 517.4409 518.2657 519.0779 520.2747 522.1584 528.1399 529.3173 531.1453 533.0059 537.3658 542.7713 543.5209 546.1447 547.0486 549.0401 553.2217 555.8703 557.9484 561.1995 562.0273 568.2609 574.1810 575.9733 577.3002 578.4282 579.5886 583.4700 584.7160 586.2695 587.2089 588.1901 589.3297 590.8264 596.1005 598.8209 599.4614 600.3657 601.3851 602.3392 604.3453 605.5561 612.6790 614.3278 615.7708 616.4172 618.3073 619.5785 625.9096 632.2582 634.2405 634.9560 636.0547 644.7774 647.3933 650.0336 655.0643 656.0058 658.1935 659.4125 660.4209 661.3862 662.3001 668.3742 669.5141 671.0125 672.2191 672.8754 677.6085 678.4711 684.4069 686.7532 690.8365 691.5204 692.7213 693.5538 694.6512 695.5095 696.4465 697.3856 698.2626 700.1693 701.5884 702.5576 704.4716 705.5855 706.3614 707.2552 708.9446 714.9379 719.9528 720.6530 721.4449 722.5185 723.3188 725.1766 730.1107 732.4985 741.5456 743.4431 745.9914 746.6793 748.4077 749.5251 755.5034 756.4111 757.1909 758.3714 760.3879 761.4011 763.5425 764.4570 766.6517 769.2108 770.2787 770.9116 775.0515 776.1511 777.3389 778.3056 779.3911 781.2295 783.2359 784.0864 785.2942 786.5158 788.1550 788.8935 791.2961 792.2492 793.4121 794.2834 794.8853 799.2510 800.1431 800.8760 802.1324 804.9783 807.6463 811.0676 813.3052 814.1748 818.6032 819.8773 820.5369 821.2690 823.3438 824.1729 824.8098 826.0527 826.7680 830.6498 831.5505 833.9725 834.7603 835.4443 837.2088 838.8663 840.3897 841.1557 843.3222 844.3497 845.4462 846.4551 847.4792 848.3829 849.9952 850.9881 852.7861 856.1987 856.9511 857.6238 859.9268 861.1257 862.1689 863.2673 864.1008 865.5912 867.3397 868.2449 870.1732 872.8954 874.0253 875.4199 876.3032 877.7094 878.4007 879.1054 880.8305 882.1107 884.2063 886.2969 887.2461 888.5373 889.4424 890.5363 891.4711 895.3788 896.5696 899.8397 900.5723 902.4795 903.3190 904.0875 904.8262 906.5564 907.4622 908.2554 909.3530 910.1611 911.2778 912.7902 913.5569 915.2399 917.2781 918.4448 920.1915 921.6672 925.0764 925.8985 927.8044 928.6380 929.7339 930.6306 932.0803 933.5059 934.3492 935.4163 936.2333 938.2280 939.6257 942.8901 943.7336 944.4680 945.0829 946.3312 947.3308 948.4017 949.3831 950.5120 951.1990 953.3817 955.2790 956.4444 957.4495 959.2953 960.3568 961.3559 962.2510 963.8233 964.6780 966.1072 967.2949 967.9041 969.3903 970.0180 972.5438 973.4310 974.6245 975.4291 976.2036 977.8686 978.8047 979.5064 980.8099 981.6885 982.8694 983.9150 986.1586 986.8849 988.6154 989.8579 991.2148 992.3150 993.6907 994.8007 995.8435 997.5283 998.2278 999.3420 1000.8774 1004.1041 1005.1081 1006.3886 1008.0444 1008.7605 1009.6301 1010.4102 1011.1902 1012.3957 1013.0112 1013.6276 1014.3865 1015.3806 1016.8649 1017.8294 1018.9973 1020.2168 1021.0508 1022.8062 1023.8928 1024.6741 1025.5602 1027.0774 1027.9182 1028.6938 1029.6450 1030.4016 1031.1428 1031.8799 1032.6040 1033.9194 1035.0521 1035.8300 1036.9064 1038.4028 1039.5544 1040.5033 1041.5558 1042.2976 1043.0061 1043.8560 1044.4673 1045.5693 1046.6289 1048.0798 1049.1487 1049.8953 1051.1707 1051.8075 1052.7578 1054.0664 1056.2206 1057.3115 1058.6471 1059.3623 1060.1843 1061.1813 1063.2637 1063.8937 1064.6082 1067.6022 1068.5436 1070.4143 1073.8324 1074.4854 1075.6296 1077.5215 1078.7728 1079.6797 1080.5966 1081.3116 1082.8440 1083.4913 1084.4801 1085.5917 1086.3186 1087.5177 1088.4213 1089.5858 1091.9376 1093.6687 1096.1257 1097.7383 1098.5665 1099.8446 1101.7408 1104.1158 1105.0193 1106.6691 1109.3883 1110.0417 1110.8109 1111.6754 1112.5588 1114.2137 1117.1703 1118.7562 1119.6354 1121.5552 1122.4783 1125.8068 1126.5062 1127.3027 1128.4645 1129.3394 1130.4718 1131.7727 1132.3931 1133.1520 1134.8618 1135.8544 1136.7268 1137.8665 1138.9940 1140.4271 1141.1722 1142.1083 1143.3627 1144.6188 1145.2980 1147.1053 1149.1876 1150.1573 1150.9237 1152.8646 1153.9529 1154.8275 1155.5189 1156.6376 1157.8301 1158.8705 1159.8807 1160.6486 1161.4875 1163.3159 1165.5519 1167.3486 1168.8508 1169.6659 1171.2729 1172.3824 1173.1112 1176.1285 1177.2781 1178.1449 1179.4564 1180.4569 1181.7239 1182.6207 1183.7595 1185.7343 1188.1429 1189.0431 1189.6774 1191.4640 1192.5618 1193.5658 1194.8416 1195.5509 1196.5480 1197.6661 1198.5800 1199.6740 1200.7408 1202.4299 1204.0262 1206.1571 1207.0011 1207.6847 1210.7443 1212.2711 1213.1403 1213.8700 1214.5084 1215.4905 1216.3856 1217.6212 1218.7476 1219.5159 1220.4584 1221.2958 1222.0941 1223.2582 1224.4431 1225.1934 1226.9341 1227.5494 1228.2169 1229.2250 1230.3502 1231.1119 1233.0883 1234.5504 1235.8893 1238.8624 1239.7577 1240.6467 1241.8114 1242.6564 1243.3212 1244.4535 1245.9132 1247.2084 1248.5177 1249.9370 1251.2473 1252.1356 1253.4420 1255.5792 1256.3678 1257.2438 1258.5654 1259.6080 1261.2924 1262.0133 1262.7606 1263.5397 1264.5056 1265.4819 1266.2118 1267.3071 1268.6116 1269.6219 1270.8040 1271.9053 1272.9305 1274.3118 1275.1403 1276.1952 1277.0780 1278.8470 1280.0765 1281.6877 1283.1969 1285.1021 1286.0947 1287.3153 1288.3663 1289.0408 1289.7804 1290.4738 1291.1433 1292.2286 1292.9154 1293.9307 1295.2352 1296.5833 1297.4636 1298.8580 1299.5538 1301.5502 1302.1819 1302.7853 1303.5138 1305.8978 1307.0115 1308.0680 1309.0383 1310.2512 1310.9983 1312.3962 1313.3129 1314.1918 1314.9108 1315.9288 1316.5973 1317.6083 1318.3568 1319.9128 1320.6820 1322.8466 1323.8477 1324.4873 1326.1058 1326.9562 1328.3691 1329.3285 1330.3256 1331.5922 1332.5153 1333.7073 1335.3253 1336.4666 1337.6293 1338.5098 1339.8680 1341.0546 1342.1763 1343.5287 1344.5222 1345.3486 1345.9896 1346.7664 1347.7000 1349.1268 1350.1544 1351.1793 1351.8549 1352.5951 1354.2925 1354.9467 1355.7598 1356.6874 1357.5726 1358.4680 1359.3387 1359.9834 1360.7842 1361.4207 1362.2504 1363.0944 1364.5067 1365.4633 1366.7472 1367.4696 1368.8267 1369.9672 1370.8593 1371.4626 1372.5177 1373.4644 1374.5326 1375.4686 1376.3918 1377.1687 1378.0614 1379.2006 1380.0397 1381.3709 1382.3823 1383.1343 1383.8593 1384.5813 1385.5964 1386.4283 1387.5092 1388.4943 1389.4509 1390.3361 1391.2609 1391.9382 1392.6139 1393.4957 1394.2208 1394.8849 1395.6302 1397.4410 1398.9955 1399.7090 1400.3776 1401.0082 1402.6064 1403.8135 1404.8600 1408.1729 1408.9955 1412.5879 1413.8361 1414.5884 1417.4901 1418.3378 1419.2512 1419.8925 1423.4171 1425.0929 1426.5471 1428.1871 1430.0979 1431.2125 1432.5609 1434.8376 1437.0071 1438.4773 1440.1837 1441.5282 1442.5403 1443.3225 1444.4987 1445.5729 1446.7213 1447.8928 1448.9817 1449.7942 1450.6229 1451.3451 1452.4407 1453.6246 1454.2584 1455.4415 1456.7585 1458.9193 1463.1229 1463.8900 1465.2791 1467.1940 1468.4724 1470.5989 1471.4646 1472.3035 1473.1034 1474.8070 1477.1874 1478.5344 1479.5206 1480.4601 1481.4905 1482.5090 1483.6610 1484.8904 1485.6355 1486.6951 1487.4030 1489.5216 1491.4435 1492.4117 1493.5546 1495.1490 1496.0404 1496.6921 1497.5963 1500.2513 1501.1467 1502.2924 1504.7384 1506.7328 1508.5890 1509.5657 1510.6417 1511.5657 1512.7714 1513.4022 1514.2220 1515.1892 1515.9622 1516.6791 1519.0306 1519.9967 1521.2291 1522.1139 1523.2526 1524.3158 1525.3829 1526.5032 1528.7216 1529.4207 1530.5813 1532.9574 1534.4117 1535.6248 1537.3634 1538.3651 1539.1365 1540.1622 1540.8871 1541.8827 1542.6510 1546.9823 1548.3737 1549.7220 1550.7257 1551.4734 1552.3499 1554.8102 1555.8829 1556.8192 1559.1213 1560.6205 1561.2299 1562.5834 1563.7611 1564.9724 1566.1536 1566.7748 1567.6414 1569.7770 1571.3156 1572.6013 1573.5187 1574.6320 1575.4623 1576.7740 1578.4156 1579.3646 1580.9421 1582.0262 1582.9362 1583.6995 1584.7473 1585.4773 1587.3556 1588.6100 1589.2535 1589.9210 1590.9388 1592.6239 1593.4801 1594.8108 1595.6331 1596.6759 1597.5315 1598.7552 1599.6293 1600.8079 1601.4324 1603.4369 1604.5647 1606.6755 1607.9733 1610.1649 1610.7836 1611.7459 1612.5382 1613.4845 1614.9130 1616.0526 1617.1052 1617.9305 1619.1810 1621.5902 1622.3422 1623.4144 1624.2610 1625.0881 1626.1832 1628.7346 1630.3409 1631.2977 1632.2302 1633.0955 1634.6721 1636.4924 1638.6404 1640.4127 1641.6337 1643.9996 1645.8635 1646.6339 1647.7058 1649.7590 1651.1925 1652.5905 1653.9025 1654.6809 1655.7311 1656.6876 1657.7750 1659.5773 1661.7122 1662.9540 1663.6642 1665.8490 1666.8977 1668.0911 1668.8577 1669.8044 1671.3678 1673.4745 1674.6852 1675.7462 1676.9249 1678.8080 1679.5559 1680.3009 1681.6830 1683.0099 1683.9071 1685.6615 1687.5011 1688.1622 1688.9943 1690.2024 1692.0653 1693.5717 1694.7338 1695.4806 1696.1813 1696.8948 1697.6115 1698.9225 1700.2782 1701.3210 1702.1239 1702.8544 1703.7957 1704.7933 1706.4465 1707.1056 1708.0559 1709.1427 1709.8922 1710.8323 1711.8210 1712.7755 1713.9504 1714.9691 1716.7858 1718.0265 1719.0309 1719.8810 1720.8185 1722.9835 1723.9435 1724.7341 1725.7323 1726.5270 1727.5505 1729.0011 1729.9222 1731.0447 1732.1539 1733.8221 1734.8827 1736.3485 1737.5382 1738.6692 1740.2506 1740.9163 1743.7560 1744.6329 1745.5900 1746.3591 1747.7025 1749.0897 1749.7540 1752.7738 1753.6683 1755.0564 1755.7859 1756.7357 1757.6791 1759.6892 1760.4733 1761.1599 1762.2556 1764.7103 1765.9706 1766.8046 1768.2101 1768.8157 1769.9657 1770.7970 1771.9164 1772.9025 1773.8059 1775.1458 1776.6107 1779.2338 1780.1027 1781.0817 1781.9913 1782.7195 1783.4801 1784.1356 1785.5419 1786.3993 1787.6823 1789.5367 1790.4017 1791.3219 1792.4680 1793.1882 1795.7698 1796.5364 1797.2938 1798.4198 1799.3319 1800.0663 1801.1501 1803.3821 1804.6417 1805.9270 1807.1834 1807.9470 1809.0968 1810.1481 1811.6378 1812.4764 1814.2875 1817.0807 1817.9548 1819.2286 1820.1857 1821.4830 1823.0793 1823.9237 1825.2963 1826.2532 1827.0155 1829.1477 1831.3790 1832.2288 1832.9703 1834.2249 1835.1229 1835.8087 1836.8464 1837.9998 1839.3899 1840.1019 1840.8835 1841.7587 1843.5868 1845.3617 1846.1794 1847.0574 1849.7654 1850.7377 1851.9037 1852.5720 1853.3700 1854.2758 1855.6716 1856.8563 1857.9340 1858.6801 1859.7845 1860.7200 1861.5496 1863.4694 1864.0726 1864.8372 1866.0847 1868.1243 1869.1791 1869.8289 1870.5437 1872.1674 1873.2410 1875.0300 1876.2096 1877.3793 1878.5165 1879.6874 1880.4792 1881.6610 1883.1312 1885.2472 1887.0271 1888.1625 1888.9174 1890.5309 1891.2589 1893.3943 1894.4636 1895.6503 1896.5255 1897.2307 1897.9181 1898.6760 1899.3431 1900.9559 1902.2091 1903.5544 1904.4203 1905.1531 1906.1698 1907.9913 1909.0251 1910.7616 1911.5227 1912.1790 1913.0300 1914.0295 1914.7692 1915.6569 1916.6051 1917.5935 1918.5018 1919.3541 1919.9784 1921.6935 1923.4358 1925.7581 1927.1697 1928.0433 1928.8586 1930.2390 1931.2316 1932.0490 1933.0448 1934.0111 1934.7220 1935.4039 1938.1046 1939.1642 1939.9382 1940.9369 1941.8190 1944.0131 1944.9138 1945.9586 1946.7902 1947.6591 1948.4996 1949.7133 1951.1160 1952.2699 1953.3293 1954.5367 1955.4891 1956.4583 1957.0695 1958.6932 1961.0066 1961.8845 1962.5778 1963.3214 1964.5984 1965.7990 1966.7601 1967.8685 1968.7721 1969.4603 1970.6687 1971.7404 1972.9569 1974.2152 1975.1781 1975.9866 1976.6185 1977.9000 1978.8500 1979.6599 1980.8884 1981.7853 1982.6971 1984.0935 1984.7003 1987.0709 1987.8046 1988.9127 1989.6251 1990.4127 1991.2408 1992.2101 1993.2214 1994.1090 1995.3894 1996.1937 1997.2961 1998.4218 1999.6508", " 0.7882 1.2338 1.4690 5.2715 2.7157 0.8665 1.6112 2.9554 1.3347 4.1027 3.8946 3.0272 29.1180 92.1873 18.7286 1.6491 5.1260 0.7851 0.7923 315.9619 110.0733 13.9588 1.7858 4.1573 9.7864 5.5606 1.1364 4.9930 1.6353 1.3330 3.2970 18.8724 13.0217 3.0066 4.0489 1.4200 2.3865 2.7739 1.8415 3.5709 4.6604 2.5864 2.2279 2.9136 3.2431 132.1895 15.9678 29.7801 7.8762 1.8624 0.7930 4.7272 0.7881 1.4935 3.3303 6.1205 1.9669 1.7625 4.8351 4.4149 1.0977 5.5422 2.5520 1.6473 2.1585 0.6312 6.7079 5.8302 3.3232 22.1818 1.5718 3.2131 7.0913 1.3245 1.6089 1.0221 1.5416 7.5623 0.9457 2.2525 5.2898 3.3345 182.4794 45.2480 16.5450 14.5041 2.1931 6.8329 2.8742 10.2193 2.3163 4.6695 3.1755 2.9844 2.3901 3.5107 1.9076 1.1518 0.9497 20.2494 3.3190 11.0620 1.6660 1.7885 2.4268 3.0563 1.5379 0.5539 7.3357 12.4545 1.0707 6.0737 9.9238 7.0426 42.9061 8.9792 0.8669 2.9589 1.8796 3.2521 1.3315 145.5146 37.0337 3.6117 1.4463 74.4829 24.5854 14.8762 8.6619 5.9887 10.8583 0.6368 9.0039 12.2474 8.1285 1.4736 7.2705 2.3549 0.7095 16.7374 25.6815 36.7998 4.8877 2.9292 7.4774 1.7576 2.5155 1.0239 103.7108 22.9241 19.9536 15.3724 6.8771 5.2714 13.2522 12.5899 3.5023 3.2909 4.4146 14.3020 20.8035 8.6278 8.7088 42.2430 88.1366 899.3025 1000.0000 423.5352 29.6849 14.2239 8.9192 21.5592 5.0350 5.6656 10.3790 90.1816 18.8989 7.1451 5.6359 11.6304 7.3775 2.7498 3.9538 4.6622 3.4874 8.9575 3.8797 6.2168 5.9806 3.3273 13.8733 0.9658 6.8611 18.4296 107.5015 11.9635 8.8080 4.7998 9.5301 10.4798 1.1775 1.8836 2.9827 9.3508 12.5125 1.7291 3.7092 32.0875 9.3238 9.1529 1.8324 16.4488 3.1251 3.5275 8.5837 7.7945 0.9962 4.1653 32.9291 21.6273 10.7102 2.1521 2.1954 233.5511 37.5855 4.5931 2.6888 1.1378 9.8956 5.9154 6.4284 12.1675 98.4197 9.7095 2.4615 2.5431 2.3061 3.2045 19.4397 7.8092 4.5308 21.1395 16.7198 40.1602 0.6974 3.6422 18.5252 7.9833 12.8113 4.9480 3.6519 5.0524 5.8375 2.6901 3.4764 15.8601 16.2370 13.5469 2.5415 189.6745 76.8495 28.1688 13.2680 28.1880 26.4373 3.0931 6.9593 3.0615 17.6371 3.2466 7.1994 49.6675 48.7677 54.9408 50.2091 9.6626 7.2094 2.2310 5.4398 5.8776 6.8273 45.3912 2.8537 1.2580 2.3087 32.5015 18.0361 5.5497 1.2442 5.7918 7.9674 24.7011 1.5223 5.7114 4.2552 9.0050 19.2156 3.1398 7.4090 3.3731 2.8531 92.6507 1.0116 0.7883 13.9968 2.8556 44.3379 16.5552 40.5248 27.4875 14.9865 27.5186 11.5219 10.7622 52.8381 24.3738 1.2978 7.5290 6.3854 24.4063 14.3000 15.9755 8.8281 2.9272 58.1891 114.0278 33.1024 14.8397 22.7402 9.4772 11.9262 4.4631 7.3775 7.5562 16.0341 10.6938 29.8320 2.9340 14.5792 21.9621 47.1874 2.1519 28.3740 6.7118 15.1696 0.8143 10.4319 12.5107 6.2136 33.3331 4.9963 16.8548 18.1042 0.9928 8.9262 36.8391 37.8557 22.0204 65.8654 15.4924 51.1154 64.2312 7.5328 3.4474 16.5854 1.8822 9.2501 20.6316 3.7565 12.3188 12.7473 46.1698 28.1419 6.2244 2.8962 6.2451 33.6466 34.6984 6.9332 57.7374 37.9611 100.3497 12.7352 17.6961 49.9136 53.0904 82.0319 66.6688 15.2200 4.2142 10.9943 9.6479 49.1216 124.8409 74.6264 48.5882 21.3874 14.2358 131.5370 20.6068 54.6720 123.8634 59.9938 15.6989 23.2243 84.2466 448.8117 729.3666 415.6860 400.0499 228.7654 10.9615 78.2260 17.9154 23.6912 46.1553 56.7357 7.2724 5.5523 3.1658 7.2333 6.9645 2.5917 8.5677 22.6664 2.9167 12.8866 1.8680 3.8731 1.5003 1.4150 8.2251 6.6937 6.7158 54.6595 40.5610 25.5735 26.5802 25.7058 32.9240 4.7233 7.0271 9.4470 101.3233 61.6267 19.3270 6.7386 27.3538 5.8047 29.4897 8.6042 10.9515 6.7882 108.2355 38.1058 23.2399 23.0468 6.3150 7.3250 10.1624 2.4303 3.1598 9.1313 12.9203 11.4054 16.3637 15.4630 12.6306 8.8983 15.0054 3.1066 2.5454 3.1221 4.8013 8.7342 19.5644 33.7218 53.9973 16.0492 4.1033 12.1449 11.7813 4.3366 11.3464 26.1843 36.2671 17.1257 12.0484 11.4197 27.4982 12.7326 9.1530 16.5634 44.9096 0.5508 34.2772 14.0924 40.9731 4.4487 50.2529 55.8065 12.9221 15.8507 15.6793 4.7133 19.4843 16.7195 16.2017 14.6401 5.1641 43.6599 30.2467 11.0664 2.0359 22.7743 16.6831 47.7048 15.0643 17.2578 8.9148 14.0071 1.7875 24.3035 17.3980 12.3099 3.9429 10.5832 21.7551 11.7909 6.6174 35.9319 45.7622 49.2996 25.8661 24.7929 37.6086 3.4061 10.7790 19.1435 26.6210 133.2804 71.6528 31.1831 22.6257 14.2815 30.2932 9.9040 6.6790 3.3256 7.4046 18.5438 13.9573 9.7036 4.6337 5.2810 6.1957 20.6643 28.9472 177.8307 102.4394 22.3683 16.5090 7.7104 8.2458 25.9384 10.0650 7.4178 10.7713 51.6587 3.0736 2.2825 5.1280 15.0373 16.8868 7.1792 19.0850 20.7129 4.7520 17.2991 25.2128 35.0184 18.6991 28.7550 13.9657 2.6156 4.3171 23.0390 19.3593 41.7318 62.1964 19.0136 41.0846 26.0256 40.3554 35.7827 30.7425 12.2687 1.1788 4.8741 9.9576 26.9510 7.6796 25.3728 2.5439 15.3496 276.8694 140.9403 66.8089 40.1855 28.3261 5.6646 13.2502 1.1692 18.7341 76.7152 22.0055 6.5392 4.1076 3.3208 9.0892 3.4477 15.3705 1.7882 40.8286 13.2536 4.9919 50.0643 179.0947 21.1458 17.4503 6.3555 5.6109 20.3739 31.1409 7.4474 9.5979 0.9318 22.8467 3.0125 12.9197 4.6544 10.1378 14.2818 5.5517 37.4230 49.7872 52.5437 65.4898 67.9736 29.0907 9.5927 1.8327 35.9073 70.7768 40.3347 18.9421 33.7865 38.6511 12.4221 42.6717 48.4038 41.2194 89.6144 33.4612 9.6977 52.9020 84.1777 65.4023 4.8584 15.2862 103.6673 67.3765 163.6603 37.0745 53.5752 34.4623 73.6682 159.8176 70.8152 19.9635 56.5708 20.0970 190.8416 75.6044 42.8530 16.1060 265.4394 357.4647 118.7277 69.0456 98.4367 95.9682 669.7959 272.6677 32.6305 18.6214 22.6137 51.3712 67.0088 114.0852 83.8836 72.7718 163.4914 148.9661 287.9714 209.1821 212.1409 529.3602 734.4439 449.1429 37.1894 15.4887 111.1239 52.6632 29.3436 8.5445 5.8198 18.8332 40.2829 17.3968 12.5103 2.5262 4.6379 5.9340 2.6933 19.9679 5.1856 2.8044 5.4177 4.3256 16.3718 11.9438 5.2611 3.6056 7.9556 17.1140 19.6393 15.6255 1.4935 2.7949 13.1273 5.6584 16.6632 11.6434 22.8122 21.6332 38.5820 5.4408 2.9926 4.1127 16.9628 4.4425 18.9169 59.1490 23.6358 24.3605 18.9449 11.4542 19.6536 10.7939 12.4849 5.1658 45.6344 49.4934 34.1920 19.5189 1.6754 1.8842 2.1514 2.6423 11.7624 3.6703 9.7487 12.9905 35.3189 43.4424 9.1075 8.1898 14.6987 44.8164 82.9347 35.1636 24.0687 9.4809 9.1777 12.7550 18.9022 8.8221 0.9432 9.1233 6.3374 4.8303 9.7621 10.1872 4.1039 3.0005 16.0191 51.7438 66.0449 25.1428 13.0474 1.4431 13.0180 7.0912 5.1896 5.8161 8.8903 28.7951 9.6813 27.5525 25.9896 7.3851 19.4597 26.1919 11.4152 3.3117 0.8425 4.4223 10.9286 12.3103 6.4925 4.7694 17.7922 14.9555 13.8515 54.9117 8.8562 4.2778 9.1613 2.9274 12.6820 19.1942 19.5758 11.1650 10.1294 9.4094 4.2609 1.0210 6.5288 4.5425 5.8404 2.0670 10.2111 4.7946 1.5700 3.4809 7.1907 6.3686 16.7089 5.7932 15.1646 2.5100 25.7024 10.8899 43.2942 21.2989 24.6382 26.8564 1.7809 16.2150 6.0329 53.3263 31.6996 11.1775 7.6595 29.8364 19.2204 14.2775 3.5022 75.2761 93.9829 25.7818 39.4646 12.3446 5.9996 7.6165 10.5357 1.4668 15.1383 17.5517 53.9785 44.2829 3.5110 3.0863 3.6781 13.0000 5.8848 19.1277 15.5125 3.4551 1.3886 22.8519 9.9976 16.2180 13.1197 7.6040 11.3070 9.7544 16.3058 8.9744 9.2886 23.7590 2.4494 5.7015 8.1026 6.1667 26.2368 17.5402 4.2452 6.0370 29.7126 13.3919 40.4039 1.8471 24.4204 4.5108 12.5156 25.9107 3.0860 1.2098 3.1305 21.6278 38.8935 14.6334 4.0924 9.0087 19.2632 4.2845 10.9829 9.6669 4.5447 20.8103 8.2753 11.7439 17.6609 2.6647 3.8683 7.5676 32.2318 15.8165 19.5057 11.8576 9.2740 16.7955 13.6268 58.7846 65.1262 16.6333 6.8582 6.4038 12.0963 27.5998 18.8584 25.1758 27.3996 7.1412 11.1917 0.5174 5.9764 47.9578 90.3362 152.1247 42.3611 57.8727 22.3458 7.5690 16.9555 19.7501 5.3896 17.9180 23.1288 38.3125 57.1665 10.8149 8.8784 6.1971 8.9094 24.1074 13.5064 44.3308 118.6540 51.7940 24.1366 42.5735 62.0631 28.3070 14.8120 2.9579 12.1073 20.8824 54.8472 36.4654 29.6668 26.6935 14.0049 5.8890 4.8282 5.2406 7.0041 10.2295 3.2089 10.2921 10.5749 22.6961 14.4206 24.1620 15.3352 15.9632 18.3046 17.4620 14.6835 2.5325 36.8980 15.0390 7.6405 13.8095 8.5752 9.0806 10.2180 7.5096 19.1217 2.9220 10.7044 3.0632 21.4457 3.9442 3.2078 59.1480 76.8403 30.1047 1.2281 9.2401 14.2531 27.2254 10.0098 4.5519 2.4809 3.0208 7.4779 6.9956 14.3988 12.0743 20.9794 2.3019 23.3461 27.2394 31.7722 12.4663 3.4009 11.4335 42.1608 33.5015 8.9897 14.8191 12.6126 28.3521 45.6324 4.6593 8.9367 4.0243 15.4324 13.4652 6.2845 12.7486 24.3929 3.9183 9.1934 30.8826 33.8580 67.2932 26.6427 32.7887 21.9741 17.6815 22.4838 10.8720 15.7800 1.5712 8.7224 7.2089 13.1418 8.1982 9.2143 3.6575 15.8164 13.5247 5.5736 3.7005 8.7226 5.1440 6.7949 3.3984 8.9614 30.4627 16.8158 6.6020 2.1429 11.3900 8.0702 49.1393 83.4953 26.3869 13.9723 20.6791 13.9586 5.4295 5.1951 10.2817 3.9876 7.3068 30.8753 27.9145 11.0200 2.7721 9.9651 19.3649 32.7778 35.9366 53.2385 13.5144 2.2395 4.4096 17.8227 31.6407 16.3919 5.4519 6.8358 25.7027 1.3013 14.2578 6.1699 10.7177 5.0816 16.1772 12.6636 15.9320 1.7283 8.2588 25.4254 13.7164 3.1962 3.4199 13.4309 14.2145 15.5726 24.2617 17.0439 21.0429 26.2592 82.4623 76.8849 41.5466 15.9525 7.5481 38.1850 49.3495 49.8431 36.6124 2.3115 8.5146 14.4192 17.8063 4.3331 17.4075 16.2087 37.1296 47.7948 70.5014 126.4190 59.3923 13.9014 9.8167 12.2739 12.6826 183.1271 177.8186 161.7365 60.2777 47.0338 30.7163 55.8528 24.6995 10.2564 11.8114 20.8701 45.1977 44.0494 51.2530 31.1729 10.2021 7.9284 74.1734 11.7898 19.4566 40.7594 17.8223 12.2809 10.6742 1.7347 25.0762 35.2629 15.0124 7.4382 32.0495 8.2455 13.6037 37.0519 14.7269 30.9821 29.9967 53.4566 15.8324 16.5273", "6", "ETD", 695.04, true, 2, 4, 0.9, "3 6", 0, false }, // 20090326_Yest_LysC_1x6ETD_longGrad_01.10231.10231.5.dta { "199.9968 203.3892 217.9639 219.2876 230.3625 231.2264 233.4094 244.2236 246.3432 273.0931 278.3110 287.3306 288.3451 300.9216 301.8600 318.0997 346.9664 357.3155 358.2166 359.1941 365.1911 372.4192 373.1793 374.2338 375.2891 377.2897 378.3042 379.2480 389.3028 402.2855 412.2734 421.2726 430.2226 443.0610 444.0184 445.4998 448.9448 452.1257 460.4586 471.1894 481.1470 487.4255 488.3946 489.5114 493.3804 502.1929 505.7596 514.4465 515.2761 516.4627 529.4846 530.3494 531.5333 533.4164 534.4004 541.1827 542.0539 556.8998 558.8531 564.4246 570.2122 581.1977 587.5244 596.4286 597.0301 601.3938 619.0530 626.8019 629.2461 630.1948 631.3355 632.3667 636.5231 643.1704 645.6285 646.6180 650.0156 656.6390 658.4033 659.6189 660.5480 667.5349 668.4302 669.1138 670.1107 671.8558 683.4437 684.3170 687.5054 690.7796 696.3185 703.2939 708.2760 710.4343 712.9634 713.6234 714.2911 715.2505 743.0220 744.4070 749.9543 750.6201 751.4276 756.4520 759.9512 761.4014 765.2022 768.4483 769.7205 770.4863 771.3599 772.4193 773.5159 774.4064 777.8081 781.2615 784.3503 786.4894 788.3555 792.4168 795.1695 797.5469 798.4954 799.4752 801.4368 803.5952 805.2787 809.6343 810.8914 813.3586 814.2593 815.2007 816.4573 817.2343 820.4378 822.0837 828.1140 829.6492 830.9940 831.6106 832.3195 849.5237 858.2823 859.1848 866.5513 869.4810 870.4755 875.3311 877.2744 879.4274 880.5972 881.2021 883.6060 892.2300 893.5712 894.1797 895.6813 896.3052 897.4622 898.8010 899.5786 901.5259 904.5444 907.5441 908.7720 909.6478 910.6677 915.4683 917.5506 921.2318 925.4321 927.1816 928.4699 929.4986 931.1143 931.7744 937.8880 940.5587 943.7704 947.2046 949.2724 950.2670 954.0981 955.5023 960.2236 961.3193 962.8962 963.6597 964.7088 965.7717 967.6285 968.3437 976.9644 977.6417 979.6945 985.3494 990.3233 991.2648 992.5762 994.2827 996.5015 998.1729 999.5853 1002.1657 1007.8813 1012.2427 1013.4610 1015.3331 1015.9792 1016.7728 1019.3039 1020.4933 1021.3461 1022.1887 1023.8343 1026.4688 1027.1772 1027.9828 1029.1892 1030.2264 1030.9963 1032.0424 1043.7311 1044.8026 1048.3547 1049.2153 1058.7727 1059.5665 1060.7236 1062.0500 1064.5720 1065.1926 1066.1375 1068.6206 1071.0164 1073.6232 1075.5795 1076.2839 1077.5339 1079.2949 1083.4153 1084.9513 1087.4999 1090.6151 1092.1388 1092.8107 1094.6973 1097.0104 1097.8096 1098.5801 1099.2081 1100.0697 1101.7253 1103.4839 1106.8026 1108.9430 1110.1464 1113.0355 1114.6616 1115.4230 1119.2159 1120.3712 1121.6892 1123.3085 1125.1543 1125.9171 1126.9982 1127.8264 1128.7831 1132.0010 1133.7784 1134.5132 1135.3239 1136.3513 1139.2911 1139.9486 1141.6228 1142.4706 1143.4874 1144.6455 1145.4458 1146.6713 1147.3684 1148.4218 1149.5150 1150.4442 1151.0565 1151.6959 1152.4464 1153.3569 1154.6511 1155.6222 1156.5662 1157.2361 1158.1544 1159.3284 1160.2274 1161.2325 1162.2584 1162.9725 1164.6285 1165.3418 1167.0341 1169.7928 1170.7620 1172.5529 1174.3608 1175.3719 1179.5142 1180.5903 1181.2582 1182.0927 1184.7328 1185.8318 1186.5153 1190.8060 1191.4373 1193.6167 1195.8188 1200.8970 1201.8322 1207.1527 1209.3734 1212.1838 1215.0480 1216.0809 1216.9240 1222.0365 1224.6493 1227.3143 1228.1488 1229.5078 1231.5402 1233.1925 1236.9253 1237.7500 1238.9708 1239.5934 1241.8324 1242.6617 1243.5510 1244.4005 1247.3298 1248.8254 1252.3721 1253.1113 1253.7217 1254.5360 1255.6528 1256.8463 1258.4022 1259.0864 1259.7694 1261.0781 1263.7369 1264.7242 1265.6049 1266.2859 1266.8942 1267.5886 1268.6367 1269.3829 1271.0029 1272.0626 1273.1268 1274.6068 1275.7810 1276.8475 1277.6908 1279.2212 1280.4325 1281.3257 1282.7299 1283.8431 1285.4242 1286.3147 1287.2496 1288.3251 1288.9520 1289.9506 1290.5951 1291.6273 1293.1234 1294.0182 1294.6876 1295.4559 1296.6429 1297.3284 1298.3654 1299.7465 1301.5834 1302.5348 1303.1448 1303.7810 1305.4895 1307.0480 1308.5162 1310.6530 1322.2665 1324.6090 1325.3912 1326.1967 1328.6816 1329.4915 1330.1071 1331.4850 1336.3151 1337.8545 1338.7771 1339.5541 1340.5658 1341.6544 1342.3667 1343.5753 1345.5013 1347.2640 1348.8749 1351.1949 1352.0460 1352.9468 1354.1296 1355.9504 1356.7135 1357.3826 1360.4873 1361.4817 1364.7675 1365.8361 1368.3119 1369.3562 1371.2378 1373.0154 1374.3073 1380.1006 1381.2966 1382.1339 1384.5953 1386.6671 1387.4862 1389.6205 1391.6823 1393.8027 1395.3778 1398.7206 1402.5897 1403.2291 1404.2162 1405.7178 1409.6974 1410.8346 1412.0652 1412.7459 1413.8644 1414.7704 1415.4298 1416.4241 1417.8678 1420.3739 1422.0052 1423.2833 1424.9669 1426.4757 1427.4905 1428.6627 1429.4583 1430.9574 1431.9563 1432.7750 1435.6735 1437.2614 1438.4911 1439.8132 1442.8597 1443.7821 1444.4789 1446.1693 1446.8107 1448.7933 1451.0183 1451.9075 1452.9984 1456.4574 1459.8391 1460.5907 1462.3885 1463.1023 1464.5487 1465.4086 1466.1863 1467.3358 1469.4706 1470.6277 1472.2717 1473.3860 1476.2083 1477.3331 1478.2662 1481.0092 1482.1669 1483.3353 1484.6349 1485.6622 1486.5348 1488.6351 1491.1277 1494.1429 1495.1176 1496.6829 1497.4846 1498.6361 1499.4708 1500.1746 1501.0580 1502.7214 1503.7355 1505.5406 1507.7498 1508.9955 1509.6993 1510.8724 1512.0980 1513.1663 1514.1228 1515.2155 1516.0603 1516.9320 1518.0652 1519.5046 1520.1854 1521.4220 1522.3212 1523.5261 1524.3551 1525.6578 1526.7985 1527.6752 1528.8207 1529.9440 1530.7136 1531.3710 1532.3114 1533.4865 1535.0594 1535.9149 1536.6276 1537.2911 1538.9327 1539.7517 1540.5729 1541.2230 1541.9208 1542.8248 1543.6492 1544.6127 1545.4789 1546.5535 1547.3517 1548.8375 1551.9415 1553.3087 1555.7809 1556.7722 1557.4882 1558.1554 1559.6254 1562.8792 1565.8635 1569.8210 1572.8729 1575.5411 1576.7335 1578.6332 1583.7629 1585.2416 1586.1223 1587.2738 1588.0520 1589.9310 1590.7679 1591.4988 1592.5266 1595.0131 1600.4128 1605.4078 1606.3152 1608.2335 1609.0292 1613.7843 1614.4235 1615.0240 1617.4705 1618.2316 1620.2174 1621.1448 1623.4460 1625.0553 1626.7288 1628.3973 1630.0243 1634.9392 1635.9377 1636.8392 1637.9626 1640.2648 1641.5309 1642.1378 1645.0062 1647.3020 1654.0756 1655.5837 1658.4904 1660.6063 1661.4950 1662.2313 1662.9808 1663.8503 1665.6305 1671.3563 1673.4164 1676.8075 1680.4739 1681.5331 1684.1039 1685.0872 1686.1285 1687.0353 1688.6887 1694.0150 1694.7936 1696.5917 1697.3898 1709.8912 1711.3949 1716.2777 1719.2097 1721.3435 1725.4178 1727.8567 1731.3132 1732.1276 1732.9091 1734.1439 1739.8469 1740.8627 1741.9377 1743.1740 1744.0885 1748.9207 1749.7902 1751.4054 1754.9792 1755.6819 1756.9647 1760.7775 1761.9359 1762.9423 1774.4584 1775.7214 1777.2146 1777.9000 1778.6409 1779.6849 1780.4164 1781.5988 1784.6150 1785.4786 1786.4226 1787.0295 1788.9304 1792.2430 1793.5470 1794.6105 1796.8732 1797.5880 1799.4418 1804.2677 1806.3702 1807.0431 1808.5135 1810.1678 1810.9910 1812.2628 1814.0519 1816.0890 1816.8850 1817.4900 1818.8058 1819.6410 1820.7987 1822.8992 1827.8724 1828.9021 1832.9716 1834.5807 1835.5642 1836.9562 1839.7180 1842.3806 1843.4514 1844.7516 1846.0460 1847.1014 1847.8693 1850.0310 1850.6803 1851.8031 1852.6888 1853.3849 1854.0485 1855.2161 1856.7922 1857.8839 1861.8253 1863.5110 1864.6586 1865.8446 1867.0265 1872.2233 1872.8591 1875.1160 1876.8230 1877.8879 1878.9817 1879.9806 1884.8640 1885.9685 1886.8761 1888.2507 1890.1453 1891.0648 1892.5250 1893.5046 1895.5006 1896.6990 1897.9305 1898.8899 1899.9142 1901.0745 1902.1547 1902.9152 1903.9285 1904.9880 1905.6917 1906.3856 1907.1786 1908.0311 1908.7242 1909.7391 1911.7196 1912.5292 1913.4950 1914.2708 1915.0756 1916.1615 1917.4456 1919.4734 1920.6144 1921.8298 1922.7296 1923.7186 1924.6965 1925.8077 1926.8290 1928.0314 1928.9969 1930.0419 1931.1810 1931.9924 1932.7919 1934.0353 1934.7501 1936.2020 1937.0485 1938.4026 1939.9923 1941.0868 1941.8502 1942.6708 1943.8409 1947.2426 1950.8925 1954.6056 1955.6066 1958.3883 1968.1917 1970.5634 1971.3766 1973.0155 1975.0997 1978.9559 1982.6322 1983.3234 1984.2694 1985.1986 1986.3406 1987.0579 1994.9388 1995.9553 1998.4855", " 3.6016 2.1781 10.1620 7.6023 10.0603 3.0831 2.3715 4.6235 4.4300 1.8208 2.2721 123.0606 29.0272 9.0489 3.1364 8.1317 1.4704 2.0508 1.4641 2.9302 3.0248 5.6357 2.8385 178.4803 37.6749 108.5945 22.0127 4.4572 1.9127 1.0174 2.3556 3.5009 4.4925 2.2436 3.6303 2.9498 3.3862 2.1287 2.6850 1.7065 12.8303 41.9667 5.8168 2.2576 3.1353 4.8054 9.9327 19.0753 4.8223 5.3841 3.3041 6.4941 2.1635 6.2719 5.0523 6.6585 16.6893 0.5703 6.9696 1.7052 2.2385 1.7965 5.5334 1.2431 10.3704 3.0587 3.7108 22.3982 7.5832 25.9226 11.1733 2.8295 2.1502 5.3442 2.2480 4.3584 7.1040 2.8231 3.2184 11.0678 1.8020 9.9538 2.4955 4.8483 13.8447 10.2946 83.7919 44.7566 2.3803 5.5501 7.2935 10.1587 11.3597 2.7159 6.4879 29.6912 20.7196 17.7341 1.9123 3.1369 4.8179 3.8283 1.2447 8.2909 4.8056 22.9553 5.4880 6.9515 17.9575 714.4054 1000.0000 915.6977 44.1673 6.7532 8.5911 11.7277 3.3898 6.7872 1.3728 11.1750 4.4791 87.0462 62.8194 14.1495 7.7174 8.1923 5.1595 0.8000 0.9046 46.0808 56.2002 12.6137 9.4954 2.0218 22.4530 4.4834 7.7376 4.8174 42.1129 7.5317 5.3538 3.0543 18.4400 0.9088 2.5343 11.0701 3.4334 4.0969 2.6886 7.7208 5.1476 2.6699 16.7045 1.8505 4.2412 2.0402 18.7736 1.0203 7.2720 46.0384 26.9076 5.6503 7.6962 5.4857 40.9232 8.9633 11.5495 7.0634 18.6693 3.8990 2.3285 12.3768 42.3419 24.6978 2.2453 11.7875 15.4995 1.8514 11.6239 3.3570 12.2979 21.4512 2.2591 4.4746 1.7085 1.9108 55.7391 25.0911 21.2561 20.5229 7.0451 7.1804 8.3820 7.8361 5.4943 4.6157 8.6582 3.1558 6.5542 6.5112 8.9484 2.4692 7.4760 8.4992 27.5520 29.6512 13.1910 14.6707 10.4552 5.0611 9.5637 17.3501 75.1421 2.6628 4.8813 32.5452 46.3334 23.0088 119.1303 50.8363 2.9102 12.8323 20.4486 3.6650 27.7376 14.5682 38.0279 3.6371 1.4630 1.4594 16.6963 15.3944 13.4947 6.3783 9.8533 13.6908 1.1291 0.5741 4.3807 6.6031 40.6825 18.8058 12.4767 26.1853 92.1437 12.7664 2.9274 9.8584 33.5797 10.8649 6.0002 1.4197 1.5188 3.4842 10.6102 48.8184 27.8690 2.8027 19.8795 6.0512 12.0446 14.8769 0.9105 9.1493 12.7402 10.7742 66.4134 80.6953 35.3021 48.7407 175.0935 113.9304 89.6744 108.6400 4.4578 22.7156 38.7327 66.5691 28.4701 17.0779 16.4588 92.8622 83.5663 94.0610 137.2564 30.6636 1.6444 3.8182 4.2725 25.2232 351.3492 513.5794 323.5553 530.3840 243.5248 120.0198 49.8522 151.7019 36.0866 12.3856 10.8345 15.9476 14.2057 13.6114 4.0372 5.5699 1.2438 9.5965 6.5430 2.5804 17.5451 15.6703 4.8233 12.7172 1.0194 24.3253 3.5262 22.5319 12.6457 26.2802 39.8092 15.9194 22.2088 22.7952 76.8492 14.0347 6.7183 3.2569 9.8591 10.7724 19.3807 2.0346 18.7453 9.0429 3.1454 3.8070 12.2812 1.2422 14.4762 58.9126 42.0883 14.0934 8.1424 10.1568 59.6108 47.3159 80.4912 33.7870 10.0400 16.9593 14.6570 17.9829 2.5909 43.2117 22.4885 13.5246 31.6376 46.9633 84.9990 44.5988 13.7229 9.5891 274.9896 100.2578 13.8008 50.0539 6.4921 5.5462 35.9377 15.6007 305.8508 251.5432 57.4802 49.1734 564.9909 589.0791 280.8830 45.2754 6.5993 30.6451 2.4397 7.5348 25.4702 31.7668 2.7709 8.1462 8.1616 6.7696 17.5737 5.0442 108.2370 81.4792 55.2033 24.1922 3.1839 3.9067 1.2473 8.4202 10.0765 18.3724 39.7493 9.8224 10.2762 4.7164 4.8282 1.2411 1.3961 8.7339 4.5549 20.1582 54.7656 22.4691 8.8869 6.2968 6.9698 9.0609 5.8200 61.2628 58.5081 3.7403 19.5916 15.3810 2.9041 6.1390 11.5064 2.1780 10.1354 3.9704 1.8637 10.3703 5.6561 6.6086 8.6657 3.8186 10.3917 16.2590 10.2584 2.4232 2.0876 5.9746 5.3846 9.7090 5.8886 1.3666 8.3193 12.0021 12.2612 4.4951 28.9430 34.9571 30.1844 10.7015 72.7141 18.8182 5.1349 4.9341 11.1353 23.3139 2.0227 16.0617 17.6052 11.0747 36.6177 35.3493 27.3406 29.9640 5.9574 2.7009 4.9227 8.4978 15.3323 18.8988 57.8273 16.5461 12.2736 15.6057 5.4379 10.7086 8.6146 10.0282 2.8870 2.8222 6.2616 18.1149 4.4740 4.9275 68.6819 79.5819 36.8275 5.4694 17.7876 1.2396 24.4970 4.1348 14.7964 28.1291 5.2661 13.3220 22.9010 31.1023 11.8355 23.3682 19.9112 19.9869 17.7420 4.1990 33.8551 34.5815 59.6799 51.4557 9.2841 4.3665 14.6125 7.3738 6.0538 18.8061 28.9519 10.3743 30.5676 58.8658 54.3548 20.0509 92.4775 31.4807 28.5316 25.0807 27.5678 27.4990 25.3017 62.0100 77.4487 73.3813 34.3738 29.1524 44.7990 10.1968 55.3135 70.9857 10.5522 44.7691 21.3174 36.2008 38.4463 7.1065 6.3669 14.1117 136.4879 221.7289 371.7863 169.5908 406.2278 256.3649 300.1304 325.9155 76.1877 8.7254 6.1542 10.1097 14.7954 6.4801 6.4860 28.3451 13.4395 12.6126 12.1537 10.1850 1.5757 16.5649 2.0181 5.3720 14.1507 3.8764 3.3603 23.5219 18.6815 93.6118 118.8354 7.1111 9.7143 15.9778 7.5743 18.9328 14.2496 6.2725 19.9236 10.7421 10.6545 49.7266 6.5881 20.4936 3.1739 8.9911 7.9305 7.9815 5.1467 15.9047 3.1738 12.6110 2.2522 5.2648 3.5906 5.5694 7.1450 20.2604 23.4119 11.5469 16.0100 15.6099 7.9545 4.6756 19.7794 16.1550 39.5286 13.3297 7.2781 9.7234 2.8022 17.1476 6.5237 21.1640 3.5790 5.0739 9.6155 16.7855 51.1709 11.3454 17.2556 10.3444 8.1492 9.4472 2.3998 4.6404 4.5918 6.9811 25.8694 3.5074 7.4071 8.7327 2.1682 10.4228 36.2800 5.3763 140.2006 168.7035 207.4277 95.3589 23.9144 9.7164 8.2576 14.7594 6.3800 4.1748 1.1255 17.6303 39.6940 19.5405 9.4882 11.2341 7.5811 15.9337 1.7975 4.5935 1.7524 22.1690 72.7275 84.6949 52.6702 7.8753 1.6874 1.7067 7.2548 17.7820 25.1585 13.7912 10.2170 8.0277 4.9261 11.2626 4.2814 9.3588 8.7016 2.8790 17.3916 7.0336 4.8461 13.6477 25.3355 53.2030 3.3556 3.4744 9.5729 5.4406 10.7160 6.3282 20.6909 16.4194 6.8849 23.8984 33.6639 4.1344 9.9854 16.3974 2.9186 16.1606 5.3541 8.6729 6.2660 10.7086 15.7140 60.4747 25.7030 8.4810 3.6418 136.7862 96.7313 40.5015 4.2546 9.2299 4.5586 5.0291 20.4064 37.9694 13.9030 20.7789 32.6029 12.1402 32.6036 8.4372 25.0322 19.1940 27.4789 10.1319 17.2868 6.6996 93.2260 238.2121 152.4210 49.3212 11.2141 3.4435 11.3247 74.4382 83.1977 153.7884 164.8175 46.1960 21.3199 8.8300 101.6145 54.3686 57.5756 65.0307 20.4811 23.6840 26.2650 363.4641 630.0406 203.9385 49.3090 31.8182 40.6440 122.4566 41.5987 707.0180 989.1421 495.5886 140.0913 32.2434 12.9184 34.8640 8.3428 12.8436 5.7005 12.3609 10.9389 12.8152 4.1081 9.7312 1.6886 2.0328 1.2402 7.3164 9.9376 8.0779 20.2228 8.0435 2.2537 6.2250 10.9980 15.0756 6.3459 15.3282 8.3546 12.9332 3.5723 8.3276 15.5953 8.2561 14.8921", "5", "ETD", 771.98, true, 2, 4, 0.9, "5", 0, false }, // 20090326_Yest_LysC_1x6ETD_longGrad_01.10590.10590.3.dta { "132.0715 147.0837 218.1497 220.0796 230.4796 232.0339 247.2026 259.3970 288.2270 291.1560 299.8253 318.1685 325.1313 325.8452 342.9795 345.4805 349.1709 372.1323 374.2528 375.1326 375.9820 387.2794 388.4255 389.4038 394.8831 405.3392 406.2431 422.1203 424.0133 427.4456 428.5132 429.2105 430.1854 431.3031 443.0010 448.0626 458.1953 459.0851 467.2625 473.2182 475.3655 476.2024 477.9857 485.3104 488.3539 489.2596 492.0747 493.3931 501.1275 523.2679 524.2704 543.2321 546.2448 558.2181 559.4894 560.9747 562.1701 563.5605 572.1761 573.2726 575.4438 576.7999 585.0765 588.0498 598.0027 630.4970 641.5347 642.3078 643.3769 644.9922 648.2646 653.5646 658.4521 659.3398 661.1553 671.3445 672.2643 673.8300 686.2356 687.2797 688.3865 694.2662 702.9780 717.8011 719.0940 724.1596 735.9033 744.6633 747.7307 752.4191 753.2854 754.1927 754.8959 755.5855 756.2725 757.0895 757.9471 758.7214 759.3835 760.2155 762.5571 771.9141 773.3524 774.0510 775.0845 776.1815 777.1197 786.3012 787.1558 788.6226 790.5959 791.5471 794.0435 796.9368 801.4812 802.4707 805.9221 807.7691 813.2900 815.0375 819.3782 821.2471 826.4383 834.3730 838.5256 845.8716 848.2889 853.5008 854.1682 858.3172 861.9479 869.9322 874.4223 877.4258 878.3083 879.5461 882.4388 884.3433 886.2766 887.4866 890.3177 892.3860 894.1328 896.8228 898.6152 900.3166 901.3664 902.4816 903.2700 904.2283 905.2463 907.5801 908.5921 914.6594 915.6624 917.3672 919.1120 920.0164 921.1387 922.3276 923.3732 927.0599 928.1668 929.3540 933.0705 935.7183 937.1277 938.0724 938.7009 939.4881 944.4953 945.3680 948.3203 949.5163 951.0867 956.7850 960.2507 961.0474 961.7953 962.7480 967.9710 969.8694 971.1596 972.2363 973.5232 975.0296 976.2681 979.4318 981.0421 981.9901 984.7593 985.9832 987.3868 988.4250 989.2796 990.5510 991.8367 992.8450 994.2226 995.0679 997.8716 998.6213 999.3199 1000.5422 1001.5933 1003.1556 1004.0806 1005.2917 1006.1589 1007.3611 1008.6099 1009.6362 1010.5707 1011.6604 1012.4658 1014.5402 1015.9670 1017.7939 1018.6812 1020.3931 1021.3630 1022.9549 1023.6440 1025.9456 1026.6624 1028.3309 1031.8478 1032.5596 1033.6030 1034.4243 1036.3458 1038.7056 1040.3380 1043.4136 1045.9514 1048.1697 1049.0587 1049.9420 1050.6794 1052.7510 1056.5795 1057.4160 1058.3438 1059.0503 1059.7845 1060.4841 1063.3778 1064.2854 1065.3510 1066.1342 1067.3438 1070.7596 1073.7325 1074.5242 1075.1725 1077.2491 1077.9303 1079.5321 1080.5077 1081.6063 1082.7450 1085.4679 1086.6656 1087.3792 1089.4362 1090.0438 1091.5702 1092.6472 1093.3260 1096.6234 1097.3236 1098.6217 1099.5741 1100.5021 1101.1124 1101.7311 1102.8992 1103.8336 1104.7256 1106.4027 1107.7963 1108.7084 1109.4752 1110.7401 1111.8080 1112.7272 1113.4573 1114.3319 1114.9320 1116.0812 1117.0597 1118.2805 1119.8781 1120.8762 1122.2347 1122.9132 1123.8802 1124.6854 1125.7269 1126.9999 1128.0149 1128.7999 1129.7657 1131.0870 1132.8833 1134.1522 1135.5182 1136.3419 1137.5546 1138.4476 1139.1550 1139.8304 1141.1919 1141.8374 1143.2264 1145.2018 1146.2469 1147.3065 1147.9469 1149.5527 1150.4755 1151.9442 1152.6703 1154.1738 1155.1608 1156.5076 1159.3502 1161.2046 1167.1737 1170.2955 1171.2012 1173.1973 1176.2446 1177.4215 1178.2328 1180.5065 1181.3906 1186.8690 1187.8267 1190.8583 1192.4257 1193.9436 1194.8959 1195.5464 1198.4105 1199.5392 1201.9952 1202.5953 1204.9934 1206.0919 1211.7484 1213.1976 1214.5695 1215.7498 1217.5830 1218.2981 1220.3254 1226.4944 1228.7361 1233.7257 1235.6561 1239.3969 1240.0757 1240.8286 1242.0421 1242.7646 1244.9883 1246.4276 1247.7548 1249.3785 1250.7234 1251.9867 1252.7737 1254.0602 1255.4293 1256.5275 1257.6901 1259.8588 1260.7098 1262.3071 1263.2318 1264.1481 1264.9606 1268.8447 1269.7992 1270.6405 1272.4789 1273.1649 1275.6637 1276.6760 1277.8824 1279.0483 1282.3561 1284.8334 1287.7657 1289.6763 1290.7190 1291.4702 1292.7799 1293.5560 1294.5465 1296.1893 1300.2904 1301.1901 1302.6261 1303.7428 1305.5427 1306.1834 1307.2145 1308.1500 1314.6536 1315.8959 1319.4083 1321.2302 1330.2814 1334.6656 1335.7017 1340.0239 1340.7843 1341.6863 1342.6956 1346.4484 1347.0558 1347.8868 1348.8137 1350.6993 1353.6053 1355.2299 1356.2266 1357.1666 1358.0416 1361.2682 1362.0555 1363.2323 1367.6686 1368.4825 1371.4366 1372.5746 1374.9340 1375.9182 1378.2938 1379.1589 1379.7727 1380.7631 1382.4111 1385.3702 1386.5568 1390.0216 1390.9486 1391.7754 1392.7571 1393.8690 1394.8009 1396.9442 1398.2675 1398.8807 1400.2094 1401.3044 1402.8741 1403.8854 1407.2385 1408.1870 1411.1185 1411.8433 1416.5988 1418.4542 1419.4943 1420.5707 1422.6476 1424.9674 1426.5623 1427.3171 1428.0719 1429.7015 1431.2341 1432.2362 1432.8817 1434.8376 1436.6995 1438.9518 1440.3187 1441.0372 1441.6425 1442.3195 1443.3434 1444.0919 1444.7957 1445.6251 1447.6378 1448.2841 1449.4817 1450.7064 1451.7474 1452.6267 1455.0867 1456.0149 1457.7488 1459.4772 1460.3107 1461.2782 1462.2648 1463.1086 1463.8396 1464.6327 1465.9381 1466.7299 1467.3907 1468.3772 1469.4128 1470.5614 1471.5663 1472.3510 1473.6410 1474.4960 1475.5295 1476.5924 1478.0243 1479.1256 1480.2164 1481.1080 1482.4667 1483.4752 1484.2919 1484.9777 1486.3055 1487.0165 1487.6227 1488.5546 1489.5608 1490.3602 1491.2828 1492.1643 1492.8318 1494.0306 1495.2540 1496.0427 1497.1150 1497.9700 1498.8796 1499.6732 1500.5129 1501.2882 1502.2040 1503.4967 1504.5358 1505.5095 1506.4403 1507.5525 1508.5974 1509.6749 1510.7125 1513.4476 1514.1985 1516.1212 1517.1346 1518.1415 1519.6188 1524.7462 1530.5406 1531.6271 1532.9105 1533.7650 1536.1287 1538.3522 1540.5753 1545.5656 1548.4792 1552.3759 1555.9591 1556.8051 1557.4430 1558.6722 1560.5824 1564.6781 1565.8656 1570.8792 1573.4445 1574.9510 1575.6534 1576.5870 1577.6252 1578.5360 1586.2131 1588.5458 1589.9314 1591.4358 1592.6217 1593.6790 1594.6000 1595.3712 1597.6683 1598.7733 1599.6034 1601.7477 1602.5172 1603.6656 1604.5775 1605.7361 1606.5272 1607.3821 1608.0726 1608.7301 1610.0432 1611.7487 1613.7721 1614.9047 1616.7120 1617.9666 1619.5499 1620.2096 1626.8650 1627.6273 1629.4537 1632.9762 1633.6058 1639.7977 1641.3356 1642.4802 1646.5656 1654.2638 1655.7179 1657.8710 1659.6442 1660.9542 1662.6053 1663.8749 1668.2489 1669.1154 1672.5940 1677.8602 1678.4950 1679.4412 1684.5973 1685.4513 1688.3505 1689.4299 1690.5846 1691.5455 1694.7162 1695.5563 1697.2151 1700.8923 1702.3458 1705.5192 1706.1414 1711.7404 1716.2643 1717.3661 1718.1285 1720.4288 1723.7699 1725.2262 1725.8705 1727.8346 1731.9359 1736.0670 1736.7618 1738.4319 1739.3585 1740.3849 1754.4172 1755.6169 1760.1327 1761.8771 1766.0066 1766.9148 1771.9343 1773.3990 1774.6653 1775.5326 1780.0551 1780.6740 1781.7604 1786.6141 1787.5883 1788.3990 1790.8025 1792.9210 1793.9456 1794.7343 1795.9086 1797.9089 1799.9230 1801.6803 1803.5555 1804.6731 1805.7235 1809.8777 1811.1664 1812.3549 1813.0197 1813.8759 1815.0143 1826.7389 1831.6859 1832.8005 1833.6959 1837.2887 1838.3933 1844.3966 1846.0774 1847.7430 1849.8075 1852.8240 1853.5051 1854.5183 1855.1476 1857.3937 1858.4646 1861.0085 1862.3038 1863.0139 1865.0543 1865.8370 1869.4540 1870.1364 1871.4215 1873.7247 1874.9348 1875.8529 1876.8010 1877.6287 1878.7743 1880.5300 1881.7614 1882.4681 1883.4973 1884.7552 1885.6310 1886.4500 1887.1340 1892.7078 1893.5094 1894.6998 1895.7473 1898.3099 1901.4218 1902.3488 1903.1700 1907.8961 1908.7579 1910.9142 1914.8903 1916.6761 1918.8949 1921.9607 1931.4806 1933.1414 1936.7150 1937.5914 1938.5076 1939.6466 1940.3966 1941.0419 1944.1234 1945.2714 1948.6447 1951.8010 1952.5461 1953.8221 1954.7272 1955.5040 1956.8084 1958.7610 1960.0621 1961.2137 1962.7708 1964.9230 1967.0609 1975.5131 1978.1849 1981.8810 1983.2643 1984.0470 1984.9055 1985.7872 1989.3231 1990.1945 1991.3435 1993.7008 1996.1595 1997.3917", " 1.2076 0.2140 2.3574 0.2235 0.7150 1.5416 0.5106 0.2808 1.4575 1.2365 1.5764 1.0484 2.0898 0.3594 0.3937 0.5057 1.1949 0.4417 0.5184 0.7567 1.7286 2.5776 1.0447 0.6475 0.4878 0.5413 0.7210 0.8683 1.5805 1.2481 0.9224 0.4397 2.7264 2.9179 0.4282 3.3980 8.2613 1.4577 0.7768 0.8242 0.9273 0.2600 1.0749 0.8343 6.5725 1.3257 1.4782 1.7275 2.0267 6.2333 4.6120 0.2138 2.1553 0.6762 0.3060 0.5197 1.1004 0.5557 13.5331 3.3736 1.0484 0.2206 1.8039 0.7566 0.8574 0.6322 1.7819 6.2294 1.5022 0.4449 1.0625 1.0556 1.0846 8.6348 0.9826 1.1124 1.1257 0.7346 49.9103 17.2452 0.8687 2.5821 0.8434 1.0176 0.9266 1.3142 0.8698 0.2695 2.9848 95.5053 123.8437 415.3209 162.7748 29.4583 11.2904 4.5553 6.4016 3.3487 2.8605 1.5501 2.8116 1.2292 11.5321 164.9001 52.5358 1.8989 2.7205 7.1684 1.1077 1.7213 4.1389 0.4881 3.1712 2.0489 14.5531 1.2746 1.2662 1.4230 0.2810 0.3932 0.8920 0.6513 1.0045 1.2514 0.5283 1.1155 0.4214 1.7106 0.5640 3.0417 1.7984 1.2852 1.4770 0.3818 2.0609 3.2723 0.3714 0.7191 1.1172 1.7947 3.7536 0.7794 0.3932 4.5500 2.4211 3.7334 0.5021 3.0261 1.2865 1.7746 1.0857 0.1931 2.1706 1.3030 1.3275 1.7470 3.6695 0.7659 32.0758 22.9650 0.7790 2.6867 4.7843 0.5964 2.1821 4.6095 7.3233 3.4811 0.5895 1.5527 0.3956 0.3037 0.6638 0.8059 1.8832 0.7582 7.0576 2.7757 1.7917 0.4221 0.2137 1.1865 9.6860 2.5186 3.0589 1.8420 0.3490 3.8613 2.9495 2.1801 7.8167 2.0074 0.8264 5.8261 19.8522 3.2070 8.9683 7.8701 9.8508 6.2420 7.1219 9.3822 3.4960 3.8728 0.2815 66.7999 72.3691 56.9526 18.8768 5.7605 0.3263 1.4310 0.7763 0.8309 0.4642 1.1406 1.7456 4.3327 0.8780 1.7747 1.7727 3.3483 0.5395 2.4342 2.8337 1.0952 1.4446 5.2073 2.3888 0.3338 0.3789 0.6679 1.2664 0.8963 1.2939 4.4210 2.6471 2.5197 1.9282 1.4689 1.5747 0.1930 0.9260 2.8797 0.5058 1.4175 12.8377 4.1711 1.7514 2.1085 3.2747 3.7872 14.8720 11.9092 1.9080 1.9879 4.6735 4.8620 1.5929 2.5621 0.7800 6.2992 5.7929 0.3338 2.4582 2.1743 2.2921 3.1369 1.3672 3.2963 2.1328 6.6508 6.0206 14.9452 42.7227 66.9737 4.4493 3.8855 1.3761 18.6998 34.3735 338.7904 131.1618 5.8179 5.1552 7.6294 2.0181 11.8245 9.4991 22.9782 24.9889 7.7356 18.3284 18.1433 33.3393 27.6002 10.2412 0.1801 0.4443 10.1228 32.5019 82.3745 101.4169 1000.0000 23.3991 28.4881 4.4190 11.2680 0.7131 1.9087 0.6864 0.8469 3.8191 1.6547 3.0529 0.7080 0.5606 1.9551 1.5675 2.4145 1.4108 0.8076 3.4161 3.3622 3.2567 0.6298 1.9713 1.8804 6.0610 2.1832 0.7576 4.2365 9.0074 6.9004 0.7836 0.6294 0.6448 1.2883 0.8924 1.6529 2.3994 4.0579 0.3263 0.4654 9.7691 9.8065 1.9246 0.6522 0.5289 2.3048 2.4125 2.2490 2.0460 2.2836 0.3336 0.4194 2.9350 1.1824 2.5262 5.0736 1.9755 4.3466 4.5507 4.3216 0.4441 1.9634 2.5902 1.3023 0.8350 0.6009 1.0725 2.3361 0.9471 2.1322 7.5486 4.3870 6.5467 3.8657 0.5319 5.8366 7.9936 10.2615 2.2668 3.9705 1.0091 3.9796 1.0987 2.9872 1.0362 2.0512 2.5960 0.2360 0.4616 2.2687 3.4097 0.7655 19.5894 8.5281 3.0799 0.6448 0.9140 1.6849 2.7325 3.6269 1.5008 8.7271 1.8260 1.8703 2.0504 3.2562 2.1932 3.7697 1.0014 1.0892 2.0676 10.9117 2.6939 16.5948 47.8316 19.5815 3.9960 0.5061 2.4257 0.6470 1.6296 4.4909 0.6711 2.5167 0.9956 3.9846 0.6229 0.6300 1.2317 0.3488 1.7704 1.2194 5.4718 3.0694 8.8268 2.6515 3.4444 1.8046 5.2007 4.2030 1.2666 0.5955 1.4315 3.3365 10.9769 9.6559 3.3541 1.3873 0.8242 1.6417 0.3664 2.5252 4.5472 1.3094 4.0787 2.2106 0.7089 1.8252 1.8290 1.6118 4.9864 3.6972 0.8483 0.9548 1.3124 1.9545 0.9277 0.9933 0.6038 0.5283 2.5788 1.2767 0.2186 5.1594 4.6538 3.5988 14.1830 11.9669 18.5134 5.8140 4.3164 3.9043 5.2363 5.3522 5.2094 1.1306 0.5130 4.5587 1.7590 1.2293 4.0148 0.6274 4.5225 6.6950 26.7434 22.2381 7.7080 2.8686 1.9441 4.3427 2.3264 0.6434 0.4201 11.3562 2.3697 7.8335 1.6202 2.4843 2.9855 5.8517 17.8666 21.4525 8.2153 10.9946 5.5324 6.2264 21.3605 43.6459 14.6577 5.5590 21.0449 4.5376 160.1788 97.0698 45.0015 7.0711 16.9170 9.7769 5.0658 5.5334 7.2382 11.1346 45.0870 37.9341 15.3358 8.7210 6.6676 1.6461 7.6088 22.8921 127.6581 182.2985 118.2491 74.3847 98.4043 54.3199 14.8665 1.2609 0.6863 4.4409 0.6221 2.5149 8.1892 1.9566 2.8118 8.4393 1.9692 0.9676 0.6976 1.0319 2.0317 1.4544 0.4874 2.3965 0.3256 0.6893 0.4004 1.5528 1.9372 1.6881 2.9417 0.2133 0.7383 11.3397 58.1341 25.1474 11.6925 2.1586 1.6553 1.4886 1.6212 14.0345 16.5649 7.0838 2.6957 2.2239 2.1454 1.4155 2.4047 2.3002 3.8509 5.0052 7.1986 4.2648 1.6357 3.1159 0.9122 1.6793 5.0820 2.2470 0.5356 1.1527 2.3515 1.0578 4.9751 3.9399 0.6701 0.7594 1.0517 0.4015 0.9613 2.1521 0.1929 1.6375 10.1434 1.9662 0.4823 1.0296 1.1979 0.5108 0.4227 0.6855 3.1168 1.8406 1.2817 2.3289 4.3205 0.5351 0.7420 2.1783 4.4910 22.3696 22.1857 4.5112 0.5995 1.3008 0.6007 1.7847 1.0353 4.0656 0.4198 3.4135 1.7383 1.2329 2.7071 1.1877 1.0536 2.2255 0.3713 1.2426 0.3756 4.0904 0.4890 26.9088 15.2575 3.2073 8.5312 2.3647 0.5726 1.0939 0.4167 0.2364 0.3041 10.7180 0.7391 6.3138 0.5006 1.5169 1.9374 0.2268 5.1699 1.6165 0.4959 6.7578 0.8952 4.6251 0.2976 1.3892 1.4037 3.5373 8.7896 10.3457 2.9930 1.5991 1.4395 0.9617 1.5030 2.8196 2.5663 0.3422 4.9941 0.5507 2.4602 2.6109 2.5353 1.3524 1.3714 2.4542 2.6043 2.6284 0.9234 2.4981 0.8737 1.5071 0.4602 2.1118 3.2074 1.0979 0.8767 0.6194 0.3803 2.0895 2.7964 2.3609 6.3509 3.9330 0.6710 1.5431 0.2822 3.5670 0.3267 2.8275 6.0304 5.4242 5.4718 3.1268 3.0904 0.8519 1.1704 0.7215 0.2140 0.9974 0.8218 0.6193 1.7848 0.7198 0.9822 1.8476 0.1490 0.9795 1.1393 2.2994 0.5434 4.0934 15.5582 22.2507 13.9339 5.9831 2.6821 1.1616 3.2216 1.2479 4.5594 2.1396 0.8027 0.6561 2.5058 3.0038 1.4703 0.6191 2.6715 3.6273 3.9598 1.1740 0.6479 1.1190 0.8267 0.9587 3.9114 2.1504 0.8505 1.3656 0.6370 0.8712 0.7767 1.1165 2.0315 1.8604", "3", "ETD", 754.26, true, 2, 4, 0.9, "2 3 4 6", 0, false }, // 20090326_Yest_LysC_1x6ETD_longGrad_01.10944.10944.4.dta { "175.8720 199.8941 218.1583 245.2375 273.0284 274.2396 289.3082 346.2828 358.1471 359.0504 362.9637 385.9947 387.0605 387.6643 390.0204 403.3923 416.9887 422.3281 438.4811 449.2099 456.9319 458.2459 471.9123 473.2959 496.1605 510.5996 534.8668 558.6778 564.4798 586.2914 587.4955 593.1797 612.1970 642.2539 645.4006 673.3190 692.7047 693.7328 694.3719 707.2170 729.7064 736.3296 738.6448 774.5779 785.3604 786.3757 791.3216 792.3455 821.2388 822.4852 823.8489 824.7068 832.6044 859.9987 885.7700 895.0964 896.4106 897.1700 898.6160 899.4789 900.9644 901.8069 902.9141 904.2317 905.2639 906.5930 935.1630 936.8126 937.6146 938.2476 944.3350 949.3759 954.8591 974.3253 975.4271 976.2615 977.1982 994.7823 1010.4415 1018.3923 1019.4538 1021.3811 1028.0819 1033.3838 1039.5527 1040.4869 1041.1951 1042.4680 1049.5273 1058.4209 1069.6090 1090.3763 1104.6752 1111.2748 1121.3943 1131.6147 1132.6053 1146.3213 1147.4335 1153.2089 1155.8812 1164.2150 1165.4015 1166.3696 1170.2813 1175.3116 1176.0127 1176.8715 1178.0538 1179.4586 1180.1742 1180.9137 1182.0205 1183.0919 1185.4933 1186.2325 1187.3251 1188.1422 1189.1251 1190.2260 1191.2662 1192.4812 1193.5873 1194.2908 1195.0613 1195.8481 1196.9855 1198.0087 1198.7291 1207.3302 1211.6921 1223.9277 1224.6180 1233.6984 1235.6779 1241.8362 1251.8188 1257.3807 1259.4963 1262.5111 1263.4620 1264.1301 1264.8878 1267.9177 1273.4928 1275.4266 1277.7567 1279.6074 1282.1769 1283.6276 1284.6364 1290.4642 1293.4266 1295.2639 1296.6180 1302.2794 1307.9474 1311.6423 1313.4198 1314.0905 1315.3881 1316.1901 1316.9230 1317.6395 1319.8770 1321.4464 1322.1534 1323.1881 1324.1664 1325.4769 1328.3777 1329.6705 1330.3971 1331.5485 1333.1272 1334.5436 1335.4484 1336.4099 1337.3990 1340.6471 1341.3518 1341.9587 1342.8571 1344.1476 1344.7744 1345.5146 1346.7733 1348.1099 1348.9272 1351.2007 1356.2775 1358.0707 1359.5850 1363.6600 1369.3317 1375.6279 1377.6879 1378.3973 1381.5529 1382.1711 1387.8429 1396.8002 1397.4147 1401.4276 1404.5148 1405.6346 1407.8031 1409.7621 1418.9779 1425.5529 1430.6195 1435.7096 1437.9529 1444.8386 1446.1393 1447.4783 1453.4469 1454.5709 1457.5491 1458.9441 1464.5022 1465.4081 1469.3082 1469.9724 1470.9104 1472.9240 1477.8826 1482.6809 1489.5529 1490.4714 1492.0417 1492.9250 1493.9073 1494.7794 1501.0922 1505.6737 1506.8972 1507.7159 1510.3519 1511.5221 1514.2782 1516.4744 1518.1965 1519.8464 1522.2704 1525.4772 1529.8956 1531.4729 1534.4573 1540.1346 1546.6332 1552.2518 1556.7091 1564.0348 1564.7952 1565.6415 1566.2545 1567.6869 1568.7028 1569.5258 1578.6302 1582.7854 1594.2843 1596.6448 1599.3793 1600.3068 1601.5730 1602.5927 1604.0251 1615.4640 1616.6613 1619.0719 1621.8811 1623.5704 1626.0370 1629.8317 1634.1423 1634.9856 1636.9403 1638.3601 1639.5543 1646.2424 1650.5768 1656.0638 1657.2604 1658.0907 1660.0883 1661.8132 1662.5750 1664.4910 1671.9044 1673.8621 1674.5935 1675.6832 1676.7406 1679.4630 1680.6952 1682.0568 1683.6165 1689.6736 1692.4982 1698.9215 1699.9553 1702.7340 1703.9652 1704.8475 1706.7195 1707.3943 1708.2800 1709.0286 1713.8107 1715.9885 1717.3331 1718.0604 1720.2208 1722.3376 1724.1884 1726.0417 1726.9645 1728.1034 1728.9226 1730.5367 1731.3829 1732.3666 1733.3103 1734.3645 1735.3290 1736.6276 1738.5490 1740.6384 1741.9008 1743.9740 1744.8041 1745.9012 1747.2345 1748.1301 1749.0778 1750.0002 1750.9318 1754.7299 1755.8284 1756.8458 1758.7975 1761.0399 1761.9836 1763.1096 1764.1193 1765.1483 1765.9137 1766.7489 1767.9734 1769.0042 1769.8815 1770.6935 1771.5680 1772.3074 1773.7887 1774.8766 1775.6345 1776.3323 1777.7008 1778.6428 1779.3386 1780.2023 1781.1492 1781.9978 1783.4535 1784.4506 1785.1273 1786.0966 1787.0409 1788.2284 1789.2784 1790.3038 1791.4622 1792.3827 1793.1508 1793.9470 1794.7955 1795.7273 1796.4738 1797.2253 1798.2062 1799.4427 1800.9071 1801.6083 1802.4524 1803.4679 1805.7606 1808.3549 1809.5353 1815.8075 1818.6710 1821.8365 1830.9684 1832.8890 1840.4708 1851.7019 1867.7532 1869.0187 1871.7620 1873.1697 1878.4259 1886.9445 1890.1262 1892.5468 1893.3860 1895.0382 1896.6545 1898.0157 1900.5481 1906.9015 1910.6238 1911.7203 1913.1337 1916.8942 1917.8323 1921.5272 1933.0487 1933.7792 1934.9421 1949.1449 1949.8992 1950.8385 1952.0890 1953.9465 1956.6921 1961.7362 1967.0646 1974.6322 1982.1481 1986.6511 1987.3944 1996.0720", " 4.3624 4.7879 20.4527 6.6807 35.8763 5.0918 15.6105 1.3454 3.6138 2.1448 3.7193 27.7317 15.6468 3.0271 2.8459 3.5915 2.9039 4.4288 8.2573 33.4606 22.5337 10.9575 3.8657 1.8491 2.2616 1.5618 1.5590 2.6759 36.8597 7.2591 13.4960 3.7699 6.0739 5.3025 5.4323 1.5584 13.8957 11.9132 8.8741 5.7557 3.9342 2.6969 7.6398 1.1519 1.1325 5.2826 6.6666 35.6866 4.2547 17.8581 4.8340 2.0095 4.3716 6.5766 9.4939 402.0601 464.8441 537.4277 17.9156 11.4710 6.2864 10.5367 10.8416 31.2116 20.9992 1.9120 1.9416 4.2069 16.4157 5.3653 5.5731 3.7154 2.7373 12.0522 22.7246 10.4559 7.8981 22.9325 5.0917 70.2356 15.1801 16.5597 6.3569 7.2440 97.9662 59.2950 4.9781 3.7180 6.7488 4.8467 4.8074 25.5973 0.7196 1.2403 20.9554 2.9501 6.9573 12.7672 6.1440 25.8016 3.8721 13.1331 24.5403 15.3066 8.4548 14.2019 97.2123 61.2889 10.7561 27.8591 261.0292 81.1214 33.4735 13.0577 55.6080 1.8582 3.8286 3.2263 98.7597 78.0330 29.2879 26.7894 61.2896 113.8111 471.9098 358.8193 69.3440 15.7886 11.8259 12.7191 3.5384 4.0754 2.6276 14.6821 9.7790 15.8430 2.7378 18.5379 13.0401 4.4782 2.5456 4.4677 15.8584 13.9536 6.7222 12.2559 8.2438 26.7612 20.6164 54.1877 21.4669 14.5228 3.0030 5.9903 3.1915 5.5731 8.8791 3.9608 42.3983 26.5532 32.7512 45.2916 22.6209 7.5070 26.7845 89.1145 17.6498 63.5447 23.8606 14.8505 63.5104 19.3959 1.2831 32.9884 32.3640 28.6556 36.8855 25.8593 53.3514 40.6725 70.8280 107.3617 291.0123 192.9853 203.6091 417.3050 45.1871 20.7725 10.4230 7.1783 14.1885 2.8451 9.7166 2.9932 3.7233 20.7696 1.9156 2.9814 8.0314 9.7279 5.3751 8.3862 20.9312 7.1718 16.5633 17.5793 5.9896 2.9916 5.4384 4.1460 3.5051 8.0391 7.0511 4.4688 8.4119 14.0447 2.2393 6.5569 23.8706 5.3554 1.4536 3.4873 15.1218 2.6706 6.1644 8.7950 16.1862 4.2813 6.6045 6.5178 13.1938 1.7797 22.7762 40.2348 5.9908 47.1946 33.6723 2.1450 33.1998 12.1067 9.6527 11.6886 23.3409 1.1411 6.8669 3.0980 1.1323 1.3458 2.9472 4.8933 40.1039 9.7925 4.2470 35.5044 18.2576 12.7848 6.3117 76.5752 48.8269 10.3323 12.9210 12.3009 7.7026 5.8583 11.2033 15.7370 12.5100 10.7524 6.1776 3.9357 2.9531 9.2800 4.9446 5.0280 12.8576 1.4519 16.9346 18.0947 7.4970 1.0260 2.1293 8.9426 5.8193 29.4846 18.4077 24.6667 16.0103 2.7393 9.7548 3.7904 1.5611 1.4558 6.3051 2.4478 10.7336 14.2377 1.7755 6.2844 23.8180 12.0611 9.3421 11.4608 7.1515 3.2196 12.6391 6.7725 67.7098 32.5935 21.0991 4.1655 11.3855 4.6931 16.1719 5.1260 10.0803 8.6224 8.5366 23.9460 25.0061 51.9124 32.0715 10.3749 18.8416 9.6547 13.8276 33.7576 76.0382 30.7797 1.3435 101.8303 28.4178 24.8342 12.7440 22.9802 118.5810 24.5601 61.0085 64.8762 8.8232 55.3785 26.0974 11.1268 0.6121 73.7481 72.0108 424.9133 349.1756 131.7968 47.4989 19.6911 28.8521 129.5987 344.8895 421.7938 209.4594 37.1212 12.8375 31.8070 21.4200 38.0732 31.5828 103.0884 126.7100 17.9557 32.8707 12.6995 159.1095 188.3956 161.5748 172.3210 4.0091 28.4575 170.2840 222.2034 531.8163 1000.0000 583.4736 747.9631 198.2331 81.7858 22.8003 28.8037 5.5438 19.4686 17.0368 6.0680 11.5053 19.6225 17.7406 2.8740 1.1310 3.1348 13.2612 7.4114 2.8418 7.8868 6.3045 3.4019 2.3112 16.0399 13.7013 5.9530 12.2208 15.6279 8.3215 2.3035 18.6413 24.7575 4.8850 2.3112 7.4741 3.9194 12.8287 4.8486 10.3892 19.0347 14.9629 6.1971 3.2175 3.5099 6.7257 9.0118 20.0309 5.3249 4.1317 1.3497 11.0168 6.1148 2.7018 10.4698 11.6874 4.3419 1.5923 3.3443", "4", "ETD", 896.93, true, 2, 4, 0.9, "4", 0, false }, // 20090326_Yest_LysC_1x6ETDsa_01.02755.02755.2.dta { "230.0981 286.1379 318.3454 356.3785 371.5393 373.5950 400.2392 401.3641 402.4094 427.4315 455.0078 456.1883 457.6418 471.3203 472.2448 473.3338 474.3383 483.2625 484.4883 516.1983 527.4332 530.3140 539.4369 548.9628 554.0997 557.0588 561.3072 572.1891 573.3624 574.4203 575.5069 580.4650 586.4937 617.1796 617.9493 618.8731 620.1948 621.2181 621.9984 622.8047 623.8954 625.2957 630.2192 632.0173 633.7305 635.7570 641.9611 653.3010 657.3339 659.5907 675.3161 676.1430 677.2904 678.5961 679.3595 703.5071 704.3304 705.3985 740.1729 762.3950 766.2808 768.6506 770.0381 798.4349 800.6177 808.5179 816.2749 817.4937 818.4566 819.4445 820.8203 822.4968 823.1750 824.3505 829.4699 830.1567 832.6044 834.6618 846.2754 850.5706 854.6957 857.3557 858.9043 859.8839 862.1486 873.2971 874.3799 875.4854 876.4969 878.7475 879.3759 885.4304 890.4575 903.4590 905.9922 912.6687 913.3745 914.5020 916.3308 922.7803 925.0191 925.7469 926.6190 927.3928 928.4533 929.5112 930.6172 933.9146 937.4092 943.1749 944.7322 947.3606 954.5606 956.4565 957.6349 958.7437 961.3524 963.2213 964.5411 966.5060 972.8018 973.5627 974.4982 975.5117 976.7676 979.9922 986.5786 991.7271 993.4317 1006.2110 1010.6760 1018.1799 1019.1472 1027.8459 1029.8701 1031.1293 1034.0077 1042.6014 1047.3507 1050.4709 1053.0702 1056.7209 1057.4386 1058.3582 1059.1672 1084.7484 1085.4883 1086.6018 1092.6569 1101.5668 1102.5316 1103.4456 1104.5449 1105.4836 1106.2820 1107.3219 1108.6346 1118.7115 1119.9362 1134.4797 1136.1908 1138.3112 1143.4336 1144.3865 1145.3591 1146.4233 1147.3323 1148.7775 1156.2939 1158.3121 1159.5941 1160.4716 1161.4147 1162.6970 1163.3986 1164.3463 1165.4460 1167.3688 1169.7459 1170.3529 1173.8286 1175.2434 1176.2880 1177.2156 1178.3756 1184.8765 1186.2137 1187.5798 1188.6298 1189.5321 1190.4587 1191.2911 1192.2899 1193.4386 1198.7231 1204.5912 1205.5559 1206.5072 1207.3990 1208.5984 1209.4135 1210.0560 1214.8812 1215.6157 1216.6219 1217.4187 1218.3597 1219.3088 1220.2905 1221.2997 1225.5035 1228.3008 1229.3121 1233.5978 1234.5568 1235.5013 1236.5106 1237.4996 1238.3781 1265.4860 1268.3812 1440.9069 1466.6534 1467.7113 1484.6107 1490.2760 1494.6941 1496.7672 1520.9896 1532.8058 1537.6378 1569.5238 1596.6863 1607.9568 1621.5748 1622.5538 1650.2029 1660.3529 1668.5236 1676.0067 1677.2543 1737.1874 1740.8645 1793.6110 1800.9139 1808.6078 1820.8539 1823.1715 1832.6832 1834.9177 1836.3197 1838.1199 1849.7692 1851.6238 1852.4869 1853.9988 1856.8741", " 0.4833 2.8457 1.3471 1.5642 4.1266 2.0825 18.2947 11.9255 3.2442 1.8652 1.0598 1.7549 1.4362 23.5484 14.5760 2.9233 0.3836 0.7490 0.6133 1.0514 1.0303 0.9975 1.4244 1.7969 1.3435 1.2036 0.7670 22.5997 24.3054 3.8169 0.5100 0.6350 0.4580 1000.0000 950.0541 146.4767 20.2407 10.1327 5.6393 1.6020 2.0908 4.8558 0.7916 2.3856 1.5659 0.3025 1.3060 1.4838 0.6670 2.7304 4.8081 11.3607 15.2884 5.1882 1.5464 5.8153 1.3453 5.4665 0.6211 1.4106 0.5344 1.2328 0.7641 0.4056 0.7916 1.1898 51.8903 45.0533 20.9658 2.8625 0.6900 5.5034 1.1943 0.9176 0.7222 0.8172 1.0576 1.1637 2.8884 2.3396 1.5933 1.3111 1.4198 2.2153 1.3822 36.6191 93.2001 31.6534 13.9696 0.5607 1.0470 1.1894 1.3608 0.4800 1.2049 1.2550 0.9972 0.4859 3.2288 2.1349 4.6879 9.9833 3.0879 3.9000 9.7938 7.9775 3.2508 1.2384 0.2507 1.4634 0.8810 0.6898 2.2602 24.2051 10.3956 2.2402 1.0667 2.7753 1.0992 1.0642 23.1131 80.2114 41.9553 18.8793 6.8117 0.8456 0.8240 5.1849 2.9205 0.4809 2.4141 1.8661 0.9377 2.9857 0.4307 0.8422 0.9059 2.4583 2.0787 0.2538 1.9636 4.3802 13.6931 13.2065 3.3515 0.3303 4.0916 4.8061 1.1273 273.3655 164.5871 57.7409 117.6905 17.3177 16.4939 6.5438 1.7975 1.2035 0.6403 2.4150 1.9684 0.8133 8.3222 6.5229 3.3791 3.8109 0.6942 3.5036 0.2754 1.8501 23.3673 99.5213 47.5771 18.0218 8.4184 1.8678 4.3590 2.1376 0.7651 1.3611 2.3389 71.5708 39.1599 15.5463 5.5008 1.4616 0.7630 4.8375 22.6568 72.4867 18.4484 43.0253 10.7310 0.9463 2.4418 12.0548 48.5096 85.5242 32.0147 10.2352 0.3914 1.5637 2.8594 3.5130 47.4181 422.0222 241.4819 118.3296 40.2156 5.6453 3.3134 0.6608 2.7144 354.3168 331.3383 239.9229 102.3721 26.2857 5.2251 0.9337 1.4099 2.2105 2.6525 2.4697 0.6425 1.5885 1.0301 0.9003 2.7271 0.9299 0.4291 1.0306 1.2106 1.2834 1.1393 3.0377 1.8045 2.0633 3.3763 2.2776 2.2298 2.1149 0.7932 1.2733 0.9688 1.4401 1.2338 1.2547 2.6372 0.3283 2.3958 5.4447 2.5306 2.2378 0.3022 1.5756 3.1085", "2", "CID ETD", 617.86, true, 2, 4, 0.9, "2", 0, false }, // 20090326_Yest_LysC_1x6ETDsa_01.02929.02929.2.dta { "389.4117 391.0946 505.2968 507.3191 531.2183 532.9875 586.2795 604.4263 605.3598 606.4113 627.1395 632.1246 642.8731 647.7056 657.8644 661.1228 662.4505 663.5219 684.4991 691.8132 700.9722 756.3806 784.6460 789.4070 791.5776 804.7153 824.1043 825.2573 827.2163 828.6158 829.5567 831.2430 832.2522 833.7403 834.8653 835.9374 836.9997 838.7095 840.0015 841.4807 852.7488 855.3260 857.3301 862.5591 884.5059 888.2957 893.1559 916.4060 921.8802 924.5466 933.4266 937.3484 938.4031 945.7426 946.4650 948.7126 961.4505 962.6267 963.4643 964.3229 965.4019 972.7449 982.4905 990.2189 991.5987 992.4919 993.4343 994.4797 996.4581 1004.6815 1008.6563 1009.3945 1011.1580 1023.3934 1024.8807 1052.1252 1053.6049 1057.2513 1064.6522 1072.8944 1077.9215 1082.5858 1091.8741 1094.1873 1095.7383 1110.5525 1111.6389 1112.2892 1119.4299 1126.7136 1129.5619 1136.2286 1139.2841 1140.5375 1141.4402 1153.1908 1154.3090 1155.6510 1176.2434 1177.2328 1178.3448 1181.4806 1182.1593 1182.8680 1187.5962 1194.3029 1197.2499 1198.1327 1204.5625 1210.7902 1212.1400 1214.1775 1215.5211 1218.1316 1219.9628 1221.1005 1222.3605 1223.3898 1224.5499 1225.6085 1226.4681 1227.9926 1228.5979 1232.2542 1233.2992 1234.5721 1235.2050 1237.5599 1239.4896 1240.2415 1241.2290 1242.0975 1242.7695 1243.6515 1244.5927 1245.5897 1248.1522 1248.7697 1249.4774 1250.6180 1252.3149 1253.7596 1254.4711 1256.7651 1261.3907 1266.1443 1267.2919 1268.2922 1269.4253 1270.6189 1271.5963 1273.5363 1277.1300 1285.0336 1285.6952 1286.5616 1297.1799 1301.2589 1303.4088 1307.3865 1310.0802 1311.4427 1312.3468 1314.4532 1329.3843 1330.9202 1335.6158 1338.5448 1339.6599 1340.9244 1342.0405 1344.7380 1345.3879 1349.2100 1353.3885 1365.1899 1366.8412 1367.4452 1368.3197 1369.0911 1369.9567 1372.1359 1377.0958 1382.3802 1382.9803 1384.1898 1385.5289 1387.5792 1395.8666 1397.2480 1398.4102 1399.5603 1400.6278 1406.8954 1410.8093 1412.3290 1413.1520 1414.3805 1415.6887 1424.1570 1425.0261 1428.8671 1439.1027 1440.6417 1441.3064 1442.0126 1454.3318 1455.3502 1456.5426 1457.4420 1459.7175 1460.5052 1463.5647 1470.8596 1471.6796 1476.4039 1479.8065 1482.5315 1483.9215 1493.7325 1500.4481 1502.0992 1509.7078 1510.9183 1512.7770 1514.0159 1514.8826 1515.6151 1523.6542 1524.5192 1525.2487 1526.3709 1527.4846 1528.7477 1537.2732 1543.2845 1546.3744 1547.9034 1548.9309 1552.8575 1553.6243 1555.9164 1558.4528 1559.4818 1564.1635 1565.4012 1568.0790 1569.1183 1574.3885 1575.6483 1582.9139 1584.2750 1584.9357 1585.6139 1587.0966 1589.9462 1593.6754 1594.7550 1596.2111 1597.6212 1598.4812 1599.9320 1600.7953 1601.7797 1608.1990 1609.5865 1610.4445 1611.3497 1612.9202 1613.6732 1623.3538 1624.4572 1625.3722 1626.7540 1627.5168 1628.2701 1629.2654 1630.1409 1631.0465 1632.6423 1634.2019 1635.4436 1636.6576 1637.9016 1638.6970 1639.4714 1640.4979 1641.4641 1642.3527 1646.7335 1651.0729 1651.7736 1652.8461 1653.8489 1655.0579 1655.7216 1656.6390 1657.7958 1659.1790 1660.0687 1670.9275 1674.4968 1676.9290 1680.0575 1685.6888 1692.5092 1746.4464 1792.5345 1795.4675 1849.9757 1859.6594 1887.2311 1893.0343 1907.1237 1951.7926 1968.7068 1976.0979 1993.9811", " 0.4432 0.4417 0.9354 0.8766 0.1712 0.3226 0.5044 9.6652 44.2951 11.0255 0.3226 0.1435 0.5594 0.6825 0.3529 0.2423 20.8132 5.4826 0.7176 0.6450 0.2833 0.1577 0.5876 0.3551 0.7929 1.5588 5.9055 7.9331 94.5543 1000.0000 279.5447 13.4164 16.5519 4.1069 4.3171 1.4572 0.8147 0.5594 0.5766 0.3814 0.5656 0.1724 0.5781 2.1148 0.1717 0.3526 0.1161 0.6280 0.3660 0.4753 0.3448 2.2703 0.3503 0.6154 0.5865 1.0615 0.5179 2.1165 1.1192 1.8186 0.9755 0.9463 0.3675 2.6630 1.6269 4.0809 31.7227 12.0026 1.5629 0.6499 1.2754 0.8833 0.7261 0.1851 0.1983 5.4962 5.1440 0.3706 0.4881 0.6551 1.5435 0.6472 1.7838 0.6593 0.7380 2.0398 0.6327 1.2175 1.7458 0.5819 0.2884 0.2446 21.3980 19.5155 2.7173 2.2491 4.5808 1.1293 0.2402 2.2120 0.4669 2.6793 0.9654 0.7541 0.1891 0.1845 0.4222 2.3650 1.8310 1.2977 3.1053 1.1177 2.5762 0.9639 3.7044 0.1880 1.2117 2.3801 0.5720 2.9481 3.3816 2.9527 0.2321 1.7355 3.1817 1.7169 1.0149 1.3746 17.7523 20.2252 27.3089 4.6224 21.3270 0.7230 2.2827 1.7491 1.5890 0.9138 0.7536 0.9966 0.8261 0.4897 0.2551 0.7031 0.2696 15.5479 15.3047 38.6617 59.0178 15.4684 2.6112 0.4600 0.1848 0.3089 1.4164 0.1486 1.5678 0.4534 1.0769 0.4082 0.6693 1.3501 1.3779 0.2397 0.5309 1.0835 0.1988 1.7497 0.8761 2.4669 3.7735 0.1852 2.0049 1.8926 0.4897 0.1716 24.5692 52.9824 23.6798 2.4613 0.7268 0.9052 0.9184 2.1461 3.2504 2.5592 0.4701 0.7751 0.1299 43.3387 43.6989 5.6293 0.9027 0.2285 0.7651 0.9710 2.5743 2.5314 1.0250 0.5931 0.4779 0.1987 1.1296 2.4663 0.1482 0.3540 10.8254 18.9384 6.9893 2.5497 0.9191 0.7696 0.2815 0.8776 1.5641 0.8658 0.5190 1.4253 0.1582 2.3857 0.2170 1.0275 1.3075 0.4332 0.9517 0.9760 0.6412 0.2401 3.2072 2.0572 3.5485 49.1692 56.2148 13.3726 0.2985 1.6213 0.8056 0.9215 0.2296 0.7948 0.1711 1.0435 0.7248 1.0573 0.7018 0.4461 0.6351 0.1712 0.1220 0.8497 0.6124 3.0896 3.0315 2.7034 0.7005 0.5733 4.2601 2.0835 4.6959 4.6664 0.8142 3.0912 3.7012 2.1484 0.2718 6.9363 8.1365 5.7538 2.7637 5.9932 2.9869 5.4791 7.3112 34.1085 29.4706 101.2335 66.5634 19.2596 0.5331 2.4087 1.1253 0.5604 10.6444 6.6425 11.4832 118.5447 94.5447 54.5129 0.4179 1.3111 0.6019 4.5231 10.5781 5.7964 30.3947 198.2271 336.4221 387.8374 4.3948 1.2012 0.2840 1.2967 0.6841 0.7698 0.6992 0.9044 0.1992 0.4794 0.4203 0.2556 0.9895 0.2512 0.6975 0.1596 0.2560 0.3940 0.4488 0.6522", "2", "CID ETD", 828.69, true, 2, 4, 0.9, "2", 0, false }, // 20090326_Yest_LysC_1x6ETDsa_01.03022.03022.3.dta { "174.1554 179.0752 188.1227 189.3757 199.0582 204.2504 205.0559 218.2308 230.1408 231.3153 244.1837 246.2132 259.3337 260.2889 261.8342 277.0529 278.3394 302.2882 303.2218 304.1876 305.0680 319.1481 321.0120 322.0627 325.8947 332.1807 333.9844 337.2158 338.3555 339.0264 343.1706 344.0677 359.2288 360.6847 367.9915 378.2617 379.3112 389.2911 405.3777 406.0213 407.3484 416.2676 431.4978 432.1053 432.7890 433.4138 434.3278 437.5497 440.1097 450.2363 451.2313 452.2657 471.0859 472.1441 473.2143 474.2384 476.4431 481.1189 487.2791 488.3115 489.4159 495.2060 496.0844 500.8728 502.1552 506.3493 508.9581 514.4097 515.2046 515.8235 516.4713 517.3395 518.2429 519.0676 519.7510 520.9240 522.0898 522.8770 525.3414 526.3989 527.1591 527.9026 531.2535 533.2774 534.0975 535.9919 538.3132 539.1142 541.3626 542.7073 549.4869 550.2532 553.2217 565.2968 566.1797 566.8476 568.3304 569.6433 570.2741 571.2880 572.3028 573.0214 586.6914 589.3284 597.0137 598.1807 600.0079 604.0874 610.3766 612.4822 613.3114 619.8691 622.3531 625.0349 625.8797 629.3589 630.4100 632.1529 634.1899 635.3845 640.3384 645.5893 648.1205 652.3812 655.3437 656.3964 657.2783 658.4047 659.1335 669.4590 670.4255 671.4442 673.9225 676.9805 678.3733 679.5092 682.0251 683.4218 684.3719 685.2919 686.7169 687.3264 697.1274 698.0479 700.1506 703.7377 704.9965 707.8172 708.5850 709.8153 711.1500 712.8489 713.4771 714.4347 726.3566 727.7513 728.9944 733.5585 735.3016 736.4961 737.6189 738.2994 739.2595 740.4065 741.9040 743.1981 744.1530 745.2916 746.5226 748.9809 750.2281 750.9960 752.3406 752.9756 754.3780 755.5276 756.3692 758.2634 759.0110 759.7686 761.7732 762.9434 764.4741 765.3917 766.6286 767.4312 770.1957 771.1882 772.7053 773.5267 774.7447 776.6511 777.8210 778.7165 779.6204 780.7280 782.1320 782.9822 784.2060 785.6016 786.4901 787.9463 790.5060 792.1089 798.3909 800.2761 801.1783 807.3977 808.4180 809.3495 811.3911 815.3892 816.1534 823.2515 828.4472 835.0657 841.3511 845.4922 847.7346 857.4641 858.6213 861.3310 862.4926 863.5303 867.1469 868.1398 869.3214 871.2722 873.0120 876.2525 877.3261 883.4003 884.2711 886.6406 892.3677 893.9593 897.2706 898.3701 899.4016 900.1539 901.5656 902.4991 903.3836 904.6151 913.5021 915.0329 916.4500 917.8973 924.1539 925.5574 932.6861 933.3383 934.5273 935.4116 937.0532 937.8554 938.4962 940.7910 943.3398 948.5141 949.4937 950.4376 951.5229 957.2259 962.9388 963.7307 966.1238 968.4544 969.2480 969.8521 970.5481 971.1883 972.3713 973.9487 975.5293 976.4604 977.3992 978.0324 980.2961 981.3935 982.3759 984.0764 985.4116 987.2023 988.3969 992.0993 996.1435 997.1547 998.5941 999.2305 1000.3836 1001.2307 1002.1909 1003.0289 1004.7115 1009.8257 1010.6499 1011.4964 1012.4798 1013.3533 1014.4931 1015.3984 1016.2422 1018.9663 1020.0115 1021.2588 1022.4805 1023.6997 1026.5995 1027.5355 1028.6578 1030.4266 1031.3927 1032.4086 1033.5220 1036.5186 1037.5435 1038.3613 1040.8837 1043.6375 1047.5848 1049.6929 1053.3673 1056.1361 1057.4950 1058.4175 1059.7382 1061.5444 1062.6033 1069.4982 1070.5929 1074.5464 1075.5112 1076.5323 1094.0470 1094.7539 1095.4060 1096.3177 1097.1804 1098.6792 1106.3046 1111.6324 1112.7260 1113.5006 1114.6757 1115.6527 1116.7783 1120.6261 1127.2771 1128.2255 1130.9427 1142.5581 1149.3495 1150.4750 1156.3373 1158.3846 1159.3934 1166.5638 1167.3893 1168.3226 1179.4652 1181.1132 1182.8070 1184.4824 1185.6229 1186.8967 1188.7745 1198.0908 1202.0013 1202.7391 1203.6868 1204.6486 1207.7235 1208.3269 1209.3125 1210.6682 1222.6799 1224.0740 1224.9460 1225.7700 1226.5751 1232.3053 1233.6705 1240.3016 1242.0094 1242.6102 1243.5892 1244.6050 1245.5419 1255.7289 1257.0131 1258.3273 1263.4673 1265.6155 1270.8903 1271.6210 1272.5895 1274.6886 1277.0499 1278.8348 1281.0328 1283.3326 1298.9988 1300.7955 1312.8987 1313.9017 1315.6721 1316.6818 1317.7777 1327.3593 1328.6724 1334.4410 1350.9503 1354.4154 1355.7457 1356.7155 1357.5637 1358.3634 1359.5591 1360.3795 1370.4689 1371.5935 1372.5089 1373.5098 1374.3971 1382.8084 1384.6149 1385.2179 1385.9840 1387.7052 1388.7964 1398.0221 1398.7335 1399.5337 1400.5376 1401.2437 1403.0814 1405.5397 1406.5472 1414.0992 1414.7181 1415.6832 1416.5590 1417.3118 1439.9700 1440.9714 1441.7449 1444.8362 1446.7238 1452.5648 1455.9109 1457.6229 1458.2463 1458.9991 1464.7961 1467.6711 1468.9851 1469.7860 1471.3777 1472.6039 1473.4760 1474.5516 1475.6071 1476.4310 1481.3157 1484.0294 1484.7820 1485.6501 1486.7737 1487.8479 1488.8738 1494.5118 1495.4846 1496.9874 1498.2531 1499.5580 1500.6381 1501.6008 1502.8416 1503.5187 1510.0199 1510.7570 1511.7748 1512.9452 1513.8280 1514.9672 1516.0631 1516.9602 1518.3619 1519.9796 1526.1310 1527.5311 1528.7311 1529.7216 1530.7430 1531.9368 1540.5118 1541.5272 1542.5696 1543.8453 1544.6794 1545.3503 1545.9773 1546.7645 1547.4601 1548.0663 1549.9073 1559.0773", " 30.7727 2.0161 1.6459 4.3806 1.1425 1.1789 0.8878 2.6694 66.7722 5.0787 2.6722 3.9851 1.1518 1.2032 2.4317 4.6574 1.6702 4.2097 117.4776 12.4575 1.2703 3.0528 27.1081 3.9674 3.6453 2.3061 2.1601 59.6653 11.9821 3.2825 75.5054 8.0337 8.7827 1.9702 1.3510 41.6213 2.1465 6.2814 3.5642 12.8342 4.9883 1.0159 8.8457 50.0453 1.3800 2.6002 5.8939 1.5987 0.9524 305.1002 51.2715 13.4841 484.2204 127.2207 19.2103 1.3571 4.1935 5.1572 257.3338 93.9001 17.8799 9.0634 2.8279 1.2680 2.7964 2.5447 2.0365 158.8841 299.0704 481.5560 115.0965 5.6347 6.5330 9.8330 1.4780 8.6310 6.5452 0.5629 35.5242 9.4683 3.4381 3.4979 3.0431 19.5555 9.6309 5.5580 6.4886 5.0219 4.3135 3.9848 11.5080 0.9534 4.7663 98.4411 20.8500 0.3967 2.5985 19.5768 238.1391 75.5913 5.2974 1.8430 4.0059 4.8391 8.7758 5.8762 5.8455 2.2052 2.9844 21.6526 13.9778 3.7561 2.6716 11.6179 7.8719 4.0101 1.2784 25.2776 1.1432 8.4523 3.6400 3.2014 2.6722 2.8581 3.0325 4.6598 1.9732 9.7426 2.5893 49.3025 26.8525 6.6824 2.0560 4.3248 45.3667 19.9832 1.5250 10.0611 2.7264 3.5644 18.5327 6.7304 2.1628 2.2221 5.9178 1.7232 0.8251 270.8201 295.9683 3.7999 8.2268 4.1318 9.0103 6.8250 3.9068 2.2854 8.9261 1.9069 1.4708 39.8080 44.8511 159.0369 70.2632 11.9191 3.6196 181.3270 26.1012 43.0580 11.7856 8.9266 130.4149 133.3700 61.0688 1.7780 76.7575 51.7504 23.3879 39.1915 31.7174 6.8720 4.4801 96.5574 1000.0000 312.7447 24.9426 6.9890 75.4365 43.6599 953.2108 402.4480 19.2552 5.4729 4.6419 4.7435 3.5571 12.3355 2.4764 12.4966 16.7230 2.0993 1.5892 4.2731 4.1348 1.2068 2.8595 18.4958 2.6202 269.7065 67.5150 31.2379 1.7309 2.6001 1.1432 2.4499 6.6494 2.0343 6.2935 1.6530 3.9444 12.9029 4.0644 2.9379 3.9357 3.5597 60.0388 12.8828 8.2587 2.3077 5.8863 58.8523 39.2800 4.3824 1.4790 2.0320 7.5404 8.8032 2.6946 18.7148 12.3221 6.6297 118.5322 33.3893 1.4592 3.6276 8.6612 8.8691 3.9989 25.9733 0.7611 4.5409 2.1792 11.1640 9.2868 5.3895 1.2807 3.0070 3.0537 10.7582 0.9533 8.0324 14.9159 10.3385 5.3296 3.6935 11.8476 6.1669 5.0133 32.8007 1.6640 3.4646 1.2114 7.0836 22.4836 15.3114 222.6936 130.4593 56.0358 2.1928 93.1751 51.1742 22.4876 2.4862 2.8197 10.0822 2.3525 7.5709 3.0341 6.7221 8.6199 2.8012 5.3345 4.4545 20.9498 7.7847 3.4295 11.7081 7.0559 12.4439 50.6903 13.2968 61.2776 29.6710 3.4264 0.5693 54.4382 25.1104 1.1427 4.3269 9.3992 24.5318 39.7347 473.4945 213.1830 67.0806 8.3608 7.5046 4.5102 2.8610 2.1589 1.2126 1.5994 3.1353 4.7299 1.4756 7.6072 3.3712 3.5634 0.7592 1.0165 5.8512 2.4799 503.8126 292.1578 59.3837 11.2216 21.5553 313.6450 154.7770 60.7759 1.1587 2.4143 27.2744 18.1139 43.7092 42.0509 10.8123 1.5881 3.6201 1.6662 1.3973 2.1608 0.4417 1.1521 5.8088 2.7345 13.5170 4.7015 9.1603 6.5711 9.4365 7.4895 5.1638 3.7094 9.7980 3.5850 1.9021 12.9247 0.6993 21.0758 59.9580 74.1291 12.3582 7.6579 85.4680 50.8627 18.1032 1.7348 7.7953 14.2360 6.4149 5.0288 11.9227 0.8295 7.1470 12.9598 76.9328 65.2442 23.9005 2.3542 4.8173 3.6250 3.2443 11.6651 6.1660 11.6351 8.2687 24.0939 2.5337 0.9496 1.6613 5.7392 3.6960 10.9175 7.2121 7.2563 6.2668 61.5208 76.7468 8.1182 2.2901 2.0347 5.9157 6.3640 24.8738 27.1733 25.1642 12.6795 12.6037 9.9568 4.0782 97.9387 238.7174 126.1478 80.0853 18.7889 3.4394 3.3667 4.1946 1.1294 9.1245 4.7423 22.6290 43.2759 27.8529 12.3748 9.5206 3.0884 2.8751 5.0830 85.2423 221.9227 323.0743 101.9702 47.9052 0.9774 3.6228 5.1394 4.5138 0.8336 2.7239 6.8520 16.2821 1.1911 2.1605 1.6688 2.2945 11.0464 11.9652 23.7036 23.3097 23.9616 28.4958 2.7745 3.5857 1.5495 27.6622 48.3842 93.3411 86.9475 38.9364 13.8767 7.2797 5.9672 2.1445 18.0167 45.0836 137.9359 62.3037 39.9054 9.9711 13.6787 23.5004 73.1363 26.9701 34.7489 1.5825 21.2115 13.4220 4.8053 1.9705 8.0361 205.9319 775.8333 524.7843 204.9251 12.5449 2.0510 2.0342 10.6749 162.8668 214.5419 183.2698 124.4973 114.2632 13.9038 50.7772 1.5754 2.8177", "3", "CID ETD", 515.67, true, 2, 4, 0.9, "3", 0, false }, // 20090326_Yest_LysC_1x6ETDsa_01.03090.03090.4.dta { "243.7879 248.2352 256.2038 260.0671 260.8535 261.9995 275.7320 290.2630 303.2579 324.1052 331.1282 332.3542 340.1091 349.3828 392.1447 402.2183 403.2556 404.0996 405.1668 406.0318 418.1470 418.9594 420.7508 431.1273 432.2661 470.3546 475.0428 485.4223 487.2188 517.3171 518.4039 519.0720 520.1177 521.3829 530.0964 531.0302 532.0327 533.2005 534.2474 536.0812 543.2462 547.2946 548.3525 559.3591 562.9785 566.3115 591.8767 600.1329 602.4547 604.0406 625.2937 626.4370 634.4691 635.4151 645.2241 646.2679 650.5569 654.5934 664.5505 665.5209 666.2430 666.9123 667.6990 668.6552 669.8634 673.0308 675.1030 679.1826 682.6284 687.2708 688.2209 689.3478 700.4522 701.2593 702.0752 715.2581 716.0817 717.2546 723.1075 728.2315 747.5339 748.2724 750.2634 755.8646 762.2759 769.3102 770.0140 772.0799 774.6414 778.6964 779.3589 800.2402 801.3123 802.7204 803.6292 806.2991 809.4399 815.0102 816.4662 817.3740 818.2971 819.5718 823.5381 824.3093 827.9058 829.3743 831.2183 837.5764 842.1263 843.3616 844.1660 844.8753 845.6047 846.7016 848.9698 852.7267 856.3286 859.3588 860.1613 863.6732 864.4836 868.1258 869.7119 871.5098 872.4384 873.0388 873.9880 875.3660 876.2717 877.9868 879.1215 881.7221 882.9334 884.0421 886.0036 887.2063 888.0679 889.4487 890.5137 891.7407 893.3141 896.2202 897.0464 900.6588 902.3458 903.5149 904.9387 905.5971 908.9622 909.7800 910.5516 912.8056 915.3342 918.0927 922.3116 924.2397 926.3204 928.4907 929.4748 931.4737 932.1279 932.9814 935.2791 936.5615 939.3074 941.0369 944.0950 944.9709 950.6240 953.5076 955.1049 957.3259 958.0078 958.6191 959.3874 960.2178 961.4774 968.2621 969.0814 970.3516 971.2019 972.6970 973.8386 974.9577 975.7839 976.6500 977.2662 978.0444 979.8441 980.4866 981.5150 983.2332 983.9152 984.5562 985.8335 987.9278 989.2733 990.5781 991.6534 992.2967 994.0283 995.1682 996.0893 996.7576 997.6959 998.7651 1000.0078 1001.1967 1002.4177 1003.2166 1004.1922 1005.6064 1006.3274 1008.5909 1014.5851 1015.5349 1016.4651 1017.0720 1020.1202 1021.8987 1023.5038 1028.3291 1037.6019 1043.4714 1044.4396 1046.3817 1050.5145 1053.8496 1054.4580 1055.6554 1060.5215 1064.1461 1065.7567 1066.6307 1067.9528 1068.8159 1071.6482 1072.4299 1073.6187 1075.8084 1078.6600 1080.1945 1082.4708 1083.6788 1085.0514 1085.7885 1086.6343 1087.7355 1088.8904 1090.5883 1091.8010 1093.0393 1094.9630 1098.5443 1100.2257 1103.1823 1105.4001 1106.2609 1108.2299 1109.0792 1111.3062 1112.1854 1115.1538 1119.3478 1121.1239 1122.1865 1126.6741 1128.5758 1129.3092 1130.2064 1131.1403 1132.1752 1133.1498 1134.8640 1136.5469 1137.8358 1139.6202 1140.4686 1142.4139 1144.0797 1145.3140 1146.2294 1146.8634 1148.9181 1149.6946 1151.3239 1152.7325 1156.8146 1157.7513 1158.5095 1159.2571 1161.7758 1162.9086 1165.7037 1166.8081 1170.6285 1173.0693 1174.6534 1175.6210 1176.5850 1178.1290 1179.8569 1180.7069 1182.9113 1183.5262 1184.5698 1187.1746 1188.8331 1194.1100 1195.0675 1196.4001 1197.1163 1198.5291 1199.5568 1200.5071 1201.4010 1202.3007 1203.1454 1203.7914 1204.9648 1205.6096 1207.7416 1208.7045 1209.6604 1211.3644 1212.3815 1214.2264 1215.3739 1216.5845 1218.3002 1236.0392 1237.8418 1239.5880 1240.3123 1243.9308 1244.8210 1245.7513 1246.8600 1248.2845 1252.9122 1255.3536 1256.6062 1257.5916 1258.2028 1259.1376 1259.7753 1261.5348 1262.6210 1263.3873 1264.7200 1265.6898 1266.5570 1267.4847 1268.2734 1268.9828 1269.6935 1270.5500 1271.6449 1272.3439 1273.3456 1274.0927 1275.4904 1276.1138 1276.8590 1281.9656 1283.2112 1284.5497 1285.7233 1286.5983 1287.5159 1288.8540 1290.6437 1292.5269 1293.1344 1294.3699 1295.1715 1296.9884 1298.2716 1299.4836 1300.2164 1301.3239 1302.3589 1303.3157 1304.2849 1304.9520 1306.1122 1306.9321 1308.2411 1309.1156 1310.1351 1311.0634 1312.0157 1312.7286 1313.4656 1314.6344 1315.7052 1316.8828 1317.8702 1318.6637 1319.6012 1320.5795 1321.5009 1322.3763 1323.2101 1324.1195 1325.1630 1326.0287 1327.5521 1328.6740 1329.5428 1330.4265 1331.3120 1332.1520 1332.8768 1333.6855 1334.6652 1336.0970 1337.1306 1338.5605 1341.4021 1342.0756 1342.7965 1345.4364 1347.1927 1348.1262 1349.5397 1352.6696 1354.5559 1356.7841 1368.4066 1369.6239 1373.8602 1374.4603 1375.4882 1380.6715 1383.9158 1386.2748 1390.6932 1392.5404 1393.6093 1394.6329 1395.7740 1397.7992 1398.6327 1399.6852 1400.6708 1401.7643 1402.6301 1403.5635 1405.9886 1415.6130 1421.7067 1425.9807 1433.7421 1436.1149 1453.0121 1458.2045 1458.8499 1463.9680 1467.4247 1475.7245 1476.9900 1481.4274 1487.9906 1490.0920 1497.4567 1507.5260 1508.8215 1510.6302 1514.5507 1521.4270 1529.1095 1532.1146 1532.7543 1533.8010 1535.5734 1536.7006 1538.9001 1539.7325 1541.3253 1545.6788 1555.6199 1556.8606 1557.7072 1558.4188 1562.3300 1564.2053 1565.2517 1566.3585 1568.6472 1570.0729 1570.9081 1574.8679 1576.5817 1577.8307 1578.7906 1579.9139 1580.7203 1585.5433 1588.2838 1588.9833 1590.9456 1594.6622 1595.4481 1596.4623 1600.3292 1601.5031 1602.5115 1608.5905 1611.9725 1613.0826 1615.1105 1616.5769 1629.3666 1634.1407 1635.8585 1641.7272 1642.5457 1648.6711 1651.9296 1652.9420 1655.5812 1656.7283 1659.8629 1660.8605 1661.6638 1662.3485 1663.2076 1664.7709 1665.5188 1671.5364 1672.9659 1673.9637 1674.6150 1675.7322 1678.1320 1680.3798 1683.6414 1688.7131 1689.8280 1693.2284 1694.5199 1695.3002 1695.9480 1696.5748 1703.6605 1704.6127 1705.6389 1706.7621 1707.8983 1708.5499 1710.3943 1711.4486 1720.8822 1727.2303 1727.8524 1737.8192 1739.3956 1746.6827 1758.8782 1764.5946 1775.1521 1776.0402 1784.8909 1786.1140 1786.9799 1787.7216 1788.8445 1800.1788 1800.9778 1801.8905 1803.6886 1806.7655 1807.7987 1808.5040 1809.6721 1817.1617 1818.5787 1819.2245 1820.5875 1821.6638 1823.6163 1824.9684 1830.0878 1832.4257 1844.2258 1846.2727 1848.7760 1850.9319 1852.9744 1857.5016 1860.8910 1861.9016 1862.9977 1864.8854 1865.8596 1867.2062 1867.9637 1869.0101 1877.6544 1882.0580 1901.7526 1903.9530 1904.9755 1907.1428 1908.0741 1909.6555 1910.3221 1912.5148 1914.8358 1916.1473 1917.4291 1918.5476 1931.0032 1931.8480 1933.0316 1934.2292 1936.1769 1937.0603 1938.1121 1939.8079 1940.8578 1946.8407 1950.1467 1950.9208 1952.0140 1953.0594 1955.9314 1957.8478 1961.9181 1963.7831 1964.6874 1965.3129 1966.2650 1967.3536 1968.3961 1969.2345 1971.4152 1974.0541 1975.0831 1976.0770 1977.0219 1978.4110 1979.8290 1980.8768 1981.8845 1983.1393 1990.7211 1992.0797 1992.8196 1994.0579 1995.0470 1995.8445 1997.1169 1998.4944 1999.1747 1999.9548", " 2.5076 18.9266 3.2094 49.4415 11.1240 3.1239 4.4428 2.3743 8.4930 1.5319 116.0403 9.2358 5.1740 1.9491 8.2785 250.2189 90.3265 9.7607 10.4975 3.3480 29.8301 6.2930 5.4928 33.4564 3.1056 3.4949 7.2611 11.4222 8.1265 3.9918 11.0943 111.8997 80.7320 12.8881 1.6924 163.0821 59.2097 11.5111 13.1041 11.4829 43.7376 18.5996 24.1879 9.4563 6.9902 5.1199 1.6691 4.4790 8.0981 2.0882 5.3213 19.1654 47.6864 38.9337 8.3869 9.7502 8.0166 6.9817 510.2017 712.8604 490.7755 237.6616 47.8276 21.1665 5.7600 3.7721 8.7153 5.3138 9.1014 39.9138 31.6539 17.3705 268.0664 14.8031 8.1302 4.1933 4.0638 10.3567 1.5317 3.7257 46.7505 42.0271 2.6775 16.5575 3.2252 18.1619 18.9057 18.8581 6.5679 8.4362 4.1945 60.4761 52.8047 9.8821 11.6152 4.3330 7.1869 2.6757 43.8517 21.5576 7.9495 1.9516 5.8711 6.4767 16.3193 10.0589 2.5057 5.7654 6.8518 14.8569 77.5502 58.4654 8.8919 3.6298 88.5366 7.0855 53.4351 1.3915 21.5080 8.2630 4.0534 25.5232 14.2767 1.9576 197.6710 250.7894 78.0244 2.9596 50.7061 170.0106 8.1694 272.8869 253.9160 4.1857 87.1401 1000.0000 526.3197 64.7075 39.7636 17.3089 10.2896 7.5661 5.1657 26.6056 9.5840 10.7909 43.7524 3.4637 50.6477 24.6092 3.4639 29.0624 2.2321 23.3793 7.1294 15.3133 6.0014 4.9342 1.9994 33.9224 38.0253 32.7196 14.3473 10.4929 4.2926 27.0133 17.0891 23.0027 6.4361 8.6253 9.2514 171.9624 47.5352 125.9794 10.9860 1.5289 11.1903 60.2448 34.3771 22.3051 4.1909 10.1036 24.5529 14.4163 20.5782 5.9393 10.2954 9.0187 7.4659 2.3401 18.8896 33.2652 35.2743 10.2916 8.9569 128.8345 195.4695 162.2259 11.3918 7.8248 17.0745 66.5099 148.9855 181.8809 570.1615 436.6480 65.4046 25.1590 6.1581 10.6282 1.6718 16.7032 4.1507 3.4973 318.0643 97.9090 18.1858 12.7225 10.9274 1.3910 5.0489 6.4388 18.6934 45.5914 15.3617 5.3042 13.4612 39.2124 48.8572 4.8387 9.8630 8.3484 205.8090 49.0299 29.8948 6.5187 193.9734 189.5334 72.9852 1.1134 8.7717 32.6508 34.8928 24.1992 61.1739 150.9486 97.6246 13.0581 16.9272 5.7557 5.0259 14.8936 27.8568 13.4189 2.7282 11.4069 29.6101 16.0605 82.8358 13.4283 19.5077 1.8127 8.5283 6.3117 7.5451 9.5664 1.6779 183.3642 98.0382 415.0550 146.1843 7.2957 7.4197 6.4443 92.8868 27.0742 3.0738 29.7548 13.9411 10.3046 19.0847 2.6452 2.3885 12.5378 3.9204 18.8801 10.4848 67.6086 118.3790 23.9461 9.1204 18.1228 8.4828 234.8195 89.1072 5.8637 6.2577 15.8360 8.9748 4.0529 14.9671 20.9793 8.3787 39.5979 68.9838 60.0038 3.7880 27.3046 49.5608 2.2327 11.6102 5.1699 6.6042 38.9037 79.8768 362.8020 135.8894 28.7132 17.5083 3.9135 15.2511 223.2500 182.6142 1.9003 3.6386 17.5666 6.2038 44.5620 10.5063 6.2867 26.5601 18.6813 9.6625 6.6326 64.7087 107.9688 29.7563 16.6371 32.8420 8.0484 29.7604 8.0878 62.2472 34.1126 13.3664 14.8972 303.8790 64.7862 50.1557 28.0513 150.3060 244.6863 75.4416 56.2096 43.2100 84.1846 79.0920 140.3058 249.1291 129.4778 108.6126 11.4286 18.1975 4.0765 37.5395 32.7084 5.1724 61.5775 2.5167 106.5414 48.5900 5.5421 38.9133 4.8854 162.9593 91.7801 21.3603 7.4532 51.1259 87.4694 324.2788 481.0876 242.3429 89.6649 8.6949 22.5628 42.8109 395.4991 906.8211 351.9747 45.2140 42.2932 131.3575 143.6703 279.8663 101.1041 108.7031 64.1748 14.4714 14.8446 59.5402 132.8098 542.4203 605.4359 138.1729 59.9986 7.7087 46.8506 184.1397 169.4386 209.7629 580.2321 303.5908 383.0007 38.1204 5.1781 14.4704 2.6467 10.4877 3.2835 4.7570 6.5749 6.1762 2.6568 11.5992 14.8157 13.4205 20.5046 3.3428 19.7544 6.5771 7.0176 7.4121 6.2113 10.0306 6.3449 2.6622 4.4946 66.9666 101.4519 5.9236 9.2178 8.6639 11.3079 32.9729 149.7118 115.2870 89.5708 1.9438 6.1423 10.6356 11.0249 11.3324 5.1689 12.6315 12.0286 13.7912 12.4758 5.8607 14.9925 10.4446 1.3918 6.5768 10.0995 2.0937 7.2864 2.0943 2.8438 5.2996 16.6985 3.6360 9.9587 2.7950 5.1792 6.5680 9.0599 2.3702 7.8762 2.4463 17.1443 4.7590 19.5622 53.1501 12.3967 5.1623 2.7934 12.9506 8.9373 13.9133 4.1008 5.7210 2.5134 15.5638 171.8266 63.7603 41.9141 40.0678 3.5398 4.3739 10.3743 3.6293 7.4224 7.1716 1.8108 22.0531 2.7937 6.8615 8.5185 10.7562 6.4110 25.5629 19.1717 7.2008 1.5301 6.7089 6.5802 10.8492 7.2661 6.8547 26.7061 12.6254 25.8981 8.6692 20.8036 27.5724 24.8403 22.5842 28.0092 31.8056 12.7479 2.9316 6.0303 4.4677 12.7609 15.2388 4.1883 4.8802 4.4712 4.8785 6.6209 25.0085 17.3346 15.8456 12.2698 13.7656 3.5826 121.5698 90.2465 59.1607 22.9261 3.0484 3.2337 22.3640 7.2639 27.9444 1.2528 1.0145 10.4351 7.6937 4.6031 6.1586 14.8440 4.4704 1.3903 61.6618 36.3846 17.9140 23.4125 9.6047 16.0947 22.8557 10.3551 8.4454 3.0415 3.8349 49.2699 18.4090 43.2297 15.9098 10.8577 13.5819 8.0912 21.4863 8.6807 2.6542 15.9513 11.3206 10.4575 8.6845 2.5100 2.8714 63.3186 32.1922 34.7627 43.9835 25.1937 7.8191 4.0462 7.5328 10.7146 6.7111 4.1300 6.4390 6.8518 17.0808 19.2425 5.7076 6.6691 6.9303 31.3079 31.3799 10.9830 16.0658 11.8404 3.4938 6.9670 21.4177 54.3157 5.1703 5.7322 14.2698 3.2217 11.2535 26.3494 33.8623 23.5860 10.0005 7.4197 4.1937 22.3184 17.1360 12.8346 7.0810 34.6404 14.0404 20.1090 24.0768 11.7454 7.1177 23.8897 68.5088 74.6106 83.0404 36.4579 22.8864 29.4717 8.4930 38.9218 67.0819 72.2918 129.4568 221.4474 207.6776 270.2602 93.7133 1.0129 4.3882", "4", "CID ETD", 665.96, true, 2, 4, 0.9, "2 3 4 6", 0, false }, // 20090326_Yest_LysC_1x6ETDsa_02.02321.02321.2.dta { "943.4871 951.7823 1064.8960 1066.7097 1067.6230 1068.8214 1069.5854 1070.6409 1071.4691 1073.5938 1074.4456 1075.2776 1076.1846 1088.1877 1089.7196 1090.7126 1156.2903 1169.5214 1174.4698 1186.7987 1200.3717 1201.4275 1202.6658 1217.5098 1256.7128 1287.5265 1288.6165 1289.6875 1291.0149 1313.4830 1316.3944 1317.5052 1318.4432 1358.7137 1371.3746 1383.7867 1386.4844 1387.4824 1402.4170 1403.4615 1404.3643 1405.4310 1426.9939 1427.6129 1428.4337 1429.6627 1430.7828 1431.5824 1432.5782 1457.5984 1473.4108 1474.6364 1475.4916 1499.4441 1500.5341 1501.4215 1502.5790 1503.3033 1504.8606 1517.4626 1518.6984 1519.6815 1520.9386 1524.8741 1530.2655 1543.8617 1569.6876 1592.7599 1597.5741 1599.8959 1600.7618 1627.9799 1628.6863 1629.5306 1630.5973 1631.6581 1632.6907 1634.9969 1643.8317 1664.1378 1685.4745 1686.7106 1687.7426 1688.4935 1701.6852 1702.4674 1703.5613 1704.6144 1705.5582 1743.1940 1756.2999 1778.0231 1783.6737 1785.4012 1786.9049 1787.7581 1788.8737 1789.8173 1803.2833 1804.8668 1817.6497 1818.5804 1819.7025 1820.7083 1830.7328 1831.6576 1871.6897 1885.7474 1886.8210 1887.6454 1888.6915 1889.7943 1890.6288 1892.1139 1906.2728 1912.0148 1956.3971 1958.4529 1959.4286 1974.0027 1986.7545 1999.7296", " 0.5446 1.8406 12.4060 1000.0000 380.4662 8.4849 3.0875 6.6752 5.4134 1.9659 1.0996 1.3749 2.7091 2.3103 1.1925 0.8041 1.2601 0.6269 0.9139 0.3304 7.1713 8.2900 2.3422 3.2041 0.3247 7.2178 7.8656 3.9263 1.4840 0.7850 3.8859 0.6056 1.1658 0.8953 1.6970 0.7994 0.7038 0.2345 11.9077 17.7421 6.6932 3.8471 0.4160 0.7663 6.1038 22.5824 5.8907 6.3597 1.2397 1.1754 0.6179 2.7984 0.5540 12.9965 24.0521 7.2658 6.2846 0.7290 2.5242 9.1656 11.7215 4.6917 0.5513 1.3358 0.4055 0.4577 1.9369 0.4230 1.0108 3.9809 1.6382 2.3505 13.1796 15.7449 11.9472 11.9523 3.0888 0.5268 0.1617 0.4460 8.2503 11.0468 5.8862 0.8511 1.7488 20.8060 17.6306 6.7047 1.5912 0.6065 3.5587 3.5022 0.2711 1.0538 27.4272 19.9590 9.9348 2.1255 1.5608 0.7332 24.3087 22.5312 14.8691 5.0499 0.6407 1.4617 0.6787 15.8553 14.5014 6.4299 5.6243 5.2153 1.6044 0.4411 1.4996 0.1980 1.3020 0.4044 1.2132 3.6717 0.5728 0.7156", "2", "CID ETD", 1066.72, true, 2, 4, 0.9, "2 3 4 6", 0, false }, // MakeMS2 behavior { "126.9657 129.2652 135.9172 141.9427 143.1286 147.1841 149.0127 150.2528 158.0455 163.0535 167.0655 177.1013 192.9888 203.2619 204.075 206.9989 208.9082 209.8115 211.9883 221.0683 225.0675 226.106 227.2834 228.0121 234.9963 237.0106 243.0448 247.1461 249.2151 253.3426 256.2594 257.1935 259.2448 261.0975 263.2516 268.0759 269.1938 270.3783 271.2178 277.2914 280.9584 283.1599 285.0426 288.2384 289.4238 291.1711 293.0654 294.0734 295.0374 297.267 299.9413 301.1416 301.9647 303.0014 304.1252 305.7378 308.8322 309.4466 311.3066 313.0665 313.9782 315.1105 317.1343 318.1869 318.9812 319.9492 321.1036 322.9846 324.2249 325.0501 326.029 327.1547 331.18 333.1406 334.1884 337.0988 341.0733 342.0545 343.0352 344.0117 345.1031 346.165 347.1043 349.1555 350.0966 353.1221 357.0199 357.921 359.0819 360.0584 361.1577 362.3141 363.2353 364.0934 365.3022 366.2242 367.0972 368.0494 369.3801 370.5183 371.2664 372.2919 373.0294 373.9725 375.0907 376.1542 377.2523 379.4164 382.4076 383.3729 385.1636 386.0052 387.1495 389.0345 390.0276 390.9678 391.8777 393.0433 393.9705 400.3051 401.1996 402.1906 402.9228 409.0102 410.9843 412.0966 413.1009 415.1218 417.7721 418.8526 420.6482 427.3444 428.114 429.0626 429.9189 446.916 474.9332 500.6554 529.2106 554.9348 607.3796", "11.65686 5.973924 6.336542 9.801903 16.33596 43.81474 351.6202 17.81902 13.21312 43.67112 43.36504 31.75116 9.61234 29.10818 5.006023 45.31382 1384.851 49.05672 22.97882 48.93507 168.9132 44.21313 11.85654 11.1582 18.42228 14.85892 22.64454 14.755 30.44192 6.76189 6.028577 15.03836 39.42986 9.79327 13.60227 6.030219 17.97449 119.7174 136.11 9.588016 48.16204 6.028051 26.51938 50.67508 5.54958 31.8689 56.91853 18.76982 86.78511 47.78939 21.39392 44.05758 43.10071 12.93362 15.29362 22.67178 9.169868 22.70414 36.61877 36.40493 38.88861 62.4144 18.80965 73.55255 8358.035 616.7208 59.05638 41.89165 18.19917 70.24268 11.38647 158.0707 318.9193 38.72861 9.516384 32.10003 17329.54 1931.043 1095.633 146.2284 60.64346 8.186502 95.90353 213.953 48.77734 68.7878 65.71793 25.57602 47967.95 5397.058 248.9106 130.2801 257.1089 159.5846 89.56769 122.899 215.5294 149.6132 187.0416 115.1558 154.1615 19.63517 111.0804 45.56202 52.11806 74.48772 33.20785 22.3274 52.99072 65.79727 281.6389 28.11442 58.28289 73.20836 76.31909 141.2777 9.116022 395.3716 99.41208 56.91262 69.17138 64.92921 7.586085 75.60397 907.0748 208.3159 189.4094 4.653344 22.02694 21.07499 79.46523 21.16875 9.565468 127.7872 46.66726 49.75043 14.75244 30.76107 17.54733 12.85513 22.61628", "1", "CID", 429.03, false, 2, 4, 0.2, "1", 0, true }, { "126.9657 129.2652 135.9172 141.9427 143.1286 147.1841 149.0127 150.2528 158.0455 163.0535 167.0655 177.1013 192.9888 203.2619 204.075 206.9989 208.9082 209.8115 211.9883 221.0683 225.0675 226.106 227.2834 228.0121 234.9963 237.0106 243.0448 247.1461 249.2151 253.3426 256.2594 257.1935 259.2448 261.0975 263.2516 268.0759 269.1938 270.3783 271.2178 277.2914 280.9584 283.1599 285.0426 288.2384 289.4238 291.1711 293.0654 294.0734 295.0374 297.267 299.9413 301.1416 301.9647 303.0014 304.1252 305.7378 308.8322 309.4466 311.3066 313.0665 313.9782 315.1105 317.1343 318.1869 318.9812 319.9492 321.1036 322.9846 324.2249 325.0501 326.029 327.1547 331.18 333.1406 334.1884 337.0988 341.0733 342.0545 343.0352 344.0117 345.1031 346.165 347.1043 349.1555 350.0966 353.1221 357.0199 357.921 359.0819 360.0584 361.1577 362.3141 363.2353 364.0934 365.3022 366.2242 367.0972 368.0494 369.3801 370.5183 371.2664 372.2919 373.0294 373.9725 375.0907 376.1542 377.2523 379.4164 382.4076 383.3729 385.1636 386.0052 387.1495 389.0345 390.0276 390.9678 391.8777 393.0433 393.9705 400.3051 401.1996 402.1906 402.9228 409.0102 410.9843 412.0966 413.1009 415.1218 417.7721 418.8526 420.6482 427.3444 428.114 429.0626 429.9189 446.916 474.9332 500.6554 529.2106 554.9348 607.3796", "11.65686 5.973924 6.336542 9.801903 16.33596 43.81474 351.6202 17.81902 13.21312 43.67112 43.36504 31.75116 9.61234 29.10818 5.006023 45.31382 1384.851 49.05672 22.97882 48.93507 168.9132 44.21313 11.85654 11.1582 18.42228 14.85892 22.64454 14.755 30.44192 6.76189 6.028577 15.03836 39.42986 9.79327 13.60227 6.030219 17.97449 119.7174 136.11 9.588016 48.16204 6.028051 26.51938 50.67508 5.54958 31.8689 56.91853 18.76982 86.78511 47.78939 21.39392 44.05758 43.10071 12.93362 15.29362 22.67178 9.169868 22.70414 36.61877 36.40493 38.88861 62.4144 18.80965 73.55255 8358.035 616.7208 59.05638 41.89165 18.19917 70.24268 11.38647 158.0707 318.9193 38.72861 9.516384 32.10003 17329.54 1931.043 1095.633 146.2284 60.64346 8.186502 95.90353 213.953 48.77734 68.7878 65.71793 25.57602 47967.95 5397.058 248.9106 130.2801 257.1089 159.5846 89.56769 122.899 215.5294 149.6132 187.0416 115.1558 154.1615 19.63517 111.0804 45.56202 52.11806 74.48772 33.20785 22.3274 52.99072 65.79727 281.6389 28.11442 58.28289 73.20836 76.31909 141.2777 9.116022 395.3716 99.41208 56.91262 69.17138 64.92921 7.586085 75.60397 907.0748 208.3159 189.4094 4.653344 22.02694 21.07499 79.46523 21.16875 9.565468 127.7872 46.66726 49.75043 14.75244 30.76107 17.54733 12.85513 22.61628", "2 3", "CID", 429.03, false, 2, 4, 0.2, "1 2 3", 0, true }, { "126.9657 129.2652 135.9172 141.9427 143.1286 147.1841 149.0127 150.2528 158.0455 163.0535 167.0655 177.1013 192.9888 203.2619 204.075 206.9989 208.9082 209.8115 211.9883 221.0683 225.0675 226.106 227.2834 228.0121 234.9963 237.0106 243.0448 247.1461 249.2151 253.3426 256.2594 257.1935 259.2448 261.0975 263.2516 268.0759 269.1938 270.3783 271.2178 277.2914 280.9584 283.1599 285.0426 288.2384 289.4238 291.1711 293.0654 294.0734 295.0374 297.267 299.9413 301.1416 301.9647 303.0014 304.1252 305.7378 308.8322 309.4466 311.3066 313.0665 313.9782 315.1105 317.1343 318.1869 318.9812 319.9492 321.1036 322.9846 324.2249 325.0501 326.029 327.1547 331.18 333.1406 334.1884 337.0988 341.0733 342.0545 343.0352 344.0117 345.1031 346.165 347.1043 349.1555 350.0966 353.1221 357.0199 357.921 359.0819 360.0584 361.1577 362.3141 363.2353 364.0934 365.3022 366.2242 367.0972 368.0494 369.3801 370.5183 371.2664 372.2919 373.0294 373.9725 375.0907 376.1542 377.2523 379.4164 382.4076 383.3729 385.1636 386.0052 387.1495 389.0345 390.0276 390.9678 391.8777 393.0433 393.9705 400.3051 401.1996 402.1906 402.9228 409.0102 410.9843 412.0966 413.1009 415.1218 417.7721 418.8526 420.6482 427.3444 428.114 429.0626 429.9189 446.916 474.9332 500.6554 529.2106 554.9348 607.3796", "11.65686 5.973924 6.336542 9.801903 16.33596 43.81474 351.6202 17.81902 13.21312 43.67112 43.36504 31.75116 9.61234 29.10818 5.006023 45.31382 1384.851 49.05672 22.97882 48.93507 168.9132 44.21313 11.85654 11.1582 18.42228 14.85892 22.64454 14.755 30.44192 6.76189 6.028577 15.03836 39.42986 9.79327 13.60227 6.030219 17.97449 119.7174 136.11 9.588016 48.16204 6.028051 26.51938 50.67508 5.54958 31.8689 56.91853 18.76982 86.78511 47.78939 21.39392 44.05758 43.10071 12.93362 15.29362 22.67178 9.169868 22.70414 36.61877 36.40493 38.88861 62.4144 18.80965 73.55255 8358.035 616.7208 59.05638 41.89165 18.19917 70.24268 11.38647 158.0707 318.9193 38.72861 9.516384 32.10003 17329.54 1931.043 1095.633 146.2284 60.64346 8.186502 95.90353 213.953 48.77734 68.7878 65.71793 25.57602 47967.95 5397.058 248.9106 130.2801 257.1089 159.5846 89.56769 122.899 215.5294 149.6132 187.0416 115.1558 154.1615 19.63517 111.0804 45.56202 52.11806 74.48772 33.20785 22.3274 52.99072 65.79727 281.6389 28.11442 58.28289 73.20836 76.31909 141.2777 9.116022 395.3716 99.41208 56.91262 69.17138 64.92921 7.586085 75.60397 907.0748 208.3159 189.4094 4.653344 22.02694 21.07499 79.46523 21.16875 9.565468 127.7872 46.66726 49.75043 14.75244 30.76107 17.54733 12.85513 22.61628", "2 3", "ETD", 429.03, false, 2, 4, 0.2, "1 2 3", 0, true }, { "126.9657 129.2652 135.9172 141.9427 143.1286 147.1841 149.0127 150.2528 158.0455 163.0535 167.0655 177.1013 192.9888 203.2619 204.075 206.9989 208.9082 209.8115 211.9883 221.0683 225.0675 226.106 227.2834 228.0121 234.9963 237.0106 243.0448 247.1461 249.2151 253.3426 256.2594 257.1935 259.2448 261.0975 263.2516 268.0759 269.1938 270.3783 271.2178 277.2914 280.9584 283.1599 285.0426 288.2384 289.4238 291.1711 293.0654 294.0734 295.0374 297.267 299.9413 301.1416 301.9647 303.0014 304.1252 305.7378 308.8322 309.4466 311.3066 313.0665 313.9782 315.1105 317.1343 318.1869 318.9812 319.9492 321.1036 322.9846 324.2249 325.0501 326.029 327.1547 331.18 333.1406 334.1884 337.0988 341.0733 342.0545 343.0352 344.0117 345.1031 346.165 347.1043 349.1555 350.0966 353.1221 357.0199 357.921 359.0819 360.0584 361.1577 362.3141 363.2353 364.0934 365.3022 366.2242 367.0972 368.0494 369.3801 370.5183 371.2664 372.2919 373.0294 373.9725 375.0907 376.1542 377.2523 379.4164 382.4076 383.3729 385.1636 386.0052 387.1495 389.0345 390.0276 390.9678 391.8777 393.0433 393.9705 400.3051 401.1996 402.1906 402.9228 409.0102 410.9843 412.0966 413.1009 415.1218 417.7721 418.8526 420.6482 427.3444 428.114 429.0626 429.9189 446.916 474.9332 500.6554 529.2106 554.9348 607.3796", "11.65686 5.973924 6.336542 9.801903 16.33596 43.81474 351.6202 17.81902 13.21312 43.67112 43.36504 31.75116 9.61234 29.10818 5.006023 45.31382 1384.851 49.05672 22.97882 48.93507 168.9132 44.21313 11.85654 11.1582 18.42228 14.85892 22.64454 14.755 30.44192 6.76189 6.028577 15.03836 39.42986 9.79327 13.60227 6.030219 17.97449 119.7174 136.11 9.588016 48.16204 6.028051 26.51938 50.67508 5.54958 31.8689 56.91853 18.76982 86.78511 47.78939 21.39392 44.05758 43.10071 12.93362 15.29362 22.67178 9.169868 22.70414 36.61877 36.40493 38.88861 62.4144 18.80965 73.55255 8358.035 616.7208 59.05638 41.89165 18.19917 70.24268 11.38647 158.0707 318.9193 38.72861 9.516384 32.10003 17329.54 1931.043 1095.633 146.2284 60.64346 8.186502 95.90353 213.953 48.77734 68.7878 65.71793 25.57602 47967.95 5397.058 248.9106 130.2801 257.1089 159.5846 89.56769 122.899 215.5294 149.6132 187.0416 115.1558 154.1615 19.63517 111.0804 45.56202 52.11806 74.48772 33.20785 22.3274 52.99072 65.79727 281.6389 28.11442 58.28289 73.20836 76.31909 141.2777 9.116022 395.3716 99.41208 56.91262 69.17138 64.92921 7.586085 75.60397 907.0748 208.3159 189.4094 4.653344 22.02694 21.07499 79.46523 21.16875 9.565468 127.7872 46.66726 49.75043 14.75244 30.76107 17.54733 12.85513 22.61628", "2 3", "CID", 429.03, false, 2, 2, 0.2, "1 2 3", 0, true }, { "126.9657 129.2652 135.9172 141.9427 143.1286 147.1841 149.0127 150.2528 158.0455 163.0535 167.0655 177.1013 192.9888 203.2619 204.075 206.9989 208.9082 209.8115 211.9883 221.0683 225.0675 226.106 227.2834 228.0121 234.9963 237.0106 243.0448 247.1461 249.2151 253.3426 256.2594 257.1935 259.2448 261.0975 263.2516 268.0759 269.1938 270.3783 271.2178 277.2914 280.9584 283.1599 285.0426 288.2384 289.4238 291.1711 293.0654 294.0734 295.0374 297.267 299.9413 301.1416 301.9647 303.0014 304.1252 305.7378 308.8322 309.4466 311.3066 313.0665 313.9782 315.1105 317.1343 318.1869 318.9812 319.9492 321.1036 322.9846 324.2249 325.0501 326.029 327.1547 331.18 333.1406 334.1884 337.0988 341.0733 342.0545 343.0352 344.0117 345.1031 346.165 347.1043 349.1555 350.0966 353.1221 357.0199 357.921 359.0819 360.0584 361.1577 362.3141 363.2353 364.0934 365.3022 366.2242 367.0972 368.0494 369.3801 370.5183 371.2664 372.2919 373.0294 373.9725 375.0907 376.1542 377.2523 379.4164 382.4076 383.3729 385.1636 386.0052 387.1495 389.0345 390.0276 390.9678 391.8777 393.0433 393.9705 400.3051 401.1996 402.1906 402.9228 409.0102 410.9843 412.0966 413.1009 415.1218 417.7721 418.8526 420.6482 427.3444 428.114 429.0626 429.9189 446.916 474.9332 500.6554 529.2106 554.9348 607.3796", "11.65686 5.973924 6.336542 9.801903 16.33596 43.81474 351.6202 17.81902 13.21312 43.67112 43.36504 31.75116 9.61234 29.10818 5.006023 45.31382 1384.851 49.05672 22.97882 48.93507 168.9132 44.21313 11.85654 11.1582 18.42228 14.85892 22.64454 14.755 30.44192 6.76189 6.028577 15.03836 39.42986 9.79327 13.60227 6.030219 17.97449 119.7174 136.11 9.588016 48.16204 6.028051 26.51938 50.67508 5.54958 31.8689 56.91853 18.76982 86.78511 47.78939 21.39392 44.05758 43.10071 12.93362 15.29362 22.67178 9.169868 22.70414 36.61877 36.40493 38.88861 62.4144 18.80965 73.55255 8358.035 616.7208 59.05638 41.89165 18.19917 70.24268 11.38647 158.0707 318.9193 38.72861 9.516384 32.10003 17329.54 1931.043 1095.633 146.2284 60.64346 8.186502 95.90353 213.953 48.77734 68.7878 65.71793 25.57602 47967.95 5397.058 248.9106 130.2801 257.1089 159.5846 89.56769 122.899 215.5294 149.6132 187.0416 115.1558 154.1615 19.63517 111.0804 45.56202 52.11806 74.48772 33.20785 22.3274 52.99072 65.79727 281.6389 28.11442 58.28289 73.20836 76.31909 141.2777 9.116022 395.3716 99.41208 56.91262 69.17138 64.92921 7.586085 75.60397 907.0748 208.3159 189.4094 4.653344 22.02694 21.07499 79.46523 21.16875 9.565468 127.7872 46.66726 49.75043 14.75244 30.76107 17.54733 12.85513 22.61628", "2 3", "CID", 429.03, false, 2, 4, 0.00001, "2 3 4", 0, true }, { "126.9657 129.2652 135.9172 141.9427 143.1286 147.1841 149.0127 150.2528 158.0455 163.0535 167.0655 177.1013 192.9888 203.2619 204.075 206.9989 208.9082 209.8115 211.9883 221.0683 225.0675 226.106 227.2834 228.0121 234.9963 237.0106 243.0448 247.1461 249.2151 253.3426 256.2594 257.1935 259.2448 261.0975 263.2516 268.0759 269.1938 270.3783 271.2178 277.2914 280.9584 283.1599 285.0426 288.2384 289.4238 291.1711 293.0654 294.0734 295.0374 297.267 299.9413 301.1416 301.9647 303.0014 304.1252 305.7378 308.8322 309.4466 311.3066 313.0665 313.9782 315.1105 317.1343 318.1869 318.9812 319.9492 321.1036 322.9846 324.2249 325.0501 326.029 327.1547 331.18 333.1406 334.1884 337.0988 341.0733 342.0545 343.0352 344.0117 345.1031 346.165 347.1043 349.1555 350.0966 353.1221 357.0199 357.921 359.0819 360.0584 361.1577 362.3141 363.2353 364.0934 365.3022 366.2242 367.0972 368.0494 369.3801 370.5183 371.2664 372.2919 373.0294 373.9725 375.0907 376.1542 377.2523 379.4164 382.4076 383.3729 385.1636 386.0052 387.1495 389.0345 390.0276 390.9678 391.8777 393.0433 393.9705 400.3051 401.1996 402.1906 402.9228 409.0102 410.9843 412.0966 413.1009 415.1218 417.7721 418.8526 420.6482 427.3444 428.114 429.0626 429.9189 446.916 474.9332 500.6554 529.2106 554.9348 607.3796", "11.65686 5.973924 6.336542 9.801903 16.33596 43.81474 351.6202 17.81902 13.21312 43.67112 43.36504 31.75116 9.61234 29.10818 5.006023 45.31382 1384.851 49.05672 22.97882 48.93507 168.9132 44.21313 11.85654 11.1582 18.42228 14.85892 22.64454 14.755 30.44192 6.76189 6.028577 15.03836 39.42986 9.79327 13.60227 6.030219 17.97449 119.7174 136.11 9.588016 48.16204 6.028051 26.51938 50.67508 5.54958 31.8689 56.91853 18.76982 86.78511 47.78939 21.39392 44.05758 43.10071 12.93362 15.29362 22.67178 9.169868 22.70414 36.61877 36.40493 38.88861 62.4144 18.80965 73.55255 8358.035 616.7208 59.05638 41.89165 18.19917 70.24268 11.38647 158.0707 318.9193 38.72861 9.516384 32.10003 17329.54 1931.043 1095.633 146.2284 60.64346 8.186502 95.90353 213.953 48.77734 68.7878 65.71793 25.57602 47967.95 5397.058 248.9106 130.2801 257.1089 159.5846 89.56769 122.899 215.5294 149.6132 187.0416 115.1558 154.1615 19.63517 111.0804 45.56202 52.11806 74.48772 33.20785 22.3274 52.99072 65.79727 281.6389 28.11442 58.28289 73.20836 76.31909 141.2777 9.116022 395.3716 99.41208 56.91262 69.17138 64.92921 7.586085 75.60397 907.0748 208.3159 189.4094 4.653344 22.02694 21.07499 79.46523 21.16875 9.565468 127.7872 46.66726 49.75043 14.75244 30.76107 17.54733 12.85513 22.61628", "2 3 4", "CID", 429.03, false, 2, 3, 0.00001, "2 3 4", 0, true }, { "126.9657 129.2652 135.9172 141.9427 143.1286 147.1841 149.0127 150.2528 158.0455 163.0535 167.0655 177.1013 192.9888 203.2619 204.075 206.9989 208.9082 209.8115 211.9883 221.0683 225.0675 226.106 227.2834 228.0121 234.9963 237.0106 243.0448 247.1461 249.2151 253.3426 256.2594 257.1935 259.2448 261.0975 263.2516 268.0759 269.1938 270.3783 271.2178 277.2914 280.9584 283.1599 285.0426 288.2384 289.4238 291.1711 293.0654 294.0734 295.0374 297.267 299.9413 301.1416 301.9647 303.0014 304.1252 305.7378 308.8322 309.4466 311.3066 313.0665 313.9782 315.1105 317.1343 318.1869 318.9812 319.9492 321.1036 322.9846 324.2249 325.0501 326.029 327.1547 331.18 333.1406 334.1884 337.0988 341.0733 342.0545 343.0352 344.0117 345.1031 346.165 347.1043 349.1555 350.0966 353.1221 357.0199 357.921 359.0819 360.0584 361.1577 362.3141 363.2353 364.0934 365.3022 366.2242 367.0972 368.0494 369.3801 370.5183 371.2664 372.2919 373.0294 373.9725 375.0907 376.1542 377.2523 379.4164 382.4076 383.3729 385.1636 386.0052 387.1495 389.0345 390.0276 390.9678 391.8777 393.0433 393.9705 400.3051 401.1996 402.1906 402.9228 409.0102 410.9843 412.0966 413.1009 415.1218 417.7721 418.8526 420.6482 427.3444 428.114 429.0626 429.9189 446.916 474.9332 500.6554 529.2106 554.9348 607.3796", "11.65686 5.973924 6.336542 9.801903 16.33596 43.81474 351.6202 17.81902 13.21312 43.67112 43.36504 31.75116 9.61234 29.10818 5.006023 45.31382 1384.851 49.05672 22.97882 48.93507 168.9132 44.21313 11.85654 11.1582 18.42228 14.85892 22.64454 14.755 30.44192 6.76189 6.028577 15.03836 39.42986 9.79327 13.60227 6.030219 17.97449 119.7174 136.11 9.588016 48.16204 6.028051 26.51938 50.67508 5.54958 31.8689 56.91853 18.76982 86.78511 47.78939 21.39392 44.05758 43.10071 12.93362 15.29362 22.67178 9.169868 22.70414 36.61877 36.40493 38.88861 62.4144 18.80965 73.55255 8358.035 616.7208 59.05638 41.89165 18.19917 70.24268 11.38647 158.0707 318.9193 38.72861 9.516384 32.10003 17329.54 1931.043 1095.633 146.2284 60.64346 8.186502 95.90353 213.953 48.77734 68.7878 65.71793 25.57602 47967.95 5397.058 248.9106 130.2801 257.1089 159.5846 89.56769 122.899 215.5294 149.6132 187.0416 115.1558 154.1615 19.63517 111.0804 45.56202 52.11806 74.48772 33.20785 22.3274 52.99072 65.79727 281.6389 28.11442 58.28289 73.20836 76.31909 141.2777 9.116022 395.3716 99.41208 56.91262 69.17138 64.92921 7.586085 75.60397 907.0748 208.3159 189.4094 4.653344 22.02694 21.07499 79.46523 21.16875 9.565468 127.7872 46.66726 49.75043 14.75244 30.76107 17.54733 12.85513 22.61628", "2 3", "CID", 429.03, false, 2, 2, 0.00001, "2 3", 0, true }, { "126.9657 129.2652 135.9172 141.9427 143.1286 147.1841 149.0127 150.2528 158.0455 163.0535 167.0655 177.1013 192.9888 203.2619 204.075 206.9989 208.9082 209.8115 211.9883 221.0683 225.0675 226.106 227.2834 228.0121 234.9963 237.0106 243.0448 247.1461 249.2151 253.3426 256.2594 257.1935 259.2448 261.0975 263.2516 268.0759 269.1938 270.3783 271.2178 277.2914 280.9584 283.1599 285.0426 288.2384 289.4238 291.1711 293.0654 294.0734 295.0374 297.267 299.9413 301.1416 301.9647 303.0014 304.1252 305.7378 308.8322 309.4466 311.3066 313.0665 313.9782 315.1105 317.1343 318.1869 318.9812 319.9492 321.1036 322.9846 324.2249 325.0501 326.029 327.1547 331.18 333.1406 334.1884 337.0988 341.0733 342.0545 343.0352 344.0117 345.1031 346.165 347.1043 349.1555 350.0966 353.1221 357.0199 357.921 359.0819 360.0584 361.1577 362.3141 363.2353 364.0934 365.3022 366.2242 367.0972 368.0494 369.3801 370.5183 371.2664 372.2919 373.0294 373.9725 375.0907 376.1542 377.2523 379.4164 382.4076 383.3729 385.1636 386.0052 387.1495 389.0345 390.0276 390.9678 391.8777 393.0433 393.9705 400.3051 401.1996 402.1906 402.9228 409.0102 410.9843 412.0966 413.1009 415.1218 417.7721 418.8526 420.6482 427.3444 428.114 429.0626 429.9189 446.916 474.9332 500.6554 529.2106 554.9348 607.3796", "11.65686 5.973924 6.336542 9.801903 16.33596 43.81474 351.6202 17.81902 13.21312 43.67112 43.36504 31.75116 9.61234 29.10818 5.006023 45.31382 1384.851 49.05672 22.97882 48.93507 168.9132 44.21313 11.85654 11.1582 18.42228 14.85892 22.64454 14.755 30.44192 6.76189 6.028577 15.03836 39.42986 9.79327 13.60227 6.030219 17.97449 119.7174 136.11 9.588016 48.16204 6.028051 26.51938 50.67508 5.54958 31.8689 56.91853 18.76982 86.78511 47.78939 21.39392 44.05758 43.10071 12.93362 15.29362 22.67178 9.169868 22.70414 36.61877 36.40493 38.88861 62.4144 18.80965 73.55255 8358.035 616.7208 59.05638 41.89165 18.19917 70.24268 11.38647 158.0707 318.9193 38.72861 9.516384 32.10003 17329.54 1931.043 1095.633 146.2284 60.64346 8.186502 95.90353 213.953 48.77734 68.7878 65.71793 25.57602 47967.95 5397.058 248.9106 130.2801 257.1089 159.5846 89.56769 122.899 215.5294 149.6132 187.0416 115.1558 154.1615 19.63517 111.0804 45.56202 52.11806 74.48772 33.20785 22.3274 52.99072 65.79727 281.6389 28.11442 58.28289 73.20836 76.31909 141.2777 9.116022 395.3716 99.41208 56.91262 69.17138 64.92921 7.586085 75.60397 907.0748 208.3159 189.4094 4.653344 22.02694 21.07499 79.46523 21.16875 9.565468 127.7872 46.66726 49.75043 14.75244 30.76107 17.54733 12.85513 22.61628", "1", "CID", 429.03, false, 2, 4, 0.00001, "1", 0, true }, { "126.9657 129.2652 135.9172 141.9427 143.1286 147.1841 149.0127 150.2528 158.0455 163.0535 167.0655 177.1013 192.9888 203.2619 204.075 206.9989 208.9082 209.8115 211.9883 221.0683 225.0675 226.106 227.2834 228.0121 234.9963 237.0106 243.0448 247.1461 249.2151 253.3426 256.2594 257.1935 259.2448 261.0975 263.2516 268.0759 269.1938 270.3783 271.2178 277.2914 280.9584 283.1599 285.0426 288.2384 289.4238 291.1711 293.0654 294.0734 295.0374 297.267 299.9413 301.1416 301.9647 303.0014 304.1252 305.7378 308.8322 309.4466 311.3066 313.0665 313.9782 315.1105 317.1343 318.1869 318.9812 319.9492 321.1036 322.9846 324.2249 325.0501 326.029 327.1547 331.18 333.1406 334.1884 337.0988 341.0733 342.0545 343.0352 344.0117 345.1031 346.165 347.1043 349.1555 350.0966 353.1221 357.0199 357.921 359.0819 360.0584 361.1577 362.3141 363.2353 364.0934 365.3022 366.2242 367.0972 368.0494 369.3801 370.5183 371.2664 372.2919 373.0294 373.9725 375.0907 376.1542 377.2523 379.4164 382.4076 383.3729 385.1636 386.0052 387.1495 389.0345 390.0276 390.9678 391.8777 393.0433 393.9705 400.3051 401.1996 402.1906 402.9228 409.0102 410.9843 412.0966 413.1009 415.1218 417.7721 418.8526 420.6482 427.3444 428.114 429.0626 429.9189 446.916 474.9332 500.6554 529.2106 554.9348 607.3796", "11.65686 5.973924 6.336542 9.801903 16.33596 43.81474 351.6202 17.81902 13.21312 43.67112 43.36504 31.75116 9.61234 29.10818 5.006023 45.31382 1384.851 49.05672 22.97882 48.93507 168.9132 44.21313 11.85654 11.1582 18.42228 14.85892 22.64454 14.755 30.44192 6.76189 6.028577 15.03836 39.42986 9.79327 13.60227 6.030219 17.97449 119.7174 136.11 9.588016 48.16204 6.028051 26.51938 50.67508 5.54958 31.8689 56.91853 18.76982 86.78511 47.78939 21.39392 44.05758 43.10071 12.93362 15.29362 22.67178 9.169868 22.70414 36.61877 36.40493 38.88861 62.4144 18.80965 73.55255 8358.035 616.7208 59.05638 41.89165 18.19917 70.24268 11.38647 158.0707 318.9193 38.72861 9.516384 32.10003 17329.54 1931.043 1095.633 146.2284 60.64346 8.186502 95.90353 213.953 48.77734 68.7878 65.71793 25.57602 47967.95 5397.058 248.9106 130.2801 257.1089 159.5846 89.56769 122.899 215.5294 149.6132 187.0416 115.1558 154.1615 19.63517 111.0804 45.56202 52.11806 74.48772 33.20785 22.3274 52.99072 65.79727 281.6389 28.11442 58.28289 73.20836 76.31909 141.2777 9.116022 395.3716 99.41208 56.91262 69.17138 64.92921 7.586085 75.60397 907.0748 208.3159 189.4094 4.653344 22.02694 21.07499 79.46523 21.16875 9.565468 127.7872 46.66726 49.75043 14.75244 30.76107 17.54733 12.85513 22.61628", "1", "ETD", 429.03, false, 2, 4, 0.00001, "1", 0, true }, { "126.9657 129.2652 135.9172 141.9427 143.1286 147.1841 149.0127 150.2528 158.0455 163.0535 167.0655 177.1013 192.9888 203.2619 204.075 206.9989 208.9082 209.8115 211.9883 221.0683 225.0675 226.106 227.2834 228.0121 234.9963 237.0106 243.0448 247.1461 249.2151 253.3426 256.2594 257.1935 259.2448 261.0975 263.2516 268.0759 269.1938 270.3783 271.2178 277.2914 280.9584 283.1599 285.0426 288.2384 289.4238 291.1711 293.0654 294.0734 295.0374 297.267 299.9413 301.1416 301.9647 303.0014 304.1252 305.7378 308.8322 309.4466 311.3066 313.0665 313.9782 315.1105 317.1343 318.1869 318.9812 319.9492 321.1036 322.9846 324.2249 325.0501 326.029 327.1547 331.18 333.1406 334.1884 337.0988 341.0733 342.0545 343.0352 344.0117 345.1031 346.165 347.1043 349.1555 350.0966 353.1221 357.0199 357.921 359.0819 360.0584 361.1577 362.3141 363.2353 364.0934 365.3022 366.2242 367.0972 368.0494 369.3801 370.5183 371.2664 372.2919 373.0294 373.9725 375.0907 376.1542 377.2523 379.4164 382.4076 383.3729 385.1636 386.0052 387.1495 389.0345 390.0276 390.9678 391.8777 393.0433 393.9705 400.3051 401.1996 402.1906 402.9228 409.0102 410.9843 412.0966 413.1009 415.1218 417.7721 418.8526 420.6482 427.3444 428.114 429.0626 429.9189 446.916 474.9332 500.6554 529.2106 554.9348 607.3796", "11.65686 5.973924 6.336542 9.801903 16.33596 43.81474 351.6202 17.81902 13.21312 43.67112 43.36504 31.75116 9.61234 29.10818 5.006023 45.31382 1384.851 49.05672 22.97882 48.93507 168.9132 44.21313 11.85654 11.1582 18.42228 14.85892 22.64454 14.755 30.44192 6.76189 6.028577 15.03836 39.42986 9.79327 13.60227 6.030219 17.97449 119.7174 136.11 9.588016 48.16204 6.028051 26.51938 50.67508 5.54958 31.8689 56.91853 18.76982 86.78511 47.78939 21.39392 44.05758 43.10071 12.93362 15.29362 22.67178 9.169868 22.70414 36.61877 36.40493 38.88861 62.4144 18.80965 73.55255 8358.035 616.7208 59.05638 41.89165 18.19917 70.24268 11.38647 158.0707 318.9193 38.72861 9.516384 32.10003 17329.54 1931.043 1095.633 146.2284 60.64346 8.186502 95.90353 213.953 48.77734 68.7878 65.71793 25.57602 47967.95 5397.058 248.9106 130.2801 257.1089 159.5846 89.56769 122.899 215.5294 149.6132 187.0416 115.1558 154.1615 19.63517 111.0804 45.56202 52.11806 74.48772 33.20785 22.3274 52.99072 65.79727 281.6389 28.11442 58.28289 73.20836 76.31909 141.2777 9.116022 395.3716 99.41208 56.91262 69.17138 64.92921 7.586085 75.60397 907.0748 208.3159 189.4094 4.653344 22.02694 21.07499 79.46523 21.16875 9.565468 127.7872 46.66726 49.75043 14.75244 30.76107 17.54733 12.85513 22.61628", "", "CID", 429.03, false, 2, 3, 0.2, "1", 0, true }, { "126.9657 129.2652 135.9172 141.9427 143.1286 147.1841 149.0127 150.2528 158.0455 163.0535 167.0655 177.1013 192.9888 203.2619 204.075 206.9989 208.9082 209.8115 211.9883 221.0683 225.0675 226.106 227.2834 228.0121 234.9963 237.0106 243.0448 247.1461 249.2151 253.3426 256.2594 257.1935 259.2448 261.0975 263.2516 268.0759 269.1938 270.3783 271.2178 277.2914 280.9584 283.1599 285.0426 288.2384 289.4238 291.1711 293.0654 294.0734 295.0374 297.267 299.9413 301.1416 301.9647 303.0014 304.1252 305.7378 308.8322 309.4466 311.3066 313.0665 313.9782 315.1105 317.1343 318.1869 318.9812 319.9492 321.1036 322.9846 324.2249 325.0501 326.029 327.1547 331.18 333.1406 334.1884 337.0988 341.0733 342.0545 343.0352 344.0117 345.1031 346.165 347.1043 349.1555 350.0966 353.1221 357.0199 357.921 359.0819 360.0584 361.1577 362.3141 363.2353 364.0934 365.3022 366.2242 367.0972 368.0494 369.3801 370.5183 371.2664 372.2919 373.0294 373.9725 375.0907 376.1542 377.2523 379.4164 382.4076 383.3729 385.1636 386.0052 387.1495 389.0345 390.0276 390.9678 391.8777 393.0433 393.9705 400.3051 401.1996 402.1906 402.9228 409.0102 410.9843 412.0966 413.1009 415.1218 417.7721 418.8526 420.6482 427.3444 428.114 429.0626 429.9189 446.916 474.9332 500.6554 529.2106 554.9348 607.3796", "11.65686 5.973924 6.336542 9.801903 16.33596 43.81474 351.6202 17.81902 13.21312 43.67112 43.36504 31.75116 9.61234 29.10818 5.006023 45.31382 1384.851 49.05672 22.97882 48.93507 168.9132 44.21313 11.85654 11.1582 18.42228 14.85892 22.64454 14.755 30.44192 6.76189 6.028577 15.03836 39.42986 9.79327 13.60227 6.030219 17.97449 119.7174 136.11 9.588016 48.16204 6.028051 26.51938 50.67508 5.54958 31.8689 56.91853 18.76982 86.78511 47.78939 21.39392 44.05758 43.10071 12.93362 15.29362 22.67178 9.169868 22.70414 36.61877 36.40493 38.88861 62.4144 18.80965 73.55255 8358.035 616.7208 59.05638 41.89165 18.19917 70.24268 11.38647 158.0707 318.9193 38.72861 9.516384 32.10003 17329.54 1931.043 1095.633 146.2284 60.64346 8.186502 95.90353 213.953 48.77734 68.7878 65.71793 25.57602 47967.95 5397.058 248.9106 130.2801 257.1089 159.5846 89.56769 122.899 215.5294 149.6132 187.0416 115.1558 154.1615 19.63517 111.0804 45.56202 52.11806 74.48772 33.20785 22.3274 52.99072 65.79727 281.6389 28.11442 58.28289 73.20836 76.31909 141.2777 9.116022 395.3716 99.41208 56.91262 69.17138 64.92921 7.586085 75.60397 907.0748 208.3159 189.4094 4.653344 22.02694 21.07499 79.46523 21.16875 9.565468 127.7872 46.66726 49.75043 14.75244 30.76107 17.54733 12.85513 22.61628", "", "ETD", 429.03, true, 2, 3, 0.2, "1", 0, true }, { "126.9657 129.2652 135.9172 141.9427 143.1286 147.1841 149.0127 150.2528 158.0455 163.0535 167.0655 177.1013 192.9888 203.2619 204.075 206.9989 208.9082 209.8115 211.9883 221.0683 225.0675 226.106 227.2834 228.0121 234.9963 237.0106 243.0448 247.1461 249.2151 253.3426 256.2594 257.1935 259.2448 261.0975 263.2516 268.0759 269.1938 270.3783 271.2178 277.2914 280.9584 283.1599 285.0426 288.2384 289.4238 291.1711 293.0654 294.0734 295.0374 297.267 299.9413 301.1416 301.9647 303.0014 304.1252 305.7378 308.8322 309.4466 311.3066 313.0665 313.9782 315.1105 317.1343 318.1869 318.9812 319.9492 321.1036 322.9846 324.2249 325.0501 326.029 327.1547 331.18 333.1406 334.1884 337.0988 341.0733 342.0545 343.0352 344.0117 345.1031 346.165 347.1043 349.1555 350.0966 353.1221 357.0199 357.921 359.0819 360.0584 361.1577 362.3141 363.2353 364.0934 365.3022 366.2242 367.0972 368.0494 369.3801 370.5183 371.2664 372.2919 373.0294 373.9725 375.0907 376.1542 377.2523 379.4164 382.4076 383.3729 385.1636 386.0052 387.1495 389.0345 390.0276 390.9678 391.8777 393.0433 393.9705 400.3051 401.1996 402.1906 402.9228 409.0102 410.9843 412.0966 413.1009 415.1218 417.7721 418.8526 420.6482 427.3444 428.114 429.0626 429.9189 446.916 474.9332 500.6554 529.2106 554.9348 607.3796", "11.65686 5.973924 6.336542 9.801903 16.33596 43.81474 351.6202 17.81902 13.21312 43.67112 43.36504 31.75116 9.61234 29.10818 5.006023 45.31382 1384.851 49.05672 22.97882 48.93507 168.9132 44.21313 11.85654 11.1582 18.42228 14.85892 22.64454 14.755 30.44192 6.76189 6.028577 15.03836 39.42986 9.79327 13.60227 6.030219 17.97449 119.7174 136.11 9.588016 48.16204 6.028051 26.51938 50.67508 5.54958 31.8689 56.91853 18.76982 86.78511 47.78939 21.39392 44.05758 43.10071 12.93362 15.29362 22.67178 9.169868 22.70414 36.61877 36.40493 38.88861 62.4144 18.80965 73.55255 8358.035 616.7208 59.05638 41.89165 18.19917 70.24268 11.38647 158.0707 318.9193 38.72861 9.516384 32.10003 17329.54 1931.043 1095.633 146.2284 60.64346 8.186502 95.90353 213.953 48.77734 68.7878 65.71793 25.57602 47967.95 5397.058 248.9106 130.2801 257.1089 159.5846 89.56769 122.899 215.5294 149.6132 187.0416 115.1558 154.1615 19.63517 111.0804 45.56202 52.11806 74.48772 33.20785 22.3274 52.99072 65.79727 281.6389 28.11442 58.28289 73.20836 76.31909 141.2777 9.116022 395.3716 99.41208 56.91262 69.17138 64.92921 7.586085 75.60397 907.0748 208.3159 189.4094 4.653344 22.02694 21.07499 79.46523 21.16875 9.565468 127.7872 46.66726 49.75043 14.75244 30.76107 17.54733 12.85513 22.61628", "2 3", "CID", 429.03, true, 2, 4, 0.2, "1", 0, true }, { "126.9657 129.2652 135.9172 141.9427 143.1286 147.1841 149.0127 150.2528 158.0455 163.0535 167.0655 177.1013 192.9888 203.2619 204.075 206.9989 208.9082 209.8115 211.9883 221.0683 225.0675 226.106 227.2834 228.0121 234.9963 237.0106 243.0448 247.1461 249.2151 253.3426 256.2594 257.1935 259.2448 261.0975 263.2516 268.0759 269.1938 270.3783 271.2178 277.2914 280.9584 283.1599 285.0426 288.2384 289.4238 291.1711 293.0654 294.0734 295.0374 297.267 299.9413 301.1416 301.9647 303.0014 304.1252 305.7378 308.8322 309.4466 311.3066 313.0665 313.9782 315.1105 317.1343 318.1869 318.9812 319.9492 321.1036 322.9846 324.2249 325.0501 326.029 327.1547 331.18 333.1406 334.1884 337.0988 341.0733 342.0545 343.0352 344.0117 345.1031 346.165 347.1043 349.1555 350.0966 353.1221 357.0199 357.921 359.0819 360.0584 361.1577 362.3141 363.2353 364.0934 365.3022 366.2242 367.0972 368.0494 369.3801 370.5183 371.2664 372.2919 373.0294 373.9725 375.0907 376.1542 377.2523 379.4164 382.4076 383.3729 385.1636 386.0052 387.1495 389.0345 390.0276 390.9678 391.8777 393.0433 393.9705 400.3051 401.1996 402.1906 402.9228 409.0102 410.9843 412.0966 413.1009 415.1218 417.7721 418.8526 420.6482 427.3444 428.114 429.0626 429.9189 446.916 474.9332 500.6554 529.2106 554.9348 607.3796", "11.65686 5.973924 6.336542 9.801903 16.33596 43.81474 351.6202 17.81902 13.21312 43.67112 43.36504 31.75116 9.61234 29.10818 5.006023 45.31382 1384.851 49.05672 22.97882 48.93507 168.9132 44.21313 11.85654 11.1582 18.42228 14.85892 22.64454 14.755 30.44192 6.76189 6.028577 15.03836 39.42986 9.79327 13.60227 6.030219 17.97449 119.7174 136.11 9.588016 48.16204 6.028051 26.51938 50.67508 5.54958 31.8689 56.91853 18.76982 86.78511 47.78939 21.39392 44.05758 43.10071 12.93362 15.29362 22.67178 9.169868 22.70414 36.61877 36.40493 38.88861 62.4144 18.80965 73.55255 8358.035 616.7208 59.05638 41.89165 18.19917 70.24268 11.38647 158.0707 318.9193 38.72861 9.516384 32.10003 17329.54 1931.043 1095.633 146.2284 60.64346 8.186502 95.90353 213.953 48.77734 68.7878 65.71793 25.57602 47967.95 5397.058 248.9106 130.2801 257.1089 159.5846 89.56769 122.899 215.5294 149.6132 187.0416 115.1558 154.1615 19.63517 111.0804 45.56202 52.11806 74.48772 33.20785 22.3274 52.99072 65.79727 281.6389 28.11442 58.28289 73.20836 76.31909 141.2777 9.116022 395.3716 99.41208 56.91262 69.17138 64.92921 7.586085 75.60397 907.0748 208.3159 189.4094 4.653344 22.02694 21.07499 79.46523 21.16875 9.565468 127.7872 46.66726 49.75043 14.75244 30.76107 17.54733 12.85513 22.61628", "", "CID", 429.03, false, 2, 4, 0.2, "1", 0, true }, { "126.9657 129.2652 135.9172 141.9427 143.1286 147.1841 149.0127 150.2528 158.0455 163.0535 167.0655 177.1013 192.9888 203.2619 204.075 206.9989 208.9082 209.8115 211.9883 221.0683 225.0675 226.106 227.2834 228.0121 234.9963 237.0106 243.0448 247.1461 249.2151 253.3426 256.2594 257.1935 259.2448 261.0975 263.2516 268.0759 269.1938 270.3783 271.2178 277.2914 280.9584 283.1599 285.0426 288.2384 289.4238 291.1711 293.0654 294.0734 295.0374 297.267 299.9413 301.1416 301.9647 303.0014 304.1252 305.7378 308.8322 309.4466 311.3066 313.0665 313.9782 315.1105 317.1343 318.1869 318.9812 319.9492 321.1036 322.9846 324.2249 325.0501 326.029 327.1547 331.18 333.1406 334.1884 337.0988 341.0733 342.0545 343.0352 344.0117 345.1031 346.165 347.1043 349.1555 350.0966 353.1221 357.0199 357.921 359.0819 360.0584 361.1577 362.3141 363.2353 364.0934 365.3022 366.2242 367.0972 368.0494 369.3801 370.5183 371.2664 372.2919 373.0294 373.9725 375.0907 376.1542 377.2523 379.4164 382.4076 383.3729 385.1636 386.0052 387.1495 389.0345 390.0276 390.9678 391.8777 393.0433 393.9705 400.3051 401.1996 402.1906 402.9228 409.0102 410.9843 412.0966 413.1009 415.1218 417.7721 418.8526 420.6482 427.3444 428.114 429.0626 429.9189 446.916 474.9332 500.6554 529.2106 554.9348 607.3796", "11.65686 5.973924 6.336542 9.801903 16.33596 43.81474 351.6202 17.81902 13.21312 43.67112 43.36504 31.75116 9.61234 29.10818 5.006023 45.31382 1384.851 49.05672 22.97882 48.93507 168.9132 44.21313 11.85654 11.1582 18.42228 14.85892 22.64454 14.755 30.44192 6.76189 6.028577 15.03836 39.42986 9.79327 13.60227 6.030219 17.97449 119.7174 136.11 9.588016 48.16204 6.028051 26.51938 50.67508 5.54958 31.8689 56.91853 18.76982 86.78511 47.78939 21.39392 44.05758 43.10071 12.93362 15.29362 22.67178 9.169868 22.70414 36.61877 36.40493 38.88861 62.4144 18.80965 73.55255 8358.035 616.7208 59.05638 41.89165 18.19917 70.24268 11.38647 158.0707 318.9193 38.72861 9.516384 32.10003 17329.54 1931.043 1095.633 146.2284 60.64346 8.186502 95.90353 213.953 48.77734 68.7878 65.71793 25.57602 47967.95 5397.058 248.9106 130.2801 257.1089 159.5846 89.56769 122.899 215.5294 149.6132 187.0416 115.1558 154.1615 19.63517 111.0804 45.56202 52.11806 74.48772 33.20785 22.3274 52.99072 65.79727 281.6389 28.11442 58.28289 73.20836 76.31909 141.2777 9.116022 395.3716 99.41208 56.91262 69.17138 64.92921 7.586085 75.60397 907.0748 208.3159 189.4094 4.653344 22.02694 21.07499 79.46523 21.16875 9.565468 127.7872 46.66726 49.75043 14.75244 30.76107 17.54733 12.85513 22.61628", "", "CID", 429.03, false, 2, 4, 0.00001, "2 3 4", 0, true }, { "126.9657 129.2652 135.9172 141.9427 143.1286 147.1841 149.0127 150.2528 158.0455 163.0535 167.0655 177.1013 192.9888 203.2619 204.075 206.9989 208.9082 209.8115 211.9883 221.0683 225.0675 226.106 227.2834 228.0121 234.9963 237.0106 243.0448 247.1461 249.2151 253.3426 256.2594 257.1935 259.2448 261.0975 263.2516 268.0759 269.1938 270.3783 271.2178 277.2914 280.9584 283.1599 285.0426 288.2384 289.4238 291.1711 293.0654 294.0734 295.0374 297.267 299.9413 301.1416 301.9647 303.0014 304.1252 305.7378 308.8322 309.4466 311.3066 313.0665 313.9782 315.1105 317.1343 318.1869 318.9812 319.9492 321.1036 322.9846 324.2249 325.0501 326.029 327.1547 331.18 333.1406 334.1884 337.0988 341.0733 342.0545 343.0352 344.0117 345.1031 346.165 347.1043 349.1555 350.0966 353.1221 357.0199 357.921 359.0819 360.0584 361.1577 362.3141 363.2353 364.0934 365.3022 366.2242 367.0972 368.0494 369.3801 370.5183 371.2664 372.2919 373.0294 373.9725 375.0907 376.1542 377.2523 379.4164 382.4076 383.3729 385.1636 386.0052 387.1495 389.0345 390.0276 390.9678 391.8777 393.0433 393.9705 400.3051 401.1996 402.1906 402.9228 409.0102 410.9843 412.0966 413.1009 415.1218 417.7721 418.8526 420.6482 427.3444 428.114 429.0626 429.9189 446.916 474.9332 500.6554 529.2106 554.9348 607.3796", "11.65686 5.973924 6.336542 9.801903 16.33596 43.81474 351.6202 17.81902 13.21312 43.67112 43.36504 31.75116 9.61234 29.10818 5.006023 45.31382 1384.851 49.05672 22.97882 48.93507 168.9132 44.21313 11.85654 11.1582 18.42228 14.85892 22.64454 14.755 30.44192 6.76189 6.028577 15.03836 39.42986 9.79327 13.60227 6.030219 17.97449 119.7174 136.11 9.588016 48.16204 6.028051 26.51938 50.67508 5.54958 31.8689 56.91853 18.76982 86.78511 47.78939 21.39392 44.05758 43.10071 12.93362 15.29362 22.67178 9.169868 22.70414 36.61877 36.40493 38.88861 62.4144 18.80965 73.55255 8358.035 616.7208 59.05638 41.89165 18.19917 70.24268 11.38647 158.0707 318.9193 38.72861 9.516384 32.10003 17329.54 1931.043 1095.633 146.2284 60.64346 8.186502 95.90353 213.953 48.77734 68.7878 65.71793 25.57602 47967.95 5397.058 248.9106 130.2801 257.1089 159.5846 89.56769 122.899 215.5294 149.6132 187.0416 115.1558 154.1615 19.63517 111.0804 45.56202 52.11806 74.48772 33.20785 22.3274 52.99072 65.79727 281.6389 28.11442 58.28289 73.20836 76.31909 141.2777 9.116022 395.3716 99.41208 56.91262 69.17138 64.92921 7.586085 75.60397 907.0748 208.3159 189.4094 4.653344 22.02694 21.07499 79.46523 21.16875 9.565468 127.7872 46.66726 49.75043 14.75244 30.76107 17.54733 12.85513 22.61628", "", "CID", 429.03, true, 2, 3, 0.00001, "2 3", 0, true }, { "126.9657 129.2652 135.9172 141.9427 143.1286 147.1841 149.0127 150.2528 158.0455 163.0535 167.0655 177.1013 192.9888 203.2619 204.075 206.9989 208.9082 209.8115 211.9883 221.0683 225.0675 226.106 227.2834 228.0121 234.9963 237.0106 243.0448 247.1461 249.2151 253.3426 256.2594 257.1935 259.2448 261.0975 263.2516 268.0759 269.1938 270.3783 271.2178 277.2914 280.9584 283.1599 285.0426 288.2384 289.4238 291.1711 293.0654 294.0734 295.0374 297.267 299.9413 301.1416 301.9647 303.0014 304.1252 305.7378 308.8322 309.4466 311.3066 313.0665 313.9782 315.1105 317.1343 318.1869 318.9812 319.9492 321.1036 322.9846 324.2249 325.0501 326.029 327.1547 331.18 333.1406 334.1884 337.0988 341.0733 342.0545 343.0352 344.0117 345.1031 346.165 347.1043 349.1555 350.0966 353.1221 357.0199 357.921 359.0819 360.0584 361.1577 362.3141 363.2353 364.0934 365.3022 366.2242 367.0972 368.0494 369.3801 370.5183 371.2664 372.2919 373.0294 373.9725 375.0907 376.1542 377.2523 379.4164 382.4076 383.3729 385.1636 386.0052 387.1495 389.0345 390.0276 390.9678 391.8777 393.0433 393.9705 400.3051 401.1996 402.1906 402.9228 409.0102 410.9843 412.0966 413.1009 415.1218 417.7721 418.8526 420.6482 427.3444 428.114 429.0626 429.9189 446.916 474.9332 500.6554 529.2106 554.9348 607.3796", "11.65686 5.973924 6.336542 9.801903 16.33596 43.81474 351.6202 17.81902 13.21312 43.67112 43.36504 31.75116 9.61234 29.10818 5.006023 45.31382 1384.851 49.05672 22.97882 48.93507 168.9132 44.21313 11.85654 11.1582 18.42228 14.85892 22.64454 14.755 30.44192 6.76189 6.028577 15.03836 39.42986 9.79327 13.60227 6.030219 17.97449 119.7174 136.11 9.588016 48.16204 6.028051 26.51938 50.67508 5.54958 31.8689 56.91853 18.76982 86.78511 47.78939 21.39392 44.05758 43.10071 12.93362 15.29362 22.67178 9.169868 22.70414 36.61877 36.40493 38.88861 62.4144 18.80965 73.55255 8358.035 616.7208 59.05638 41.89165 18.19917 70.24268 11.38647 158.0707 318.9193 38.72861 9.516384 32.10003 17329.54 1931.043 1095.633 146.2284 60.64346 8.186502 95.90353 213.953 48.77734 68.7878 65.71793 25.57602 47967.95 5397.058 248.9106 130.2801 257.1089 159.5846 89.56769 122.899 215.5294 149.6132 187.0416 115.1558 154.1615 19.63517 111.0804 45.56202 52.11806 74.48772 33.20785 22.3274 52.99072 65.79727 281.6389 28.11442 58.28289 73.20836 76.31909 141.2777 9.116022 395.3716 99.41208 56.91262 69.17138 64.92921 7.586085 75.60397 907.0748 208.3159 189.4094 4.653344 22.02694 21.07499 79.46523 21.16875 9.565468 127.7872 46.66726 49.75043 14.75244 30.76107 17.54733 12.85513 22.61628", "", "ETD", 429.03, true, 2, 3, 0.00001, "2 3", 0, true }, { "126.9657 129.2652 135.9172 141.9427 143.1286 147.1841 149.0127 150.2528 158.0455 163.0535 167.0655 177.1013 192.9888 203.2619 204.075 206.9989 208.9082 209.8115 211.9883 221.0683 225.0675 226.106 227.2834 228.0121 234.9963 237.0106 243.0448 247.1461 249.2151 253.3426 256.2594 257.1935 259.2448 261.0975 263.2516 268.0759 269.1938 270.3783 271.2178 277.2914 280.9584 283.1599 285.0426 288.2384 289.4238 291.1711 293.0654 294.0734 295.0374 297.267 299.9413 301.1416 301.9647 303.0014 304.1252 305.7378 308.8322 309.4466 311.3066 313.0665 313.9782 315.1105 317.1343 318.1869 318.9812 319.9492 321.1036 322.9846 324.2249 325.0501 326.029 327.1547 331.18 333.1406 334.1884 337.0988 341.0733 342.0545 343.0352 344.0117 345.1031 346.165 347.1043 349.1555 350.0966 353.1221 357.0199 357.921 359.0819 360.0584 361.1577 362.3141 363.2353 364.0934 365.3022 366.2242 367.0972 368.0494 369.3801 370.5183 371.2664 372.2919 373.0294 373.9725 375.0907 376.1542 377.2523 379.4164 382.4076 383.3729 385.1636 386.0052 387.1495 389.0345 390.0276 390.9678 391.8777 393.0433 393.9705 400.3051 401.1996 402.1906 402.9228 409.0102 410.9843 412.0966 413.1009 415.1218 417.7721 418.8526 420.6482 427.3444 428.114 429.0626 429.9189 446.916 474.9332 500.6554 529.2106 554.9348 607.3796", "11.65686 5.973924 6.336542 9.801903 16.33596 43.81474 351.6202 17.81902 13.21312 43.67112 43.36504 31.75116 9.61234 29.10818 5.006023 45.31382 1384.851 49.05672 22.97882 48.93507 168.9132 44.21313 11.85654 11.1582 18.42228 14.85892 22.64454 14.755 30.44192 6.76189 6.028577 15.03836 39.42986 9.79327 13.60227 6.030219 17.97449 119.7174 136.11 9.588016 48.16204 6.028051 26.51938 50.67508 5.54958 31.8689 56.91853 18.76982 86.78511 47.78939 21.39392 44.05758 43.10071 12.93362 15.29362 22.67178 9.169868 22.70414 36.61877 36.40493 38.88861 62.4144 18.80965 73.55255 8358.035 616.7208 59.05638 41.89165 18.19917 70.24268 11.38647 158.0707 318.9193 38.72861 9.516384 32.10003 17329.54 1931.043 1095.633 146.2284 60.64346 8.186502 95.90353 213.953 48.77734 68.7878 65.71793 25.57602 47967.95 5397.058 248.9106 130.2801 257.1089 159.5846 89.56769 122.899 215.5294 149.6132 187.0416 115.1558 154.1615 19.63517 111.0804 45.56202 52.11806 74.48772 33.20785 22.3274 52.99072 65.79727 281.6389 28.11442 58.28289 73.20836 76.31909 141.2777 9.116022 395.3716 99.41208 56.91262 69.17138 64.92921 7.586085 75.60397 907.0748 208.3159 189.4094 4.653344 22.02694 21.07499 79.46523 21.16875 9.565468 127.7872 46.66726 49.75043 14.75244 30.76107 17.54733 12.85513 22.61628", "1", "CID", 429.03, true, 2, 4, 0.00001, "2 3 4", 0, true }, { "1218.258 1244.477 1354.132 1391.253", "29.83101 15.71422 9.135175 6.936273", "", "CID", 1390.47, false, 2, 3, 0.2, "1", 0, true }, { "1218.258 1244.477 1354.132 1391.253", "29.83101 15.71422 9.135175 6.936273", "", "CID", 1390.47, false, 2, 3, 0.00001, "1", 0, true }, }; const size_t testChargeStateCalculatorsSize = sizeof(testChargeStateCalculators) / sizeof(TestChargeStateCalculator); vector parseDoubleArray(const string& doubleArray) { vector doubleVector; vector tokens; bal::split(tokens, doubleArray, bal::is_space(), bal::token_compress_on); if (!tokens.empty()) for (size_t i=0; i < tokens.size(); ++i) if (!tokens[i].empty()) doubleVector.push_back(lexical_cast(tokens[i])); return doubleVector; } vector parseCVTermArray(const string& cvTermArray) { static pwiz::data::CVTranslator cvTranslator; vector cvTermVector; vector tokens; bal::split(tokens, cvTermArray, bal::is_space()); if (!tokens.empty() && !tokens[0].empty()) for (size_t i=0; i < tokens.size(); ++i) cvTermVector.push_back(cvTranslator.translate(tokens[i])); return cvTermVector; } int test() { int failedTests = 0; for (size_t i=0; i < testChargeStateCalculatorsSize; ++i) { SpectrumListSimple* sl = new SpectrumListSimple; SpectrumListPtr originalList(sl); SpectrumPtr s(new Spectrum); s->set(MS_MSn_spectrum); s->set(MS_ms_level, 2); sl->spectra.push_back(s); try { TestChargeStateCalculator& t = testChargeStateCalculators[i]; vector inputMZArray = parseDoubleArray(t.inputMZArray); vector inputIntensityArray = parseDoubleArray(t.inputIntensityArray); s->setMZIntensityArrays(inputMZArray, inputIntensityArray, MS_number_of_detector_counts); s->precursors.push_back(Precursor(t.inputPrecursorMZ)); vector inputChargeStateArray = parseDoubleArray(t.inputChargeStateArray); CVID inputChargeStateTerm = inputChargeStateArray.size() > 1 ? MS_possible_charge_state : MS_charge_state; BOOST_FOREACH(int z, inputChargeStateArray) s->precursors[0].selectedIons[0].cvParams.push_back(CVParam(inputChargeStateTerm, z)); vector inputActivationTypes = parseCVTermArray(t.inputActivationTypeArray); BOOST_FOREACH(CVID cvid, inputActivationTypes) s->precursors[0].activation.set(cvid); SpectrumListPtr calculator(new SpectrumList_ChargeStateCalculator( originalList, t.overrideExistingChargeState, t.maxMultipleCharge, t.minMultipleCharge, t.singlyChargedFraction, t.maxKnownCharge, t.useMakeMS2Behavior)); vector outputChargeStateArray = parseDoubleArray(t.chargeStateArray); CVID outputChargeStateTerm = outputChargeStateArray.size() > 1 ? MS_possible_charge_state : MS_charge_state; SpectrumPtr calculatedSpectrum = calculator->spectrum(0, true); BOOST_FOREACH(const CVParam& cvParam, calculatedSpectrum->precursors[0].selectedIons[0].cvParams) { if (cvParam.cvid != MS_charge_state && cvParam.cvid != MS_possible_charge_state) continue; unit_assert_operator_equal(outputChargeStateTerm, cvParam.cvid); unit_assert(find(outputChargeStateArray.begin(), outputChargeStateArray.end(), cvParam.valueAs()) != outputChargeStateArray.end()); } } catch (exception& e) { cerr << "Test case " << (i+1) << " failed:\n" << e.what() << endl; ++failedTests; } } return failedTests; } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; int failedTests = test(); unit_assert_operator_equal(0, failedTests); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/spectrum_processing/SpectrumList_PeakFilter.cpp0000664000175100017510000000476612664775614027754 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_PeakFilter.cpp 6902 2014-11-17 22:34:37Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "pwiz/data/msdata/MSData.hpp" #include "SpectrumList_PeakFilter.hpp" namespace pwiz { namespace analysis { using namespace msdata; PWIZ_API_DECL SpectrumList_PeakFilter::SpectrumList_PeakFilter(const SpectrumListPtr& inner, SpectrumDataFilterPtr filterFunctor) : SpectrumListWrapper(inner), filterFunctor_(filterFunctor) { // add processing methods to the copy of the inner SpectrumList's data processing ProcessingMethod method; method.order = dp_->processingMethods.size(); filterFunctor_->describe(method); if (!dp_->processingMethods.empty()) method.softwarePtr = dp_->processingMethods[0].softwarePtr; dp_->processingMethods.push_back(method); } PWIZ_API_DECL SpectrumPtr SpectrumList_PeakFilter::spectrum(size_t index, bool getBinaryData) const { return spectrum(index, getBinaryData ? DetailLevel_FullData : DetailLevel_FullMetadata); } PWIZ_API_DECL SpectrumPtr SpectrumList_PeakFilter::spectrum(size_t index, DetailLevel detailLevel) const { // the effects of running the peak filter on the defaultArrayLength is unknown; 0 denotes that to other filters; // for full metadata detail, the defaultArrayLength must be known, so go ahead and get binary data anyway if (detailLevel < DetailLevel_FullMetadata) { SpectrumPtr innerSpectrum = inner_->spectrum(index, detailLevel); innerSpectrum->defaultArrayLength = 0; return innerSpectrum; } const SpectrumPtr currentSpectrum = inner_->spectrum(index, true); (*filterFunctor_)(currentSpectrum); currentSpectrum->dataProcessingPtr = dp_; return currentSpectrum; } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/SpectrumList_ScanSummerTest.cpp0000664000175100017510000001416712664775615030640 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_ScanSummerTest.cpp 6389 2014-06-13 19:46:19Z frenchwr $ // // // Original author: William French vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "SpectrumList_ScanSummer.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/data/msdata/examples.hpp" #include "pwiz/data/msdata/TextWriter.hpp" #include "pwiz/data/common/CVTranslator.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::msdata; using namespace pwiz::analysis; ostream* os_ = 0; ostream& operator<< (ostream& os, const vector& v) { os << "("; for (size_t i=0; i < v.size(); ++i) os << " " << v[i]; os << " )"; return os; } struct TestScanSummerCalculator { // space-delimited doubles const char* inputMZArray; const char* inputIntensityArray; double inputPrecursorMZ; double rTime; }; TestScanSummerCalculator testScanSummerCalculators[] = { { "112 120 121 123 124 128 129", "7 0 1 4 2 1 7", 120.0, 20.0}, { "119 120 121 122 123 124 127 128 129", "4 5 6 7 8 9 10 11 12", 120.01, 20.1}, { "200 200.01 200.02 200.09 200.20", "1.0 3.0 1.0 0.0 3.0", 401.23, 21.01}, { "120 126 127", "7 7 7", 119.96, 21.05}, { "200.01 200.02 200.03 200.08 200.09", "1.0 3.0 1.0 1.0 4.0", 401.19, 21.1}, }; TestScanSummerCalculator goldStandard[] = { { "112 119 120 121 122 123 124 126 127 128 129", "7 4 12 7 7 12 11 7 17 12 19", 120.0, 20.0}, { "200 200.01 200.02 200.03 200.08 200.09 200.20", "1.0 4.0 4.0 1.0 1.0 4.0 3.0", 401.23, 21.01}, }; const size_t testScanSummerSize = sizeof(testScanSummerCalculators) / sizeof(TestScanSummerCalculator); const size_t goldStandardSize = sizeof(goldStandard) / sizeof(TestScanSummerCalculator); vector parseDoubleArray(const string& doubleArray) { vector doubleVector; vector tokens; bal::split(tokens, doubleArray, bal::is_space(), bal::token_compress_on); if (!tokens.empty()) for (size_t i=0; i < tokens.size(); ++i) if (!tokens[i].empty()) doubleVector.push_back(lexical_cast(tokens[i])); return doubleVector; } int test() { int failedTests = 0; // create the spectrum list SpectrumListSimple* sl = new SpectrumListSimple; SpectrumListPtr originalList(sl); for (size_t i=0; i < testScanSummerSize; ++i) { TestScanSummerCalculator& t = testScanSummerCalculators[i]; SpectrumPtr s(new Spectrum); s->set(MS_MSn_spectrum); s->set(MS_ms_level,2); s->index = i; s->scanList.scans.push_back(Scan()); Scan& scanRef = s->scanList.scans[0]; scanRef.set(MS_scan_start_time,t.rTime,UO_second); s->precursors.push_back(Precursor(t.inputPrecursorMZ)); vector inputMZArray = parseDoubleArray(t.inputMZArray); vector inputIntensityArray = parseDoubleArray(t.inputIntensityArray); s->setMZIntensityArrays(inputMZArray, inputIntensityArray, MS_number_of_detector_counts); s->defaultArrayLength = inputMZArray.size(); scanRef.scanWindows.push_back(ScanWindow()); scanRef.scanWindows[0].set(MS_scan_window_lower_limit,inputMZArray[0]); scanRef.scanWindows[0].set(MS_scan_window_upper_limit,inputMZArray[inputMZArray.size()-1]); sl->spectra.push_back(s); } vector goldMZArray = parseDoubleArray(goldStandard[0].inputMZArray); vector goldIntensityArray = parseDoubleArray(goldStandard[0].inputIntensityArray); // run spectral summation try { SpectrumListPtr calculator(new SpectrumList_ScanSummer(originalList,0.05,10)); for (size_t i=0; i < calculator->size(); ++i) { SpectrumPtr s = calculator->spectrum(i,true); vector& mzs = s->getMZArray()->data; vector& intensities = s->getIntensityArray()->data; Precursor& precursor = s->precursors[0]; SelectedIon& selectedIon = precursor.selectedIons[0]; double precursorMZ = selectedIon.cvParam(MS_selected_ion_m_z).valueAs(); double rTime = s->scanList.scans[0].cvParam(MS_scan_start_time).timeInSeconds(); vector goldMZArray = parseDoubleArray(goldStandard[i].inputMZArray); vector goldIntensityArray = parseDoubleArray(goldStandard[i].inputIntensityArray); unit_assert(mzs.size() == goldMZArray.size()); unit_assert(intensities.size() == goldIntensityArray.size()); unit_assert(precursorMZ == goldStandard[i].inputPrecursorMZ); unit_assert(rTime == goldStandard[i].rTime); for (size_t j=0; j < mzs.size(); ++j) { unit_assert_equal(mzs[j], goldMZArray[j], 1e-5); unit_assert_equal(intensities[j], goldIntensityArray[j], 1e-5); } } } catch (exception& e) { cerr << "Test failed:\n" << e.what() << endl; ++failedTests; } return failedTests; } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; int failedTests = test(); unit_assert_operator_equal(0, failedTests); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/spectrum_processing/SpectrumList_MetadataFixer.cpp0000664000175100017510000000563312664775615030437 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_MetadataFixer.cpp 4922 2013-09-05 22:33:08Z pcbrefugee $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_MetadataFixer.hpp" #include "pwiz/utility/misc/Container.hpp" #include "pwiz/utility/misc/String.hpp" namespace pwiz { namespace analysis { using namespace msdata; using namespace pwiz::util; PWIZ_API_DECL SpectrumList_MetadataFixer::SpectrumList_MetadataFixer(const msdata::SpectrumListPtr& inner) : SpectrumListWrapper(inner) { // metadata fixing isn't really worth a processingMethod, is it? } PWIZ_API_DECL bool SpectrumList_MetadataFixer::accept(const msdata::SpectrumListPtr& inner) { return true; } namespace { template void replaceCvParam(ParamContainer& pc, CVID cvid, const value_type& value, CVID unit) { vector::iterator itr; itr = std::find(pc.cvParams.begin(), pc.cvParams.end(), cvid); if (itr == pc.cvParams.end()) pc.set(cvid, value, unit); else itr->value = lexical_cast(value); } } // namespace PWIZ_API_DECL SpectrumPtr SpectrumList_MetadataFixer::spectrum(size_t index, bool getBinaryData) const { // always get binary data SpectrumPtr s = inner_->spectrum(index, true); BinaryDataArrayPtr mzArray = s->getMZArray(); BinaryDataArrayPtr intensityArray = s->getIntensityArray(); if (!mzArray.get() || !intensityArray.get()) return s; vector& mzs = mzArray->data; vector& intensities = intensityArray->data; double tic = 0; if (!mzs.empty()) { double bpmz, bpi = -1; for (size_t i=0, end=mzs.size(); i < end; ++i) { tic += intensities[i]; if (bpi < intensities[i]) { bpi = intensities[i]; bpmz = mzs[i]; } } replaceCvParam(*s, MS_base_peak_intensity, bpi, MS_number_of_detector_counts); replaceCvParam(*s, MS_base_peak_m_z, bpmz, MS_m_z); replaceCvParam(*s, MS_lowest_observed_m_z, mzs.front(), MS_m_z); replaceCvParam(*s, MS_highest_observed_m_z, mzs.back(), MS_m_z); } replaceCvParam(*s, MS_TIC, tic, MS_number_of_detector_counts); return s; } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/SpectrumList_Smoother.cpp0000664000175100017510000000573112664775615027520 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_Smoother.cpp 3180 2011-12-19 23:17:13Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_Smoother.hpp" #include "pwiz/analysis/common/SavitzkyGolaySmoother.hpp" //#include "WhittakerSmoother.hpp" #include "pwiz/utility/misc/Container.hpp" namespace pwiz { namespace analysis { using namespace msdata; using namespace pwiz::util; PWIZ_API_DECL SpectrumList_Smoother::SpectrumList_Smoother( const msdata::SpectrumListPtr& inner, SmootherPtr algorithm, const IntegerSet& msLevelsToSmooth) : SpectrumListWrapper(inner), algorithm_(algorithm), msLevelsToSmooth_(msLevelsToSmooth) { // add processing methods to the copy of the inner SpectrumList's data processing ProcessingMethod method; method.order = dp_->processingMethods.size(); method.set(MS_smoothing); method.userParams.push_back(UserParam("Savitzky-Golay smoothing (9 point window)")); if (!dp_->processingMethods.empty()) method.softwarePtr = dp_->processingMethods[0].softwarePtr; dp_->processingMethods.push_back(method); } PWIZ_API_DECL bool SpectrumList_Smoother::accept(const msdata::SpectrumListPtr& inner) { return true; } PWIZ_API_DECL SpectrumPtr SpectrumList_Smoother::spectrum(size_t index, bool getBinaryData) const { //if (!getBinaryData) // return inner_->spectrum(index, false); SpectrumPtr s = inner_->spectrum(index, true); vector& cvParams = s->cvParams; vector::iterator itr = std::find(cvParams.begin(), cvParams.end(), MS_profile_spectrum); // return non-profile spectra as-is if (itr == cvParams.end()) return s; try { vector& mzs = s->getMZArray()->data; vector& intensities = s->getIntensityArray()->data; vector smoothedMZs, smoothedIntensities; algorithm_->smooth(mzs, intensities, smoothedMZs, smoothedIntensities); mzs.swap(smoothedMZs); intensities.swap(smoothedIntensities); s->defaultArrayLength = mzs.size(); } catch(std::exception& e) { throw std::runtime_error(std::string("[SpectrumList_Smoother] Error smoothing intensity data: ") + e.what()); } s->dataProcessingPtr = dp_; return s; } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/SpectrumListFactory.cpp0000664000175100017510000022021612664775615027165 0ustar teamcityteamcity00000000000000// // $Id: SpectrumListFactory.cpp 9095 2015-11-01 01:14:24Z pcbrefugee $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumListFactory.hpp" #include "pwiz/analysis/spectrum_processing/SpectrumList_Filter.hpp" #include "pwiz/analysis/spectrum_processing/SpectrumList_Sorter.hpp" #include "pwiz/analysis/spectrum_processing/SpectrumList_ScanSummer.hpp" #include "pwiz/analysis/spectrum_processing/SpectrumList_PeakPicker.hpp" #include "pwiz/analysis/spectrum_processing/SpectrumList_Smoother.hpp" #include "pwiz/analysis/spectrum_processing/SpectrumList_PeakFilter.hpp" #include "pwiz/analysis/spectrum_processing/SpectrumList_ChargeStateCalculator.hpp" #include "pwiz/analysis/spectrum_processing/SpectrumList_ChargeFromIsotope.hpp" #include "pwiz/analysis/spectrum_processing/SpectrumList_PrecursorRecalculator.hpp" #include "pwiz/analysis/spectrum_processing/SpectrumList_PrecursorRefine.hpp" #include "pwiz/analysis/spectrum_processing/SpectrumList_MZWindow.hpp" #include "pwiz/analysis/spectrum_processing/SpectrumList_MZRefiner.hpp" #include "pwiz/analysis/spectrum_processing/SpectrumList_LockmassRefiner.hpp" #include "pwiz/analysis/spectrum_processing/SpectrumList_MetadataFixer.hpp" #include "pwiz/analysis/spectrum_processing/SpectrumList_TitleMaker.hpp" #include "pwiz/analysis/spectrum_processing/PrecursorMassFilter.hpp" #include "pwiz/analysis/spectrum_processing/ThresholdFilter.hpp" #include "pwiz/analysis/spectrum_processing/SpectrumList_ZeroSamplesFilter.hpp" #include "pwiz/analysis/spectrum_processing/MS2NoiseFilter.hpp" #include "pwiz/analysis/spectrum_processing/MS2Deisotoper.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace analysis { using namespace pwiz::cv; using namespace pwiz::msdata; using namespace pwiz::util; namespace { inline const char* cppTypeToNaturalLanguage(short T) { return "a small integer"; } inline const char* cppTypeToNaturalLanguage(int T) { return "an integer"; } inline const char* cppTypeToNaturalLanguage(long T) { return "an integer"; } inline const char* cppTypeToNaturalLanguage(unsigned short T) { return "a small positive integer"; } inline const char* cppTypeToNaturalLanguage(unsigned int T) { return "a positive integer"; } inline const char* cppTypeToNaturalLanguage(unsigned long T) { return "a positive integer"; } inline const char* cppTypeToNaturalLanguage(float T) { return "a real number"; } inline const char* cppTypeToNaturalLanguage(double T) { return "a real number"; } inline const char* cppTypeToNaturalLanguage(bool T) { return "true or false"; } /// parses a lexical-castable key=value pair from a string of arguments which may also include non-key-value strings; /// if the key is not in the argument string, defaultValue is returned; /// if bad_lexical_cast is thrown, it is converted into a sensible error message template ArgT parseKeyValuePair(string& args, const string& tokenName, const ArgT& defaultValue) { try { size_t keyIndex = args.rfind(tokenName); if (keyIndex != string::npos) { size_t valueIndex = keyIndex + tokenName.length(); if (valueIndex < args.length()) { string valueStr; try { valueStr = args.substr(valueIndex, args.find(" ", valueIndex) - valueIndex); ArgT value = lexical_cast(valueStr); args.erase(keyIndex, args.find(" ", valueIndex) - keyIndex); return value; } catch (bad_lexical_cast&) { throw runtime_error("error parsing \"" + valueStr + "\" as value for \"" + tokenName + "\"; expected " + cppTypeToNaturalLanguage(defaultValue)); } } } return defaultValue; } catch (exception& e) { throw runtime_error(string("[parseKeyValuePair] ") + e.what()); } } /// parses a lexical-castable key=value pair from a string of arguments which may also include non-key-value strings; /// if the key is not in the argument string or if bad_lexical_cast is thrown, a default-constructed ArgT is returned template ArgT parseKeyValuePair(string& args, const string& tokenName) { return parseKeyValuePair(args, tokenName, ArgT()); } // // each SpectrumListWrapper has a filterCreator_* function, // and an entry in the jump table below // typedef SpectrumListPtr (*FilterCreator)(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr); typedef const char *UsageInfo[2]; // usage like , and details SpectrumListPtr filterCreator_index(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { IntegerSet indexSet; indexSet.parse(arg); return SpectrumListPtr(new SpectrumList_Filter(msd.run.spectrumListPtr, SpectrumList_FilterPredicate_IndexSet(indexSet))); } UsageInfo usage_index = {"", "Selects spectra by index - an index value 0-based numerical order in which the spectrum appears in the input.\n" " is an int_set of indexes." }; SpectrumListPtr filterCreator_scanNumber(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { IntegerSet scanNumberSet; scanNumberSet.parse(arg); return SpectrumListPtr(new SpectrumList_Filter(msd.run.spectrumListPtr, SpectrumList_FilterPredicate_ScanNumberSet(scanNumberSet))); } UsageInfo usage_scanNumber = {"", "This filter selects spectra by scan number. Depending on the input data type, scan number and spectrum index are not always the same thing - scan numbers are not always contiguous, and are usually 1-based.\n" " is an int_set of scan numbers to be kept." }; SpectrumListPtr filterCreator_scanEvent(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { IntegerSet scanEventSet; scanEventSet.parse(arg); return SpectrumListPtr(new SpectrumList_Filter(msd.run.spectrumListPtr, SpectrumList_FilterPredicate_ScanEventSet(scanEventSet))); } UsageInfo usage_scanEvent = {"","This filter selects spectra by scan event. For example, to include all scan events except scan event 5, use " "filter \"scanEvent 1-4 6-\". A \"scan event\" is a preset scan configuration: a user-defined scan configuration that " "specifies the instrumental settings in which a spectrum is acquired. An instrument may cycle through a list of preset " "scan configurations to acquire data. This is a more generic term for the Thermo \"scan event\", which is defined in " "the Thermo Xcalibur glossary as: \"a mass spectrometer scan that is defined by choosing the necessary scan parameter " "settings. Multiple scan events can be defined for each segment of time.\"."}; SpectrumListPtr filterCreator_scanTime(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { double scanTimeLow = 0; double scanTimeHigh = 0; istringstream iss(arg); char open='\0', comma='\0', close='\0'; iss >> open >> scanTimeLow >> comma >> scanTimeHigh >> close; if (open!='[' || comma!=',' || close!=']') { cerr << "scanTime filter argument does not have form \"[\",\"]\", ignored." << endl; return SpectrumListPtr(); } return SpectrumListPtr(new SpectrumList_Filter(msd.run.spectrumListPtr, SpectrumList_FilterPredicate_ScanTimeRange(scanTimeLow, scanTimeHigh))); } UsageInfo usage_scanTime = {"", "This filter selects only spectra within a given time range.\n" " is a time range, specified in seconds. For example, to select only spectra within the " "second minute of the run, use \"scanTime [60-119.99]\"."}; SpectrumListPtr filterCreator_sortScanTime(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { return SpectrumListPtr(new SpectrumList_Sorter(msd.run.spectrumListPtr, SpectrumList_SorterPredicate_ScanStartTime())); } UsageInfo usage_sortScanTime = {"","This filter reorders spectra, sorting them by ascending scan start time."}; SpectrumListPtr filterCreator_scanSummer(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { // defaults double precursorTol = 0.05; // m/z double scanTimeTol = 10; // seconds istringstream parser(arg); string nextStr; while ( parser >> nextStr ) { if ( string::npos == nextStr.rfind('=') ) throw user_error("[filterCreator_scanSummer] = sign required after keyword argument"); string keyword = nextStr.substr(0,nextStr.rfind('=')); string paramVal = nextStr.substr(nextStr.rfind('=')+1); if ( boost::iequals(keyword,"precursorTol") ) { try { lexical_cast(paramVal); } catch (...) { throw user_error("[filterCreator_scanSummer] A numeric value must follow the precursorTol argument."); } precursorTol = lexical_cast(paramVal); if ( precursorTol < 0 ) { throw user_error("[filterCreator_scanSummer] precursorTol must be greater than or equal to zero."); } } else if ( boost::iequals(keyword,"scanTimeTol") ) { try { lexical_cast(paramVal); } catch (...) { throw user_error("[filterCreator_scanSummer] A numeric value must follow the scanTimeTol argument."); } scanTimeTol = lexical_cast(paramVal); if ( scanTimeTol < 0 ) { throw user_error("[filterCreator_scanSummer] scanTimeTol must be greater than or equal to zero."); } } else { throw user_error("[filterCreator_scanSummer] Invalid keyword entered."); } } return SpectrumListPtr(new SpectrumList_ScanSummer(msd.run.spectrumListPtr,precursorTol,scanTimeTol)); } UsageInfo usage_scanSummer = {"[precursorTol=] [scanTimeTol=]", "This filter sums MS2 sub-scans whose precursors are within (default: 0.05 Th.)" "and (default: 10 secs.). Its use is intended for some Waters DDA data, where sub-scans " "should be summed together to increase the SNR. This filter has only been tested for Waters data."}; SpectrumListPtr filterCreator_nativeCentroid(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { // by default assume we are using the low-quality localMax code unless explicitly told otherwise // default values for CWT bool preferVendor = false; bool preferCwt = false; double mzTol = 0.1; // default value, minimum spacing between peaks double minSnr = 1.0; // for the cwt algorithm, default value is 1.01 int fixedPeaksKeep = 0; // this will always be set to zero, except from charge determination algorithm string msLevelSets = "1-"; // peak-pick all MS levels by default istringstream parser(arg); string pickerType; parser >> pickerType; string nextStr; bool backwardsCompatible = pickerType == "true" || pickerType == "false"; if ( !pickerType.empty() && !backwardsCompatible ) { preferVendor = boost::iequals(pickerType,"vendor"); preferCwt = boost::iequals(pickerType,"cwt"); while ( parser >> nextStr ) { if ( string::npos == nextStr.rfind('=') ) throw user_error("[SpectrumList_PeakPicker] = sign required after keyword argument"); string keyword = nextStr.substr(0,nextStr.rfind('=')); string paramVal = nextStr.substr(nextStr.rfind('=')+1); if ( boost::iequals(keyword,"snr") ) { try { lexical_cast(paramVal); } catch (...) { throw user_error("[SpectrumList_PeakPicker] A numeric value must follow the snr argument."); } minSnr = lexical_cast(paramVal); if ( minSnr < 0 ) { throw user_error("[SpectrumList_PeakPicker] snr must be greater than or equal to zero."); } } else if ( boost::iequals(keyword,"peakSpace") ) { try { lexical_cast(paramVal); } catch (...) { throw user_error("[SpectrumList_PeakPicker] A numeric value must follow the peakSpace argument."); } mzTol = lexical_cast(paramVal); if ( mzTol < 0 ) { throw user_error("[SpectrumList_PeakPicker] peakSpace must be greater than or equal to zero."); } } else if ( boost::iequals(keyword,"msLevel") ) { msLevelSets = paramVal; } else { throw user_error("[SpectrumList_PeakPicker] Invalid keyword argument."); } } // give the user some feedback if ( preferCwt & preferVendor ) { throw user_error("[SpectrumList_PeakPicker] Cannot request both cwt and vendor peak-picking."); } else if ( preferCwt ) { //TODO: Give user some feedback for the applied parameters //cout << "---CantWaiT Parameters---" << endl; //cout << "minimum SNR: " << minSnr << endl; //cout << "minimum peak spacing: " << mzTol << endl; //cout << "msLevels: " << msLevelSets << endl << endl; } else if ( preferVendor ) { //cout << "Applying vendor peak-picking" << endl; } else { //cout << "WARNING: applying simple local maxima peak-picking. Specify cwt or vendor for high-quality processing." << endl; } } else { preferVendor = lexical_cast(pickerType); parser >> msLevelSets; } IntegerSet msLevelsToCentroid; msLevelsToCentroid.parse(msLevelSets); if (preferVendor && msd.countFiltersApplied()) cerr << "[SpectrumList_PeakPicker] Warning: vendor peakPicking requested, but peakPicking is not the first filter. Since the vendor DLLs can only operate directly on raw data, this filter will likely not have any effect." << endl; if (preferCwt) { return SpectrumListPtr(new SpectrumList_PeakPicker(msd.run.spectrumListPtr, PeakDetectorPtr(new CwtPeakDetector(minSnr,fixedPeaksKeep,mzTol)), preferVendor, msLevelsToCentroid)); } else { return SpectrumListPtr(new SpectrumList_PeakPicker(msd.run.spectrumListPtr, PeakDetectorPtr(new LocalMaximumPeakDetector(3)), preferVendor, msLevelsToCentroid)); } } UsageInfo usage_nativeCentroid = {"[ [snr=] [peakSpace=] [msLevel=]]","This filter performs centroiding on spectra" "with the selected , expressed as an int_set. The value for must be \"cwt\" or \"vendor\": when = " "\"vendor\", vendor (Windows DLL) code is used if available. IMPORTANT NOTE: since this filter operates on the raw " "data through the vendor DLLs, IT MUST BE THE FIRST FILTER IN ANY LIST OF FILTERS when \"vendor\" is used. " "The other option for PickerType is \"cwt\", which uses ProteoWizard's wavelet-based algorithm for performing peak-picking with a " "wavelet-space signal-to-noise ratio of .\n" "Defaults:\n " " is a low-quality (non-vendor) local maxima algorithm\n " " = 1.0\n " " = 0.1\n " " = 1-\n " }; /** * Handler for --filter zeroSamples removeExtra|addMissing[=FlankingZeroCount] [mslevels] * **/ SpectrumListPtr filterCreator_ZeroSamples(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { istringstream parser(arg); string action; parser >> action; bool bRemover = ("removeExtra"==action); int FlankingZeroCount=-1; if (string::npos!=action.rfind('=')) { FlankingZeroCount = atoi(action.substr(action.rfind('=')+1).c_str()); action = action.substr(0,action.rfind('=')); } if (!bRemover && ("addMissing"!=action)) throw user_error("[SpectrumListFactory::filterCreator_ZeroSamples()] unknown mode \"" + action + "\""); string msLevelSets; getline(parser, msLevelSets); if (""==msLevelSets) msLevelSets="1-"; // default is all msLevels IntegerSet msLevelsToFilter; msLevelsToFilter.parse(msLevelSets); return SpectrumListPtr(new SpectrumList_ZeroSamplesFilter(msd.run.spectrumListPtr,msLevelsToFilter, bRemover ? SpectrumList_ZeroSamplesFilter::Mode_RemoveExtraZeros : SpectrumList_ZeroSamplesFilter::Mode_AddMissingZeros, FlankingZeroCount)); } UsageInfo usage_zeroSamples = {" []", "This filter deals with zero values in spectra - either removing them, or adding them where they are missing.\n" " is either removeExtra or addMissing[=] .\n" " is optional, when provided (as an int_set) the filter is applied only to spectra with those MS levels.\n" "When is \"removeExtra\", consecutive zero intensity peaks are removed from spectra. For example, a peak list\n" " \"100.1,1000 100.2,0 100.3,0 100.4,0 100.5,0 100.6,1030\"\n" "would become \n" " \"100.1,1000 100.2,0 100.5,0 100.6,1030\"\n" "and a peak list \n" " \"100.1,0 100.2,0 100.3,0 100.4,0 100.5,0 100.6,1030 100.7,0 100.8,1020 100.9,0 101.0,0\"\n" "would become \n" " \"100.5,0 100.6,1030 100.7,0 100.8,1020 100.9,0\"\n" "When is \"addMissing\", each spectrum's sample rate is automatically determined (the rate can change but only " "gradually) and flanking zeros are inserted around non-zero data points. The optional [=] value " "can be used to limit the number of flanking zeros, otherwise the spectrum is completely populated between nonzero points. " "For example, to make sure spectra have at least 5 flanking zeros around runs on nonzero points, use filter \"addMissing=5\"." }; /** * Handler for --filter "ETDFilter". There are five optional arguments for this filter: * remove unreacted precursor * remove charge reduced precursor * remove neutral loss species from charge reduced precursor * float_val matching tolerance -- floating point value, followed by units (example: 3.1 MZ) */ SpectrumListPtr filterCreator_ETDFilter(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { istringstream parser(arg); string removePrecursor; parser >> removePrecursor; bool bRemPrecursor = removePrecursor == "false" || removePrecursor == "0" ? false : true; string removeChargeReduced; parser >> removeChargeReduced; bool bRemChgRed = removeChargeReduced == "false" || removeChargeReduced == "0" ? false : true; string removeNeutralLoss; parser >> removeNeutralLoss; bool bRemNeutralLoss = removeNeutralLoss == "false" || removeNeutralLoss == "0" ? false : true; string useBlanketFiltering; parser >> useBlanketFiltering; bool bUseBlanketFiltering = useBlanketFiltering == "false" || useBlanketFiltering == "0" ? false : true; MZTolerance mzt(3.1); if (parser.good()) { parser >> mzt; } SpectrumDataFilterPtr filter; if (bRemNeutralLoss) { filter = SpectrumDataFilterPtr(new PrecursorMassFilter(PrecursorMassFilter::Config(mzt, bRemPrecursor, bRemChgRed, bUseBlanketFiltering))); } else { filter = SpectrumDataFilterPtr(new PrecursorMassFilter(PrecursorMassFilter::Config(mzt, bRemPrecursor, bRemChgRed, bUseBlanketFiltering, 0))); } return SpectrumListPtr(new SpectrumList_PeakFilter(msd.run.spectrumListPtr, filter)); } UsageInfo usage_ETDFilter = {"[ [ [ [ [ ]]]]]", "Filters ETD MSn spectrum data points, removing unreacted precursors, charge-reduced precursors, and neutral losses.\n" " - if \"true\", remove unreacted precursor (default is \"true\")\n" " - if \"true\", remove charge reduced precursor (default is \"true\")\n" " - if \"true\", remove neutral loss species from charge reduced precursor (default is \"true\")\n" " - if \"true\", remove neutral losses in a charge-scaled 60 Da swath rather than only around known loss species (default is \"true\")\n" " - specify matching tolerance in m/z or ppm (examples: \"3.1 mz\" (the default) or \"2.2 ppm\")" }; SpectrumListPtr filterCreator_MS2Denoise(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { istringstream parser(arg); size_t numPeaksInWindow = 6; double windowSize = 30.; bool relaxLowMass = false; string npeaks, wsize, relax; parser >> npeaks; if (npeaks.empty() == false) numPeaksInWindow = lexical_cast(npeaks); parser >> wsize; if (wsize.empty() == false) windowSize = lexical_cast(wsize); parser >> relax; if (relax.empty() == false) relaxLowMass = lexical_cast(relax); SpectrumDataFilterPtr filter = SpectrumDataFilterPtr(new MS2NoiseFilter(MS2NoiseFilter::Config(numPeaksInWindow, windowSize, relaxLowMass))); return SpectrumListPtr(new SpectrumList_PeakFilter(msd.run.spectrumListPtr, filter)); } UsageInfo usage_MS2Denoise = {"[ [ [multicharge_fragment_relaxation]]]", "Noise peak removal for spectra with precursor ions.\n" " - the number peaks to select in moving window, default is 6.\n" " - the width of the window in Da, default is 30.\n" " - if \"true\" (the default), allows more data below multiply charged precursors.\n" "The filter first removes any m/z values above the precursor mass minus the mass of glycine.\n" "It then removes any m/z values within .5 Da of the unfragmented precursor mass.\n" "Finally it retains only the most intense ions within a " "sliding window of .\n" "If is true, allows more peaks at lower mass (i.e. below precursor).\n" "If is set to 0, the window size defaults to the highest observed mass in the spectrum " "(this leaving only ions in the output spectrum).\n" "Reference: \"When less can yield more - Computational preprocessing of MS/MS spectra for peptide " "identification\", Bernhard Y. Renard, Marc Kirchner, Flavio Monigatti, Alexander R. Ivanov, " "Juri Rappsilber, Dominic Winter, Judith A. J. Steen, Fred A. Hamprecht and Hanno Steen " "Proteomics, 9, 4978-4984, 2009.\n" }; SpectrumListPtr filterCreator_MS2Deisotope(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { istringstream parser(arg); bool hires = false; string buf; parser >> buf; MZTolerance mzt(hires? 0.01 : 0.5); bool poisson = false; int maxCharge = 3, minCharge = 1; if ( !buf.empty() ) { if ( boost::iequals(buf,"Poisson") ) poisson = true; else if ( boost::iequals(buf,"hi_res") ) hires = true; else throw user_error("[filterCreator_MS2Deisotope] Invalid keyword entered."); int whileLoopCnt = 0; while ( parser >> buf ) { bool backwardsCompatible = false; if ( hires && whileLoopCnt == 0 ) { bool changeBool = true; try { lexical_cast(buf); } catch (...) { changeBool = false; } if (changeBool) backwardsCompatible = true; } if (backwardsCompatible) { mzt = lexical_cast(buf); break; } if ( string::npos == buf.rfind('=') ) throw user_error("[filterCreator_MS2Deisotope] = sign required after keyword argument"); string keyword = buf.substr(0,buf.rfind('=')); string paramVal = buf.substr(buf.rfind('=')+1); if ( boost::iequals(keyword,"minCharge") ) { try { lexical_cast(paramVal); } catch (...) { throw user_error("[filterCreator_MS2Deisotope] An integer must follow the minCharge argument."); } minCharge = lexical_cast(paramVal); if ( minCharge < 0 ) { throw user_error("[filterCreator_MS2Deisotope] minCharge must be a positive integer."); } } else if ( boost::iequals(keyword,"maxCharge") ) { try { lexical_cast(paramVal); } catch (...) { throw user_error("[filterCreator_MS2Deisotope] An integer must follow the maxCharge argument."); } maxCharge = lexical_cast(paramVal); if ( maxCharge < 0 ) { throw user_error("[filterCreator_MS2Deisotope] maxCharge must be a positive integer."); } } else if ( boost::iequals(keyword,"mzTol") ) { try { lexical_cast(paramVal); } catch (...) { throw user_error("[filterCreator_MS2Deisotope] A numeric value must follow the mzTol keyword."); } if ( lexical_cast(paramVal) < 0 ) { throw user_error("[filterCreator_MS2Deisotope] mzTol must be a positive."); } mzt = lexical_cast(paramVal); } else { throw user_error("[filterCreator_MS2Deisotope] Invalid keyword entered."); } whileLoopCnt++; } // sanity check if ( minCharge > maxCharge) throw user_error("[filterCreator_MS2Deisotope] minCharge must be less than maxCharge."); } SpectrumDataFilterPtr filter = SpectrumDataFilterPtr(new MS2Deisotoper(MS2Deisotoper::Config(mzt, hires, poisson, maxCharge, minCharge))); return SpectrumListPtr(new SpectrumList_PeakFilter(msd.run.spectrumListPtr, filter)); } UsageInfo usage_MS2Deisotope = { "[hi_res [mzTol=]] [Poisson [minCharge=] [maxCharge=]]", "Deisotopes ms2 spectra using the Markey method or a Poisson model.\n" " For the Markey method, hi_res sets high resolution mode to \"false\" (the default) or \"true\".\n" " sets the mz tolerance. It defaults to .01 in high resoltion mode, otherwise it defaults to 0.5.\n" " Poisson activates a Poisson model based on the relative intensity distribution.\n" " (default: 1) and (default: 3) define the charge search range within the Poisson deisotoper. (default: 1)" }; struct StripIonTrapSurveyScans : public SpectrumList_Filter::Predicate { virtual boost::logic::tribool accept(const SpectrumIdentity& spectrumIdentity) const { return boost::logic::indeterminate; // need full Spectrum } virtual boost::logic::tribool accept(const Spectrum& spectrum) const { if (!spectrum.hasCVParam(MS_ms_level) || spectrum.scanList.scans.empty() || !spectrum.scanList.scans[0].instrumentConfigurationPtr.get()) return boost::logic::indeterminate; CVID massAnalyzerType = spectrum.scanList.scans[0].instrumentConfigurationPtr->componentList.analyzer(0). cvParamChild(MS_mass_analyzer_type).cvid; if (massAnalyzerType == CVID_Unknown) return boost::logic::indeterminate; return !(spectrum.cvParam(MS_ms_level).value == "1" && cvIsA(massAnalyzerType, MS_ion_trap)); } }; SpectrumListPtr filterCreator_stripIT(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { return SpectrumListPtr(new SpectrumList_Filter(msd.run.spectrumListPtr, StripIonTrapSurveyScans())); } UsageInfo usage_stripIT={"","This filter rejects ion trap data spectra with MS level 1."}; SpectrumListPtr filterCreator_precursorRecalculation(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { return SpectrumListPtr(new SpectrumList_PrecursorRecalculator(msd)); } UsageInfo usage_precursorRecalculation = {"","This filter recalculates the precursor m/z and charge for MS2 spectra. " "It looks at the prior MS1 scan to better infer the parent mass. However, it only works on orbitrap and FT data," "although it does not use any 3rd party (vendor DLL) code. Since the time the code was written, Thermo has since fixed " "up its own estimation in response, so it's less critical than it used to be (though can still be useful)."}; SpectrumListPtr filterCreator_mzRefine(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { // Example string: // "mzRefiner input1.pepXML input2.mzid msLevels=1- thresholdScore=specEValue thresholdValue=1e-10 thresholdStep=10 maxSteps=3" istringstream parser(arg); // expand the filenames by globbing to handle wildcards vector globbedFilenames; string thresholdCV = "MS-GF:SpecEValue"; // Remove this default? string thresholdSet = "-1e-10"; // Remove this default? double thresholdStep = 0.0; int maxSteps = 0; string msLevelSets = "1-"; string nextStr; while (parser >> nextStr) { if (nextStr.rfind('=') == string::npos) { // Add to ident file list, and check for existence? // Remove quotes that may be used to encapsulate a path with spaces if ((bal::starts_with(nextStr, "\'") && bal::ends_with(nextStr, "\'")) || (bal::starts_with(nextStr, "\"") && bal::ends_with(nextStr, "\""))) { // Remove the first and last characters nextStr = nextStr.substr(1, nextStr.length() - 2); } // expand the filenames by globbing to handle wildcards if (expand_pathmask(bfs::path(nextStr), globbedFilenames) == 0) cout << "[mzRefiner] no files found matching \"" << nextStr << "\"" << endl; } else { string keyword = nextStr.substr(0, nextStr.rfind('=')); string paramVal = nextStr.substr(nextStr.rfind('=') + 1); if (keyword == "msLevels") { // use an IntegerSet msLevelSets = paramVal; } else if (keyword == "thresholdScore") { thresholdCV = paramVal; } else if (keyword == "thresholdValue") { thresholdSet = paramVal; } else if (keyword == "thresholdStep") { thresholdStep = boost::lexical_cast(paramVal); } else if (keyword == "maxSteps") { maxSteps = boost::lexical_cast(paramVal); } } } // expand the filenames by globbing to handle wildcards vector files; BOOST_FOREACH(const bfs::path& filename, globbedFilenames) files.push_back(filename.string()); IntegerSet msLevelsToRefine; msLevelsToRefine.parse(msLevelSets); string identFilePath = ""; vector possibleDataFiles; string lastSourceFile; BOOST_FOREACH(const SourceFilePtr& sf, msd.fileDescription.sourceFilePtrs) { lastSourceFile = sf->name; } lastSourceFile = lastSourceFile.substr(0, lastSourceFile.rfind(".gz")); // remove a ".gz", if there is one lastSourceFile = lastSourceFile.substr(0, lastSourceFile.rfind(".")); // remove the extension possibleDataFiles.push_back(lastSourceFile); possibleDataFiles.push_back(msd.run.id); // Search for a file that matches the MSData file name, then search for one matching the dataset if not found. // Load identfiles, and look at mzid.DataCollection.Inputs.SpectraData.name? BOOST_FOREACH(string &dataFile, possibleDataFiles) { BOOST_FOREACH(string &file, files) { if (file.find(dataFile) != string::npos) { identFilePath = file; break; } } if (identFilePath != "") { break; } } return SpectrumListPtr(new SpectrumList_MZRefiner(msd, identFilePath, thresholdCV, thresholdSet, msLevelsToRefine, thresholdStep, maxSteps, ilr)); } UsageInfo usage_mzRefine = { "input1.pepXML input2.mzid [msLevels=<1->] [thresholdScore=] [thresholdValue=] [thresholdStep=] [maxSteps=]", "This filter recalculates the m/z and charges, adjusting precursors for MS2 spectra and spectra masses for MS1 spectra. " "It uses an ident file with a threshold field and value to calculate the error and will then choose a shifting mechanism to correct masses throughout the file. " "It only works on orbitrap, FT, and TOF data. It is designed to work on mzML files created by msconvert from a single dataset (single run), and with an identification file created using that mzML file. " "It does not use any 3rd party (vendor DLL) code. " "Recommended Scores and thresholds: MS-GF:SpecEValue,-1e-10 (<1e-10); MyriMatch:MVH,35- (>35); xcorr,3- (>3)" }; SpectrumListPtr filterCreator_lockmassRefiner(const MSData& msd, const string& carg, pwiz::util::IterationListenerRegistry* ilr) { const string mzToken("mz="); const string mzNegIonsToken("mzNegIons="); const string toleranceToken("tol="); string arg = carg; double lockmassMz = parseKeyValuePair(arg, mzToken, 0); double lockmassMzNegIons = parseKeyValuePair(arg, mzNegIonsToken, lockmassMz); // Optional double lockmassTolerance = parseKeyValuePair(arg, toleranceToken, 1.0); bal::trim(arg); if (!arg.empty()) throw runtime_error("[lockmassRefiner] unhandled text remaining in argument string: \"" + arg + "\""); if (lockmassMz <= 0 || lockmassTolerance <= 0 || lockmassMzNegIons <= 0) { cerr << "lockmassMz and lockmassTolerance must be postive real numbers" << endl; return SpectrumListPtr(); } return SpectrumListPtr(new SpectrumList_LockmassRefiner(msd.run.spectrumListPtr, lockmassMz, lockmassMzNegIons, lockmassTolerance)); } UsageInfo usage_lockmassRefiner = { "mz= mzNegIons= tol=", "For Waters data, adjusts m/z values according to the specified lockmass m/z and tolerance. Distinct m/z value for negative ions is optional and defaults to the given mz value. For other data, currently does nothing." }; SpectrumListPtr filterCreator_precursorRefine(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { return SpectrumListPtr(new SpectrumList_PrecursorRefine(msd)); } UsageInfo usage_precursorRefine = {"", "This filter recalculates the precursor m/z and charge for MS2 spectra. " "It looks at the prior MS1 scan to better infer the parent mass. It only works on orbitrap, FT, and TOF data. " "It does not use any 3rd party (vendor DLL) code."}; SpectrumListPtr filterCreator_mzWindow(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { double mzLow = 0; double mzHigh = 0; istringstream iss(arg); char open='\0', comma='\0', close='\0'; iss >> open >> mzLow >> comma >> mzHigh >> close; if (open!='[' || comma!=',' || close!=']') { cerr << "mzWindow filter expected an mzrange formatted something like \"[123.4,567.8]\"" << endl; return SpectrumListPtr(); } return SpectrumListPtr(new SpectrumList_MZWindow(msd.run.spectrumListPtr, mzLow, mzHigh)); } UsageInfo usage_mzWindow = {"", "keeps mz/intensity pairs whose m/z values fall within the specified range.\n" " is formatted as [mzLow,mzHigh]. For example, in msconvert to retain data in the m/z range " "100.1 to 307.5, use --filter \"mzWindow [100.1,307.5]\" ." }; SpectrumListPtr filterCreator_mzPrecursors(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { char open='\0', comma='\0', close='\0'; std::set setMz; istringstream iss(arg); iss >> open; while (isdigit(iss.peek())) { double mz = 0; iss >> mz; setMz.insert(mz); if (iss.peek() == ',') iss >> comma; } iss >> close; if (open!='[' || close!=']') { cerr << "mzPrecursors filter expected a list of m/z values formatted something like \"[123.4,567.8,789.0]\"" << endl; return SpectrumListPtr(); } return SpectrumListPtr(new SpectrumList_Filter(msd.run.spectrumListPtr, SpectrumList_FilterPredicate_PrecursorMzSet(setMz))); } UsageInfo usage_mzPrecursors = {"", "Retains spectra with precursor m/z values found in the . For example, in msconvert to retain " "only spectra with precursor m/z values of 123.4 and 567.8 you would use --filter \"mzPrecursors [123.4,567.8]\". " "Note that this filter will drop MS1 scans unless you include 0.0 in the list of precursor values." }; SpectrumListPtr filterCreator_msLevel(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { IntegerSet msLevelSet; msLevelSet.parse(arg); return SpectrumListPtr(new SpectrumList_Filter(msd.run.spectrumListPtr, SpectrumList_FilterPredicate_MSLevelSet(msLevelSet))); } UsageInfo usage_msLevel = {"", "This filter selects only spectra with the indicated , expressed as an int_set."}; SpectrumListPtr filterCreator_mzPresent(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { istringstream parser(arg); MZTolerance mzt; parser >> mzt; string byTypeArg, orientationArg; double threshold; IntegerSet msLevels(1, INT_MAX); parser >> byTypeArg >> threshold >> orientationArg; ThresholdFilter::ThresholdingBy_Type byType; if (byTypeArg == "count") byType = ThresholdFilter::ThresholdingBy_Count; else if (byTypeArg == "count-after-ties") byType = ThresholdFilter::ThresholdingBy_CountAfterTies; else if (byTypeArg == "absolute") byType = ThresholdFilter::ThresholdingBy_AbsoluteIntensity; else if (byTypeArg == "bpi-relative") byType = ThresholdFilter::ThresholdingBy_FractionOfBasePeakIntensity; else if (byTypeArg == "tic-relative") byType = ThresholdFilter::ThresholdingBy_FractionOfTotalIntensity; else if (byTypeArg == "tic-cutoff") byType = ThresholdFilter::ThresholdingBy_FractionOfTotalIntensityCutoff; else return SpectrumListPtr(); ThresholdFilter::ThresholdingOrientation orientation; if (orientationArg == "most-intense") orientation = ThresholdFilter::Orientation_MostIntense; else if (orientationArg == "least-intense") orientation = ThresholdFilter::Orientation_LeastIntense; else return SpectrumListPtr(); char open='\0', comma='\0', close='\0'; std::set setMz; parser >> open; while (isdigit(parser.peek())) { double mz = 0; parser >> mz; setMz.insert(mz); if (parser.peek() == ',') parser >> comma; } parser >> close; std::string inex = "include"; bool inverse = false; if (parser.good()) parser >> inex; if (inex != "include" && inex != "exclude") throw user_error("[SpectrumListFactory::filterCreator_mzPresent()] invalid parameter (expected \"include\" or \"exclude\")"); if (inex == "exclude") inverse = true; if (open!='[' || close!=']') { cerr << "mzPresent filter expected a list of mz values like \"[100,200,300.4\\" << endl ; return SpectrumListPtr(); } return SpectrumListPtr(new SpectrumList_Filter(msd.run.spectrumListPtr, SpectrumList_FilterPredicate_MzPresent(mzt, setMz, ThresholdFilter(byType, threshold, orientation, msLevels), inverse))); } UsageInfo usage_mzPresent = {" []", "This filter is similar to the \"threshold\" filter, with a few more options.\n" " is specified as a number and units (PPM or MZ). For example, \"5 PPM\" or \"2.1 MZ\".\n" " , , and operate as in the \"threshold\" filter (see above).\n" " is a list of mz values of the form [mz1,mz2, ... mzn] (for example, \"[100, 300, 405.6]\"). " "Data points within of any of these values will be kept.\n" " is optional and has value \"include\" (the default) or \"exclude\". If \"exclude\" is " "used the filter drops data points that match the various criteria instead of keeping them." }; SpectrumListPtr filterCreator_chargeState(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { IntegerSet chargeStateSet; chargeStateSet.parse(arg); return SpectrumListPtr(new SpectrumList_Filter(msd.run.spectrumListPtr, SpectrumList_FilterPredicate_ChargeStateSet(chargeStateSet))); } UsageInfo usage_chargeState = {"", "This filter keeps spectra that match the listed charge state(s), expressed as an int_set. Both known/single " "and possible/multiple charge states are tested. Use 0 to include spectra with no charge state at all."}; SpectrumListPtr filterCreator_defaultArrayLength(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { IntegerSet defaultArrayLengthSet; defaultArrayLengthSet.parse(arg); return SpectrumListPtr(new SpectrumList_Filter(msd.run.spectrumListPtr, SpectrumList_FilterPredicate_DefaultArrayLengthSet(defaultArrayLengthSet))); } UsageInfo usage_defaultArrayLength = { "", "Keeps only spectra with peak counts within , expressed as an int_set. (In mzML the peak list " "length is expressed as \"defaultArrayLength\", hence the name.) For example, to include only spectra with 100 " "or more peaks, you would use filter \"defaultArrayLength 100-\" ." }; SpectrumListPtr filterCreator_metadataFixer(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { return SpectrumListPtr(new SpectrumList_MetadataFixer(msd.run.spectrumListPtr)); } UsageInfo usage_metadataFixer={"","This filter is used to add or replace a spectra's TIC/BPI metadata, usually after " "peakPicking where the change from profile to centroided data may make the TIC and BPI values inconsistent with " "the revised scan data. The filter traverses the m/z intensity arrays to find the sum and max. For example, in " "msconvert it can be used as: --filter \"peakPicking true 1-\" --filter metadataFixer. It can also be used without " "peak picking for some strange results. Certainly adding up all the samples of profile data to get the TIC is " "just wrong, but we do it anyway."}; SpectrumListPtr filterCreator_titleMaker(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { return SpectrumListPtr(new SpectrumList_TitleMaker(msd, bal::trim_copy(arg))); } UsageInfo usage_titleMaker={"","This filter adds or replaces spectrum titles according to specified " ". You can use it, for example, to customize the TITLE line in MGF output in msconvert. The following " "keywords are recognized: \n" " \"\" - prints the spectrum's Run id - for example, \"Data.d\" from \"C:/Agilent/Data.d/AcqData/mspeak.bin\"\n" " \"\" - prints the spectrum's index\n" " \"\" - prints the spectrum's nativeID\n" " \"\" - prints the path of the spectrum's source data\n" " \"\" - if the nativeID can be represented as a single number, prints that number, else index+1\n" " \"\" - for the first precursor, prints the spectrum's \"dissociation method\" value\n" " \"\" - for the first precursor, prints the the spectrum's \"isolation target m/z\" value\n" " \"\" - prints the nativeID of the spectrum of the first precursor\n" " \"\" - prints the m/z value of the first selected ion of the first precursor\n" " \"\" - prints the charge state for the first selected ion of the first precursor\n" " \"\" - prints the spectrum type\n" " \"\" - prints the spectrum's first scan's start time, in seconds\n" " \"\" - prints the spectrum's first scan's start time, in minutes\n" " \"\" - prints the spectrum's base peak m/z\n" " \"\" - prints the spectrum's base peak intensity\n" " \"\" - prints the spectrum's total ion current\n" " \"\" - prints the spectrum's MS level\n" "For example, to create a TITLE line in msconvert MGF output with the \"name.first_scan.last_scan.charge\" style (eg. \"mydata.145.145.2\"), use\n" "--filter \"titleMaker ...\"" }; SpectrumListPtr filterCreator_chargeStatePredictor(const MSData& msd, const string& carg, pwiz::util::IterationListenerRegistry* ilr) { const string overrideExistingChargeToken("overrideExistingCharge="); const string maxMultipleChargeToken("maxMultipleCharge="); const string minMultipleChargeToken("minMultipleCharge="); const string singleChargeFractionTICToken("singleChargeFractionTIC="); const string maxKnownChargeToken("maxKnownCharge="); const string makeMS2Token("makeMS2="); string arg = carg; bool overrideExistingCharge = parseKeyValuePair(arg, overrideExistingChargeToken, false); int maxMultipleCharge = parseKeyValuePair(arg, maxMultipleChargeToken, 3); int minMultipleCharge = parseKeyValuePair(arg, minMultipleChargeToken, 2); double singleChargeFractionTIC = parseKeyValuePair(arg, singleChargeFractionTICToken, 0.9); int maxKnownCharge = parseKeyValuePair(arg, maxKnownChargeToken, 0); bool makeMS2 = parseKeyValuePair(arg, makeMS2Token, false); bal::trim(arg); if (!arg.empty()) throw runtime_error("[chargeStatePredictor] unhandled text remaining in argument string: \"" + arg + "\""); return SpectrumListPtr(new SpectrumList_ChargeStateCalculator(msd.run.spectrumListPtr, overrideExistingCharge, maxMultipleCharge, minMultipleCharge, singleChargeFractionTIC, maxKnownCharge, makeMS2)); } UsageInfo usage_chargeStatePredictor = {"[overrideExistingCharge=] [maxMultipleCharge=] [minMultipleCharge=] [singleChargeFractionTIC=] [maxKnownCharge=] [makeMS2=]", "Predicts MSn spectrum precursors to be singly or multiply charged depending on the ratio of intensity above and below the precursor m/z, or optionally using the \"makeMS2\" algorithm\n" " : always override existing charge information (default:\"false\")\n" " (default 3) and (default 2): range of values to add to the spectrum's existing \"MS_possible_charge_state\" values." "If these are the same values, the spectrum's MS_possible_charge_state values are removed and replaced with this single value.\n" " : is a percentage expressed as a value between 0 and 1 (the default is 0.9, or 90 percent). " "This is the value used as the previously mentioned ratio of intensity above and below the precursor m/z.\n" " (default is 0, meaning no maximum): the maximum charge allowed for \"known\" charges even if override existing charge is false. " "This allows overriding junk charge calls like +15 peptides.\n" " : default is \"false\", when set to \"true\" the \"makeMS2\" algorithm is used instead of the one described above." }; SpectrumListPtr filterCreator_chargeFromIsotope(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { // defaults int maxCharge = 8; int minCharge = 1; int precursorsBefore = 2; int precursorsAfter = 0; double isolationWidth = 1.25; int defaultChargeMax = 0; int defaultChargeMin = 0; istringstream parser(arg); string nextStr; while ( parser >> nextStr ) { if ( string::npos == nextStr.rfind('=') ) throw user_error("[filterCreator_turbocharger] = sign required after keyword argument"); string keyword = nextStr.substr(0,nextStr.rfind('=')); string paramVal = nextStr.substr(nextStr.rfind('=')+1); if ( boost::iequals(keyword,"minCharge") ) { try { lexical_cast(paramVal); } catch (...) { throw user_error("[filterCreator_turbocharger] An integer must follow the minCharge argument."); } minCharge = lexical_cast(paramVal); if ( minCharge < 0 ) { throw user_error("[filterCreator_turbocharger] minCharge must be a positive integer."); } } else if ( boost::iequals(keyword,"maxCharge") ) { try { lexical_cast(paramVal); } catch (...) { throw user_error("[filterCreator_turbocharger] An integer must follow the maxCharge argument."); } maxCharge = lexical_cast(paramVal); if ( maxCharge < 0 ) { throw user_error("[filterCreator_turbocharger] maxCharge must be a positive integer."); } } else if ( boost::iequals(keyword,"precursorsBefore") ) { try { lexical_cast(paramVal); } catch (...) { throw user_error("[filterCreator_turbocharger] An integer must follow the precursorsBefore argument."); } precursorsBefore = lexical_cast(paramVal); if ( precursorsBefore < 0 ) { throw user_error("[filterCreator_turbocharger] precursorsBefore must be a positive integer."); } } else if ( boost::iequals(keyword,"precursorsAfter") ) { try { lexical_cast(paramVal); } catch (...) { throw user_error("[filterCreator_turbocharger] An integer must follow the precursorsAfter argument."); } precursorsAfter = lexical_cast(paramVal); if ( precursorsAfter < 0 ) { throw user_error("[filterCreator_turbocharger] precursorsAfter must be a positive integer."); } } else if ( boost::iequals(keyword,"halfIsoWidth") ) { try { lexical_cast(paramVal); } catch (...) { throw user_error("[filterCreator_turbocharger] A numeric value must follow the halfIsoWidth argument."); } isolationWidth = lexical_cast(paramVal); if ( isolationWidth <= 0 ) { throw user_error("[filterCreator_turbocharger] halfIsoWidth must be positive."); } } else if ( boost::iequals(keyword,"defaultMinCharge") ) { try { lexical_cast(paramVal); } catch (...) { throw user_error("[filterCreator_turbocharger] An integer must follow the defaultChargeMin argument."); } defaultChargeMin = lexical_cast(paramVal); if ( defaultChargeMin < 0 ) { throw user_error("[filterCreator_turbocharger] defaultChargeMin must be a positive integer."); } } else if ( boost::iequals(keyword,"defaultMaxCharge") ) { try { lexical_cast(paramVal); } catch (...) { throw user_error("[filterCreator_turbocharger] An integer must follow the defaultChargeMax argument."); } defaultChargeMax = lexical_cast(paramVal); if ( defaultChargeMax < 0 ) { throw user_error("[filterCreator_turbocharger] defaultChargeMax must be a positive integer."); } } else { throw user_error("[filterCreator_turbocharger] Invalid keyword entered."); } } // a few more sanity checks if ( minCharge > maxCharge ) { throw user_error("[filterCreator_turbocharger] maxCharge must be greater than or equal to minCharge."); } if ( defaultChargeMin > defaultChargeMax ) { throw user_error("[filterCreator_turbocharger] defaultMaxCharge must be greater than or equal to defaultMinCharge."); } // TODO: give the user some feedback regarding parameter selection //cout << "***turbocharger parameters***" << endl; //cout << "minCharge: " << minCharge << endl; //cout << "maxCharge: " << maxCharge << endl; //cout << "parentsBefore: " << parentsBefore << endl; //cout << "parentsAfter: " << parentsAfter << endl; //cout << "halfIsoWidth: " << isolationWidth << endl; //cout << "defaultMinCharge: " << defaultChargeMin << endl; //cout << "defaultMaxCharge: " << defaultChargeMax << endl; return SpectrumListPtr(new SpectrumList_ChargeFromIsotope(msd,maxCharge,minCharge,precursorsBefore,precursorsAfter,isolationWidth, defaultChargeMax,defaultChargeMin)); } UsageInfo usage_chargeFromIsotope = {"[minCharge=] [maxCharge=] [precursorsBefore=] [precursorsAfter=] [halfIsoWidth=] [defaultMinCharge=] [defaultMaxCharge=] [useVendorPeaks=]", "Predicts MSn spectrum precursor charge based on the isotopic distribution associated with the survey scan(s) of the selected precursor\n" " (default: 8) and (default 1): defines range of possible precursor charge states.\n" " (default: 2) and (default 0): number of survey (MS1) scans to check for precursor isotopes, before and after a MS/MS in retention time.\n" " (default: 1.25): half-width of the isolation window (in Th.) from which precursor is derived. Window is centered at target m/z with a total size of +/- the value entered.\n" " (default: 0) and (default: 0): in the event that no isotope is found in the isolation window, a range of charges between these two values will be assigned to the spectrum. If both values are left at zero, no charge will be assigned to the spectrum." }; /** * filter on the basis of ms2 activation type * * handler for --filter Activation option. Use it to create * output files containing only ETD or CID MSn data where both activation modes have been * interleaved within a given input vendor data file (eg: Thermo's Decision Tree acquisition mode). */ SpectrumListPtr filterCreator_ActivationType(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { istringstream parser(arg); string activationType; parser >> activationType; bal::to_upper(activationType); // MS_collision_induced_dissociation gets used together with MS_electron_transfer_dissociation // for the ETD/Supplemental Activation mode. Our filter is for separating B/Y from C/Z ions. // // Activation Type ETD "flag" CID "flag" Fragment Ion Type // ------------------------------------------------------------ // ETD Yes No C/Z // CID No Yes B/Y // HCD No Yes B/Y // ETD/SA Yes Yes C/Z // // Check for presence or absence of ETD flag only. set cvIDs; bool hasNot = false; // TODO: replace hand-written code with CVTranslator if (activationType == "CID") // HACK: CID means neither of HCD or ETD { hasNot = true; cvIDs.insert(MS_higher_energy_beam_type_collision_induced_dissociation); cvIDs.insert(MS_HCD); cvIDs.insert(MS_BIRD); cvIDs.insert(MS_ECD); cvIDs.insert(MS_ETD); cvIDs.insert(MS_IRMPD); cvIDs.insert(MS_PD); cvIDs.insert(MS_PSD); cvIDs.insert(MS_PQD); cvIDs.insert(MS_SID); cvIDs.insert(MS_SORI); } else if (activationType == "SA") { cvIDs.insert(MS_ETD); cvIDs.insert(MS_CID); } else if (activationType == "HECID") cvIDs.insert(MS_higher_energy_beam_type_collision_induced_dissociation); else if (activationType == "HCD") cvIDs.insert(MS_HCD); else if (activationType == "BIRD") cvIDs.insert(MS_BIRD); else if (activationType == "ECD") cvIDs.insert(MS_ECD); else if (activationType == "ETD") cvIDs.insert(MS_ETD); else if (activationType == "IRMPD") cvIDs.insert(MS_IRMPD); else if (activationType == "PD") cvIDs.insert(MS_PD); else if (activationType == "PSD") cvIDs.insert(MS_PSD); else if (activationType == "PQD") cvIDs.insert(MS_PQD); else if (activationType == "SID") cvIDs.insert(MS_SID); else if (activationType == "SORI") cvIDs.insert(MS_SORI); else throw user_error("[SpectrumListFactory::filterCreator_ActivationType()] invalid activation type \"" + activationType + "\""); return SpectrumListPtr(new SpectrumList_Filter(msd.run.spectrumListPtr, SpectrumList_FilterPredicate_ActivationType(cvIDs, hasNot))); } UsageInfo usage_activation = { "", "Keeps only spectra whose precursors have the specifed activation type. It doesn't affect non-MS spectra, and doesn't " "affect MS1 spectra. Use it to create output files containing only ETD or CID MSn data where both activation modes " "have been interleaved within a given input vendor data file (eg: Thermo's Decision Tree acquisition mode).\n" " is any one of: ETD CID SA HCD HECID BIRD ECD IRMPD PD PSD PQD SID or SORI." }; SpectrumListPtr filterCreator_AnalyzerType(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { istringstream parser(arg); string analyzerType; parser >> analyzerType; bal::to_upper(analyzerType); set cvIDs; // sometimes people use FT and Orbi interchangeably, which is OK because there are no hybrid FT+Orbi instruments if (bal::starts_with(analyzerType, "FT") || bal::starts_with(analyzerType, "ORBI")) { cvIDs.insert(MS_orbitrap); cvIDs.insert(MS_FT_ICR); } else if (bal::starts_with(analyzerType, "IT")) cvIDs.insert(MS_ion_trap); else if (bal::starts_with(analyzerType, "QUAD")) cvIDs.insert(MS_quadrupole); else if (analyzerType == "TOF") cvIDs.insert(MS_TOF); else throw user_error("[SpectrumListFactory::filterCreator_AnalyzerType()] invalid filter argument."); return SpectrumListPtr(new SpectrumList_Filter(msd.run.spectrumListPtr, SpectrumList_FilterPredicate_AnalyzerType(cvIDs))); } UsageInfo usage_analyzerTypeOld = { "", "This is deprecated syntax for filtering by mass analyzer type.\n" " can be \"FTMS\" or \"ITMS\"." }; UsageInfo usage_analyzerType = { "", "This filter keeps only spectra with the indicated mass analyzer type. \n" " is any one of \"quad\" \"orbi\" \"FT\" \"IT\" or \"TOF\".\n" "Sometimes people use the terms FT and Orbi interchangeably, which is OK " "because there are no hybrid FT+Orbi instruments - so this filter does too.\n" }; SpectrumListPtr filterCreator_thresholdFilter(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { istringstream parser(arg); string byTypeArg, orientationArg; double threshold; IntegerSet msLevels(1, INT_MAX); parser >> byTypeArg >> threshold >> orientationArg; if (parser) { string msLevelSets; getline(parser, msLevelSets); if (!msLevelSets.empty()) { msLevels = IntegerSet(); msLevels.parse(msLevelSets); } } ThresholdFilter::ThresholdingBy_Type byType; if (byTypeArg == "count") byType = ThresholdFilter::ThresholdingBy_Count; else if (byTypeArg == "count-after-ties") byType = ThresholdFilter::ThresholdingBy_CountAfterTies; else if (byTypeArg == "absolute") byType = ThresholdFilter::ThresholdingBy_AbsoluteIntensity; else if (byTypeArg == "bpi-relative") byType = ThresholdFilter::ThresholdingBy_FractionOfBasePeakIntensity; else if (byTypeArg == "tic-relative") byType = ThresholdFilter::ThresholdingBy_FractionOfTotalIntensity; else if (byTypeArg == "tic-cutoff") byType = ThresholdFilter::ThresholdingBy_FractionOfTotalIntensityCutoff; else { cerr << "unknown ThresholdFilter type " << byTypeArg << endl; return SpectrumListPtr(); } ThresholdFilter::ThresholdingOrientation orientation; if (orientationArg == "most-intense") orientation = ThresholdFilter::Orientation_MostIntense; else if (orientationArg == "least-intense") orientation = ThresholdFilter::Orientation_LeastIntense; else { cerr << "unknown ThresholdFilter orientation " << orientationArg << endl; return SpectrumListPtr(); } SpectrumDataFilterPtr filter(new ThresholdFilter(byType, threshold, orientation, msLevels)); return SpectrumListPtr(new SpectrumList_PeakFilter(msd.run.spectrumListPtr, filter)); } UsageInfo usage_thresholdFilter={" []", "This filter keeps data whose values meet various threshold criteria.\n" " must be one of:\n" " count - keep the n= [most|least] intense data points, where n is an integer. Any data points with the same intensity as the nth [most|least] intense data point are removed.\n" " count-after-ties - like \"count\", except that any data points with the same intensity as the nth [most|least] data point are retained.\n" " absolute - keep data whose absolute intensity is [more|less] than \n" " bpi-relative - keep data whose intensity is [more|less] than percent of the base peak intensity. Percentage is expressed as a number between 0 and 1, for example 75 percent is \"0.75\".\n" " tic-relative - keep data whose individual intensities are [more|less] than percent of the total ion current for the scan. Again, precentage is expressed as a number between 0 and 1.\n" " tic-cutoff - keep the [most|least] intense data points up to percent of the total ion current. That is, the TIC of the retained points is percent (expressed as a number between 0 and 1) of the original TIC.\n" " must be one of:\n" " most-intense (keep m/z-intensity pairs above the threshold)\n" " least-intense (keep m/z-intensity pairs below the threshold)\n" " is an optional int_set of MS levels - if provided, only scans with those MS levels will be filtered, and others left untouched." }; SpectrumListPtr filterCreator_polarityFilter(const MSData& msd, const string& arg, pwiz::util::IterationListenerRegistry* ilr) { istringstream parser(arg); string polarityArg; parser >> polarityArg; CVID polarity = CVID_Unknown; if (parser) { if (polarityArg == "positive" || polarityArg == "+") polarity = MS_positive_scan; else if (polarityArg == "negative" || polarityArg == "-") polarity = MS_negative_scan; } if (polarity == CVID_Unknown) throw user_error("[SpectrumListFactory::filterCreator_polarityFilter()] invalid polarity (expected \"positive\" or \"negative\")"); return SpectrumListPtr(new SpectrumList_Filter(msd.run.spectrumListPtr, SpectrumList_FilterPredicate_Polarity(polarity))); } UsageInfo usage_polarity = { "", "Keeps only spectra with scan of the selected .\n" " is any one of \"positive\" \"negative\" \"+\" or \"-\"." }; struct JumpTableEntry { const char* command; const UsageInfo& usage; // {const char *usage,const char &details} FilterCreator creator; }; JumpTableEntry jumpTable_[] = { {"index", usage_index, filterCreator_index}, {"msLevel", usage_msLevel, filterCreator_msLevel}, {"chargeState", usage_chargeState, filterCreator_chargeState}, {"precursorRecalculation", usage_precursorRecalculation, filterCreator_precursorRecalculation}, {"mzRefiner", usage_mzRefine, filterCreator_mzRefine}, {"lockmassRefiner", usage_lockmassRefiner, filterCreator_lockmassRefiner}, {"precursorRefine", usage_precursorRefine, filterCreator_precursorRefine}, {"peakPicking", usage_nativeCentroid, filterCreator_nativeCentroid}, {"scanNumber", usage_scanNumber, filterCreator_scanNumber}, {"scanEvent", usage_scanEvent, filterCreator_scanEvent}, {"scanTime", usage_scanTime, filterCreator_scanTime}, {"sortByScanTime",usage_sortScanTime, filterCreator_sortScanTime}, {"stripIT", usage_stripIT, filterCreator_stripIT}, {"metadataFixer", usage_metadataFixer, filterCreator_metadataFixer}, {"titleMaker", usage_titleMaker, filterCreator_titleMaker}, {"threshold", usage_thresholdFilter, filterCreator_thresholdFilter}, {"mzWindow", usage_mzWindow, filterCreator_mzWindow}, {"mzPrecursors", usage_mzPrecursors, filterCreator_mzPrecursors}, {"defaultArrayLength", usage_defaultArrayLength, filterCreator_defaultArrayLength}, {"zeroSamples", usage_zeroSamples , filterCreator_ZeroSamples}, {"mzPresent", usage_mzPresent, filterCreator_mzPresent}, {"scanSumming", usage_scanSummer, filterCreator_scanSummer}, // MSn Spectrum Processing/Filtering {"MS2Denoise", usage_MS2Denoise, filterCreator_MS2Denoise}, {"MS2Deisotope", usage_MS2Deisotope, filterCreator_MS2Deisotope}, {"ETDFilter", usage_ETDFilter, filterCreator_ETDFilter}, {"chargeStatePredictor", usage_chargeStatePredictor, filterCreator_chargeStatePredictor}, {"turbocharger", usage_chargeFromIsotope, filterCreator_chargeFromIsotope}, {"activation", usage_activation, filterCreator_ActivationType}, {"analyzer", usage_analyzerType, filterCreator_AnalyzerType}, {"analyzerType", usage_analyzerTypeOld, filterCreator_AnalyzerType}, {"polarity", usage_polarity, filterCreator_polarityFilter} }; size_t jumpTableSize_ = sizeof(jumpTable_)/sizeof(JumpTableEntry); JumpTableEntry* jumpTableEnd_ = jumpTable_ + jumpTableSize_; struct HasCommand { HasCommand(const string& command) : command_(command) {} bool operator()(const JumpTableEntry& entry) {return command_ == entry.command;} string command_; }; } // namespace PWIZ_API_DECL void SpectrumListFactory::wrap(MSData& msd, const string& wrapper, pwiz::util::IterationListenerRegistry* ilr) { if (!msd.run.spectrumListPtr) return; // split wrapper string into command + arg istringstream iss(wrapper); string command; iss >> command; string arg = wrapper.substr(command.size()); // switch on command, instantiate the filter JumpTableEntry* entry = find_if(jumpTable_, jumpTableEnd_, HasCommand(command)); if (entry == jumpTableEnd_) { // possibly a quoted commandline copied to a config file, // eg filter=\"index [3,7]\" or filter=\"precursorRecalculation\" string quot; if (bal::starts_with(command,"\"")) quot="\""; else if (bal::starts_with(command,"'")) quot="\'"; if (quot.size()) { command = command.substr(1); if (arg.size()) { if (bal::ends_with(arg,quot)) { arg = arg.substr(0,arg.size()-1); } } else if (bal::ends_with(command,quot)) { command = command.substr(0,command.size()-1); } entry = find_if(jumpTable_, jumpTableEnd_, HasCommand(command)); } } if (entry == jumpTableEnd_) { cerr << "[SpectrumListFactory] Ignoring wrapper: " << wrapper << endl; return; } SpectrumListPtr filter = entry->creator(msd, arg, ilr); msd.filterApplied(); // increase the filter count if (!filter.get()) { cerr << "command: " << command << endl; cerr << "arg: " << arg << endl; throw runtime_error("[SpectrumListFactory::wrap()] Error creating filter."); } // replace existing SpectrumList with the new one msd.run.spectrumListPtr = filter; } PWIZ_API_DECL void SpectrumListFactory::wrap(msdata::MSData& msd, const vector& wrappers, pwiz::util::IterationListenerRegistry* ilr) { for (vector::const_iterator it=wrappers.begin(); it!=wrappers.end(); ++it) wrap(msd, *it, ilr); } PWIZ_API_DECL string SpectrumListFactory::usage(bool detailedHelp, const char *morehelp_prompt, int maxLineLength) { ostringstream oss; MSData fakemsd; oss << endl; oss << "FILTER OPTIONS" << endl; if (!detailedHelp) { if (morehelp_prompt) oss << morehelp_prompt << endl; } else { oss << endl; oss << "Note: Filters are applied sequentially in the order that you list them, and the sequence order\n"; oss << "can make a large difference in your output. In particular, the peakPicking filter must be first\n"; oss << "in line if you wish to use the vendor-supplied centroiding algorithms since these use the vendor\n"; oss << "DLLs, which only operate on raw untransformed data.\n\n"; oss << "Many filters take 'int_set' arguments. An \'int_set\' is a list of intervals of the form [a,b] or a[-][b].\n"; oss << "For example \'[0,3]\' and \'0-3\' both mean \'the set of integers from 0 to 3 inclusive\'.\n"; oss << "\'1-\' means \'the set of integers from 1 to the largest allowable number\'. \n"; oss << "\'9\' is also an integer set, equivalent to \'[9,9]\'.\n"; oss << "\'[0,2] 5-7\' is the set \'0 1 2 5 6 7\'. \n"; } for (JumpTableEntry* it=jumpTable_; it!=jumpTableEnd_; ++it) { if (detailedHelp) oss << it->command << " " << it->usage[0] << endl << it->usage[1] << endl << endl ; else oss << it->command << " " << it->usage[0] << endl ; } oss << endl; // tidy up the word wrap std::string str = oss.str(); size_t lastPos = 0; for (size_t curPos = maxLineLength; curPos < str.length();) { std::string::size_type newlinePos = str.rfind( '\n', curPos ); if( newlinePos == std::string::npos || (newlinePos <= lastPos)) { // no newline within next wrap chars, add one std::string::size_type spacePos = str.rfind( ' ', curPos ); lastPos = curPos; if( spacePos == std::string::npos ) { curPos++; // no spaces, go long } else { str[ spacePos ] = '\n'; curPos = spacePos + maxLineLength + 1; } } else { lastPos = curPos; curPos = newlinePos + maxLineLength + 1; } } return str; } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/SpectrumList_ZeroSamplesFilter.cpp0000664000175100017510000000670012664775615031327 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_ZeroSamplesFilter.cpp 3550 2012-04-18 16:23:06Z chambm $ // // // Original author: Brian Pratt insilicos.com> // // Copyright 2012 Spielberg Family Center for Applied Proteomics // University of Southern California, Los Angeles, California 90033 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_ZeroSamplesFilter.hpp" #include "pwiz/utility/misc/Container.hpp" #include "pwiz/analysis/common/ExtraZeroSamplesFilter.hpp" #include "pwiz/analysis/common/ZeroSampleFiller.hpp" namespace pwiz { namespace analysis { using namespace msdata; using namespace pwiz::util; PWIZ_API_DECL SpectrumList_ZeroSamplesFilter::SpectrumList_ZeroSamplesFilter( const msdata::SpectrumListPtr& inner, const IntegerSet& msLevelsToFilter, Mode mode, size_t flankingZeroCount) : SpectrumListWrapper(inner), mode_(mode), flankingZeroCount_(flankingZeroCount), msLevelsToFilter_(msLevelsToFilter) { // add processing methods to the copy of the inner SpectrumList's data processing ProcessingMethod method; method.order = dp_->processingMethods.size(); if (Mode_RemoveExtraZeros == mode) { method.userParams.push_back(UserParam("removed extra zero samples")); } else { method.userParams.push_back(UserParam("added missing zero samples")); } if (!dp_->processingMethods.empty()) method.softwarePtr = dp_->processingMethods[0].softwarePtr; dp_->processingMethods.push_back(method); } PWIZ_API_DECL bool SpectrumList_ZeroSamplesFilter::accept(const msdata::SpectrumListPtr& inner) { return true; } PWIZ_API_DECL SpectrumPtr SpectrumList_ZeroSamplesFilter::spectrum(size_t index, bool getBinaryData) const { SpectrumPtr s = inner_->spectrum(index, true); if (!msLevelsToFilter_.contains(s->cvParam(MS_ms_level).valueAs())) return s; try { vector& mzs = s->getMZArray()->data; vector& intensities = s->getIntensityArray()->data; vector FilteredMZs, FilteredIntensities; if (Mode_AddMissingZeros == mode_) ZeroSampleFiller().fill(mzs, intensities, FilteredMZs, FilteredIntensities, flankingZeroCount_); else ExtraZeroSamplesFilter().remove_zeros(mzs, intensities, FilteredMZs, FilteredIntensities, !s->hasCVParam(MS_centroid_spectrum)); // preserve flanking zeros if not centroided mzs.swap(FilteredMZs); intensities.swap(FilteredIntensities); s->defaultArrayLength = mzs.size(); } catch(std::exception& e) { throw std::runtime_error(std::string("[SpectrumList_ZeroSamplesFilter] Error filtering intensity data: ") + e.what()); } s->dataProcessingPtr = dp_; return s; } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/PrecursorRecalculator.hpp0000664000175100017510000000326412664775615027533 0ustar teamcityteamcity00000000000000// // $Id: PrecursorRecalculator.hpp 3235 2012-01-25 13:44:50Z broter $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PRECURSORRECALCULATOR_HPP_ #define _PRECURSORRECALCULATOR_HPP_ #include "pwiz/data/msdata/MSData.hpp" namespace pwiz { namespace analysis { class PWIZ_API_DECL PrecursorRecalculator { public: struct PWIZ_API_DECL PrecursorInfo { double mz; double intensity; int charge; double score; PrecursorInfo() : mz(0), intensity(0), charge(0), score(0) {} }; typedef pwiz::msdata::MZIntensityPair MZIntensityPair; virtual void recalculate(const MZIntensityPair* begin, const MZIntensityPair* end, const PrecursorInfo& initialEstimate, std::vector& result) const = 0; virtual ~PrecursorRecalculator() {} }; } // namespace analysis } // namespace pwiz #endif // _PRECURSORRECALCULATOR_HPP_ pwiz/pwiz/analysis/spectrum_processing/SpectrumList_LockmassRefinerTest.cpp0000664000175100017510000000617412664775615031651 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_LockmassRefinerTest.cpp 9098 2015-11-01 04:11:45Z pcbrefugee $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2015 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/almost_equal.hpp" #include "pwiz/data/msdata/MSDataFile.hpp" #include "pwiz/data/msdata/Diff.hpp" #include "pwiz/data/vendor_readers/ExtendedReaderList.hpp" #include "SpectrumList_LockmassRefiner.hpp" #include "boost/foreach_field.hpp" #include "boost/core/null_deleter.hpp" using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::msdata; using namespace pwiz::analysis; ostream* os_ = 0; void test(const string& filepath, double lockmassMz, double lockmassTolerance) { ExtendedReaderList readerList; MSDataFile msd(filepath, &readerList); bfs::path targetResultFilename = bfs::path(__FILE__).parent_path() / "SpectrumList_LockmassRefinerTest.data" / (msd.run.id + ".mzML"); if (!bfs::exists(targetResultFilename)) throw runtime_error("test result file does not exist: " + targetResultFilename.string()); MSDataFile targetResult(targetResultFilename.string()); SpectrumList_LockmassRefiner lmr(msd.run.spectrumListPtr, lockmassMz, lockmassMz, lockmassTolerance); SpectrumListPtr sl(&lmr, boost::null_deleter()); msd.run.spectrumListPtr = sl; DiffConfig config; config.ignoreMetadata = true; Diff diff(msd, targetResult, config); if (lockmassMz == 0) { unit_assert(diff); } else { if (os_ && diff) *os_ << diff; unit_assert(!diff); } } void parseArgs(const vector& args, vector& rawpaths) { for (size_t i = 1; i < args.size(); ++i) { if (args[i] == "-v") os_ = &cout; else if (bal::starts_with(args[i], "--")) continue; else rawpaths.push_back(args[i]); } } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { vector args(argv, argv+argc); vector rawpaths; parseArgs(args, rawpaths); BOOST_FOREACH(const string& filepath, rawpaths) { if (bal::ends_with(filepath, "091204_NFDM_008.raw")) { test(filepath, 615.38, 0.1); test(filepath, 0, 0.1); } } } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/spectrum_processing/SpectrumList_3D.hpp0000664000175100017510000000370112664775615026166 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_3D.hpp 6385 2014-06-12 22:56:04Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_3D_HPP_ #define _SPECTRUMLIST_3D_HPP_ #include "pwiz/utility/misc/Export.hpp" #include #include "pwiz/data/msdata/SpectrumListWrapper.hpp" #include namespace pwiz { namespace analysis { typedef boost::container::flat_map > Spectrum3D; typedef boost::shared_ptr Spectrum3DPtr; /// SpectrumList implementation that can create 3D spectra of ion mobility drift time and m/z class PWIZ_API_DECL SpectrumList_3D : public msdata::SpectrumListWrapper { public: SpectrumList_3D(const msdata::SpectrumListPtr& inner); static bool accept(const msdata::SpectrumListPtr& inner); virtual msdata::SpectrumPtr spectrum(size_t index, bool getBinaryData = false) const; /// creates a 3d spectrum at the given scan start time (specified in seconds) and including the given drift time ranges (specified in milliseconds) virtual Spectrum3DPtr spectrum3d(double scanStartTime, const boost::icl::interval_set& driftTimeRanges) const; private: int mode_; }; } // namespace analysis } // namespace pwiz #endif // _SPECTRUMLIST_3D_HPP_ pwiz/pwiz/analysis/spectrum_processing/SpectrumList_PeakPicker.cpp0000664000175100017510000001747512664775615027746 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_PeakPicker.cpp 9071 2015-10-29 23:25:16Z pcbrefugee $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_PeakPicker.hpp" #include "pwiz/utility/misc/Container.hpp" #include #include "pwiz/data/vendor_readers/ABI/SpectrumList_ABI.hpp" #include "pwiz/data/vendor_readers/ABI/T2D/SpectrumList_ABI_T2D.hpp" #include "pwiz/data/vendor_readers/Agilent/SpectrumList_Agilent.hpp" #include "pwiz/data/vendor_readers/Bruker/SpectrumList_Bruker.hpp" #include "pwiz/data/vendor_readers/Thermo/SpectrumList_Thermo.hpp" namespace pwiz { namespace analysis { using namespace msdata; using namespace pwiz::util; PWIZ_API_DECL SpectrumList_PeakPicker::SpectrumList_PeakPicker( const msdata::SpectrumListPtr& inner, PeakDetectorPtr algorithm, bool preferVendorPeakPicking, const IntegerSet& msLevelsToPeakPick) : SpectrumListWrapper(inner), algorithm_(algorithm), msLevelsToPeakPick_(msLevelsToPeakPick), mode_(0) { if (preferVendorPeakPicking) { detail::SpectrumList_Thermo* thermo = dynamic_cast(&*inner); if (thermo) { mode_ = 1; } detail::SpectrumList_Bruker* bruker = dynamic_cast(&*inner); if (bruker) { mode_ = 2; } detail::SpectrumList_ABI* abi = dynamic_cast(&*inner); if (abi) { mode_ = 3; } detail::SpectrumList_Agilent* agilent = dynamic_cast(&*inner); if (agilent) { mode_ = 4; } detail::SpectrumList_ABI_T2D* abi_t2d = dynamic_cast(&*inner); if (abi_t2d) { mode_ = 5; } } // add processing methods to the copy of the inner SpectrumList's data processing ProcessingMethod method; method.order = dp_->processingMethods.size(); method.set(MS_peak_picking); if (!dp_->processingMethods.empty()) method.softwarePtr = dp_->processingMethods[0].softwarePtr; if (mode_ == 1) method.userParams.push_back(UserParam("Thermo/Xcalibur peak picking")); else if (mode_ == 2) method.userParams.push_back(UserParam("Bruker/Agilent/CompassXtract peak picking")); else if (mode_ == 3) method.userParams.push_back(UserParam("ABI/Analyst peak picking")); else if (mode_ == 4) method.userParams.push_back(UserParam("Agilent/MassHunter peak picking")); else if (mode_ == 5) method.userParams.push_back(UserParam("ABI/DataExplorer peak picking")); //else // method.userParams.push_back(algorithm->name()); if (preferVendorPeakPicking && !mode_ && (algorithm_ != NULL)) // VendorOnlyPeakPicker sets algorithm null, we deal with this at get binary data time { cerr << "Warning: vendor peakPicking was requested, but is unavailable"; #ifdef WIN32 cerr << " for this input data. "; #else cerr << " as it depends on Windows DLLs. "; #endif cerr << "Using ProteoWizard centroiding algorithm instead." << endl; cerr << "High-quality peak-picking can be enabled using the cwt flag." << endl; } dp_->processingMethods.push_back(method); } PWIZ_API_DECL bool SpectrumList_PeakPicker::accept(const msdata::SpectrumListPtr& inner) { return true; } PWIZ_API_DECL SpectrumPtr SpectrumList_PeakPicker::spectrum(size_t index, DetailLevel detailLevel) const { // for full metadata, defaultArrayLength must be accurate, so go ahead and do peak picking anyway return (int) detailLevel >= (int) DetailLevel_FullMetadata ? spectrum(index, true) : inner_->spectrum(index, detailLevel); } PWIZ_API_DECL SpectrumPtr SpectrumList_PeakPicker::spectrum(size_t index, bool getBinaryData) const { SpectrumPtr s; switch (mode_) { case 1: s = dynamic_cast(&*inner_)->spectrum(index, getBinaryData, msLevelsToPeakPick_); break; case 2: s = dynamic_cast(&*inner_)->spectrum(index, getBinaryData, msLevelsToPeakPick_); break; case 3: s = dynamic_cast(&*inner_)->spectrum(index, getBinaryData, msLevelsToPeakPick_); break; case 4: s = dynamic_cast(&*inner_)->spectrum(index, getBinaryData, msLevelsToPeakPick_); break; case 5: s = dynamic_cast(&*inner_)->spectrum(index, getBinaryData, msLevelsToPeakPick_); break; case 0: default: s = inner_->spectrum(index, true); // TODO you'd think this would be "getBinaryData" instead of "true" but that breaks SpectrumListFactoryTest break; } if (!getBinaryData || !msLevelsToPeakPick_.contains(s->cvParam(MS_ms_level).valueAs())) return s; vector& cvParams = s->cvParams; vector::iterator itr = std::find(cvParams.begin(), cvParams.end(), MS_centroid_spectrum); // return non-profile spectra as-is // (could have been acquired as centroid, or vendor may have done the centroiding) if (itr != cvParams.end()) { // the vendor spectrum lists must put "profile spectrum" if they actually performed centroiding vector::iterator itr2 = boost::range::remove_if(cvParams, CVParamIs(MS_profile_spectrum)); if (itr2 != cvParams.end()) cvParams.erase(itr2); else this->warn_once("[SpectrumList_PeakPicker]: one or more spectra are already centroided, no processing needed"); return s; } // is this declared as profile? itr = std::find(cvParams.begin(), cvParams.end(), MS_profile_spectrum); if (cvParams.end() == itr) { this->warn_once("[SpectrumList_PeakPicker]: one or more spectra have undeclared profile/centroid status, assuming profile data and that peakpicking is needed"); itr = std::find(cvParams.begin(), cvParams.end(), MS_spectrum_representation); // this should be there if nothing else } // make sure the spectrum has binary data if (!s->getMZArray().get() || !s->getIntensityArray().get()) s = inner_->spectrum(index, true); // replace profile or nonspecific term with centroid term *itr = MS_centroid_spectrum; try { if (algorithm_ == NULL) // As with VendorOnlyPeakPicker throw NoVendorPeakPickingException(); vector& mzs = s->getMZArray()->data; vector& intensities = s->getIntensityArray()->data; vector xPeakValues, yPeakValues; algorithm_->detect(mzs, intensities, xPeakValues, yPeakValues); mzs.swap(xPeakValues); intensities.swap(yPeakValues); s->defaultArrayLength = mzs.size(); } catch(std::exception& e) { throw std::runtime_error(std::string("[SpectrumList_PeakPicker::spectrum()] Error picking peaks: ") + e.what()); } s->dataProcessingPtr = dp_; return s; } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/SpectrumList_PeakFilter.hpp0000664000175100017510000000350412664775615027747 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_PeakFilter.hpp 6902 2014-11-17 22:34:37Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_PEAKFILTER_HPP_ #define _SPECTRUMLIST_PEAKFILTER_HPP_ #include #include "pwiz/data/msdata/SpectrumListWrapper.hpp" #include "pwiz/analysis/common/DataFilter.hpp" namespace pwiz { namespace analysis { /// SpectrumList implementation that returns spectra with the specified SpectrumDataFilter operation applied class PWIZ_API_DECL SpectrumList_PeakFilter : public msdata::SpectrumListWrapper { public: SpectrumList_PeakFilter(const msdata::SpectrumListPtr& inner, SpectrumDataFilterPtr filterFunctor); /// peak filters work on any SpectrumList static bool accept(const msdata::SpectrumListPtr& inner) {return true;} virtual msdata::SpectrumPtr spectrum(size_t index, bool getBinaryData = false) const; virtual msdata::SpectrumPtr spectrum(size_t index, msdata::DetailLevel detailLevel = msdata::DetailLevel_FullMetadata) const; private: SpectrumDataFilterPtr filterFunctor_; }; } // namespace analysis } // namespace pwiz #endif // _SPECTRUMLIST_PEAKFILTER_HPP_ pwiz/pwiz/analysis/spectrum_processing/SpectrumList_LockmassRefiner.cpp0000664000175100017510000000602712664775614031005 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_LockmassRefiner.cpp 9095 2015-11-01 01:14:24Z pcbrefugee $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_LockmassRefiner.hpp" #include "pwiz/data/vendor_readers/Waters/SpectrumList_Waters.hpp" namespace pwiz { namespace analysis { using namespace msdata; using namespace pwiz::util; PWIZ_API_DECL SpectrumList_LockmassRefiner::SpectrumList_LockmassRefiner(const msdata::SpectrumListPtr& inner, double lockmassMzPosScans, double lockmassMzNegScans, double lockmassTolerance) : SpectrumListWrapper(inner), mzPositiveScans_(lockmassMzPosScans), mzNegativeScans_(lockmassMzNegScans), tolerance_(lockmassTolerance) { // add processing methods to the copy of the inner SpectrumList's data processing ProcessingMethod method; method.order = dp_->processingMethods.size(); method.set(MS_m_z_calibration); if (!dp_->processingMethods.empty()) method.softwarePtr = dp_->processingMethods[0].softwarePtr; detail::SpectrumList_Waters* waters = dynamic_cast(&*inner); if (waters) { method.userParams.push_back(UserParam("Waters lockmass correction")); } else { cerr << "Warning: lockmass refinement was requested, but is unavailable"; #ifdef WIN32 cerr << " for non-Waters input data. "; #else cerr << " as it depends on Windows DLLs. "; #endif } dp_->processingMethods.push_back(method); } PWIZ_API_DECL bool SpectrumList_LockmassRefiner::accept(const msdata::SpectrumListPtr& inner) { return true; } PWIZ_API_DECL SpectrumPtr SpectrumList_LockmassRefiner::spectrum(size_t index, DetailLevel detailLevel) const { // for full metadata, defaultArrayLength must be accurate, so go ahead and do peak picking anyway return (int) detailLevel >= (int) DetailLevel_FullMetadata ? spectrum(index, true) : inner_->spectrum(index, detailLevel); } PWIZ_API_DECL SpectrumPtr SpectrumList_LockmassRefiner::spectrum(size_t index, bool getBinaryData) const { SpectrumPtr s; detail::SpectrumList_Waters* waters = dynamic_cast(&*inner_); if (waters) s = waters->spectrum(index, getBinaryData, mzPositiveScans_, mzNegativeScans_, tolerance_); else s = inner_->spectrum(index, true); s->dataProcessingPtr = dp_; return s; } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/SpectrumList_TitleMaker.hpp0000664000175100017510000000550512664775615027765 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_TitleMaker.hpp 2532 2011-03-03 22:48:24Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_TITLEMAKER_HPP_ #define _SPECTRUMLIST_TITLEMAKER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/SpectrumListWrapper.hpp" namespace pwiz { namespace analysis { /// SpectrumList implementation to add (or replace) a spectrum title to each spectrum /// according to a user-specified format. class PWIZ_API_DECL SpectrumList_TitleMaker : public msdata::SpectrumListWrapper { public: /// The format string recognizes some keywords to replace with the appropriate field: /// - Run::id /// - SpectrumIdentity::index /// - SpectrumIdentity::id (nativeID) /// - if the nativeID can be represented as a single number, that number, else index /// - for the first precursor, Activation::cvParamChild("dissociation method") /// - for the first precursor, IsolationWindow::cvParam("isolation target m/z") /// - for the first selected ion of the first precursor, SelectedIon::cvParam("selected ion m/z") /// - for the first selected ion of the first precursor, SelectedIon::cvParam("charge state") /// - Spectrum::cvParamChild("spectrum type") /// - for the first scan, Scan::cvParam("scan start time") converted to seconds /// - for the first scan, Scan::cvParam("scan start time") converted to minutes /// - Spectrum::cvParam("base peak m/z") /// - Spectrum::cvParam("base peak intensity") /// - Spectrum::cvParam("total ion current") SpectrumList_TitleMaker(const msdata::MSData& msd, const std::string& format); static bool accept(const msdata::SpectrumListPtr& inner) {return true;} virtual msdata::SpectrumPtr spectrum(size_t index, bool getBinaryData = false) const; private: const msdata::MSData& msd_; const std::string format_; cv::CVID nativeIdFormat_; }; } // namespace analysis } // namespace pwiz #endif // _SPECTRUMLIST_TITLEMAKER_HPP_ pwiz/pwiz/analysis/spectrum_processing/SpectrumList_Smoother.hpp0000664000175100017510000000343612664775615027525 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_Smoother.hpp 1191 2009-08-14 19:33:05Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_SMOOTHER_HPP_ #define _SPECTRUMLIST_SMOOTHER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/utility/misc/IntegerSet.hpp" #include "pwiz/data/msdata/SpectrumListWrapper.hpp" #include "pwiz/analysis/common/SavitzkyGolaySmoother.hpp" #include "pwiz/analysis/common/WhittakerSmoother.hpp" namespace pwiz { namespace analysis { /// SpectrumList implementation to return smoothed spectral data class PWIZ_API_DECL SpectrumList_Smoother : public msdata::SpectrumListWrapper { public: SpectrumList_Smoother(const msdata::SpectrumListPtr& inner, SmootherPtr algorithm, const util::IntegerSet& msLevelsToSmooth); static bool accept(const msdata::SpectrumListPtr& inner); virtual msdata::SpectrumPtr spectrum(size_t index, bool getBinaryData = false) const; private: SmootherPtr algorithm_; const util::IntegerSet msLevelsToSmooth_; }; } // namespace analysis } // namespace pwiz #endif // _SPECTRUMLIST_SMOOTHER_HPP_ pwiz/pwiz/analysis/spectrum_processing/SpectrumList_PrecursorRecalculator.cpp0000664000175100017510000001717712664775615032254 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_PrecursorRecalculator.cpp 6643 2014-09-01 21:24:30Z paragmallick $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_PrecursorRecalculator.hpp" #include "PrecursorRecalculatorDefault.hpp" #include "pwiz/analysis/peakdetect/PeakFamilyDetectorFT.hpp" #include "pwiz/analysis/passive/MSDataCache.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace analysis { using namespace pwiz::cv; using namespace pwiz::msdata; using namespace pwiz::data; // // SpectrumList_PrecursorRecalculator::Impl // struct SpectrumList_PrecursorRecalculator::Impl { shared_ptr precursorRecalculator; MSDataCache cache; CVID targetMassAnalyzerType; Impl(const MSData& msd); }; namespace { shared_ptr createPrecursorRecalculator_msprefix(CVID targetMassAnalyzerType) { // instantiate PeakFamilyDetector PeakFamilyDetectorFT::Config pfdftConfig; if (targetMassAnalyzerType == MS_FT_ICR) pfdftConfig.cp = CalibrationParameters::thermo_FT(); else if (targetMassAnalyzerType == MS_orbitrap) pfdftConfig.cp = CalibrationParameters::thermo_Orbitrap(); else throw runtime_error("[SpectrumList_PrecursorRecalculator] This isn't happening"); shared_ptr pfd(new PeakFamilyDetectorFT(pfdftConfig)); // instantiate PrecursorRecalculatorDefault PrecursorRecalculatorDefault::Config config; config.peakFamilyDetector = pfd; config.mzLeftWidth = 3; config.mzRightWidth = 1.6; return shared_ptr(new PrecursorRecalculatorDefault(config)); } } // namespace SpectrumList_PrecursorRecalculator::Impl::Impl(const MSData& msd) : targetMassAnalyzerType(CVID_Unknown) { cache.open(msd); // choose highest-accuracy mass analyzer for targetMassAnalyzerType for (vector::const_iterator it=msd.instrumentConfigurationPtrs.begin(), end=msd.instrumentConfigurationPtrs.end(); it!=end; ++it) { if (!it->get()) continue; const InstrumentConfiguration& ic = **it; BOOST_FOREACH(const Component& component, ic.componentList) { if (component.type == ComponentType_Analyzer) if (targetMassAnalyzerType!=MS_FT_ICR && targetMassAnalyzerType!=MS_orbitrap ) targetMassAnalyzerType = component.cvParamChild(MS_mass_analyzer_type).cvid; } } //if (targetMassAnalyzerType!=MS_FT_ICR && // targetMassAnalyzerType!=MS_orbitrap) // targetMassAnalyzerType = ic.componentList.analyzer(0).cvParamChild(MS_mass_analyzer_type).cvid; //} if (targetMassAnalyzerType!=MS_FT_ICR && targetMassAnalyzerType!=MS_orbitrap) throw runtime_error(("[SpectrumList_PrecursorRecalculator] Mass analyzer not supported: " + cvTermInfo(targetMassAnalyzerType).name).c_str()); precursorRecalculator = createPrecursorRecalculator_msprefix(targetMassAnalyzerType); } // // SpectrumList_PrecursorRecalculator // PWIZ_API_DECL SpectrumList_PrecursorRecalculator::SpectrumList_PrecursorRecalculator( const MSData& msd) : SpectrumListWrapper(msd.run.spectrumListPtr), impl_(new Impl(msd)) { // add processing methods to the copy of the inner SpectrumList's data processing ProcessingMethod method; method.order = dp_->processingMethods.size(); method.userParams.push_back(UserParam("precursor recalculation", "msPrefix defaults")); if (!dp_->processingMethods.empty()) method.softwarePtr = dp_->processingMethods[0].softwarePtr; dp_->processingMethods.push_back(method); } namespace{ PrecursorRecalculator::PrecursorInfo getInitialEstimate(const Spectrum& spectrum) { PrecursorRecalculator::PrecursorInfo result; if (spectrum.precursors.empty()) return result; const Precursor& precursor = spectrum.precursors[0]; if (precursor.selectedIons.empty()) return result; const SelectedIon& selectedIon = precursor.selectedIons[0]; result.mz = selectedIon.cvParam(MS_selected_ion_m_z).valueAs(); result.charge = selectedIon.cvParam(MS_charge_state).valueAs(); return result; } void encodePrecursorInfo(Spectrum& spectrum, vector precursorInfos) { if (spectrum.precursors.empty() || precursorInfos.empty()) return; Precursor& precursor = spectrum.precursors[0]; precursor.selectedIons.clear(); for (vector::const_iterator it=precursorInfos.begin(), end=precursorInfos.end(); it!=end; ++it) { precursor.selectedIons.push_back(SelectedIon()); SelectedIon& selectedIon = precursor.selectedIons.back(); selectedIon.set(MS_selected_ion_m_z, it->mz); selectedIon.set(MS_peak_intensity, it->intensity); selectedIon.set(MS_charge_state, it->charge); selectedIon.userParams.push_back(UserParam("msprefix score", lexical_cast(it->score), "xsd:float")); } } } // namespace PWIZ_API_DECL SpectrumPtr SpectrumList_PrecursorRecalculator::spectrum(size_t index, bool getBinaryData) const { SpectrumPtr originalSpectrum = inner_->spectrum(index, getBinaryData); // find parent spectrum in cache size_t parentIndex = index; while (1) { if (parentIndex-- == 0) return originalSpectrum; const SpectrumInfo& info = impl_->cache.spectrumInfo(parentIndex); if (info.msLevel==1 && info.massAnalyzerType==impl_->targetMassAnalyzerType) break; } const SpectrumInfo& parent = impl_->cache.spectrumInfo(parentIndex, true); if (parent.data.empty()) return originalSpectrum; // run precursorRecalculator PrecursorRecalculator::PrecursorInfo initialEstimate = getInitialEstimate(*originalSpectrum); if (initialEstimate.mz == 0) return originalSpectrum; vector result; try { impl_->precursorRecalculator->recalculate(&parent.data[0], &parent.data[0]+parent.data.size(), initialEstimate, result); } catch (exception& e) { cerr << e.what() << endl << "[SpectrumList_PrecursorRecalculator] Caught exception in spectrum index " << originalSpectrum->index << " (" << originalSpectrum->id << "," << ")\n"; return originalSpectrum; } // encode result in Spectrum SpectrumPtr newSpectrum(new Spectrum(*originalSpectrum)); encodePrecursorInfo(*newSpectrum, result); return newSpectrum; } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/SpectrumList_FilterTest.cpp0000664000175100017510000004576612664775615030021 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_FilterTest.cpp 6478 2014-07-08 20:01:38Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "SpectrumList_Filter.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/IntegerSet.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/data/msdata/examples.hpp" #include "pwiz/data/msdata/Serializer_mzML.hpp" #include using namespace pwiz; using namespace pwiz::msdata; using namespace pwiz::analysis; using namespace pwiz::util; using boost::logic::tribool; ostream* os_ = 0; void printSpectrumList(const SpectrumList& sl, ostream& os) { os << "size: " << sl.size() << endl; for (size_t i=0, end=sl.size(); iindex << " " << spectrum->id << " " << "ms" << spectrum->cvParam(MS_ms_level).value << " " << "scanEvent:" << spectrum->scanList.scans[0].cvParam(MS_preset_scan_configuration).value << " " << "scanTime:" << spectrum->scanList.scans[0].cvParam(MS_scan_start_time).timeInSeconds() << " " << endl; } } SpectrumListPtr createSpectrumList() { SpectrumListSimplePtr sl(new SpectrumListSimple); for (size_t i=0; i<10; ++i) { SpectrumPtr spectrum(new Spectrum); spectrum->index = i; spectrum->id = "scan=" + lexical_cast(100+i); spectrum->setMZIntensityPairs(vector(i), MS_number_of_detector_counts); // add mz/intensity to the spectra for mzPresent filter vector mzint(i*2); for (size_t j=1.0; jsetMZIntensityPairs(mzint, MS_number_of_detector_counts); bool isMS1 = i%3==0; spectrum->set(MS_ms_level, isMS1 ? 1 : 2); spectrum->set(isMS1 ? MS_MS1_spectrum : MS_MSn_spectrum); // outfit the spectra with mass analyzer definitions to test the massAnalyzer filter spectrum->scanList.scans.push_back(Scan()); spectrum->scanList.scans[0].instrumentConfigurationPtr = InstrumentConfigurationPtr(new InstrumentConfiguration()); InstrumentConfigurationPtr p = spectrum->scanList.scans[0].instrumentConfigurationPtr; if (i%3 == 0) { p->componentList.push_back(Component(MS_orbitrap, 0/*order*/)); } else { if (i%2) p->componentList.push_back(Component(MS_orbitrap, 0/*order*/)); else p->componentList.push_back(Component(MS_radial_ejection_linear_ion_trap, 0/*order*/)); } if (i%3 != 0) spectrum->precursors.push_back(Precursor(500, 3)); // add precursors and activation types to the MS2 spectra if (i==1 || i ==5) // ETD { spectrum->precursors[0].activation.set(MS_electron_transfer_dissociation); } else if (i==2) // CID { spectrum->precursors[0].activation.set(MS_collision_induced_dissociation); } else if (i==4) // HCD { spectrum->precursors[0].activation.set(MS_HCD); } else if (i==8) // IRMPD { spectrum->precursors[0].activation.set(MS_IRMPD); } else if (i==7) // ETD + SA { spectrum->precursors[0].activation.set(MS_electron_transfer_dissociation); spectrum->precursors[0].activation.set(MS_collision_induced_dissociation); } spectrum->scanList.scans.push_back(Scan()); spectrum->scanList.scans[0].set(MS_preset_scan_configuration, i%4); spectrum->scanList.scans[0].set(MS_scan_start_time, 420+i, UO_second); sl->spectra.push_back(spectrum); } if (os_) { *os_ << "original spectrum list:\n"; printSpectrumList(*sl, *os_); *os_ << endl; } return sl; } struct EvenPredicate : public SpectrumList_Filter::Predicate { virtual tribool accept(const SpectrumIdentity& spectrumIdentity) const { return spectrumIdentity.index%2 == 0; } }; void testEven(SpectrumListPtr sl) { if (os_) *os_ << "testEven:\n"; SpectrumList_Filter filter(sl, EvenPredicate()); if (os_) { printSpectrumList(filter, *os_); *os_ << endl; } unit_assert(filter.size() == 5); for (size_t i=0, end=filter.size(); i5) pastMaxIndex = true; return (spectrumIdentity.index==1 || spectrumIdentity.index==3 || spectrumIdentity.index==5); } virtual bool done() const { return pastMaxIndex; } }; void testSelectedIndices(SpectrumListPtr sl) { if (os_) *os_ << "testSelectedIndices:\n"; SpectrumList_Filter filter(sl, SelectedIndexPredicate()); if (os_) { printSpectrumList(filter, *os_); *os_ << endl; } unit_assert(filter.size() == 3); unit_assert(filter.spectrumIdentity(0).id == "scan=101"); unit_assert(filter.spectrumIdentity(1).id == "scan=103"); unit_assert(filter.spectrumIdentity(2).id == "scan=105"); } struct HasBinaryDataPredicate : public SpectrumList_Filter::Predicate { HasBinaryDataPredicate(DetailLevel suggestedDetailLevel) : detailLevel_(suggestedDetailLevel) {} DetailLevel detailLevel_; virtual DetailLevel suggestedDetailLevel() const {return detailLevel_;} virtual tribool accept(const msdata::SpectrumIdentity& spectrumIdentity) const { return boost::logic::indeterminate; } virtual tribool accept(const Spectrum& spectrum) const { if (spectrum.binaryDataArrayPtrs.empty()) return boost::logic::indeterminate; return !spectrum.binaryDataArrayPtrs[0]->data.empty(); } }; void testHasBinaryData(SpectrumListPtr sl) { if (os_) *os_ << "testHasBinaryData:\n"; MSData msd; examples::initializeTiny(msd); shared_ptr ss(new stringstream); Serializer_mzML serializer; serializer.write(*ss, msd); MSData msd2; serializer.read(ss, msd2); sl = msd2.run.spectrumListPtr; { SpectrumList_Filter filter(sl, HasBinaryDataPredicate(DetailLevel_FullMetadata)); unit_assert(filter.empty()); } { SpectrumList_Filter filter(sl, HasBinaryDataPredicate(DetailLevel_FullData)); if (os_) { printSpectrumList(filter, *os_); *os_ << endl; } unit_assert_operator_equal(4, filter.size()); } } void testIndexSet(SpectrumListPtr sl) { if (os_) *os_ << "testIndexSet:\n"; IntegerSet indexSet; indexSet.insert(3,5); indexSet.insert(7); indexSet.insert(9); SpectrumList_Filter filter(sl, SpectrumList_FilterPredicate_IndexSet(indexSet)); if (os_) { printSpectrumList(filter, *os_); *os_ << endl; } unit_assert(filter.size() == 5); unit_assert(filter.spectrumIdentity(0).id == "scan=103"); unit_assert(filter.spectrumIdentity(1).id == "scan=104"); unit_assert(filter.spectrumIdentity(2).id == "scan=105"); unit_assert(filter.spectrumIdentity(3).id == "scan=107"); unit_assert(filter.spectrumIdentity(4).id == "scan=109"); } void testScanNumberSet(SpectrumListPtr sl) { if (os_) *os_ << "testScanNumberSet:\n"; IntegerSet scanNumberSet; scanNumberSet.insert(102,104); scanNumberSet.insert(107); SpectrumList_Filter filter(sl, SpectrumList_FilterPredicate_ScanNumberSet(scanNumberSet)); if (os_) { printSpectrumList(filter, *os_); *os_ << endl; } unit_assert(filter.size() == 4); unit_assert(filter.spectrumIdentity(0).id == "scan=102"); unit_assert(filter.spectrumIdentity(1).id == "scan=103"); unit_assert(filter.spectrumIdentity(2).id == "scan=104"); unit_assert(filter.spectrumIdentity(3).id == "scan=107"); } void testScanEventSet(SpectrumListPtr sl) { if (os_) *os_ << "testScanEventSet:\n"; IntegerSet scanEventSet; scanEventSet.insert(0,0); scanEventSet.insert(2,3); SpectrumList_Filter filter(sl, SpectrumList_FilterPredicate_ScanEventSet(scanEventSet)); if (os_) { printSpectrumList(filter, *os_); *os_ << endl; } unit_assert(filter.size() == 7); unit_assert(filter.spectrumIdentity(0).id == "scan=100"); unit_assert(filter.spectrumIdentity(1).id == "scan=102"); unit_assert(filter.spectrumIdentity(2).id == "scan=103"); unit_assert(filter.spectrumIdentity(3).id == "scan=104"); unit_assert(filter.spectrumIdentity(4).id == "scan=106"); unit_assert(filter.spectrumIdentity(5).id == "scan=107"); unit_assert(filter.spectrumIdentity(6).id == "scan=108"); } void testScanTimeRange(SpectrumListPtr sl) { if (os_) *os_ << "testScanTimeRange:\n"; const double low = 422.5; const double high = 427.5; SpectrumList_Filter filter(sl, SpectrumList_FilterPredicate_ScanTimeRange(low, high)); if (os_) { printSpectrumList(filter, *os_); *os_ << endl; } unit_assert(filter.size() == 5); unit_assert(filter.spectrumIdentity(0).id == "scan=103"); unit_assert(filter.spectrumIdentity(1).id == "scan=104"); unit_assert(filter.spectrumIdentity(2).id == "scan=105"); unit_assert(filter.spectrumIdentity(3).id == "scan=106"); unit_assert(filter.spectrumIdentity(4).id == "scan=107"); } void testMSLevelSet(SpectrumListPtr sl) { if (os_) *os_ << "testMSLevelSet:\n"; IntegerSet msLevelSet; msLevelSet.insert(1); SpectrumList_Filter filter(sl, SpectrumList_FilterPredicate_MSLevelSet(msLevelSet)); if (os_) { printSpectrumList(filter, *os_); *os_ << endl; } unit_assert(filter.size() == 4); unit_assert(filter.spectrumIdentity(0).id == "scan=100"); unit_assert(filter.spectrumIdentity(1).id == "scan=103"); unit_assert(filter.spectrumIdentity(2).id == "scan=106"); unit_assert(filter.spectrumIdentity(3).id == "scan=109"); IntegerSet msLevelSet2; msLevelSet2.insert(2); SpectrumList_Filter filter2(sl, SpectrumList_FilterPredicate_MSLevelSet(msLevelSet2)); if (os_) { printSpectrumList(filter2, *os_); *os_ << endl; } unit_assert(filter2.size() == 6); unit_assert(filter2.spectrumIdentity(0).id == "scan=101"); unit_assert(filter2.spectrumIdentity(1).id == "scan=102"); unit_assert(filter2.spectrumIdentity(2).id == "scan=104"); unit_assert(filter2.spectrumIdentity(3).id == "scan=105"); unit_assert(filter2.spectrumIdentity(4).id == "scan=107"); unit_assert(filter2.spectrumIdentity(5).id == "scan=108"); } void testMS2Activation(SpectrumListPtr sl) { if (os_) *os_ << "testMS2Activation:\n"; SpectrumListPtr ms2filter(new SpectrumList_Filter(sl, SpectrumList_FilterPredicate_MSLevelSet(IntegerSet(2)))); set cvIDs; // CID cvIDs.insert(MS_electron_transfer_dissociation); cvIDs.insert(MS_HCD); cvIDs.insert(MS_IRMPD); SpectrumList_Filter filter(ms2filter, SpectrumList_FilterPredicate_ActivationType(cvIDs, true)); if (os_) { printSpectrumList(filter, *os_); *os_ << endl; } unit_assert(filter.size() == 1); unit_assert(filter.spectrumIdentity(0).id == "scan=102"); // ETD + SA cvIDs.clear(); cvIDs.insert(MS_electron_transfer_dissociation); cvIDs.insert(MS_collision_induced_dissociation); SpectrumList_Filter filter1(ms2filter, SpectrumList_FilterPredicate_ActivationType(cvIDs, false)); if (os_) { printSpectrumList(filter1, *os_); *os_ << endl; } unit_assert(filter1.size() == 1); unit_assert(filter1.spectrumIdentity(0).id == "scan=107"); // ETD cvIDs.clear(); cvIDs.insert(MS_electron_transfer_dissociation); SpectrumList_Filter filter2(ms2filter, SpectrumList_FilterPredicate_ActivationType(cvIDs, false)); if (os_) { printSpectrumList(filter2, *os_); *os_ << endl; } unit_assert(filter2.size() == 3); unit_assert(filter2.spectrumIdentity(0).id == "scan=101"); unit_assert(filter2.spectrumIdentity(1).id == "scan=105"); unit_assert(filter2.spectrumIdentity(2).id == "scan=107"); // HCD cvIDs.clear(); cvIDs.insert(MS_HCD); SpectrumList_Filter filter3(ms2filter, SpectrumList_FilterPredicate_ActivationType(cvIDs, false)); if (os_) { printSpectrumList(filter3, *os_); *os_ << endl; } unit_assert(filter3.size() == 1); unit_assert(filter3.spectrumIdentity(0).id == "scan=104"); // IRMPD cvIDs.clear(); cvIDs.insert(MS_IRMPD); SpectrumList_Filter filter4(ms2filter, SpectrumList_FilterPredicate_ActivationType(cvIDs, false)); if (os_) { printSpectrumList(filter4, *os_); *os_ << endl; } unit_assert(filter4.size() == 1); unit_assert(filter4.spectrumIdentity(0).id == "scan=108"); } void testMassAnalyzerFilter(SpectrumListPtr sl) { if (os_) *os_ << "testMassAnalyzerFilter:\n"; set cvIDs; // msconvert mass analyzer filter FTMS option cvIDs.insert(MS_orbitrap); cvIDs.insert(MS_fourier_transform_ion_cyclotron_resonance_mass_spectrometer); SpectrumList_Filter filter(sl, SpectrumList_FilterPredicate_AnalyzerType(cvIDs)); if (os_) { printSpectrumList(filter, *os_); *os_ << endl; } unit_assert(filter.size() == 7); unit_assert(filter.spectrumIdentity(0).id == "scan=100"); cvIDs.clear(); // msconvert mass analyzer filter ITMS option cvIDs.insert(MS_ion_trap); SpectrumList_Filter filter1(sl, SpectrumList_FilterPredicate_AnalyzerType(cvIDs)); if (os_) { printSpectrumList(filter1, *os_); *os_ << endl; } unit_assert(filter1.size() == 3); unit_assert(filter1.spectrumIdentity(0).id == "scan=102"); } void testMZPresentFilter(SpectrumListPtr sl) { if (os_) *os_ << "testMZPresentFilter:\n"; // test mzpresent on MS level 2 (include test) SpectrumListPtr ms2filter(new SpectrumList_Filter(sl, SpectrumList_FilterPredicate_MSLevelSet(IntegerSet(2)))); chemistry::MZTolerance mzt(3.0); std::set mzSet; mzSet.insert(200.0); mzSet.insert(300.0); mzSet.insert(400.0); double threshold = 10; IntegerSet msLevels(1, INT_MAX); ThresholdFilter tf(ThresholdFilter::ThresholdingBy_Count, threshold, ThresholdFilter::Orientation_MostIntense, msLevels); SpectrumList_Filter filter(ms2filter, SpectrumList_FilterPredicate_MzPresent(mzt, mzSet, tf, false)); if (os_) { printSpectrumList(filter, *os_); *os_ << endl; } unit_assert(filter.size() == 4); unit_assert(filter.spectrumIdentity(0).id == "scan=102"); unit_assert(filter.spectrumIdentity(1).id == "scan=104"); unit_assert(filter.spectrumIdentity(2).id == "scan=105"); unit_assert(filter.spectrumIdentity(3).id == "scan=107"); // test mz present on MS level 1 (exclude test) SpectrumListPtr ms1filter(new SpectrumList_Filter(sl, SpectrumList_FilterPredicate_MSLevelSet(IntegerSet(1)))); chemistry::MZTolerance mzt1(3.0); std::set mzSet1; mzSet1.insert(200.0); mzSet1.insert(300.0); double threshold1 = 5; ThresholdFilter tf1(ThresholdFilter::ThresholdingBy_Count, threshold1, ThresholdFilter::Orientation_MostIntense, msLevels); SpectrumList_Filter filter1(ms1filter, SpectrumList_FilterPredicate_MzPresent(mzt1, mzSet1, tf1, true)); if (os_) { printSpectrumList(filter1, *os_); *os_ << endl; } unit_assert(filter1.size() == 3); unit_assert(filter1.spectrumIdentity(0).id == "scan=100"); unit_assert(filter1.spectrumIdentity(1).id == "scan=106"); unit_assert(filter1.spectrumIdentity(2).id == "scan=109"); } void test() { SpectrumListPtr sl = createSpectrumList(); testEven(sl); testEvenMS2(sl); testSelectedIndices(sl); testHasBinaryData(sl); testIndexSet(sl); testScanNumberSet(sl); testScanEventSet(sl); testScanTimeRange(sl); testMSLevelSet(sl); testMS2Activation(sl); testMassAnalyzerFilter(sl); testMZPresentFilter(sl); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/spectrum_processing/ThresholdFilter.cpp0000664000175100017510000002631012664775614026277 0ustar teamcityteamcity00000000000000// // $Id: ThresholdFilter.cpp 2894 2011-07-29 20:05:08Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "pwiz/utility/misc/Std.hpp" #include "pwiz/data/msdata/MSData.hpp" #include "ThresholdFilter.hpp" #include namespace { bool orientationLess_Predicate (const pwiz::msdata::MZIntensityPair& lhs, const pwiz::msdata::MZIntensityPair& rhs) { return lhs.intensity < rhs.intensity; } bool orientationMore_Predicate (const pwiz::msdata::MZIntensityPair& lhs, const pwiz::msdata::MZIntensityPair& rhs) { return lhs.intensity > rhs.intensity; } struct MZIntensityPairSortByMZ { bool operator() (const pwiz::msdata::MZIntensityPair& lhs, const pwiz::msdata::MZIntensityPair& rhs) const { return lhs.mz < rhs.mz; } }; struct MZIntensityPairIntensitySum { double operator() (double lhs, const pwiz::msdata::MZIntensityPair& rhs) { return lhs + rhs.intensity; } }; struct MZIntensityPairIntensityFractionLessThan { MZIntensityPairIntensityFractionLessThan(double denominator) : denominator_(denominator) { } bool operator() (const pwiz::msdata::MZIntensityPair& lhs, const pwiz::msdata::MZIntensityPair& rhs) { return (lhs.intensity / denominator_) < (rhs.intensity / denominator_); } private: double denominator_; }; struct MZIntensityPairIntensityFractionGreaterThan { MZIntensityPairIntensityFractionGreaterThan(double denominator) : denominator_(denominator) { } bool operator() (const pwiz::msdata::MZIntensityPair& lhs, const pwiz::msdata::MZIntensityPair& rhs) { return (lhs.intensity / denominator_) > (rhs.intensity / denominator_); } private: double denominator_; }; } // namespace namespace pwiz { namespace analysis { using namespace msdata; // Filter params class initialization const char* ThresholdFilter::byTypeMostIntenseName[] = {"most intense count (excluding ties at the threshold)", "most intense count (including ties at the threshold)", "absolute intensity greater than", "with greater intensity relative to BPI", "with greater intensity relative to TIC", "most intense TIC cutoff"}; const char* ThresholdFilter::byTypeLeastIntenseName[] = {"least intense count (excluding ties at the threshold)", "least intense count (including ties at the threshold)", "absolute intensity less than", "with less intensity relative to BPI", "with less intensity relative to TIC", "least intense TIC cutoff"}; PWIZ_API_DECL ThresholdFilter::ThresholdFilter(ThresholdingBy_Type byType_ /* = ThresholdingBy_Count */, double threshold_ /* = 1.0 */, ThresholdingOrientation orientation_, /* = Orientation_MostIntense */ const pwiz::util::IntegerSet& msLevelsToThreshold /* = [1-] */ ) : byType(byType_), threshold(byType == ThresholdingBy_Count || byType == ThresholdingBy_CountAfterTies ? round(threshold_) : threshold_), orientation(orientation_), msLevelsToThreshold(msLevelsToThreshold) { } PWIZ_API_DECL void ThresholdFilter::describe(ProcessingMethod& method) const { string name = orientation == Orientation_MostIntense ? byTypeMostIntenseName[byType] : byTypeLeastIntenseName[byType]; method.userParams.push_back(UserParam(name, lexical_cast(threshold))); } PWIZ_API_DECL void ThresholdFilter::operator () (const SpectrumPtr s) const { if (!msLevelsToThreshold.contains(s->cvParam(MS_ms_level).valueAs())) return; // do nothing to empty spectra if (s->defaultArrayLength == 0) return; if (byType == ThresholdingBy_Count || byType == ThresholdingBy_CountAfterTies) { // if count threshold is greater than number of data points, return as is if (s->defaultArrayLength <= threshold) return; else if (threshold == 0) { s->getMZArray()->data.clear(); s->getIntensityArray()->data.clear(); s->defaultArrayLength = 0; return; } } vector mzIntensityPairs; s->getMZIntensityPairs(mzIntensityPairs); if (orientation == Orientation_MostIntense) sort(mzIntensityPairs.begin(), mzIntensityPairs.end(), orientationMore_Predicate); else if (orientation == Orientation_LeastIntense) sort(mzIntensityPairs.begin(), mzIntensityPairs.end(), orientationLess_Predicate); else throw runtime_error("[threshold()] invalid orientation type"); double tic = accumulate(mzIntensityPairs.begin(), mzIntensityPairs.end(), 0.0, MZIntensityPairIntensitySum()); if (tic == 0) { s->getMZArray()->data.clear(); s->getIntensityArray()->data.clear(); s->defaultArrayLength = 0; return; } double bpi = orientation == Orientation_MostIntense ? mzIntensityPairs.front().intensity : mzIntensityPairs.back().intensity; // after the threshold is applied, thresholdItr should be set to the first data point to erase vector::iterator thresholdItr; switch (byType) { case ThresholdingBy_Count: // no need to check bounds on thresholdItr because it gets checked above thresholdItr = mzIntensityPairs.begin() + (size_t) threshold; // iterate backward until a non-tie is found while (true) { const double& i = thresholdItr->intensity; if (thresholdItr == mzIntensityPairs.begin()) break; else if (i != (--thresholdItr)->intensity) { ++thresholdItr; break; } } break; case ThresholdingBy_CountAfterTies: // no need to check bounds on thresholdItr because it gets checked above thresholdItr = mzIntensityPairs.begin() + ((size_t) threshold)-1; // iterate forward until a non-tie is found while (true) { const double& i = thresholdItr->intensity; if (++thresholdItr == mzIntensityPairs.end() || i != thresholdItr->intensity) break; } break; case ThresholdingBy_AbsoluteIntensity: if (orientation == Orientation_MostIntense) thresholdItr = lower_bound(mzIntensityPairs.begin(), mzIntensityPairs.end(), MZIntensityPair(0, threshold), orientationMore_Predicate); else thresholdItr = lower_bound(mzIntensityPairs.begin(), mzIntensityPairs.end(), MZIntensityPair(0, threshold), orientationLess_Predicate); break; case ThresholdingBy_FractionOfBasePeakIntensity: if (orientation == Orientation_MostIntense) thresholdItr = lower_bound(mzIntensityPairs.begin(), mzIntensityPairs.end(), MZIntensityPair(0, threshold*bpi), MZIntensityPairIntensityFractionGreaterThan(bpi)); else thresholdItr = lower_bound(mzIntensityPairs.begin(), mzIntensityPairs.end(), MZIntensityPair(0, threshold*bpi), MZIntensityPairIntensityFractionLessThan(bpi)); break; case ThresholdingBy_FractionOfTotalIntensity: if (orientation == Orientation_MostIntense) thresholdItr = lower_bound(mzIntensityPairs.begin(), mzIntensityPairs.end(), MZIntensityPair(0, threshold*tic), MZIntensityPairIntensityFractionGreaterThan(tic)); else thresholdItr = lower_bound(mzIntensityPairs.begin(), mzIntensityPairs.end(), MZIntensityPair(0, threshold*tic), MZIntensityPairIntensityFractionLessThan(tic)); break; case ThresholdingBy_FractionOfTotalIntensityCutoff: { // example (ties are included) // intensities: 12 2 2 1 1 1 1 0 0 (TIC 20) // cumulative: 12 14 16 17 18 19 20 20 20 // fraction: .60 .70 .80 .85 .90 .95 1.0 1.0 1.0 // at threshold 1.0 ---------------------------^ cut here // at threshold .99 ---------------------------^ cut here // at threshold .90 ---------------------------^ cut here // at threshold .80 -----------^ cut here // at threshold .65 -----------^ cut here // at threshold .60 ---^ cut here // at threshold .15 ---^ cut here // starting at the (most/least intense point)/TIC fraction, calculate the running sum vector cumulativeIntensityFraction; cumulativeIntensityFraction.reserve(mzIntensityPairs.size()); cumulativeIntensityFraction.push_back(mzIntensityPairs[0].intensity / tic); size_t i=1; while (cumulativeIntensityFraction.back() < threshold - 1e-6 && i < mzIntensityPairs.size()) { cumulativeIntensityFraction.push_back(cumulativeIntensityFraction[i-1] + mzIntensityPairs[i].intensity / tic); ++i; } thresholdItr = mzIntensityPairs.begin() + (i-1); // iterate forward until a non-tie is found while (thresholdItr != mzIntensityPairs.end()) { const double& i = thresholdItr->intensity; if (++thresholdItr == mzIntensityPairs.end() || i != thresholdItr->intensity) break; } } break; default: throw runtime_error("[threshold()] invalid thresholding type"); } sort(mzIntensityPairs.begin(), thresholdItr, MZIntensityPairSortByMZ()); s->setMZIntensityPairs(&mzIntensityPairs[0], thresholdItr - mzIntensityPairs.begin(), s->getIntensityArray()->cvParam(MS_intensity_array).units); } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/SpectrumList_ChargeFromIsotope.cpp0000664000175100017510000013600712664775614031300 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_ChargeFromIsotope.cpp 6394 2014-06-18 16:47:39Z frenchwr $ // // // Original author: William French vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_ChargeFromIsotope.hpp" #include "pwiz/analysis/spectrum_processing/SpectrumList_PeakPicker.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/IntegerSet.hpp" #include "pwiz/utility/chemistry/Ion.hpp" #include // Predicate for sorting score data structures bool sortScoresByMZ (scoreChain i, scoreChain j) { return (i.mzPvalue < j.mzPvalue); } bool sortScoresByKLScore (scoreChain i, scoreChain j) { return (i.intensityPvalue < j.intensityPvalue); } bool sortScoresByIntensitySum (scoreChain i, scoreChain j) { return (i.intensitySumPvalue < j.intensitySumPvalue); } bool sortScoresByOverallPvalue (scoreChain i, scoreChain j) { return (i.overallPvalue < j.overallPvalue); } bool sortScoresBySumOfRanks (scoreChain i, scoreChain j) { return (i.sumRanks < j.sumRanks); } // Predicate for sorting retention time data structure bool sortByRetentionTime (rtimeMap i, rtimeMap j) { return (i.rtime < j.rtime); } // Comparator for running upper_bound on retention time data structure bool rtimeComparator(double a, rtimeMap i) { return (i.rtime > a ); } bool pairSortFunc (pairData i, pairData j) { return (i.mz=9?9:surveyCnt); // simulate the total peak intensity simulateTotIntensity(nIsotopePeakPossibilities); } PWIZ_API_DECL SpectrumPtr SpectrumList_ChargeFromIsotope::spectrum(size_t index, bool getBinaryData) const { SpectrumPtr s = inner_->spectrum(index, true); // return non-MS/MS as-is CVParam spectrumType = s->cvParamChild(MS_spectrum_type); if (spectrumType != MS_MSn_spectrum) return s; // return MS1 as-is if (!s->hasCVParam(MS_ms_level) || s->cvParam(MS_ms_level).valueAs() < 2) return s; // return peakless spectrum as-is if (s->defaultArrayLength == 0) return s; // return precursorless MS/MS as-is if (s->precursors.empty() || s->precursors[0].selectedIons.empty()) return s; //cout << "Performing Turbocharger analysis!" << endl; // use first selected ion in first precursor // TODO: how to deal with multiple precursors and/or selected ions? Precursor& precursor = s->precursors[0]; SelectedIon& selectedIon = precursor.selectedIons[0]; //int vendorCharge = selectedIon.cvParam(MS_charge_state).valueAs(); // erase any existing charge-state-related CV params vector& cvParams = selectedIon.cvParams; IntegerSet possibleChargeStates; for(vector::iterator itr = cvParams.begin(); itr != cvParams.end(); ++itr) { if (itr->cvid == MS_charge_state || itr->cvid == MS_possible_charge_state) { // some files may have a bogus "0" charge state if (override_ || itr->value == "0") { selectedIon.userParams.push_back(UserParam("old charge state", itr->value)); itr = --cvParams.erase(itr); } else if (itr->cvid == MS_possible_charge_state) possibleChargeStates.insert(itr->valueAs()); else if (itr->cvid == MS_charge_state) return s; } } double precursorMZ = selectedIon.cvParam(MS_selected_ion_m_z).valueAs(); int nPossibleChargeStates = maxCharge_ - minCharge_ + 1; int nIsotopePeakPossibilities = maxIsotopePeaks - minIsotopePeaks + 1; // Get the upper/lower bounds of the precursor isolation window. // Of the data I've tested, only Thermo lists isolation window info. double upperIsoWidth = precursor.isolationWindow.cvParam(MS_isolation_window_upper_offset).valueAs(); upperIsoWidth = upperIsoWidth > 0.0 ? upperIsoWidth : defaultIsolationWidth_; double lowerIsoWidth = precursor.isolationWindow.cvParam(MS_isolation_window_lower_offset).valueAs(); lowerIsoWidth = lowerIsoWidth > 0.0 ? lowerIsoWidth : defaultIsolationWidth_; double targetIsoMZ = precursor.isolationWindow.cvParam(MS_isolation_window_target_m_z).valueAs(); targetIsoMZ = targetIsoMZ > 0.0 ? targetIsoMZ : precursorMZ; vector parentIndex; getParentIndices(s,parentIndex); // info about chains/score across all parent scans vector allScores; vector allChains; vector < vector > allMZs; vector < vector > allIntensities; int allChainsCnt=0; int assignedCharge = 0; double assignedMZ = targetIsoMZ; getParentPeaks(s,parentIndex,targetIsoMZ,lowerIsoWidth,upperIsoWidth,allMZs,allIntensities); // loop over peaks in parent spectra, build isotope chains and score them for (int i=0, iend=parentIndex.size(); i < iend; ++i) { int nPeaks = allMZs[i].size(); vector peakMZs(nPeaks); vector peakIntensities(nPeaks); for (int j=0, jend=nPeaks; j < jend; ++j) { peakMZs[j] = allMZs[i][j]; peakIntensities[j] = allIntensities[i][j]; } vector sortedPeakIntensities = peakIntensities; sort(sortedPeakIntensities.begin(),sortedPeakIntensities.end()); vector chains; if ( nPeaks > 1 ) // need at least two peaks to perform analysis { for (int j=0,cnt=0; j targetIsoMZ + upperIsoWidth ) break; // don't let the monoisotope move outside the isolation width for (int k = j+1; k massNeutron + mzTol) break; // subsequent sets of peaks will have spacing that is too large double recip = massNeutron / mzDiff; int possibleCharge = int(recip + 0.50); if ( possibleCharge > maxCharge_ || possibleCharge < minCharge_ ) continue; // Not going to generate chain extension if ( abs( massNeutron / double(possibleCharge) - mzDiff) < mzTol ) { // We have a hit // Start by checking if this can be connected to previous chains for (int w=0, wend=chains.size(); w < wend; ++w) { if ( possibleCharge != chains[w].charge ) continue; int nPeaksInChain = chains[w].indexList.size(); if ( nPeaksInChain >= maxIsotopePeaks ) continue; int finalIndex = chains[w].indexList[chains[w].indexList.size()-1]; if ( j == finalIndex ) // connect it and save previous chain { chains.push_back(chains[w]); // push back copy of previous chain with current size chains[w].indexList.push_back(k); // now extend the size of the chain } } // Also create a new chain of length 2 isotopeChain newChain; newChain.charge = possibleCharge; newChain.indexList.push_back(j); newChain.indexList.push_back(k); newChain.parentIndex = i; chains.push_back(newChain); } // end if peak is within tolerance } // end for loop k } // end for loop j } // end if peak list size at least 2 // Filter any chains that are not the required length if (chains.size() > 0) { vector::iterator it = chains.begin(); while ( it != chains.end() ) { if ( it->charge > 4 && it->indexList.size() < 3 ) { it = chains.erase(it); } else { ++it; } } } scoreChain initializeScore; vector scores(chains.size(),initializeScore); if (chains.size() > 0) { // Now perform the scoring vector::iterator chainIt = chains.begin(); while ( chainIt != chains.end() ) { ////////////////////////////////////////////////////////////////////////////////////// // calculate the relative intensity score, based on the K-L score from a poisson distribution int j = chainIt - chains.begin(); double KLscore = getKLscore( chains[j], peakMZs, peakIntensities ); int startIndex = (chains[j].indexList.size()-minIsotopePeaks)*nSamples; vector simValues; simValues.assign(&simulatedKLs[startIndex],&simulatedKLs[startIndex+nSamples-1]); vector< double >::iterator i1 = upper_bound(simValues.begin(),simValues.end(),KLscore); // returns iterator to first value that's > KLscore int klVectorIndex = i1 - simValues.begin(); scores[j].intensityPvalue = double(klVectorIndex+1) / double(nSamples+1); ////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////// // calculate average monoisotopic mass based on m/z positions in chain double average=0.0; for (int k=0, kend=chains[j].indexList.size(); k < kend; k++) average += peakMZs[chains[j].indexList[k]] - double(k)*massNeutron/double(chains[j].charge); average /= double(chains[j].indexList.size()); // calculate summed square error of m/z positions in chain relative to the average monoisotopic m/z double sse=0.0; for (int k=0, kend=chains[j].indexList.size(); k < kend; k++) sse += pow( average - (peakMZs[chains[j].indexList[k]] - double(k)*massNeutron/double(chains[j].charge)),2); // get the P value for the m/z sse startIndex = (chains[j].indexList.size()-minIsotopePeaks)*nPossibleChargeStates*nSamples + (chains[j].charge-minCharge_)*nSamples; simValues.assign(&simulatedSSEs[startIndex],&simulatedSSEs[startIndex+nSamples-1]); i1 = upper_bound(simValues.begin(),simValues.end(),sse); // returns iterator to first value that's > sse int mzVectorIndex = i1 - simValues.begin(); ////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////// // now calculate the sum of intensity rank score if ( nPeaks > maxNumberPeaks ) throw runtime_error("[SpectrumList_chargeFromIsotope] nPeaks exceeds maxNumberPeaks for scoring."); int intensitySumRank = 0; for (int k=0, kend=chains[j].indexList.size(); k < kend; k++) { double intensity = peakIntensities[chains[j].indexList[k]]; i1 = upper_bound(sortedPeakIntensities.begin(),sortedPeakIntensities.end(),intensity); //i1--; //int rank = nPeaks - (i1 - sortedPeakIntensities.begin()); // remember sortedPeakIntensities sorted from least to most intense //int rank = nPeaks - 1 - (i1 - sortedPeakIntensities.begin()); // remember sortedPeakIntensities sorted from least to most intense int rank = (i1 - 1) - sortedPeakIntensities.begin(); rank = nPeaks - rank; intensitySumRank += rank; } startIndex = (nPeaks - minNumberPeaks)*nIsotopePeakPossibilities*nSamples + (chains[j].indexList.size()-minIsotopePeaks)*nSamples; // need to know how many samples were generated in the event that N choose k was less than nSamples int combos; if ( nPeaks > 40 && chains[j].indexList.size() > 2 ) { combos = nSamples; } else { int combinations = nChoosek(nPeaks,chains[j].indexList.size()); combos = combinations > nSamples ? nSamples : combinations; } vector simIntValues; simIntValues.assign(&simulatedIntensityRankSum[startIndex],&simulatedIntensityRankSum[startIndex+combos-1]); vector::iterator i2 = upper_bound(simIntValues.begin(),simIntValues.end(),intensitySumRank); // returns iterator to first value that's > KLscore int intensitySumVectorIndex = i2 - simIntValues.begin(); ////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////// // probability of having lower sse by random chance scores[j].mzPvalue = double(mzVectorIndex+1) / double(nSamples+1); // K-L score is listed above scores[j].intensitySumPvalue = double(intensitySumVectorIndex) / double(combos); // don't add one here because we cannot beat the top rank sum scores[j].overallPvalue = scores[j].mzPvalue * scores[j].intensityPvalue * scores[j].intensitySumPvalue; scores[j].chainIndex = allChainsCnt++; chainIt++; } // end for through all chains allChains.insert(allChains.end(),chains.begin(),chains.end()); allScores.insert(allScores.end(),scores.begin(),scores.end()); } // end if chains.size() > 0 } // end for over parent spectra if ( allScores.size() > 0 ) { // rank scoring data structures, first by m/z sort(allScores.begin(),allScores.end(),sortScoresByMZ); for (int j=0, jend=allScores.size(); j < jend; ++j) allScores[j].mzRank = j+1; // now rank by relative intensity K-L score sort(allScores.begin(),allScores.end(),sortScoresByKLScore); for (int j=0, jend=allScores.size(); j < jend; ++j) allScores[j].intensityRank = j+1; // now rank by intensity rank sum score sort(allScores.begin(),allScores.end(),sortScoresByIntensitySum); for (int j=0, jend=allScores.size(); j < jend; ++j) allScores[j].intensitySumRank = j+1; // sum all the ranks for (int j=0, jend=allScores.size(); j < jend; ++j) allScores[j].sumRanks = allScores[j].mzRank + allScores[j].intensityRank + allScores[j].intensitySumRank; // Finally, sort by the sum of ranks. This appears to work better than // sorting by the overall p-value. sort(allScores.begin(),allScores.end(),sortScoresBySumOfRanks); int j,jend; int scoreListLength = allScores.size(); int bestChainIndex = -1; for (j=0, jend = scoreListLength > nChainsCheck_ ? nChainsCheck_ : scoreListLength; j < jend; ++j) { if ( allScores[j].intensityPvalue < sigVal_ ) { bestChainIndex = allScores[j].chainIndex; break; } } if ( bestChainIndex != -1 ) { double mzTolppm = 100.0; double mzTolparts = mzTolppm / 1000000.0; // search for longer version of chain bool updateChain = true; while ( updateChain ) { updateChain = false; for (int k=j+1, kend = scoreListLength > nChainsCheck_ ? nChainsCheck_ : scoreListLength; k < kend; ++k) { if ( allScores[k].intensityPvalue > sigVal_ ) continue; // // trying to match chain x-y-z to w-x-y-z // // what's acceptable? // have: x-y-z // - match: w-x-y-z, w-x-y // - not a match: w-x // // have x-y // - match: w-x-y // - not a match w-x // // So basically require at least two m/z matches to the chain you want to replace // // int mapIndexK = allScores[k].chainIndex; if ( allChains[bestChainIndex].charge != allChains[mapIndexK].charge ) continue; int largeChainSize = allChains[mapIndexK].indexList.size(); if ( largeChainSize < 3 ) continue; bool relatedChains = true; double epsilon = mzTolparts * allMZs[allChains[mapIndexK].parentIndex][allChains[mapIndexK].indexList[0]]; for ( int w=0; w < 2; ++w ) { double smallChainMZ = allMZs[allChains[bestChainIndex].parentIndex][allChains[bestChainIndex].indexList[w]]; double largeChainMZ = allMZs[allChains[mapIndexK].parentIndex][allChains[mapIndexK].indexList[w+1]]; if ( abs( smallChainMZ - largeChainMZ ) > epsilon ) { relatedChains = false; break; } } if ( relatedChains ) { updateChain = true; bestChainIndex = mapIndexK; j = k; break; } // end if relatedChains } // loop over remaining chains } // while update chain assignedCharge = allChains[bestChainIndex].charge; assignedMZ = allMZs[allChains[bestChainIndex].parentIndex][allChains[bestChainIndex].indexList[0]]; } // endif best chain != -1 } // make sure the possible charge states are erased if we want to override vendor charges if (override_ && !possibleChargeStates.empty()) cvParams.erase(boost::range::remove_if(cvParams, CVParamIs(MS_possible_charge_state))); if ( assignedCharge != 0 ) // output single charge and m/z value { cvParams.push_back(CVParam(override_ ? MS_charge_state : MS_possible_charge_state, assignedCharge)); s->precursors[0].selectedIons[0].set(MS_selected_ion_m_z, assignedMZ); } else if ( defaultChargeMin_ > 0 ) // output default charges, if requested by user { for (int z = defaultChargeMin_; z <= defaultChargeMax_; ++z) if (!possibleChargeStates.contains(z) && z != 1) cvParams.push_back(CVParam(MS_possible_charge_state, z)); } return s; } void SpectrumList_ChargeFromIsotope::getMS1RetentionTimes() { //cout << "Turbocharger initialization, storing and sorting survey scans by retention time. This may take a few minutes for large files." << endl << endl; int nScans = inner_->size(); MS1retentionTimes.reserve( nScans ); vector ms1Indices; for (int i=0,iend=nScans; ispectrum(i,detailLevel); // Waters: scanConfig refers to the function number // Thermo: scanConfig corresponds to the msLevel // Agilent: scanConfig always returns zero // AB Sciex: scanConfig corresponds to the experiment number (for each "cycle" there is a MS1 // scan and then a variable number of MS2s...the MS1 is experiment 1 and then all // subsequent scans are 2,3,4,...) // Bruker: untested if ( s->scanList.scans[0].empty() ) { throw runtime_error("SpectrumList_chargeFromIsotope: no scanEvent present in raw data!"); } int scanConfig = s->scanList.scans[0].cvParam(MS_preset_scan_configuration).valueAs(); if ( scanConfig == 0 ) { int level = s->cvParam(MS_ms_level).valueAs(); if ( level != 1 ) continue; } else if ( scanConfig != 1 ) continue; double rTime = s->scanList.scans[0].cvParam(MS_scan_start_time).timeInSeconds(); rtimeMap newRtime; newRtime.rtime = rTime; newRtime.indexMap = i; MS1retentionTimes.push_back(newRtime); } int surveyCnt = MS1retentionTimes.size(); if ( surveyCnt == 0 ) throw runtime_error("[SpectrumList_chargeFromIsotope] No survey scan found!"); sort(MS1retentionTimes.begin(),MS1retentionTimes.end(),sortByRetentionTime); // these are generally already sorted, but just in case } void SpectrumList_ChargeFromIsotope::simulateSSE(const int nCharges,const int nIsotopePeakPossibilities) { // generate a sample of random spacings to simulate the distribution // of summed square errors in m/z space due to random variations simulatedSSEs.resize( nSamples*nCharges*nIsotopePeakPossibilities, 0.0 ); for (int i=0; i < nIsotopePeakPossibilities; ++i) { int chainLength = i + minIsotopePeaks; for (int w=0; w spacings(nSamples,0.0); for (int j=0; j mzPoints(chainLength,0.0); double averageMonoisotope = 0.0; for (int k=1; k < chainLength; ++k) { double theoreticalMZ = double(k) * massNeutron / double(charge); double randomVar = -mzTol + ( (double)rand() / RAND_MAX ) * 2 * mzTol; // between -mzTol and +mzTol mzPoints[k] = theoreticalMZ + randomVar; averageMonoisotope += randomVar; } averageMonoisotope /= double(chainLength); double sse = 0.0; for (int k=0; k < chainLength; ++k) { sse += pow( averageMonoisotope - (mzPoints[k] - double(k)*massNeutron/double(charge)),2); } spacings[j] = sse; } // end for over nSamples sort(spacings.begin(),spacings.end()); int startIndex = i * nCharges * nSamples + w * nSamples; for (int j=0; j nineMS1indices(nMS1sims,-1); for (int i=1; i<=nMS1sims; i++) { double rTime = double(i) * finalRetentionTime / double(nMS1sims+1); vector< rtimeMap >::iterator i1 = upper_bound(MS1retentionTimes.begin(),MS1retentionTimes.end(),rTime,rtimeComparator); // returns iterator to first value that's > rTime int nearestMS1scanVectorIndex; if ( i1 == MS1retentionTimes.begin() ) nearestMS1scanVectorIndex = 0; else nearestMS1scanVectorIndex = (i1 - 1) - MS1retentionTimes.begin(); if (nearestMS1scanVectorIndex<0) nearestMS1scanVectorIndex = 0; nineMS1indices[i-1] = MS1retentionTimes[nearestMS1scanVectorIndex].indexMap; } /////////////////////////////////////////////// // now simulate the K-L score simulatedKLs.resize( nIsotopePeakPossibilities * nSamples, 0.0 ); SpectrumListPtr CWTpeakPicker = instantiatePeakPicker( nineMS1indices ); vector < vector > allIntensity, allMZ; vector < vector > mostIntensePeaks; int numberIntensePeaks = 200; for (int i=0,iend=nineMS1indices.size(); i < iend ; ++i) { SpectrumPtr s = CWTpeakPicker->spectrum( i, true ); // this applies no filtering vector peakIntensities = s->getIntensityArray()->data; vector peakMZs = s->getMZArray()->data; allIntensity.push_back( peakIntensities ); allMZ.push_back( peakMZs ); vector sortedPeakIntensities = peakIntensities; sort( sortedPeakIntensities.begin(), sortedPeakIntensities.end() ); double intensityCutoff = 0.0; int MS1Peaks = sortedPeakIntensities.size(); if ( MS1Peaks >= numberIntensePeaks ) intensityCutoff = sortedPeakIntensities[ peakIntensities.size() - numberIntensePeaks ]; vector highIntensityIndices; for (int j=0, jend=peakIntensities.size(); j < jend; ++j) { if ( peakIntensities[j] >= intensityCutoff ) highIntensityIndices.push_back(j); } mostIntensePeaks.push_back( highIntensityIndices ); } for (int j=0; j < nIsotopePeakPossibilities; ++j) { int chainLength = j + minIsotopePeaks; vector poolA(chainLength,0.0); vector poolB(chainLength,0.0); vector KLscores(nSamples,0.0); for (int k=0; k peakMZs(peakCnt), peakIntensities(peakCnt); for ( int w=0, wend = peakMZs.size(); w < wend; ++w ) { peakMZs[w] = allMZ[randomSpectrum][w]; peakIntensities[w] = allIntensity[randomSpectrum][w]; } int randomPeakIndex = rand() % mostIntensePeaks[randomSpectrum].size(); // from 0 to .size()-1 int randomMZpoint = mostIntensePeaks[randomSpectrum][randomPeakIndex]; double targetMZvalue = peakMZs[randomMZpoint]; std::vector::iterator lowerLimit = lower_bound( peakMZs.begin(), peakMZs.end(), targetMZvalue - defaultIsolationWidth_ ); lowerLimit = lowerLimit == peakMZs.end() ? peakMZs.begin() : lowerLimit; // in case value is out of bounds std::vector::iterator upperLimit = lower_bound( peakMZs.begin(), peakMZs.end(), targetMZvalue + defaultIsolationWidth_ + upperLimitPadding ); upperLimit = upperLimit == peakMZs.end() ? peakMZs.end() - 1 : upperLimit; // in case value is out of bounds vector windowIntensity, windowMZ; windowMZ.assign( lowerLimit, upperLimit ); // this is possible if we chose the last peak of the spetrum and there is nothing around it if ( windowMZ.size() == 0 ) // no peaks found { KLscores[k] = 100; // just apply a really bad KL score continue; } int lowerLimitInt = lowerLimit - peakMZs.begin(), upperLimitInt = upperLimit - peakMZs.begin(); // convert iterators to ints windowIntensity.assign( &peakIntensities[lowerLimitInt], &peakIntensities[upperLimitInt] ); // remove any zero-intensity peaks, which will lead to NAN results in KL scoring vector::iterator winIt = windowIntensity.begin(); while ( winIt != windowIntensity.end() ) { if ( *winIt == 0.0 ) { windowIntensity.erase( winIt ); int mzIndex = winIt - windowIntensity.begin(); windowMZ.erase( windowMZ.begin() + mzIndex ); } else { ++winIt; } } // filter the peaks int peaksInWindow = windowIntensity.size(); while ( peaksInWindow > maxNumberPeaks ) { vector::iterator minIt = min_element( windowIntensity.begin(), windowIntensity.end() ); vector::iterator maxIt = max_element( windowIntensity.begin(), windowIntensity.end() ); vector elementsForDeletion; for (int w=0, wend = windowIntensity.size(); w < wend; ++w) { if ( windowIntensity[w] < *maxIt * 0.05 ) elementsForDeletion.push_back( w ); else if ( windowIntensity[w] == *minIt ) elementsForDeletion.push_back( w ); // remove if element equal to min or } for (int w=0, wend = elementsForDeletion.size(); w < wend; ++w ) { windowIntensity.erase( windowIntensity.begin() + elementsForDeletion[w] - w ); windowMZ.erase( windowMZ.begin() + elementsForDeletion[w] - w ); } peaksInWindow = windowIntensity.size(); } int windowSize = windowIntensity.size(); isotopeChain localChain; localChain.charge = rand() % ( maxCharge_ - minCharge_ + 1 ) + minCharge_; // goes from minCharge_ to maxCharge_ vector randomIndicesInWindow( chainLength ); for (int w=0; w nPeaks) break; int combinations; int sampleSize; if ( nPeaks > 40 && chainLength > 2 ) { // all possible combinations could be too large to be held by a normal int combinations = nSamples; } else { combinations = nChoosek(nPeaks,chainLength); } sampleSize = combinations > nSamples ? nSamples : combinations; vector intensityRankSum(sampleSize,0); if ( combinations >= nSamples ) // sample nSamples random combinations { for (int j=0; j v(nPeaks); fill(v.begin() + chainLength, v.end(), true); do { for (int j = 0; j < nPeaks; ++j) { if (!v[j]) { intensityRankSum[combinationCnt] += j+1; } } combinationCnt++; } while (next_permutation(v.begin(), v.end())); } sort(intensityRankSum.begin(),intensityRankSum.end()); int startIndex = (nPeaks-minNumberPeaks)*nIsotopePeakPossibilities*nSamples + w * nSamples; for (int j=0; j & parents ) const { int nMS1scans = MS1retentionTimes.size(); if ( nMS1scans > 0 ) { int parentCnt = 0; double rTime = s->scanList.scans[0].cvParam(MS_scan_start_time).timeInSeconds(); vector< rtimeMap >::const_iterator i1 = upper_bound(MS1retentionTimes.begin(),MS1retentionTimes.end(),rTime,rtimeComparator); // returns iterator to first value that's > rTime int nearestMS1scanVectorIndex; if ( i1 == MS1retentionTimes.begin() ) nearestMS1scanVectorIndex = 0; else nearestMS1scanVectorIndex = (i1 - 1) - MS1retentionTimes.begin(); while (nearestMS1scanVectorIndex >= 0 && parentCnt < parentsBefore_) { parents.push_back(MS1retentionTimes[nearestMS1scanVectorIndex].indexMap); nearestMS1scanVectorIndex--; parentCnt++; } nearestMS1scanVectorIndex = i1 - MS1retentionTimes.begin(); parentCnt = 0; // resetting this //while (i1 != MS1retentionTimes.end() && parentCnt < parentsAfter_) while (nearestMS1scanVectorIndex < nMS1scans && parentCnt < parentsAfter_) { parents.push_back(MS1retentionTimes[nearestMS1scanVectorIndex].indexMap); //i1--; nearestMS1scanVectorIndex++; parentCnt++; } } } void SpectrumList_ChargeFromIsotope::getParentPeaks(const SpectrumPtr s,const vector & parents,const double targetIsoMZ,const double lowerIsoWidth,const double upperIsoWidth, vector< vector > & mzs,vector< vector > & intensities) const { // grab the peaks from the parent scans for (int i=0, iend=parents.size(); i < iend; ++i) { vector< int > currentParent(1,parents[i]); DetailLevel detailLevel = DetailLevel_FullMetadata; SpectrumPtr sSurvey = inner_->spectrum(parents[i], detailLevel); vector& cvParams = sSurvey->cvParams; vector::iterator itr; itr = std::find(cvParams.begin(), cvParams.end(), MS_centroid_spectrum); if ( itr != cvParams.end() ) // MS1 spectrum already centroided, just grab the peaks in the isolation window { SpectrumPtr sPar = inner_->spectrum( parents[i], true ); vector& peakMZs = sPar->getMZArray()->data; vector& peakIntensities = sPar->getIntensityArray()->data; vector elementsForDeletion; for (int j=0, jend = peakIntensities.size(); j < jend; ++j) { if ( peakMZs[j] < targetIsoMZ - lowerIsoWidth || peakMZs[j] > targetIsoMZ + upperIsoWidth + upperLimitPadding ) elementsForDeletion.push_back( j ); } for (int j=0, jend = elementsForDeletion.size(); j < jend; ++j ) { peakIntensities.erase( peakIntensities.begin() + elementsForDeletion[j] - j ); peakMZs.erase( peakMZs.begin() + elementsForDeletion[j] - j ); } mzs.push_back( peakMZs ); intensities.push_back( peakIntensities ); } else // need to perform CWT peak-picking to grab the peaks { SpectrumListPtr parentPeakPicker = instantiatePeakPicker( currentParent, targetIsoMZ, lowerIsoWidth, upperIsoWidth + upperLimitPadding ); // add an additional dalton on the right to check for heavy isotopes; don't let monoisotope exceed the isolation window, though. See below. SpectrumPtr sPar = parentPeakPicker->spectrum( 0, true ); vector& peakMZs = sPar->getMZArray()->data; vector& peakIntensities = sPar->getIntensityArray()->data; vector::iterator minIt = min_element( peakIntensities.begin(), peakIntensities.end() ); vector::iterator maxIt = max_element( peakIntensities.begin(), peakIntensities.end() ); vector elementsForDeletion; for (int j=0, jend = peakIntensities.size(); j < jend; ++j) { if ( peakIntensities[j] < *maxIt * 0.05 ) elementsForDeletion.push_back( j ); else if ( peakIntensities[j] == *minIt ) elementsForDeletion.push_back( j ); // remove if element equal to min or } for (int j=0, jend = elementsForDeletion.size(); j < jend; ++j ) { peakIntensities.erase( peakIntensities.begin() + elementsForDeletion[j] - j ); peakMZs.erase( peakMZs.begin() + elementsForDeletion[j] - j ); } mzs.push_back( peakMZs ); intensities.push_back( peakIntensities ); } } } SpectrumListPtr SpectrumList_ChargeFromIsotope::instantiatePeakPicker( const vector & indices ) const { shared_ptr smallSpectrumList(new SpectrumListSimple); for (int i=0,iend=indices.size(); i < iend ; ++i) { SpectrumPtr sParent = inner_->spectrum( indices[i], true); smallSpectrumList->spectra.push_back(sParent); } string msLevelSets = "1"; IntegerSet msLevelsToCentroid; msLevelsToCentroid.parse(msLevelSets); bool preferVendor = false; double snr = 0.0; double mzTol = 0.05; int fixedPeaksKeep = 0; // this is for generating peaks to simulate the K-L score SpectrumListPtr parentPeakPicker(new SpectrumList_PeakPicker(smallSpectrumList, PeakDetectorPtr(new CwtPeakDetector(snr,fixedPeaksKeep,mzTol)), preferVendor, msLevelsToCentroid ) ); return parentPeakPicker; } SpectrumListPtr SpectrumList_ChargeFromIsotope::instantiatePeakPicker( const vector & indices, const double targetIsoMZ, const double lowerIsoWidth, const double upperIsoWidth ) const { shared_ptr smallSpectrumList(new SpectrumListSimple); // parameters for re-sampling via linear interpolation SpectrumPtr s = inner_->spectrum( indices[0], true); vector summedIntensity; vector summedMZ; // Grab the binary data for the parent spectrum SpectrumPtr sParent = inner_->spectrum( indices[0], true); vector& parentMz = sParent->getMZArray()->data; vector& parentIntensity = sParent->getIntensityArray()->data; // Get window of data around the target m/z value vector windowMZ,windowIntensity; std::vector::iterator lowerLimit = lower_bound( parentMz.begin(), parentMz.end(), targetIsoMZ - lowerIsoWidth ); lowerLimit = lowerLimit == parentMz.end() ? parentMz.begin() : lowerLimit; // in case value is out of bounds std::vector::iterator upperLimit = lower_bound( parentMz.begin(), parentMz.end(), targetIsoMZ + upperIsoWidth ); upperLimit = upperLimit == parentMz.end() ? parentMz.end() - 1 : upperLimit; // in case value is out of bounds windowMZ.assign( lowerLimit, upperLimit ); if ( windowMZ.size() > 1 ) { int lowerLimitInt = lowerLimit - parentMz.begin(), upperLimitInt = upperLimit - parentMz.begin(); // convert interators to ints windowIntensity.assign( &parentIntensity[lowerLimitInt], &parentIntensity[upperLimitInt] ); summedMZ.assign( lowerLimit, upperLimit ); summedIntensity.assign( &parentIntensity[lowerLimitInt], &parentIntensity[upperLimitInt] ); } // Now fill in the spectrum data structure that will be fed to the peak-picker smallSpectrumList->spectra.push_back(SpectrumPtr(new Spectrum)); Spectrum& pSpec = *smallSpectrumList->spectra[0]; pSpec.index = 0; pSpec.set(MS_ms_level, 1); pSpec.set(MS_profile_spectrum); BinaryDataArrayPtr pSpec_mz(new BinaryDataArray), pSpec_intensity(new BinaryDataArray); pSpec_mz->set(MS_m_z_array, "", MS_m_z), pSpec_intensity->set(MS_intensity_array, "", MS_number_of_detector_counts); pSpec_mz->data.resize( summedIntensity.size() ), pSpec_intensity->data.resize( summedIntensity.size() ); for (size_t j=0, jend=summedIntensity.size() ; j < jend; ++j) { pSpec_mz->data[j] = summedMZ[j]; pSpec_intensity->data[j] = summedIntensity[j]; } pSpec.binaryDataArrayPtrs.push_back( pSpec_mz ), pSpec.binaryDataArrayPtrs.push_back( pSpec_intensity ); pSpec.defaultArrayLength = pSpec_mz->data.size(); string msLevelSets = "1"; IntegerSet msLevelsToCentroid; msLevelsToCentroid.parse(msLevelSets); bool preferVendor = false; double snr = 0.0; double mzTol = 0.05; int fixedPeaksKeep = maxNumberPeaks; SpectrumListPtr parentPeakPicker(new SpectrumList_PeakPicker(smallSpectrumList, PeakDetectorPtr(new CwtPeakDetector(snr,fixedPeaksKeep,mzTol)), preferVendor, msLevelsToCentroid ) ); return parentPeakPicker; } } // namespace analysis } // namespace pwiz int nChoosek(int n,int k) { int numerator=1; int denominator=1; // Multiplicative formula for (int i=0;i & mzs, const vector & intensities ) { if ( mzs.size() != intensities.size() ) throw runtime_error("[SpectrumList_chargeFromIsotope, getKLscore] m/z and intensity vectors must be equal in size."); //cout << "computing the KL score" << endl; // First, convert from molecular weight of ion to Mstar, which is linear mapping double lambda = 1.0 / 1800.0; // parameter for poisson model double Mstar = lambda * mzs[chain.indexList[0]] * double(chain.charge); // from msInspect paper double Mexp = exp( -Mstar ); double poissonSum = 0.0; // sum up all the poisson values to normalize double observedIntensitySum = 0.0; // initialize this sum double KLscore = 0.0; vector poissonVals(chain.indexList.size(),0.0); // calculate poisson distribution and sum up the intensities for normalization for (int k=0,kend=chain.indexList.size(); k < kend ; ++k) { // probability of seeing isotope with k additional ions relative to monoisotope double poisson = Mexp * pow(Mstar,k); for (int w=k;w>1;w--) poisson /= double(w); poissonVals[k] = poisson; // store value // sums for normalization poissonSum += poisson; observedIntensitySum += intensities[chain.indexList[k]]; } // calculate the K-L score for (int k=0,kend=chain.indexList.size(); k < kend ; ++k) { poissonVals[k] /= poissonSum; // normalize these values to use in the K-L score double normObservedIntensity = intensities[chain.indexList[k]] / observedIntensitySum; KLscore += normObservedIntensity * log10( normObservedIntensity / poissonVals[k] ); } //cout << "done computing the KL score" << endl; return KLscore; }pwiz/pwiz/analysis/spectrum_processing/PrecursorMassFilter.cpp0000664000175100017510000002303712664775615027157 0ustar teamcityteamcity00000000000000// // $Id: PrecursorMassFilter.cpp 5091 2013-10-30 20:02:10Z chambm $ // // // Original author: Chris Paulse systemsbiology.org> // // Copyright 2009 Institute for Systems Biology, Seattle, WA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "pwiz/data/msdata/MSData.hpp" #include "PrecursorMassFilter.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/chemistry/Ion.hpp" #include namespace pwiz { namespace analysis { const double leftWindow = 60.; using namespace msdata; using namespace pwiz::util; using namespace pwiz::chemistry; namespace { ///TODO: this struct probably belongs in a more central location struct MassLessThan { MassLessThan(const MZTolerance& tolerance_) : tolerance(tolerance_) { } bool operator () (double lhs, double rhs) { return lessThanTolerance(lhs, rhs, tolerance); } const MZTolerance tolerance; }; struct PrecursorReferenceMass { enum Type {Precursor, ChargeReducedPrecursor, NeutralLoss}; PrecursorReferenceMass(Type type_ = PrecursorReferenceMass::Precursor, double mass_ = 0.0, int charge_ = 0) : massType(type_), mass(mass_), charge(charge_) {} Type massType; double mass; int charge; bool operator< (const PrecursorReferenceMass& rhs) const { return mass < rhs.mass; } }; } // namespace struct PrecursorMassFilter::Impl { Impl(const Config& params_) : params(params_) {}; void filter(const SpectrumPtr& spectrum) const; const Config& params; }; void PrecursorMassFilter::Impl::filter(const SpectrumPtr& spectrum) const { vector& massList_ = spectrum->getMZArray()->data; vector& intensities_ = spectrum->getIntensityArray()->data; double upperMassRange = 10000.; if (spectrum->hasCVParam(MS_highest_observed_m_z)) { upperMassRange = spectrum->cvParam(MS_highest_observed_m_z).valueAs(); } int precursorCharge = 0; double precursorMZ = 0.; double maxPrecursorMass = 0.; vector filterMassList; vector chargeStates; for (size_t i=0; i < spectrum->precursors.size(); ++i) { const Precursor& precursor = spectrum->precursors[i]; for (size_t j=0; j < precursor.selectedIons.size(); ++j) { const SelectedIon& selectedIon = precursor.selectedIons[j]; precursorMZ = selectedIon.cvParam(MS_selected_ion_m_z).valueAs(); if (precursorMZ == 0) { // support legacy data precursorMZ = selectedIon.cvParam(MS_m_z).valueAs(); if (precursorMZ == 0) //TODO: log warning, unable to read precursor mz continue; } if (params.removePrecursor) filterMassList.push_back(PrecursorReferenceMass(PrecursorReferenceMass::Precursor, precursorMZ, 0)); precursorCharge = selectedIon.cvParam(MS_charge_state).valueAs(); if (precursorCharge != 0) { int charge = precursorCharge; chargeStates.push_back(charge); maxPrecursorMass = max(Ion::neutralMass(precursorMZ, charge), maxPrecursorMass); if (params.removeReducedChargePrecursors) { double neutralMass = Ion::neutralMass(precursorMZ, charge); for (int reducedCharge = charge - 1; reducedCharge > 0; --reducedCharge) { int electronDelta = charge - reducedCharge; double reducedChargeMZ = Ion::mz(neutralMass, charge, electronDelta); if (reducedChargeMZ < upperMassRange) filterMassList.push_back(PrecursorReferenceMass(PrecursorReferenceMass::ChargeReducedPrecursor, reducedChargeMZ, reducedCharge)); BOOST_FOREACH(const chemistry::Formula& neutralLoss, params.neutralLossSpecies) { double neutralLossMZ = Ion::mz(neutralMass - neutralLoss.monoisotopicMass(), charge, electronDelta); if (neutralLossMZ < upperMassRange) filterMassList.push_back(PrecursorReferenceMass(PrecursorReferenceMass::NeutralLoss, neutralLossMZ, reducedCharge)); } } } } } } if (filterMassList.size() > 0 && chargeStates.size() < 2) { //TODO: we should construct this list so that it doesn't require sorting. sort(filterMassList.begin(), filterMassList.end()); vector::iterator lowerBound; vector::iterator upperBound; int iLowerBound = 0; int iUpperBound = 0; BOOST_FOREACH(const PrecursorReferenceMass& mass, filterMassList) { MZTolerance matchingToleranceLeft = 0; MZTolerance matchingToleranceRight = 0; matchingToleranceLeft = matchingToleranceRight = params.matchingTolerance; if (params.useBlanketFiltering && mass.massType == PrecursorReferenceMass::ChargeReducedPrecursor) { matchingToleranceLeft = leftWindow / (double) mass.charge; } double massToUse = mass.mass; // use STL's binary search to locate fragment ions within the mass tolerance window of the reference mass // O(m*log(n)) for all matches (m-number of reference masses, n-number of observed masses in spectrum). lowerBound = lower_bound(massList_.begin(), massList_.end(), massToUse, MassLessThan(matchingToleranceLeft)); upperBound = upper_bound(massList_.begin(), massList_.end(), massToUse, MassLessThan(matchingToleranceRight)); iLowerBound = lowerBound - massList_.begin(); iUpperBound = upperBound - massList_.begin(); massList_.erase(lowerBound, upperBound); intensities_.erase(intensities_.begin() + iLowerBound, intensities_.begin() + iUpperBound); } // for each reference mass spectrum->defaultArrayLength = massList_.size(); if (maxPrecursorMass == 0) return; // we don't expect any fragments above precursor mass - 60, so we remove all masses above this value // in case there are multiple precursors, we filter everything above the highest precursor mass - 60. // we might want to record observed neutral losses for diagnostic purposes in high resolution data lowerBound = lower_bound(massList_.begin(), massList_.end(), maxPrecursorMass - 60., MassLessThan(params.matchingTolerance)); iLowerBound = lowerBound - massList_.begin(); massList_.erase(lowerBound, massList_.end()); intensities_.erase(intensities_.begin() + iLowerBound, intensities_.end()); spectrum->defaultArrayLength = massList_.size(); } } PWIZ_API_DECL PrecursorMassFilter::PrecursorMassFilter(const Config& config) : params(config), impl_(new Impl(params)) {} PWIZ_API_DECL PrecursorMassFilter::Config::Config( MZTolerance tolerance, bool removePrecursor_, bool removeReducedChargePrecursors_, bool useBlanketFiltering_, int numNeutralLossSpecies, const char* neutralLossSpecies_[]) : matchingTolerance(tolerance), removePrecursor(removePrecursor_), removeReducedChargePrecursors(removeReducedChargePrecursors_), useBlanketFiltering(useBlanketFiltering_) { if (useBlanketFiltering == false) { for (int i=0; i(params.removePrecursor))); method.userParams.push_back(UserParam("filter charge reduced precursors", lexical_cast(params.removeReducedChargePrecursors))); method.userParams.push_back(UserParam("remove neutral loss masses", lexical_cast(params.neutralLossSpecies.size() > 0))); method.userParams.push_back(UserParam("blanket removal of neutral loss masses", lexical_cast(params.useBlanketFiltering))); method.userParams.push_back(UserParam("matching tolerance", lexical_cast(params.matchingTolerance))); } PWIZ_API_DECL void PrecursorMassFilter::operator () (const SpectrumPtr spectrum) const { if (spectrum->defaultArrayLength > 0 && spectrum->cvParam(MS_ms_level).valueAs() > 1 && spectrum->hasCVParam(MS_MSn_spectrum) && !spectrum->precursors.empty() && !spectrum->precursors[0].selectedIons.empty() && !spectrum->precursors[0].selectedIons[0].empty() && spectrum->precursors[0].activation.hasCVParam(MS_ETD)) { impl_->filter(spectrum); } } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/PrecursorRecalculatorDefault.cpp0000664000175100017510000001014412664775615031026 0ustar teamcityteamcity00000000000000// // $Id: PrecursorRecalculatorDefault.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "PrecursorRecalculatorDefault.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace analysis { using namespace pwiz::msdata; using namespace pwiz::data::peakdata; // // PrecursorRecalculatorDefault::Impl // class PrecursorRecalculatorDefault::Impl { public: Impl(const Config& config) : config_(config) {} void recalculate(const MZIntensityPair* begin, const MZIntensityPair* end, const PrecursorInfo& initialEstimate, vector& result); private: Config config_; }; namespace { struct HasLowerMZ { bool operator()(const MZIntensityPair& a, const MZIntensityPair& b){return a.mz < b.mz;} }; PrecursorRecalculator::PrecursorInfo peakFamilyToPrecursorInfo(const PeakFamily& peakFamily) { PrecursorRecalculator::PrecursorInfo result; result.mz = peakFamily.mzMonoisotopic; result.charge = peakFamily.charge; result.score = peakFamily.score; if (!peakFamily.peaks.empty()) result.intensity = peakFamily.peaks[0].intensity; return result; } struct IsCloserTo { IsCloserTo(double mz) : mz_(mz) {} bool operator()(const PrecursorRecalculator::PrecursorInfo& a, const PrecursorRecalculator::PrecursorInfo& b) { return fabs(a.mz - mz_) < fabs(b.mz - mz_); } private: double mz_; }; } // namespace void PrecursorRecalculatorDefault::Impl::recalculate(const MZIntensityPair* begin, const MZIntensityPair* end, const PrecursorInfo& initialEstimate, vector& result) { // use initial estimate to find window double mzLow = initialEstimate.mz - config_.mzLeftWidth; double mzHigh = initialEstimate.mz + config_.mzRightWidth; const MZIntensityPair* low = lower_bound(begin, end, MZIntensityPair(mzLow, 0), HasLowerMZ()); const MZIntensityPair* high = lower_bound(begin, end, MZIntensityPair(mzHigh, 0), HasLowerMZ()); // peak detection vector peakFamilies; config_.peakFamilyDetector->detect(low, high, peakFamilies); // translate PeakFamily result -> PrecursorInfo result transform(peakFamilies.begin(), peakFamilies.end(), back_inserter(result), peakFamilyToPrecursorInfo); // sort if (config_.sortBy == PrecursorRecalculatorDefault::Config::SortBy_Proximity) sort(result.begin(), result.end(), IsCloserTo(initialEstimate.mz)); else throw runtime_error("[PrecursorRecalculatorDefault::recalculate()] sort not implemented"); } // // PrecursorRecalculatorDefault // PWIZ_API_DECL PrecursorRecalculatorDefault::PrecursorRecalculatorDefault(const Config& config) : impl_(new Impl(config)) {} PWIZ_API_DECL void PrecursorRecalculatorDefault::recalculate(const MZIntensityPair* begin, const MZIntensityPair* end, const PrecursorInfo& initialEstimate, vector& result) const { impl_->recalculate(begin, end, initialEstimate, result); } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/SpectrumList_3D.cpp0000664000175100017510000000474012664775615026165 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_3D.cpp 6385 2014-06-12 22:56:04Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_3D.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/data/vendor_readers/Agilent/SpectrumList_Agilent.hpp" #include "pwiz/data/vendor_readers/Waters/SpectrumList_Waters.hpp" namespace pwiz { namespace analysis { using namespace msdata; using namespace pwiz::util; PWIZ_API_DECL SpectrumList_3D::SpectrumList_3D(const msdata::SpectrumListPtr& inner) : SpectrumListWrapper(inner), mode_(0) { detail::SpectrumList_Agilent* agilent = dynamic_cast(&*inner); if (agilent) { mode_ = 1; } detail::SpectrumList_Waters* waters = dynamic_cast(&*inner); if (waters) { mode_ = 2; } } PWIZ_API_DECL bool SpectrumList_3D::accept(const msdata::SpectrumListPtr& inner) { return dynamic_cast(&*inner) || dynamic_cast(&*inner); } PWIZ_API_DECL SpectrumPtr SpectrumList_3D::spectrum(size_t index, bool getBinaryData) const { return inner_->spectrum(index, getBinaryData); } PWIZ_API_DECL Spectrum3DPtr SpectrumList_3D::spectrum3d(double scanStartTime, const boost::icl::interval_set& driftTimeRanges) const { switch (mode_) { default: case 0: throw runtime_error("[SpectrumList_3D::spectrum3d] 3d spectra currently only supported for Agilent and Waters"); case 1: return dynamic_cast(&*inner_)->spectrum3d(scanStartTime, driftTimeRanges); case 2: return dynamic_cast(&*inner_)->spectrum3d(scanStartTime, driftTimeRanges); } } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/SpectrumList_MZRefiner.hpp0000664000175100017510000001033712664775615027564 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_MZRefiner.hpp 8985 2015-10-12 22:38:57Z chambm $ // // // Original author: Bryson Gibbons // // Copyright 2014 Pacific Northwest National Laboratory // Richland, WA 99352 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_MZREFINER_HPP_ #define _SPECTRUMLIST_MZREFINER_HPP_ /*************************************************************************************** **************************************************************************************** **************************************************************************************** **************************************************************************************** ASSUMPTIONS: We are assuming that the instrument used to produce the data has at most ONE high-resolution mass analyzer. - If an instrument contained TWO high-resolution mass analyzers, two different shifts would be needed, as well as the computations to create those shifts. - We don't have such an instrument, and so we have no way to properly test that configuration, much less any reason to write code to work with it. ======================================================================================== LIMITATIONS: This feature was created to modify m/z values using a bias generated from peptide identifications consistent with a single run. - It has not been tested with merged data files. There would be little sense to using it with merged data files, since that would involve trying to create multiple shifts from one identification file and use them appropriately on one data file. - It has not been tested on data files with combined spectra. I have not seen any reason to, and producing a good result would likely involve accessing the original spectra anyway. - There are inherent challenges in finding the scan start time for a spectrum if it is not included in the identification file. If the identification file was not created using an mzML file (directly from native files), and the data file used for the refinement operation is not the mzML file (or the native file(s)), then we will probably just exclude the scan time dependent shift, since most other supported file types do not store the native ID. ======================================================================================== ======================================================================================== DETERMINE IF THESE SHOULD BE ADDED TO THE USAGE INSTRUCTIONS **************************************************************************************** **************************************************************************************** **************************************************************************************** ***************************************************************************************/ #include "pwiz/data/msdata/SpectrumListWrapper.hpp" #include "pwiz/utility/misc/IntegerSet.hpp" #include "pwiz/utility/misc/IterationListener.hpp" namespace pwiz { namespace analysis { // SpectrumList wrapper that recalculates precursor info on spectrum() requests class PWIZ_API_DECL SpectrumList_MZRefiner : public msdata::SpectrumListWrapper { public: SpectrumList_MZRefiner(const msdata::MSData& msd, const std::string& identFilePath, const std::string& cvTerm, const std::string& rangeSet, const util::IntegerSet& msLevelsToRefine, double step = 0.0, int maxStep = 0, pwiz::util::IterationListenerRegistry* ilr = NULL); /// \name SpectrumList interface //@{ virtual msdata::SpectrumPtr spectrum(size_t index, bool getBinaryData = false) const; //@} private: class Impl; boost::shared_ptr impl_; }; } // namespace analysis } // namespace pwiz #endif // _SPECTRUMLIST_MZREFINER_HPP_ pwiz/pwiz/analysis/spectrum_processing/PrecursorMassFilter.hpp0000664000175100017510000001147212664775615027164 0ustar teamcityteamcity00000000000000// // $Id: PrecursorMassFilter.hpp 2469 2011-01-18 19:27:57Z chambm $ // // // Original author: Chris Paulse systemsbiology.org> // // Copyright 2009 Institute for Systems Biology, Seattle, WA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PRECURSORMASSFILTER_HPP_ #define _PRECURSORMASSFILTER_HPP_ #include "pwiz/analysis/common/DataFilter.hpp" #include "pwiz/utility/chemistry/MZTolerance.hpp" #include "pwiz/utility/chemistry/Chemistry.hpp" namespace pwiz { namespace analysis { // See Table 1 of // "Post Acquisition ETD Spectral Processing of Increased Peptide Identifications" -- PUB 1 // by D. M. Good et al // // Experimental Section and Table 1 of // "Analytical Utility of Small Neutral Losses from Reduced Species in Electron // Capture Dissociation Studied Using SwedECD Database" by M. Falth et al -- PUB 2 // // Cooper, H. J., Hakansson, K., Marshall, A.G., Hudgins, R. R., Haselmann, K. F., // Kjeldsen, F., Budnik, B. A. Polfer, N. C., Zubarev, R. A., Letter: the diagnostic value of // amino acid side-chain losses in electron capture dissociation of polypeptides. Comment // on: "Can the (M(.)-X) region in electron capture dissociation provide reliable information on // amino acid composition of polypeptides?", Eur. J. Mass Spectrom. 8, 461-469 (2002). -- PUB 3 //17.027 Da NH3 //18.011 Da H2O //27.995 Da CO //32.026 Da CH3OH //34.053 Da N2H6 (2xNH3) //35.037 Da H4NO //36.021 Da H4O2 (2xH2O) //74.019 Da C3H6S //82.053 Da C4H6N2 //86.072 Da C3H8N3 //99.068 Da C4H9N3 //101.095 Da C4H11N3 //108.058 Da C7H8O //(131.074 Da C9H9N) //44.037 Da CH4N2 //45.021 Da CH3NO //46.006 Da CH2O2 //46.042 Da C2H6O //59.037 Da C2H5NO //59.048 Da CH5N3 //73.089 Da C4H11N #define NUM_NEUTRAL_LOSS_SPECIES 25 // All entries are PUB 1 Table 1 except where noted static const char* defaultNeutralLossFormulae[] = { "H1", // ubiquitous neutral loss (PUB 2) "N1H2", // ubiquitous neutral loss (PUB 2) "N1H3", "H2O1", "C1O1", "C1H4O1", "N2H6", // 2 * NH3 "H5N1O1", // Typo in PUB 1 Table 1 NH3 + H2O "H4O2", // 2 * H2O "C1H3N2", // PUB 2 Table 1 "C1H4N2", "C1H3N1O1", "C1H2O2", "C2H6O1", "C2H5N1O1", "C1H5N3", "C2H4O2", // PUB 2 Table 1 "C4H11N1", // PUB 3 "C3H6S1", // PUB 3 "C4H6N2", // PUB 3 "C3H8N3", // PUB 3 "C4H9N3", // PUB 3 "C4H11N3", // PUB 3 "C7H8O1", // PUB 3 "C9H9N1" // PUB 3 }; using chemistry::MZTolerance; struct PWIZ_API_DECL PrecursorMassFilter : public SpectrumDataFilter { /// PrecursorMassFilter's parameters struct PWIZ_API_DECL Config { Config( MZTolerance tolerance = MZTolerance(0.1), bool removePrecursor_ = true, bool removeReducedChargePrecursors_ = true, bool useBlanketFiltering_ = false, int numNeutralLossSpecies = NUM_NEUTRAL_LOSS_SPECIES, const char* neutralLossSpecies_[] = defaultNeutralLossFormulae ); MZTolerance matchingTolerance; /// remove the precursor m/z from the MS2 spectrum bool removePrecursor; /** electron transfer in ETD or ECD creates intact precursors with reduced charge states * this flag specifies their removal. */ bool removeReducedChargePrecursors; /** intact precursors can undergo loss of neutral molecules after the dissociation event * this flag specifies the removal of these "neutral loss" ions (precursor mass - neutral loss mass)/charge */ std::vector neutralLossSpecies; bool removeNeutralLossSpecies; /// flag indicates neutral loss removal by applying a charge scaled 60 Da exclusion window below the charge reduced precursor bool useBlanketFiltering; }; PrecursorMassFilter(const Config&); virtual void operator () (const pwiz::msdata::SpectrumPtr) const; virtual void describe(pwiz::msdata::ProcessingMethod&) const; const PrecursorMassFilter::Config params; private: struct Impl; boost::shared_ptr impl_; }; } // namespace analysis } // namespace pwiz #endif // _PRECURSORMASSFILTER_HPP_ pwiz/pwiz/analysis/spectrum_processing/SpectrumListFactory.hpp0000664000175100017510000000353312664775615027173 0ustar teamcityteamcity00000000000000// // $Id: SpectrumListFactory.hpp 7303 2015-03-13 20:19:40Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLISTFACTORY_HPP_ #define _SPECTRUMLISTFACTORY_HPP_ #include "pwiz/data/msdata/MSData.hpp" #include "pwiz/data/msdata/examples.hpp" #include "pwiz/utility/misc/IterationListener.hpp" #include #include namespace pwiz { namespace analysis { /// Factory for instantiating and wrapping SpectrumLists class PWIZ_API_DECL SpectrumListFactory { public: /// instantiate the SpectrumListWrapper indicated by wrapper static void wrap(msdata::MSData& msd, const std::string& wrapper, pwiz::util::IterationListenerRegistry* ilr = NULL); /// instantiate a list of SpectrumListWrappers static void wrap(msdata::MSData& msd, const std::vector& wrappers, pwiz::util::IterationListenerRegistry* ilr = NULL); /// user-friendly documentation, with option of less or more detail static std::string usage(bool detailedHelp = true, const char* morehelp_prompt = NULL, int maxLineLength = 80); }; } // namespace analysis } // namespace pwiz #endif // _SPECTRUMLISTFACTORY_HPP_ pwiz/pwiz/analysis/spectrum_processing/SpectrumListFactoryTest.cpp0000664000175100017510000003475312664775615030036 0ustar teamcityteamcity00000000000000// // $Id: SpectrumListFactoryTest.cpp 6393 2014-06-17 20:02:26Z frenchwr $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "SpectrumListFactory.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::analysis; using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::msdata; ostream* os_ = 0; void testUsage() { if (os_) *os_ << "SpectrumListFactory::usage():\n" << SpectrumListFactory::usage() << endl; } void testWrap() { MSData msd; examples::initializeTiny(msd); SpectrumListPtr& sl = msd.run.spectrumListPtr; unit_assert(sl.get()); unit_assert(sl->size() > 2); // CompassXtract and pwiz data processing unit_assert_operator_equal(2, msd.allDataProcessingPtrs().size()); unit_assert_operator_equal(1, msd.allDataProcessingPtrs()[1]->processingMethods.size()); SpectrumListFactory::wrap(msd, "scanNumber [19,20]"); unit_assert(sl->size() == 2); // make sure we can handle config file lines copied from commandline // with quotes intact SpectrumListFactory::wrap(msd, "'index [1,1]'"); unit_assert(sl->size() == 1); unit_assert(sl->spectrumIdentity(0).id == "scan=20"); vector profileData(sl->spectrum(0)->getMZArray()->data); unit_assert(profileData.size() == 10); unit_assert(profileData[0] == 0); unit_assert(profileData[9] == 18); unit_assert_operator_equal(2, msd.allDataProcessingPtrs().size()); unit_assert_operator_equal(1, msd.allDataProcessingPtrs()[1]->processingMethods.size()); SpectrumListFactory::wrap(msd, "peakPicking true [1,6]"); // backwards compatible syntax SpectrumListFactory::wrap(msd, "peakPicking false"); // backwards compatible syntax SpectrumListFactory::wrap(msd, "peakPicking cwt msLevel=[1,6]"); SpectrumListFactory::wrap(msd, "peakPicking cwt snr=1.2 msLevel=2-"); SpectrumListFactory::wrap(msd, "peakPicking cwt peakSpace=0.05"); vector peakData(sl->spectrum(0)->getMZArray()->data); unit_assert(peakData.size() == 1); unit_assert(peakData[0] == 0); unit_assert_operator_equal(2, msd.allDataProcessingPtrs().size()); unit_assert_operator_equal(6, msd.allDataProcessingPtrs()[1]->processingMethods.size()); } void testWrapScanTimeRange() { MSData msd; examples::initializeTiny(msd); SpectrumListPtr& sl = msd.run.spectrumListPtr; unit_assert(sl.get()); unit_assert(sl->size() > 2); double timeHighInSeconds = 5.9 * 60; // between first and second scan ostringstream oss; oss << "scanTime [0," << timeHighInSeconds << "]"; SpectrumListFactory::wrap(msd, oss.str()); unit_assert(sl->size() == 2); unit_assert(sl->spectrumIdentity(0).id == "scan=19"); unit_assert(sl->spectrumIdentity(1).id == "sample=1 period=1 cycle=23 experiment=1"); // not in scan time order (42 seconds) } void testWrapSortScanTime() { MSData msd; examples::initializeTiny(msd); SpectrumListPtr& sl = msd.run.spectrumListPtr; unit_assert(sl.get()); unit_assert(sl->size() == 5); sl->spectrum(0)->scanList.scans[0].set(MS_scan_start_time, 35, UO_second); sl->spectrum(2)->scanList.scans[0].set(MS_scan_start_time, 0.5, UO_minute); SpectrumListFactory::wrap(msd, "sortByScanTime"); unit_assert(sl->size() == 5); unit_assert(sl->spectrumIdentity(0).id == "scan=21"); unit_assert(sl->spectrumIdentity(1).id == "scan=19"); unit_assert(sl->spectrumIdentity(2).id == "sample=1 period=1 cycle=23 experiment=1"); } void testWrapMZWindow() { MSData msd; examples::initializeTiny(msd); SpectrumListPtr& sl = msd.run.spectrumListPtr; unit_assert(sl.get() && sl->size()>2); SpectrumPtr spectrum = sl->spectrum(0, true); vector data; spectrum->getMZIntensityPairs(data); unit_assert(data.size() == 15); SpectrumListFactory::wrap(msd, "mzWindow [9.5,15]"); spectrum = sl->spectrum(0, true); spectrum->getMZIntensityPairs(data); unit_assert(data.size() == 5); spectrum = sl->spectrum(1, true); spectrum->getMZIntensityPairs(data); unit_assert(data.size() == 3); } void testWrapMSLevel() { MSData msd; examples::initializeTiny(msd); SpectrumListPtr& sl = msd.run.spectrumListPtr; unit_assert(sl.get()); unit_assert_operator_equal(5, sl->size()); SpectrumListFactory::wrap(msd, "msLevel 2"); unit_assert_operator_equal(2, sl->size()); unit_assert_operator_equal("scan=20", sl->spectrumIdentity(0).id); } void testWrapChargeState() { { MSData msd; examples::initializeTiny(msd); SpectrumListPtr& sl = msd.run.spectrumListPtr; SpectrumListFactory::wrap(msd, "chargeState 2"); unit_assert_operator_equal(2, sl->size()); unit_assert_operator_equal("scan=20", sl->spectrumIdentity(0).id); SpectrumListFactory::wrap(msd, "chargeState 1"); unit_assert_operator_equal(0, sl->size()); } { MSData msd; examples::initializeTiny(msd); SpectrumListPtr& sl = msd.run.spectrumListPtr; SpectrumListFactory::wrap(msd, "chargeState 0-2"); unit_assert_operator_equal(2, sl->size()); unit_assert_operator_equal("scan=20", sl->spectrumIdentity(0).id); } } void testWrapDefaultArrayLength() { // test that the minimum length is 1 (due to 0 being the "unset" value) { MSData msd; examples::initializeTiny(msd); SpectrumListPtr& sl = msd.run.spectrumListPtr; unit_assert(sl.get()); unit_assert(sl->size() == 5); SpectrumListFactory::wrap(msd, "defaultArrayLength 0-"); unit_assert(sl->size() == 4); unit_assert(sl->find("scan=21") == sl->size()); } // test filtering out all spectra { MSData msd; examples::initializeTiny(msd); SpectrumListPtr& sl = msd.run.spectrumListPtr; SpectrumListFactory::wrap(msd, "defaultArrayLength 100-"); unit_assert(sl->size() == 0); } // test filtering out empty spectra { MSData msd; examples::initializeTiny(msd); SpectrumListPtr& sl = msd.run.spectrumListPtr; SpectrumListFactory::wrap(msd, "defaultArrayLength 1-"); unit_assert(sl->size() == 4); unit_assert(sl->find("scan=21") == sl->size()); } // test filtering out spectra with defaultArrayLength > 14 { MSData msd; examples::initializeTiny(msd); SpectrumListPtr& sl = msd.run.spectrumListPtr; SpectrumListFactory::wrap(msd, "defaultArrayLength 15-"); unit_assert(sl->size() == 2); unit_assert(sl->find("scan=20") == sl->size()); unit_assert(sl->find("scan=21") == sl->size()); } // test filtering out spectra with 0 < defaultArrayLength < 15 { MSData msd; examples::initializeTiny(msd); SpectrumListPtr& sl = msd.run.spectrumListPtr; SpectrumListFactory::wrap(msd, "defaultArrayLength 1-14"); unit_assert(sl->size() == 2); unit_assert(sl->find("scan=20") == 0); } } void testWrapActivation() { // test filter by CID activation { MSData msd; examples::initializeTiny(msd); SpectrumListFactory::wrap(msd, "msLevel 2-"); SpectrumListFactory::wrap(msd, "activation CID"); unit_assert(msd.run.spectrumListPtr->size() == 1); } // test filter by ETD activation { MSData msd; examples::initializeTiny(msd); SpectrumListFactory::wrap(msd, "msLevel 2-"); SpectrumListFactory::wrap(msd, "activation ETD"); unit_assert(msd.run.spectrumListPtr->size() == 1); } // test filter by HCD activation { MSData msd; examples::initializeTiny(msd); SpectrumListFactory::wrap(msd, "msLevel 2-"); SpectrumListFactory::wrap(msd, "activation HCD"); unit_assert(msd.run.spectrumListPtr->size() == 0); } // test filter by IRMPD activation { MSData msd; examples::initializeTiny(msd); SpectrumListFactory::wrap(msd, "msLevel 2-"); SpectrumListFactory::wrap(msd, "activation IRMPD"); unit_assert(msd.run.spectrumListPtr->size() == 0); } // test invalid argument { MSData msd; examples::initializeTiny(msd); unit_assert_throws(SpectrumListFactory::wrap(msd, "activation UNEXPECTED_INPUT"), runtime_error); } } void testWrapMassAnalyzer() { // test filter by ITMS analyzer type { MSData msd; examples::initializeTiny(msd); SpectrumListFactory::wrap(msd, "analyzerType ITMS"); unit_assert(msd.run.spectrumListPtr->size() == 5); } // test filter by ITMS analyzer type (new syntax) { MSData msd; examples::initializeTiny(msd); SpectrumListFactory::wrap(msd, "analyzerType it"); unit_assert(msd.run.spectrumListPtr->size() == 5); } // test filter by FTMS analyzer type { MSData msd; examples::initializeTiny(msd); SpectrumListFactory::wrap(msd, "analyzer FTMS"); unit_assert(msd.run.spectrumListPtr->size() == 0); } // test filter by Orbi analyzer type { MSData msd; examples::initializeTiny(msd); SpectrumListFactory::wrap(msd, "analyzer Orbi"); unit_assert(msd.run.spectrumListPtr->size() == 0); } // test filter by TOF analyzer type { MSData msd; examples::initializeTiny(msd); SpectrumListFactory::wrap(msd, "analyzer TOF"); unit_assert(msd.run.spectrumListPtr->size() == 0); } // test invalid argument { MSData msd; examples::initializeTiny(msd); unit_assert_throws(SpectrumListFactory::wrap(msd, "analyzer UNEXPECTED_INPUT"), runtime_error) } } void testWrapPolarity() { // test filter by positive polarity { MSData msd; examples::initializeTiny(msd); SpectrumListPtr& sl = msd.run.spectrumListPtr; unit_assert(sl.get()); unit_assert(sl->size() == 5); SpectrumListFactory::wrap(msd, "polarity positive"); unit_assert(sl->size() == 3); } // test filter by + polarity { MSData msd; examples::initializeTiny(msd); SpectrumListPtr& sl = msd.run.spectrumListPtr; unit_assert(sl.get()); unit_assert(sl->size() == 5); SpectrumListFactory::wrap(msd, "polarity +"); unit_assert(sl->size() == 3); } // test filter by negative polarity { MSData msd; examples::initializeTiny(msd); SpectrumListPtr& sl = msd.run.spectrumListPtr; unit_assert(sl.get()); unit_assert(sl->size() == 5); SpectrumListFactory::wrap(msd, "polarity -"); unit_assert(sl->size() == 2); } // test invalid argument { MSData msd; examples::initializeTiny(msd); SpectrumListPtr& sl = msd.run.spectrumListPtr; unit_assert(sl.get()); unit_assert(sl->size() == 5); unit_assert_throws(SpectrumListFactory::wrap(msd, "polarity UNEXPECTED_INPUT"), runtime_error) } } void testWrapTitleMaker() { MSData msd; examples::initializeTiny(msd); { SpectrumListFactory::wrap(msd, "titleMaker "); SpectrumListPtr& sl = msd.run.spectrumListPtr; unit_assert_operator_equal("scan=19", sl->spectrum(0)->cvParam(MS_spectrum_title).value); unit_assert_operator_equal("scan=20", sl->spectrum(1)->cvParam(MS_spectrum_title).value); unit_assert_operator_equal("scan=21", sl->spectrum(2)->cvParam(MS_spectrum_title).value); unit_assert_operator_equal("scan=22", sl->spectrum(3)->cvParam(MS_spectrum_title).value); unit_assert_operator_equal("sample=1 period=1 cycle=23 experiment=1", sl->spectrum(4)->cvParam(MS_spectrum_title).value); } { // the outer titleMaker overrides the inner one SpectrumListFactory::wrap(msd, "titleMaker ; , "); SpectrumListPtr& sl = msd.run.spectrumListPtr; unit_assert_operator_equal("0; MS1 spectrum, 1", sl->spectrum(0)->cvParam(MS_spectrum_title).value); unit_assert_operator_equal("1; MSn spectrum, 2", sl->spectrum(1)->cvParam(MS_spectrum_title).value); unit_assert_operator_equal("2; MS1 spectrum, 1", sl->spectrum(2)->cvParam(MS_spectrum_title).value); unit_assert_operator_equal("3; MSn spectrum, 2", sl->spectrum(3)->cvParam(MS_spectrum_title).value); unit_assert_operator_equal("4; MS1 spectrum, 1", sl->spectrum(4)->cvParam(MS_spectrum_title).value); } { SpectrumListFactory::wrap(msd, "titleMaker "); SpectrumListPtr& sl = msd.run.spectrumListPtr; unit_assert_operator_equal("19 1 ", sl->spectrum(0)->cvParam(MS_spectrum_title).value); unit_assert_operator_equal("20 2 CID 2 scan=19", sl->spectrum(1)->cvParam(MS_spectrum_title).value); unit_assert_operator_equal("21 1 ", sl->spectrum(2)->cvParam(MS_spectrum_title).value); unit_assert_operator_equal("22 2 ETD/CID 2 scan=19", sl->spectrum(3)->cvParam(MS_spectrum_title).value); unit_assert_operator_equal("5 1 ", sl->spectrum(4)->cvParam(MS_spectrum_title).value); } } void test() { testUsage(); testWrap(); testWrapScanTimeRange(); testWrapSortScanTime(); testWrapMZWindow(); testWrapMSLevel(); testWrapChargeState(); testWrapDefaultArrayLength(); testWrapActivation(); testWrapMassAnalyzer(); testWrapPolarity(); testWrapTitleMaker(); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/spectrum_processing/SpectrumList_MetadataFixer.hpp0000664000175100017510000000304212664775615030434 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_MetadataFixer.hpp 2532 2011-03-03 22:48:24Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_METADATAFIXER_HPP_ #define _SPECTRUMLIST_METADATAFIXER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/SpectrumListWrapper.hpp" namespace pwiz { namespace analysis { /// SpectrumList implementation to add (or replace) base peak and total ion metadata /// with new values calculated from the current binary data. class PWIZ_API_DECL SpectrumList_MetadataFixer : public msdata::SpectrumListWrapper { public: SpectrumList_MetadataFixer(const msdata::SpectrumListPtr& inner); static bool accept(const msdata::SpectrumListPtr& inner); virtual msdata::SpectrumPtr spectrum(size_t index, bool getBinaryData = false) const; }; } // namespace analysis } // namespace pwiz #endif // _SPECTRUMLIST_METADATAFIXER_HPP_ pwiz/pwiz/analysis/spectrum_processing/SpectrumList_PrecursorRefine.cpp0000664000175100017510000002320112664775615031025 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_PrecursorRefine.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Chris Paulse // // Copyright 2010 Institute for Systems Biology // Seattle, WA 98103 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include #include #include "SpectrumList_PrecursorRefine.hpp" #include "pwiz/analysis/passive/MSDataCache.hpp" #include "pwiz/utility/chemistry/MZTolerance.hpp" #include "pwiz/data/vendor_readers/Agilent/SpectrumList_Agilent.hpp" #include "pwiz/utility/misc/Std.hpp" #include namespace pwiz { namespace analysis { using namespace pwiz::cv; using namespace pwiz::msdata; using namespace pwiz::data; // // SpectrumList_PrecursorRefine::Impl // struct SpectrumList_PrecursorRefine::Impl { MSDataCache cache; CVID targetMassAnalyzerType; Impl(const MSData& msd); }; SpectrumList_PrecursorRefine::Impl::Impl(const MSData& msd) : targetMassAnalyzerType(CVID_Unknown), cache(MSDataCache::Config(20)) { cache.open(msd); // choose highest-accuracy mass analyzer for targetMassAnalyzerType for (vector::const_iterator it=msd.instrumentConfigurationPtrs.begin(), end=msd.instrumentConfigurationPtrs.end(); it!=end; ++it) { if (!it->get()) continue; const InstrumentConfiguration& ic = **it; BOOST_FOREACH(const Component& component, ic.componentList) { if (component.type == ComponentType_Analyzer) if (targetMassAnalyzerType!=MS_FT_ICR && targetMassAnalyzerType!=MS_orbitrap && targetMassAnalyzerType!=MS_time_of_flight) targetMassAnalyzerType = component.cvParamChild(MS_mass_analyzer_type).cvid; } } #if 1 // silently proceed with pass-through in case data can't be processed (inconsistent with other filters) if (targetMassAnalyzerType!=MS_FT_ICR && targetMassAnalyzerType!=MS_orbitrap && targetMassAnalyzerType!=MS_time_of_flight) throw runtime_error(("[SpectrumList_PrecursorRefine] Mass analyzer not supported: " + cvTermInfo(targetMassAnalyzerType).name).c_str()); #endif } // // SpectrumList_PrecursorRefine // PWIZ_API_DECL SpectrumList_PrecursorRefine::SpectrumList_PrecursorRefine( const MSData& msd) : SpectrumListWrapper(msd.run.spectrumListPtr), impl_(new Impl(msd)) { // add processing methods to the copy of the inner SpectrumList's data processing ProcessingMethod method; method.order = dp_->processingMethods.size(); method.userParams.push_back(UserParam("precursor refinement", "msPrefix defaults")); if (!dp_->processingMethods.empty()) method.softwarePtr = dp_->processingMethods[0].softwarePtr; dp_->processingMethods.push_back(method); numRefined = 0; numTotal = 0; } SpectrumList_PrecursorRefine::~SpectrumList_PrecursorRefine() { } struct HasLowerMZ { bool operator()(const MZIntensityPair& a, const MZIntensityPair& b){return a.mz < b.mz;} }; PWIZ_API_DECL SpectrumPtr SpectrumList_PrecursorRefine::spectrum(size_t index, bool getBinaryData) const { SpectrumPtr originalSpectrum; // silently return for incompatible data types if (impl_->targetMassAnalyzerType != MS_FT_ICR && impl_->targetMassAnalyzerType != MS_orbitrap && impl_->targetMassAnalyzerType != MS_time_of_flight) return inner_->spectrum(index, getBinaryData); // HACK: this is to circumvent problems with spectrum list wrapper nesting: peakPicking and precursorRefine // can't be combined in msconvert for this reason. if (dynamic_cast(&*inner_)) originalSpectrum = dynamic_cast(&*inner_)->spectrum(index, true, util::IntegerSet(1,2)); else originalSpectrum = inner_->spectrum(index, getBinaryData); // return non-MS/MS as-is CVParam spectrumType = originalSpectrum->cvParamChild(MS_spectrum_type); if (spectrumType != MS_MSn_spectrum) return originalSpectrum; // return MS1 as-is CVParam msLevel = originalSpectrum->cvParam(MS_ms_level); if (msLevel.valueAs() < 2) return originalSpectrum; if (originalSpectrum->precursors.size() == 0 || originalSpectrum->precursors[0].selectedIons.size() == 0 || originalSpectrum->precursors[0].selectedIons[0].cvParam(MS_selected_ion_m_z).valueAs() == 0.0) return originalSpectrum; BOOST_FOREACH(SelectedIon& selectedIon, originalSpectrum->precursors[0].selectedIons) { double refined = RefineMassVal(selectedIon.cvParam(MS_selected_ion_m_z).valueAs(), index); selectedIon.set(MS_selected_ion_m_z, refined); } SpectrumPtr newSpectrum = SpectrumPtr(new Spectrum(*originalSpectrum)); return newSpectrum; } PWIZ_API_DECL double SpectrumList_PrecursorRefine::RefineMassVal(double initialEstimate, size_t index) const { size_t parentIndex[3]; bool foundParent[3] = {false, false, false}; parentIndex[0] = index; parentIndex[1] = index; parentIndex[2] = index; if (initialEstimate == 0) return initialEstimate; SpectrumInfo xx1; SpectrumInfo xx2; SpectrumInfo xx3; pwiz::msdata::SpectrumInfo& info1 = xx1; pwiz::msdata::SpectrumInfo& info2 = xx2; pwiz::msdata::SpectrumInfo& info3 = xx3; while (1) { if (foundParent[0] == false && parentIndex[0]-- == 0) return initialEstimate; if (foundParent[1] == false && parentIndex[1]++ >= inner_->size()-2) return initialEstimate; if (foundParent[2] == false && parentIndex[2]++ >= inner_->size()-2) return initialEstimate; if (foundParent[0] == false) info1 = impl_->cache.spectrumInfo(parentIndex[0]); if (foundParent[1] == false) info2 = impl_->cache.spectrumInfo(parentIndex[1]); if (foundParent[1] && foundParent[2] == false) info3 = impl_->cache.spectrumInfo(parentIndex[2]); if (foundParent[0] == false && info1.msLevel == 1) { foundParent[0] = true; info1 = impl_->cache.spectrumInfo(parentIndex[0], true); } if (foundParent[1] == false && info2.msLevel == 1) { info2 = impl_->cache.spectrumInfo(parentIndex[1], true); foundParent[1] = true; parentIndex[2] = parentIndex[1] + 1; info3 = impl_->cache.spectrumInfo(parentIndex[2]); } if (foundParent[1] && parentIndex[2] != index && info3.msLevel==1) { info3 = impl_->cache.spectrumInfo(parentIndex[2], true); foundParent[2] = true; } if (foundParent[0] && foundParent[1] && foundParent[2]) break; } // return early if no data found in adjacent ms1 scans if (info1.data.empty() || info2.data.empty() || info3.data.empty()) return initialEstimate; // find the maximum intensity in a window // the initial estimate of the precursor +/- a selected window width. If these three points // form a maximum, they are used as input to an intensity weighted centriod // // refined m/z = sum over three spectra j ( sum over three data points in profile i) mz_ij * I_ij^exponent / I_ij^exponent // bool isOrbitrap = (info1.massAnalyzerType == MS_orbitrap); double windowFactor = isOrbitrap ? 30e-6 : 90e-6; double mzLow = initialEstimate - windowFactor * initialEstimate; double mzHigh = initialEstimate + windowFactor * initialEstimate; double newCentroid = 0; double denom = 0.0; int intensityWeightingExponent = isOrbitrap ? 8 : 4; // best result: exp 4 width 2 (Halo data file) int width = isOrbitrap ? 1 : 2; double intensMax = 0.; for (int i = 0; i < 3; i++) { pwiz::msdata::SpectrumInfo& info = (i == 0) ? info1 : (i == 1) ? info2 : info3; const std::vector& output = info.data; const MZIntensityPair* low = lower_bound(&output[0], &output[0]+output.size(), MZIntensityPair(mzLow, 0), HasLowerMZ()); const MZIntensityPair* high = lower_bound(&output[0], &output[0]+output.size(), MZIntensityPair(mzHigh, 0), HasLowerMZ()); int maxIndex = 0; intensMax = 0.; int ix = 0; for (const MZIntensityPair* p = low; p <= high; p++, ix++) { if (p->intensity > intensMax) { intensMax = p->intensity; maxIndex = ix; } } if (maxIndex >= width && maxIndex <= high-low-width) { for (int ii = -width; ii <= width; ii++) { newCentroid += (low + maxIndex + ii)->mz * pow((low + maxIndex + ii)->intensity, intensityWeightingExponent)/*/(double)sqrt(abs(ii)+1.0)*/; denom += pow((low + maxIndex + ii)->intensity, intensityWeightingExponent)/*/(double)sqrt(abs(ii)+1.0)*/; } } } if (denom > 0) { numRefined++; newCentroid /= denom; } else { newCentroid = initialEstimate; } numTotal++; return newCentroid; } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/SpectrumList_PrecursorRefine.hpp0000664000175100017510000000436512664775615031044 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_PrecursorRefine.hpp 1191 2009-08-14 19:33:05Z chambm $ // // // Original author: Chris Paulse // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_PRECURSORREREFINE_HPP_ #define _SPECTRUMLIST_PRECURSORREREFINE_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/SpectrumListWrapper.hpp" namespace pwiz { namespace analysis { /// SpectrumList wrapper that recalculates precursor info on spectrum() requests class PWIZ_API_DECL SpectrumList_PrecursorRefine : public msdata::SpectrumListWrapper { public: struct PWIZ_API_DECL PrecursorInfo { double mz; double intensity; double charge; double score; PrecursorInfo() : mz(0), intensity(0), charge(0), score(0) {} }; /// constructor needs the full MSData object for instrument info; /// SpectrumList_PrecursorRefine holds a reference to the original SpectrumListPtr SpectrumList_PrecursorRefine(const msdata::MSData& msd); ~SpectrumList_PrecursorRefine(); /// \name SpectrumList interface //@{ virtual msdata::SpectrumPtr spectrum(size_t index, bool getBinaryData = false) const; //@} private: double RefineMassVal(double initialEstimate, size_t index) const; struct Impl; boost::shared_ptr impl_; SpectrumList_PrecursorRefine(SpectrumList_PrecursorRefine&); SpectrumList_PrecursorRefine& operator=(SpectrumList_PrecursorRefine&); mutable int numRefined; mutable int numTotal; }; } // namespace analysis } // namespace pwiz #endif // _SPECTRUMLIST_PRECURSORREREFINE_HPP_ pwiz/pwiz/analysis/spectrum_processing/SpectrumList_MZWindow.cpp0000664000175100017510000000463712664775615027442 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_MZWindow.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_MZWindow.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace analysis { using namespace msdata; PWIZ_API_DECL SpectrumList_MZWindow::SpectrumList_MZWindow(const SpectrumListPtr original, double mzLow, double mzHigh) : SpectrumListWrapper(original), mzLow_(mzLow), mzHigh_(mzHigh) {} namespace { inline bool hasLowerMZ(const MZIntensityPair& a, const MZIntensityPair& b) {return a.mz < b.mz;} } // namespace PWIZ_API_DECL msdata::SpectrumPtr SpectrumList_MZWindow::spectrum(size_t index, bool getBinaryData) const { SpectrumPtr spectrum = inner_->spectrum(index, getBinaryData); if (!getBinaryData) return spectrum; vector data; spectrum->getMZIntensityPairs(data); vector::const_iterator begin = lower_bound( data.begin(), data.end(), MZIntensityPair(mzLow_,0), hasLowerMZ); vector::const_iterator end = upper_bound( data.begin(), data.end(), MZIntensityPair(mzHigh_,0), hasLowerMZ); vector newData; copy(begin, end, back_inserter(newData)); BinaryDataArrayPtr intensityArray = spectrum->getIntensityArray(); CVID intensityUnits = intensityArray.get() ? intensityArray->cvParam(MS_intensity_unit).cvid : CVID_Unknown; SpectrumPtr newSpectrum(new Spectrum(*spectrum)); newSpectrum->binaryDataArrayPtrs.clear(); newSpectrum->setMZIntensityPairs(newData, intensityUnits); return newSpectrum; } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/SpectrumList_SorterTest.cpp0000664000175100017510000002454612664775615030043 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_SorterTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "SpectrumList_Sorter.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include #include "pwiz/data/msdata/examples.hpp" #include "pwiz/data/msdata/TextWriter.hpp" #include "boost/logic/tribool.hpp" using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::msdata; using namespace pwiz::analysis; using boost::logic::tribool; ostream* os_ = 0; struct DefaultArrayLengthSorter : public SpectrumList_Sorter::Predicate { virtual tribool less(const SpectrumIdentity& lhs, const SpectrumIdentity& rhs) const { return boost::logic::indeterminate; } virtual tribool less(const Spectrum& lhs, const Spectrum& rhs) const { if (lhs.id.empty()) return boost::logic::indeterminate; return lhs.defaultArrayLength < rhs.defaultArrayLength; } }; struct MSLevelSorter : public SpectrumList_Sorter::Predicate { virtual tribool less(const SpectrumIdentity& lhs, const SpectrumIdentity& rhs) const { return boost::logic::indeterminate; } virtual tribool less(const Spectrum& lhs, const Spectrum& rhs) const { CVParam lhsMSLevel = lhs.cvParam(MS_ms_level); CVParam rhsMSLevel = rhs.cvParam(MS_ms_level); if (lhsMSLevel.empty() || rhsMSLevel.empty()) return boost::logic::indeterminate; return lhsMSLevel.valueAs() < rhsMSLevel.valueAs(); } }; void test() { MSData msd; examples::initializeTiny(msd); SpectrumListPtr originalList = msd.run.spectrumListPtr; SpectrumListPtr defaultArrayLengthSortedList( new SpectrumList_Sorter(originalList, DefaultArrayLengthSorter())); SpectrumListPtr msLevelUnstableSortedList( new SpectrumList_Sorter(originalList, MSLevelSorter())); SpectrumListPtr msLevelStableSortedList( new SpectrumList_Sorter(originalList, MSLevelSorter(), true)); SpectrumListPtr sillySortedList( new SpectrumList_Sorter(msLevelStableSortedList, DefaultArrayLengthSorter())); if (os_) { *os_ << "Original spectrum list (" << originalList->size() << "):\n"; TextWriter write(*os_); write(*originalList); *os_ << endl; } if (os_) { *os_ << "Default array length sorted spectrum list (" << defaultArrayLengthSortedList->size() << "):\n"; TextWriter write(*os_); write(*defaultArrayLengthSortedList); *os_ << endl; } if (os_) { *os_ << "MS level unstable sorted spectrum list (" << msLevelUnstableSortedList->size() << "):\n"; TextWriter write(*os_); write(*msLevelUnstableSortedList); *os_ << endl; } if (os_) { *os_ << "MS level stable sorted spectrum list (" << msLevelStableSortedList->size() << "):\n"; TextWriter write(*os_); write(*msLevelStableSortedList); *os_ << endl; } if (os_) { *os_ << "Silly (nested) sorted spectrum list (" << sillySortedList->size() << "):\n"; TextWriter write(*os_); write(*sillySortedList); *os_ << endl; } unit_assert_operator_equal(originalList->size(), defaultArrayLengthSortedList->size()); unit_assert_operator_equal(originalList->size(), msLevelUnstableSortedList->size()); unit_assert_operator_equal(originalList->size(), msLevelStableSortedList->size()); unit_assert_operator_equal(originalList->size(), sillySortedList->size()); SpectrumPtr s; // assert that the original list is unmodified unit_assert_operator_equal("scan=19", originalList->spectrumIdentity(0).id); unit_assert_operator_equal(0, originalList->spectrumIdentity(0).index); unit_assert_operator_equal("scan=20", originalList->spectrumIdentity(1).id); unit_assert_operator_equal(1, originalList->spectrumIdentity(1).index); unit_assert_operator_equal("scan=21", originalList->spectrumIdentity(2).id); unit_assert_operator_equal(2, originalList->spectrumIdentity(2).index); unit_assert_operator_equal("scan=22", originalList->spectrumIdentity(3).id); unit_assert_operator_equal(3, originalList->spectrumIdentity(3).index); s = originalList->spectrum(0); unit_assert_operator_equal("scan=19", s->id); unit_assert_operator_equal(0, s->index); // validate the default array length sorted list (ascending order, scan=19 and scan=22 are interchangeable) unit_assert_operator_equal("scan=21", defaultArrayLengthSortedList->spectrumIdentity(0).id); unit_assert_operator_equal(0, defaultArrayLengthSortedList->spectrumIdentity(0).index); unit_assert_operator_equal("scan=20", defaultArrayLengthSortedList->spectrumIdentity(1).id); unit_assert_operator_equal(1, defaultArrayLengthSortedList->spectrumIdentity(1).index); unit_assert_operator_equal(2, defaultArrayLengthSortedList->spectrumIdentity(2).index); unit_assert_operator_equal(3, defaultArrayLengthSortedList->spectrumIdentity(3).index); s = defaultArrayLengthSortedList->spectrum(0); unit_assert_operator_equal("scan=21", s->id); unit_assert_operator_equal(0, s->index); s = defaultArrayLengthSortedList->spectrum(1); unit_assert_operator_equal("scan=20", s->id); unit_assert_operator_equal(1, s->index); s = defaultArrayLengthSortedList->spectrum(2); unit_assert_operator_equal(2, s->index); s = defaultArrayLengthSortedList->spectrum(3); unit_assert_operator_equal(3, s->index); for (size_t i=1, end=defaultArrayLengthSortedList->size(); i < end; ++i) unit_assert(defaultArrayLengthSortedList->spectrum(i)->defaultArrayLength >= defaultArrayLengthSortedList->spectrum(i-1)->defaultArrayLength); // validate the MS level unstable sorted list (scan=19, scan=21, and scan=22 are interchangeable) unit_assert_operator_equal(0, msLevelUnstableSortedList->spectrumIdentity(0).index); unit_assert_operator_equal(1, msLevelUnstableSortedList->spectrumIdentity(1).index); unit_assert_operator_equal(2, msLevelUnstableSortedList->spectrumIdentity(2).index); unit_assert_operator_equal("scan=20", msLevelUnstableSortedList->spectrumIdentity(3).id); unit_assert_operator_equal(3, msLevelUnstableSortedList->spectrumIdentity(3).index); s = msLevelUnstableSortedList->spectrum(0); unit_assert_operator_equal(0, s->index); s = msLevelUnstableSortedList->spectrum(1); unit_assert_operator_equal(1, s->index); s = msLevelUnstableSortedList->spectrum(2); unit_assert_operator_equal(2, s->index); s = msLevelUnstableSortedList->spectrum(3); unit_assert_operator_equal("scan=20", s->id); unit_assert_operator_equal(3, s->index); // validate the MS level stable sorted list (scan=19, scan=21, and scan=22 should stay in order) unit_assert_operator_equal("scan=19", msLevelStableSortedList->spectrumIdentity(0).id); unit_assert_operator_equal(0, msLevelStableSortedList->spectrumIdentity(0).index); unit_assert_operator_equal("scan=21", msLevelStableSortedList->spectrumIdentity(1).id); unit_assert_operator_equal(1, msLevelStableSortedList->spectrumIdentity(1).index); unit_assert_operator_equal("sample=1 period=1 cycle=23 experiment=1", msLevelStableSortedList->spectrumIdentity(2).id); unit_assert_operator_equal(2, msLevelStableSortedList->spectrumIdentity(2).index); unit_assert_operator_equal("scan=20", msLevelStableSortedList->spectrumIdentity(3).id); unit_assert_operator_equal(3, msLevelStableSortedList->spectrumIdentity(3).index); s = msLevelStableSortedList->spectrum(0); unit_assert_operator_equal("scan=19", s->id); unit_assert_operator_equal(0, s->index); s = msLevelStableSortedList->spectrum(1); unit_assert_operator_equal("scan=21", s->id); unit_assert_operator_equal(1, s->index); s = msLevelStableSortedList->spectrum(2); unit_assert_operator_equal("sample=1 period=1 cycle=23 experiment=1", s->id); unit_assert_operator_equal(2, s->index); s = msLevelStableSortedList->spectrum(3); unit_assert_operator_equal("scan=20", s->id); unit_assert_operator_equal(3, s->index); // validate the silly (nested) sorted list unit_assert_operator_equal("scan=21", sillySortedList->spectrumIdentity(0).id); unit_assert_operator_equal(0, sillySortedList->spectrumIdentity(0).index); unit_assert_operator_equal("scan=20", sillySortedList->spectrumIdentity(1).id); unit_assert_operator_equal(1, sillySortedList->spectrumIdentity(1).index); unit_assert_operator_equal(2, sillySortedList->spectrumIdentity(2).index); unit_assert_operator_equal(3, sillySortedList->spectrumIdentity(3).index); s = sillySortedList->spectrum(0); unit_assert_operator_equal("scan=21", s->id); unit_assert_operator_equal(0, s->index); s = sillySortedList->spectrum(1); unit_assert_operator_equal("scan=20", s->id); unit_assert_operator_equal(1, s->index); s = sillySortedList->spectrum(2); unit_assert_operator_equal(2, s->index); s = sillySortedList->spectrum(3); unit_assert_operator_equal(3, s->index); for (size_t i=1, end=sillySortedList->size(); i < end; ++i) unit_assert(sillySortedList->spectrum(i)->defaultArrayLength >= sillySortedList->spectrum(i-1)->defaultArrayLength); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/spectrum_processing/MS2NoiseFilter.cpp0000664000175100017510000002007212664775615025742 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_PeakFilter.cpp 1191 2009-08-14 19:33:05Z chambm $ // // // Original author: Chris Paulse systemsbiology.org> // // Copyright 2009 Institute for Systems Biology, Seattle, WA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "MS2NoiseFilter.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace analysis { using namespace std; using namespace msdata; const double factor = 0.5; PWIZ_API_DECL MS2NoiseFilter::Config::Config( int numMassesInWindow_, double windowWidth_, bool relaxLowMass_) : numMassesInWindow(numMassesInWindow_), windowWidth(windowWidth_), relaxLowMass(relaxLowMass_) { } namespace { struct indexValuePair { double val; int index; }; bool Greater ( indexValuePair elem1, indexValuePair elem2 ) { return elem1.val > elem2.val; } // used in binary transform below (nullable types?) static double PropogateNulls(double& arg1, double& arg2) { if (arg1 < 0) // indicates null return arg1; else return arg2; } struct FilterSpectrum { FilterSpectrum( const MS2NoiseFilter::Config& params_, const pwiz::msdata::SpectrumPtr spectrum_); ~FilterSpectrum() { } void RetrievePrecursorMass(); // data const MS2NoiseFilter::Config params; const pwiz::msdata::SpectrumPtr spectrum; std::vector& massList_; std::vector& intensities_; double precursorMZ; int precursorCharge; }; void FilterSpectrum::RetrievePrecursorMass() { BOOST_FOREACH(Precursor& precursor, spectrum->precursors) { BOOST_FOREACH(SelectedIon& selectedIon, precursor.selectedIons) { if (selectedIon.hasCVParam(MS_m_z)) { precursorMZ = selectedIon.cvParam(MS_m_z).valueAs(); } else if (selectedIon.hasCVParam(MS_selected_ion_m_z)) { precursorMZ = selectedIon.cvParam(MS_selected_ion_m_z).valueAs(); } else { //TODO: log warning, unable to read precursor mz //cout << "unable to read precursor mz: " << spectrum->index << endl; } if (selectedIon.hasCVParam(MS_charge_state)) { precursorCharge = selectedIon.cvParam(MS_charge_state).valueAs(); } else { //TODO: log warning, unable to read precursor charge state //cout << "unable to read precursor charge: " << spectrum->index << endl; } } } } FilterSpectrum::FilterSpectrum(const MS2NoiseFilter::Config& params_, const pwiz::msdata::SpectrumPtr spectrum_) : params(params_), spectrum(spectrum_), massList_(spectrum->getMZArray()->data), intensities_(spectrum->getIntensityArray()->data), precursorMZ(0), precursorCharge(0) { if (massList_.size() < 1) { //TODO: log encounter with empty spectrum? return; } double windowWidth; if (params.windowWidth > 0.) { windowWidth = params.windowWidth; } else { if (spectrum->hasCVParam(MS_highest_observed_m_z)) { windowWidth = spectrum->cvParam(MS_highest_observed_m_z).valueAs(); } else { windowWidth = 1000000; // use a token value in place of pre-recorded full mass range. } } RetrievePrecursorMass(); if (precursorCharge > 0) { // remove any signal above the precursor minus mass of glycine //AminoAcid::Info::Record gly('G'); double upperMassBound = precursorMZ * precursorCharge - 57.0214640; vector::iterator lb = lower_bound(massList_.begin(), massList_.end(), upperMassBound); intensities_.erase(intensities_.begin() + (lb - massList_.begin()), intensities_.end()); massList_.erase(lb, massList_.end()); } // remove unfragmented precursor (within 0.5 Da) vector::iterator ub = upper_bound(massList_.begin(), massList_.end(), precursorMZ + 0.5); vector::iterator lb = lower_bound(massList_.begin(), massList_.end(), precursorMZ - 0.5); int ilb = lb - massList_.begin(); int iub = ub - massList_.begin(); intensities_.erase(intensities_.begin() + ilb, intensities_.begin() + iub); massList_.erase(lb, ub); lb = massList_.begin(); ub = massList_.begin(); while (ub != massList_.end()) { ub = upper_bound(lb, massList_.end(), *lb + windowWidth); vector::iterator it; vector indexValuePairs; for (it = lb; it 0) { indexValuePair p; p.index = it - massList_.begin(); p.val = intensities_[p.index]; indexValuePairs.push_back(p); } } size_t numMassesInWindow = params.numMassesInWindow; if (params.relaxLowMass && precursorCharge > 0) { if (min(precursorCharge, (int) ((precursorMZ * precursorCharge) / *lb)) > 1) numMassesInWindow = (size_t)(params.numMassesInWindow * (factor * min(precursorCharge, (int) ((precursorMZ * precursorCharge) / *lb)))); } if (indexValuePairs.size() > numMassesInWindow) { sort(indexValuePairs.begin(), indexValuePairs.end(), Greater); // Is there a more effective method for removing vector elements than this? for (size_t i = numMassesInWindow; i < indexValuePairs.size(); i++) { intensities_[indexValuePairs[i].index] = -1; } } do { lb++; } while (lb != massList_.end() && intensities_[lb-massList_.begin()] <= 0); } transform(intensities_.begin(), intensities_.end(), massList_.begin(), massList_.begin(), PropogateNulls); intensities_.erase(remove_if(intensities_.begin(), intensities_.end(), bind2nd(less(), 0)), intensities_.end()); massList_.erase(remove_if(massList_.begin(), massList_.end(), bind2nd(less(), 0)), massList_.end()); spectrum->defaultArrayLength = massList_.size(); } } // namespace PWIZ_API_DECL void MS2NoiseFilter::describe(ProcessingMethod& method) const { method.set(MS_low_intensity_data_point_removal); // was MS_SpectrumFilter, now obsolete - MattC suggests this, which has def: "The removal of very low intensity data points that are likely to be spurious noise rather than real signal." method.userParams.push_back(UserParam("num masses in window", lexical_cast(params.numMassesInWindow))); method.userParams.push_back(UserParam("window width (Da)", lexical_cast(params.windowWidth))); method.userParams.push_back(UserParam("allow more data below multiply charged precursor", lexical_cast(params.relaxLowMass))); } PWIZ_API_DECL void MS2NoiseFilter::operator () (const SpectrumPtr spectrum) const { if (spectrum->cvParam(MS_ms_level).valueAs() > 1 && spectrum->cvParam(MS_MSn_spectrum).empty() == false && spectrum->precursors[0].empty() == false && spectrum->precursors[0].selectedIons.empty() == false && spectrum->precursors[0].selectedIons[0].empty() == false) { FilterSpectrum(params, spectrum); } } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/SpectrumList_ChargeFromIsotopeTest.cpp0000664000175100017510000015565212664775615032150 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_ChargeFromIsotopeTest.cpp 6389 2014-06-13 19:46:19Z frenchwr $ // // // Original author: William French vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "SpectrumList_ChargeFromIsotope.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/data/msdata/examples.hpp" #include "pwiz/data/msdata/TextWriter.hpp" #include "pwiz/data/common/CVTranslator.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::msdata; using namespace pwiz::analysis; ostream* os_ = 0; ostream& operator<< (ostream& os, const vector& v) { os << "("; for (size_t i=0; i < v.size(); ++i) os << " " << v[i]; os << " )"; return os; } struct TestChargeStateCalculator { // space-delimited doubles const char* inputMZArray; const char* inputIntensityArray; double inputPrecursorMZ; int trueCharge; double MS1rTime; double MS2rTime; int minCharge; int maxCharge; int parentsBefore; int parentsAfter; double halfIsolationWidth; int defaultMinCharge; int defaultMaxCharge; }; TestChargeStateCalculator testChargeStateCalculators[] = { // Thermo Q-Exactive Jurkat Cell Lysate data { "351.166 351.167 351.169 351.17 351.172 351.173 351.175 351.177 351.178 351.18 351.181 351.183 351.184 351.186 351.191 351.192 351.194 351.195 351.197 351.198 351.2 351.202 351.203 351.205 351.206 351.208 351.209 351.211 351.212 351.214 351.216 351.217 351.219 351.22 351.222 351.223 351.647 351.648 351.65 351.652 351.653 351.655 351.656 351.658 351.659 351.661 351.662 351.664 351.666 351.667 351.669 351.675 351.677 351.678 351.68 351.681 351.683 351.684 351.686 351.687 351.689 351.691 351.692 351.694 351.695 351.825 351.827 351.828 351.83 351.831 351.833 351.835 351.836 351.838 351.839 351.841 351.844 351.846 351.847 351.849 351.996 351.997 351.999 352.001 352.002 352.004 352.005 352.007 352.008 352.01 352.012 352.013 352.015 352.016 352.018 352.019 352.019 352.021 352.022 352.024 352.066 352.068 352.069 352.071 352.073 352.074 352.076 352.077 352.079 352.08 352.082 352.084 352.085 352.087 352.088 352.09 352.091 352.093 352.095 352.096 352.098 352.099 352.101 352.102 352.104 352.106 352.107 352.109 352.111 352.113 352.114 352.116 352.117 352.119 352.12 352.122 352.124 352.125 352.127 352.128 352.129 352.131 352.132 352.136 352.137 352.139 352.14 352.145 352.146 352.148 352.15 352.151 352.153 352.154 352.156 352.157 352.159 352.16 352.162 352.163 352.165 352.166 352.168 352.169 352.171 352.171 352.173 352.174 352.176 352.177 352.179 352.181 352.182 352.184 352.185 352.187 352.188 352.19 352.192 352.193 352.195 352.196 352.198 352.199 352.201 352.203 352.204 352.206 352.207 352.209 352.211 352.212 352.214 352.215 352.217 352.218 352.22 352.222 352.223 352.225 352.226 352.228 352.229 352.231 352.233 352.234 352.236 352.237 352.239 352.24 352.242 352.243 352.245 352.247 352.248 352.25 352.251 352.253 352.254 352.256 352.258 352.259 352.261 352.262 352.264 352.265 352.267 352.269 352.27 352.272 352.273 352.275 352.276 352.278 352.28 352.281 352.283 352.284 352.286 352.287 352.289 352.291 352.292 352.294 352.295 352.297 352.298 352.3 352.301 352.303 352.305 352.325 352.327 352.328 352.33 352.331 352.333 352.334 352.336 352.338 352.339 352.341 352.342 352.344 352.345 352.347 352.349 352.35 352.352 352.353 352.355 352.356 352.358 352.36 352.361 352.363 352.364 352.366 352.367 352.369 352.371 352.372 352.374 352.375 352.377 352.378 352.38 352.382 352.383 352.49 352.491 352.493 352.494 352.496 352.498 352.499 352.501 352.502 352.504 352.505 352.507 352.509 352.51 352.512 352.513 352.515 352.516 352.518 352.52 352.521 352.523 352.524 352.526 352.527 352.529 352.531 352.532 352.534 352.535 352.537 352.538 352.54 352.542 352.543 352.545 352.546 352.548 352.549 352.551 352.553 352.554 352.556 352.557 352.568 352.57 352.571 352.573 352.575 352.576 352.578 352.579 352.581 352.582 352.584 352.586 352.587 352.589 352.59 352.592 352.593 352.595 352.597 352.598 352.6 352.601 352.603 352.604 352.606 352.608 352.609 352.611 352.612 352.614 352.615 352.617 352.619 352.62 352.622 352.623 352.625 352.628 352.629 352.631 352.633 352.659 352.661 352.662 352.664 352.666 352.667 352.669 352.67 352.672 352.672 352.674 352.675 352.677 352.678 352.68 352.681 352.683 352.684 352.686 352.688 352.689 352.691 352.692 352.694 352.695 352.697 352.699 352.699 352.7 352.702 352.703 352.705 352.706 352.708 352.71 352.711 352.713 352.714 352.717 352.719 352.721 352.722 352.724 352.725 352.727 352.728 352.73 352.732 352.733 352.735 352.736 352.738 352.739 352.743 352.744 352.746 352.747 352.749 352.75 352.752 352.754 352.755 352.757 352.758 352.76 352.761 352.763 352.765 352.766 352.768 352.769 352.771 352.772 352.774 352.776 352.777 352.779 352.78 352.782 352.783 352.785 352.787 352.788 352.79 352.791 352.793 352.794 352.796 352.798 352.799 352.801 352.838 352.84 352.842 352.843 352.845 352.846 352.848 352.85 352.851 352.853 352.854 352.856 352.857 352.859 352.861 352.862 352.864 352.865 352.867 352.868 352.87 352.872 352.873 352.875 352.876 352.878 352.879 352.881 352.883 353.002 353.004 353.005 353.007 353.008 353.01 353.011 353.013 353.015 353.016 353.018 353.019 353.021 353.022 353.173 353.175 353.176 353.178 353.18 353.181 353.183 353.184 353.186 353.187 353.189 353.191 353.192 353.194 353.195 353.197 353.199 353.2 353.201 353.203 353.205 353.206 353.51 353.512 353.513 353.515 353.516 353.518 353.52 353.521 353.523 353.524 353.526 353.528 353.529 353.531 353.533 353.534 353.536 353.664 353.665 353.667 353.668 353.67 353.672 353.673 353.675 353.676 353.678 353.679 353.681 353.683 353.684 353.686 353.687 353.689 353.69 353.692 353.694 353.695 353.697 353.698 353.7 353.701 353.703 353.704 353.706 353.845 353.846 353.848 353.849 353.851 353.853 353.854 353.856 353.857 353.859 353.861 353.862 353.864 353.866 353.867 353.869 353.87 354.167 354.169 354.171 354.172 354.174 354.175 354.177 354.178 354.18 354.182 354.183 354.185 354.186 354.188 354.19 354.191 354.193 354.194 354.196 354.197 354.199 354.201 354.202 354.204 354.205 354.207 354.209 354.21 354.212 354.213 354.215 354.216 354.218 354.22 354.221 354.671 354.672 354.674 354.675 354.677 354.679 354.68 354.682 354.683 354.685 354.687 354.688 354.69", "0 0 0 0 8120.02 23237.3 38803 41467.4 30047.5 15008.8 0 0 0 0 0 0 0 0 15759.8 25237.7 29474.8 23502.4 12698.3 0 0 0 12610.6 26647.5 36362.6 32099.8 18001.4 6000.35 0 0 0 0 0 0 0 0 4528.55 17484.2 35392.4 42725.1 34221.6 18680.2 6308.08 0 0 0 0 0 0 0 0 10422.8 19134.8 24311.8 24054.1 17420.9 8268.2 0 0 0 0 0 0 0 0 7107.35 22527.8 44300.4 85892.3 67082.5 32158.8 0 0 0 0 0 0 0 0 0 15810.4 33994.3 55078.3 85641 151659 334684 554916 732310 590781 331957 70691.2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11789.5 64744.7 121807 193186 243317 202497 115645 24317.1 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 960573 174916 0 136374 993586 1.8441e+006 1.92991e+006 3.03495e+006 1.31047e+007 4.65182e+007 9.16249e+007 1.37986e+008 1.33314e+008 8.60013e+007 4.19191e+007 1.32598e+007 4.04162e+006 1.41205e+006 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 7754.61 67937.3 99051.1 150531 216079 244565 159661 63595.9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14452.5 29005.7 35286 30588.2 21185 11831.1 0 0 0 0 0 0 0 0 1366.36 91701 179496 288109 434197 517406 359182 151024 0 0 0 63243.7 160312 171636 95034 5596.75 0 0 0 0 0 0 0 0 8179.66 16440.3 27712.5 38477.4 47929.2 31342.5 26019.9 59155.3 135782 216038 241642 167755 85729.4 12481.1 0 0 0 0 0 0 0 14483.3 49421 110574 180946 217687 173260 105397 43313.1 0 0 0 21248.7 35694.3 19325.8 5368.26 0 0 0 0 0 0 0 0 10690.2 22788 27664.4 19704 7061.11 0 0 0 6988.12 25745.4 73160.7 83506.9 50202.2 21890.8 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 1.65038e+006 6.93915e+006 2.13171e+007 3.68888e+007 4.91278e+007 4.01078e+007 2.41707e+007 9.51399e+006 2.85991e+006 620248 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 8530.51 25618 66293.5 86071.8 68466.5 37744.3 8736.74 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15988 31223.3 38828.8 30780.3 14679.4 0 0 4020.74 20084.3 96902 143334 136421 67184 3937.96 0 0 0 29215.9 58376.9 28367.3 3875.2 0 0 0 0 0 0 0 0 13779.3 28950.1 38985.4 34583.4 19994.8 7077.35 0 0 0 0 0 0 0 0 649.605 42703.1 102863 675627 2.62112e+006 5.99173e+006 9.6241e+006 1.07436e+007 7.58946e+006 4.21331e+006 1.46704e+006 480636 159069 0 0 0 0 0 0 0 0 0 6856.14 39156.2 104291 175803 203283 147265 86650.4 35519.8 10675.3 0 0 0 0 0 0 0 0 12418.6 17400.1 37178.9 107531 256363 441343 490807 339063 148145 48226.6 116906 383579 861486 1.39413e+006 1.63679e+006 1.2132e+006 707134 261800 78553.8 10524.9 0 0 0 0 0 0 0 0 785.907 25861.9 84745.9 148329 189330 150522 91819.8 38901.2 7876.87 0 0 0 0 0 0 0 0 11175.5 43705.4 97099.8 164607 190669 138639 72177.2 20538.4 17121.5 63480.2 175339 293057 374461 300567 183447 78540.5 20050.9 0 0 0 0 3744.07 17056.1 29686.2 29232.4 17226.6 5500.15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", 352.189,2,10.0,20.0, 2,6,1,0,1.25,0,0}, { "346.657 346.658 346.66 346.661 346.663 346.664 346.666 346.667 346.669 346.67 346.672 346.673 346.675 346.677 346.678 346.68 346.681 346.683 346.684 346.686 346.687 346.689 346.69 346.692 346.693 347.172 347.173 347.175 347.176 347.178 347.179 347.181 347.182 347.184 347.185 347.187 347.189 347.19 347.192 347.193 347.195 347.196 347.198 347.199 347.201 347.202 347.204 347.205 347.207 347.209 347.21 347.212 347.213 347.215 347.216 347.218 347.219 347.496 347.497 347.499 347.5 347.502 347.503 347.505 347.506 347.508 347.509 347.511 347.514 347.515 347.517 347.519 347.638 347.64 347.641 347.643 347.645 347.646 347.648 347.649 347.651 347.652 347.654 347.655 347.657 347.657 347.659 347.66 347.662 347.663 347.665 347.666 347.668 347.669 347.671 347.672 347.674 347.676 347.677 347.679 347.68 347.682 347.683 347.685 347.686 347.688 347.689 347.691 347.692 347.694 347.695 347.697 347.698 347.7 347.701 347.703 347.704 347.706 347.707 347.709 347.71 347.712 347.714 347.715 347.717 347.718 347.889 347.891 347.892 347.894 347.895 347.897 347.898 347.9 347.901 347.903 347.905 347.906 347.908 347.909 347.911 348.166 348.168 348.17 348.171 348.173 348.174 348.176 348.177 348.179 348.18 348.182 348.183 348.185 348.186 348.188 348.19 348.191 348.192 348.194 348.196 348.205 348.206 348.208 348.209 348.211 348.213 348.214 348.216 348.217 348.219 348.22 348.222 348.223 348.225 348.226 348.228 348.229 348.231 348.404 348.405 348.407 348.408 348.41 348.411 348.413 348.414 348.416 348.418 348.419 348.421 348.422 348.424 348.425 348.427 348.428 348.546 348.547 348.549 348.55 348.552 348.553 348.555 348.557 348.558 348.56 348.562 348.563 348.565 348.605 348.606 348.608 348.609 348.611 348.613 348.614 348.616 348.617 348.619 348.62 348.622 348.623 348.625 348.626 348.628 348.668 348.67 348.671 348.673 348.674 348.676 348.677 348.679 348.68 348.682 348.683 348.685 348.687 348.688 348.69 348.691 348.692 348.694 348.695 348.711 348.712 348.714 348.716 348.717 348.719 348.72 348.722 348.723 348.725 348.726 348.728 348.729 348.731 348.733 348.807 348.808 348.81 348.811 348.813 348.814 348.816 348.818 348.819 348.821 348.822 348.824 348.825 348.881 348.882 348.884 348.886 348.887 348.889 348.89 348.892 348.893 348.895 348.896 348.898 348.899 348.901 349.158 349.159 349.161 349.162 349.164 349.165 349.167 349.169 349.17 349.172 349.173 349.175 349.176 349.178 349.179 349.181 349.182 349.184 349.186 349.187 349.189 349.19 349.192 349.193 349.213 349.215 349.217 349.218 349.22 349.221 349.223 349.224 349.226 349.227 349.229 349.23 349.232 349.667 349.669 349.67 349.672 349.674 349.675 349.677 349.678 349.68 349.681 349.683 349.684 349.686 349.688 349.689 349.691 349.84 349.841 349.843 349.844 349.846 349.847 349.849 349.85 349.852 349.854 349.855 349.857 349.858 349.86 349.919 349.92 349.922 349.923 349.925 349.926 349.928 349.93 349.931 349.933 349.934 349.936 349.937 349.939 349.94 349.942 350.15 350.152 350.153 350.155 350.156 350.158 350.159 350.161 350.163 350.164 350.166 350.167 350.169 350.17", "0 0 0 0 10961 19736 23900.7 17191.3 5730.37 0 0 0 0 3925.75 20286.6 75526.5 108467 91495.9 53060.8 18969.6 10484.3 0 0 0 0 0 0 0 0 9116.28 24824.4 60098.4 85781.8 63491.9 25226.3 7365.68 0 0 0 0 0 0 0 40008.4 163375 431393 722337 905032 693399 404135 131466 30054.5 3886.23 0 0 0 0 0 0 0 0 11650.6 20274.6 28407.2 33232.8 29180.1 16913 6058.11 0 0 0 0 0 0 0 0 7175.64 29635.3 75098.1 140327 201812 157294 79670.4 19492.5 11838 0 0 0 0 0 0 0 0 27246.2 110637 321655 1.10743e+006 3.39252e+006 6.24381e+006 8.97551e+006 8.13047e+006 5.06563e+006 2.2355e+006 589552 96055 22711.6 0 0 0 0 0 0 0 0 79486.7 135314 217641 303927 274002 158762 50415.3 5843.65 0 0 0 0 0 0 0 0 6378.47 16452 30734.8 41688.5 39587.3 24186.9 7521.96 0 0 0 0 0 0 0 0 0 137228 520728 1.47305e+006 2.54686e+006 3.43152e+006 2.89775e+006 1.7807e+006 738850 205995 25882.7 0 0 0 0 0 0 0 0 0 15056.6 18107 61576.1 140634 220529 240301 167534 90248.8 19140.2 0 0 0 0 0 0 0 0 0 3490.77 28803.8 92736.3 155649 191499 148143 86985.5 27287.5 8427.73 0 0 0 0 0 0 0 0 5484.38 18207.8 28203.5 25960.7 14556.8 0 0 0 0 0 0 0 0 13145.8 49422.9 91213.8 138111 143102 93875.7 45495.6 11453.6 0 0 0 0 0 0 0 0 0 20773.2 102388 290060 494374 663565 568254 350979 140934 25125.8 0 0 0 0 0 0 0 0 0 5373.93 18669 38749.3 52802.1 49014.6 31515.1 14239.2 0 0 0 0 0 0 0 0 12293.6 20885.9 22571.3 18410.3 13445.9 0 0 0 0 0 0 0 0 9753.48 19434 24437.9 23820.9 20193.2 13995 0 0 0 0 0 0 0 0 5937.7 17324.7 27357.2 27101.8 18934.3 11837.1 0 0 8061.73 16699.2 35868.9 65709.6 93781.2 48854.5 32311.7 13667 0 0 0 0 0 0 0 0 13770.8 25438.2 31622.3 26281.8 14405.3 0 0 0 0 0 0 0 0 11981.8 39357.6 75818.3 112272 113305 74893.5 33392.6 5898.17 0 0 0 0 0 0 0 0 6927.62 21253.5 33414.9 32682.9 21266.5 9401.1 0 0 0 0 0 0 0 0 7396.2 22461.8 57287 89930.3 82061.1 35789.6 16420.5 5355.56 0 0 0 0 0 0 0 0 15290.6 35150 47154.2 39139.1 19452.8 4374.33 0 0 0 0", 347.679,2,10.0,10.1, 2,6,1,0,1.25,0,0}, { "331.417 331.418 331.42 331.421 331.422 331.424 331.425 331.427 331.428 331.43 331.431 331.432 331.434 331.435 331.498 331.5 331.501 331.503 331.504 331.505 331.507 331.508 331.51 331.511 331.513 331.514 331.515 331.527 331.528 331.53 331.531 331.533 331.534 331.536 331.537 331.538 331.54 331.541 331.543 331.544 331.546 331.657 331.659 331.66 331.662 331.663 331.664 331.666 331.667 331.669 331.67 331.672 331.673 331.674 331.676 331.679 331.68 331.682 331.683 331.684 331.686 331.687 331.689 331.69 331.692 331.693 331.695 331.696 331.697 331.699 331.7 331.702 331.703 331.705 331.706 331.707 331.709 332.168 332.169 332.171 332.172 332.174 332.175 332.176 332.178 332.179 332.181 332.182 332.184 332.185 332.187 332.188 332.189 332.191 332.192 332.194 332.195 332.197 332.198 332.199 332.201 332.202 332.204 332.205 332.207 332.208 332.209 332.211 332.212 332.214 332.215 332.217 332.218 332.22 332.221 332.488 332.49 332.491 332.493 332.494 332.495 332.497 332.498 332.5 332.501 332.503 332.504 332.506 332.507 332.508 332.51 332.511 332.513 332.514 332.516 332.517 332.529 332.53 332.531 332.533 332.534 332.536 332.537 332.539 332.54 332.541 332.543 332.544 332.546 332.547 332.644 332.645 332.647 332.648 332.649 332.651 332.652 332.654 332.655 332.657 332.658 332.66 332.661 332.662 332.664 332.665 332.667 332.668 332.67 332.671 332.672 332.674 332.675 332.677 332.678 332.68 332.681 332.682 332.684 332.685 332.687 332.688 332.69 332.691 332.693 333.148 333.149 333.151 333.152 333.154 333.155 333.157 333.158 333.16 333.161 333.162 333.164 333.165 333.167 333.168 333.17 333.171 333.172 333.174 333.175 333.177 333.178 333.18 333.181 333.182 333.184 333.185 333.187 333.188 333.19 333.191 333.193 333.194 333.195 333.197 333.198 333.2 333.201 333.203 333.204 333.206 333.207 333.208 333.21 333.426 333.428 333.429 333.431 333.432 333.434 333.435 333.436 333.438 333.439 333.441 333.442 333.444 333.445 333.447 333.496 333.497 333.499 333.5 333.501 333.503 333.504 333.506 333.507 333.509 333.51 333.512 333.513 333.65 333.652 333.653 333.655 333.656 333.658 333.659 333.66 333.662 333.663 333.665 333.666 333.668 333.669 333.671 333.672 333.673 333.675 333.676 333.678 333.679 333.681 333.682 333.684 333.685 333.686 333.688 333.689 333.691 333.692 333.694 333.695 333.697 333.698 333.7 333.701 333.702 333.825 333.827 333.828 333.83 333.831 333.833 333.834 333.836 333.837 333.838 333.84 333.841 333.843 333.844 333.846 333.847 333.848 333.85 333.908 333.909 333.911 333.912 333.914 333.915 333.916 333.918 333.919 333.921 333.922 333.924 333.925 333.927 333.928 333.929 333.931 333.932 333.934 333.935 333.937 333.938 334.022 334.024 334.025 334.026 334.028 334.029 334.031 334.032 334.034 334.035 334.037 334.038 334.039 334.041 334.042 334.044 334.096 334.097 334.099 334.1 334.102 334.103 334.105 334.106 334.108 334.109 334.11 334.112 334.113 334.145 334.147 334.148 334.15 334.151 334.152 334.154 334.155 334.157 334.158 334.16 334.161 334.163 334.164 334.165 334.167 334.169 334.17 334.172 334.173 334.175 334.176 334.178 334.179 334.18 334.181 334.183 334.184 334.193 334.194 334.196 334.197 334.199 334.2 334.202 334.203 334.205 334.206 334.208 334.209 334.21 334.212 334.416 334.418 334.419 334.421 334.422 334.424 334.425 334.426 334.428 334.429 334.431 334.432 334.434 334.435 334.437 334.438 334.496 334.498 334.499 334.5 334.502 334.503 334.505 334.506 334.508 334.509 334.511 334.512 334.513 334.515 334.516 334.518 334.519 334.521 334.522 334.524 334.525 334.759 334.76 334.762 334.763 334.765 334.766 334.768 334.769 334.77 334.772 334.773 334.775 334.776 335.137 335.138 335.14 335.141 335.143 335.144 335.146 335.147 335.149 335.15 335.151 335.153 335.154 335.156 335.157 335.159", "0 0 0 0 9061.45 22475.3 35268.8 36668.2 25438.2 11599.9 0 0 0 0 0 0 0 0 9684.82 23491.2 29876.5 22922.6 10094.9 0 0 0 0 0 0 0 0 9180.43 24616.9 35830.4 33489.6 22024.2 10769.9 0 0 0 0 0 0 0 0 12611.7 26630.1 38491 37169.5 22907.8 8361.95 0 0 0 0 0 0 0 0 6017.46 16451.4 33026.8 45513 41936.2 24121.9 31508.3 96500.6 185384 268754 251719 157307 66427.3 7982.26 0 0 0 0 0 0 0 0 5301.39 16999.7 30492.7 34702 26142 13513 0 0 12371.7 21439.5 27209.5 22933.4 11143 0 0 0 12152.6 21551.1 29616.9 29137 19870.6 9552.69 0 0 9583.44 22087.5 33917 33539.6 20342.9 6326.05 0 0 0 0 0 0 0 0 16012.6 18628.8 20134.9 20056.2 14757.2 0 0 11785.8 17414.9 18161.4 17906.6 18225.8 14577.7 0 0 0 0 0 0 0 0 16134.3 28511.5 37712.6 37489.8 25852.6 10667.3 0 0 0 0 0 0 0 0 0 19508.7 82443.3 188324 619945 1.9855e+006 4.06909e+006 6.30896e+006 6.52736e+006 4.33407e+006 2.20647e+006 626399 125657 31194.3 1467.24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 47966.7 212774 645467 1.35099e+006 2.12093e+006 2.31954e+006 1.61098e+006 869432 252399 24052.1 0 0 0 0 0 0 0 9829.23 47044.5 132065 260114 387895 434599 325228 193752 69077.4 1391.99 0 0 0 8567.48 16858.3 23593.1 19598.4 7774.21 0 0 0 0 0 0 0 0 15543.2 30067.6 41837.8 46424.1 40943.3 26134.3 10412 0 0 0 0 0 0 0 0 14687.1 24819.6 25448.2 18512.5 10335.4 0 0 0 0 0 0 0 0 5301.43 51854.2 139870 260759 390680 429501 308773 167807 48458.4 5679.48 26536.5 134058 275259 435874 415263 258480 120893 32803.5 21268.6 46093.2 77285.9 92951.2 63307.6 14315 6965.15 18630.5 30464.6 27335.3 13797.5 0 0 0 0 0 0 0 0 12223.4 40058 119628 290418 479852 572483 416679 233121 72538 13497.8 0 0 0 0 0 0 0 0 12797.7 17167.8 19493.1 18767.9 8198.32 23479.1 75136.8 150069 228020 228488 152024 81751.4 21547.1 0 0 0 0 0 0 0 0 0 6580.25 17297.4 34296.3 75219.4 90418.4 64444.5 27870.2 9619.08 0 0 0 0 0 0 0 0 9016.14 20745.7 26748.5 21052.4 9637.64 0 0 0 0 0 0 0 0 16005 31629.4 46047.7 49578.3 30034.5 0 0 18948.3 26620.7 24795.6 24223.6 34790.6 72499.6 161932 259385 313444 232452 127072 32151.1 299.507 0 0 0 0 0 0 0 0 14594.4 28556.9 39565.4 36836.2 21346.9 6174.35 0 0 0 0 0 0 0 0 10190.9 22115.6 36619.6 48988 73627.5 45387.1 21244.9 8144.69 0 0 0 0 0 0 0 0 6833.54 21736.1 33703.5 33385.7 23986.6 13445.4 0 0 15747.5 29735.5 35209.2 26973.5 13284 0 0 0 0 0 0 0 0 10951.5 18995.9 20908.2 17786.5 12780.8 0 0 0 0 0 0 0 0 9567.52 20894.6 61242.1 105287 138616 106383 57357 15748.4 0 0 0 0", 332.66,2,5.0,6.0, 2,6,1,0,1.25,0,0}, { "323.501 323.502 323.503 323.505 323.506 323.507 323.509 323.51 323.512 323.513 323.514 323.516 323.517 323.518 323.644 323.646 323.647 323.648 323.65 323.651 323.652 323.654 323.655 323.657 323.658 323.659 323.661 323.662 323.663 323.665 323.666 323.668 323.669 323.677 323.679 323.68 323.681 323.683 323.684 323.686 323.687 323.688 323.69 323.691 323.692 323.694 323.695 323.697 323.698 323.699 323.701 323.702 323.704 323.705 323.706 323.708 323.709 323.71 323.712 323.713 323.715 323.716 323.717 323.719 323.72 323.721 323.723 323.724 323.726 323.727 323.728 323.73 323.731 323.733 323.734 323.736 323.737 323.738 323.83 323.831 323.832 323.834 323.835 323.836 323.838 323.839 323.841 323.842 323.843 323.845 323.846 323.847 323.849 323.85 323.851 324.135 324.136 324.138 324.139 324.14 324.142 324.143 324.145 324.146 324.147 324.149 324.15 324.152 324.153 324.154 324.156 324.157 324.158 324.16 324.165 324.167 324.168 324.17 324.171 324.172 324.174 324.175 324.176 324.178 324.179 324.181 324.182 324.183 324.185 324.186 324.516 324.517 324.519 324.52 324.521 324.523 324.524 324.526 324.527 324.529 324.531 324.532 324.533 324.639 324.64 324.642 324.643 324.644 324.646 324.647 324.648 324.65 324.651 324.653 324.654 324.655 324.656 324.657 324.659 324.66 324.662 324.663 324.664 324.666 324.667 324.669 324.67 324.671 324.673 324.674 324.675 324.677 324.678 324.68 324.681 324.682 324.684 324.685 324.687 324.688 324.689 324.691 324.692 324.694 324.695 324.696 324.918 324.92 324.921 324.923 324.924 324.925 324.927 324.928 324.93 324.931 324.932 324.934 324.935 324.937 324.938 324.939 324.941 324.942 324.943 324.945 325.142 325.144 325.145 325.146 325.148 325.149 325.15 325.152 325.153 325.155 325.156 325.157 325.159 325.16 325.162 325.163 325.164 325.166 325.167 325.169 325.17 325.171 325.173 325.174 325.176 325.177 325.178 325.18 325.181 325.183 325.184 325.185 325.187 325.188 325.19 325.191 325.192 325.194 325.195 325.196 325.198 325.199 325.201 325.202 325.203 325.205 325.206 325.208 325.209 325.21 325.212 325.214 325.215 325.216 325.421 325.422 325.424 325.425 325.426 325.428 325.429 325.431 325.432 325.433 325.435 325.436 325.438 325.439 325.44 325.442 325.443 325.444 325.489 325.49 325.492 325.493 325.495 325.496 325.497 325.499 325.5 325.502 325.503 325.504 325.506 325.507 325.508 325.51 325.511 325.675 325.677 325.678 325.68 325.681 325.682 325.684 325.685 325.687 325.688 325.689 325.691 325.692 325.694 325.695 325.697 325.698 325.699 325.701 325.702 325.704 325.705 325.706 325.708 325.709 325.711 325.712 325.713 325.714 325.716 325.825 325.826 325.827 325.829 325.83 325.832 325.833 325.834 325.836 325.837 325.839 325.84 325.841 325.843 325.844 325.846 325.847 325.848 325.85 326.16 326.161 326.162 326.164 326.165 326.167 326.168 326.169 326.171 326.172 326.174 326.175 326.176 326.178 326.197 326.199 326.2 326.202 326.203 326.204 326.206 326.207 326.209 326.21 326.211 326.213 326.214 326.216 326.501 326.502 326.504 326.505 326.506 326.508 326.509 326.511 326.512 326.513 326.515 326.516 326.518 326.519 326.651 326.652 326.653 326.655 326.656 326.658 326.659 326.66 326.662 326.663 326.665 326.666 326.667 326.669 326.67 326.672 326.673 326.674 326.676 326.677 326.679 326.68 326.681 326.683 326.684 326.686 326.995 326.997 326.998 326.999 327.001 327.002 327.004 327.005 327.007 327.008 327.009 327.011 327.012 327.014 327.015 327.016 327.018 327.065 327.067 327.068 327.07 327.071 327.072 327.074 327.075 327.077 327.078 327.079 327.081 327.082 327.084 327.085 327.086 327.151 327.152 327.154 327.155 327.157 327.158 327.159 327.161 327.162 327.164 327.165 327.167 327.168 327.169 327.171 327.172 327.174 327.175 327.176 327.178 327.179", "0 0 0 0 10337.1 18844 26745.4 27338.4 17689.7 5789.13 0 0 0 0 0 0 0 0 7286.37 14779.3 25612.3 34223.1 35399.5 33187 35262.3 38108.1 32455.4 19427.3 8598.15 0 0 0 0 0 0 0 0 13092.2 14060.2 15507.1 15363.8 10135.6 0 0 0 0 0 5642.38 15458.7 21145.9 18790.8 12537.6 0 0 0 0 0 0 0 0 12489.5 23207.2 33056 39926.3 38876.1 27563.1 13567.1 0 0 13769.2 14960.1 16061.1 15998.7 11080.1 0 0 0 0 0 0 0 0 444.065 22480.7 71263.8 120113 161383 135434 80233.6 27299.1 10688.8 0 0 0 0 0 0 0 0 7735.29 45031.6 162487 388211 638507 727670 508868 274897 82367.1 21216.6 11121.1 0 0 0 0 0 0 0 0 10105 25859 52954.1 77839.5 47540.5 32527.4 18670.8 9286.83 0 0 0 0 0 0 0 0 8622.65 20560.3 25392.8 19865.1 10677.6 0 0 0 0 0 0 0 0 4480.47 34809.1 86216.4 139740 163679 117988 63350.3 15869.6 4045.84 9890.41 28426.1 58851.2 97328 93800.3 56353.2 19169.8 0 0 0 0 0 21221.9 49062.5 178545 592302 1.4445e+006 2.36277e+006 2.81404e+006 2.08062e+006 1.19528e+006 392884 94920.7 19428.2 20638.6 0 0 0 0 0 0 0 0 0 7383.33 48332.3 197738 610304 1.15209e+006 1.70499e+006 1.65698e+006 1.07908e+006 533628 147334 15178.8 0 0 0 0 0 0 0 0 0 6147.82 19463.3 31613 31705.4 20236.4 7952.21 0 0 0 0 0 0 0 12524.1 28646.6 31545.5 20771.6 9887.13 0 0 0 45165 167066 360552 567111 636125 456093 252319 75731 6306.24 0 0 0 0 0 0 11094.4 43336.7 140496 263926 377126 339672 213119 92716.1 24500.9 9376.3 0 0 0 0 0 0 0 0 11563.4 14262.4 48032.6 111463 177177 209161 154221 84562.3 20214.7 0 0 0 0 0 0 0 0 0 9671.24 44132.1 130536 228343 319246 284670 173476 68365.2 9568.61 0 0 0 0 0 0 0 0 12291.4 26865.5 40631.8 44295.3 33657.2 16909.4 6274.83 0 0 0 0 0 0 5595.9 26001.6 79324.7 140353 195225 181277 116702 52946 6656.33 0 0 0 0 0 0 0 0 9116.18 18771.7 26816.6 30238.6 26806.1 17842.7 11908.6 17560.3 24388.6 20879.8 10532.4 0 0 0 0 0 0 0 0 10891.5 19324.2 23277.8 21311.3 13945 3618.28 0 0 0 0 0 0 0 0 5046.92 15072.7 22015.1 21299.4 16234 10706.6 0 0 0 0 0 0 0 0 6362.38 15238.3 20163 20221.7 16411.6 9357.98 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22970.5 119833 406086 1.06384e+006 1.76941e+006 2.21103e+006 1.69738e+006 996431 330715 68393.4 0 0 0 0 0 0 0 0 0 6718.85 15941.2 58296.8 107245 139328 103126 57174.5 18600.5 6787.18 0 0 0 0 0 0 0 0 5769.67 16235.3 34910.2 71867.3 87315 65822.9 34335.3 10711.2 0 0 0 0 0 0 0 0 10055.3 18030.2 23946.1 26828 27876.2 31409.9 0 0 8799.44 77698.1 249057 523952 824207 895430 618459 331061 98200.3", 324.681,4,1.0,1.01, 2,6,1,0,1.25,0,0}, { "316.93 316.931 316.933 316.934 316.935 316.937 316.938 316.939 316.941 316.942 316.943 316.945 316.946 317.152 317.153 317.155 317.156 317.157 317.159 317.16 317.162 317.163 317.164 317.166 317.167 317.168 317.17 317.171 317.172 317.174 317.175 317.176 317.178 317.179 317.18 317.182 317.183 317.184 317.186 317.187 317.188 317.19 317.191 317.192 317.194 317.499 317.501 317.502 317.503 317.505 317.506 317.507 317.509 317.51 317.511 317.513 317.514 317.515 317.654 317.655 317.656 317.658 317.659 317.66 317.662 317.663 317.664 317.666 317.667 317.669 317.67 317.671 317.673 317.674 317.675 317.677 317.678 317.679 317.681 317.682 317.683 317.685 317.686 317.687 317.689 317.69 317.691 317.693 317.694 317.695 317.697 317.698 317.699 317.701 317.702 317.703 317.705 317.706 317.707 317.81 317.811 317.812 317.814 317.815 317.816 317.818 317.819 317.82 317.822 317.823 317.824 317.826 317.827 317.829 317.83 317.831 317.833 317.834 317.835 317.837 317.838 317.839 317.841 317.842 317.843 317.845 317.846 317.847 317.849 317.85 317.851 317.853 317.854 317.855 317.857 317.858 317.859 317.861 317.862 317.863 317.865 317.866 317.868 317.869 317.928 317.929 317.931 317.932 317.933 317.935 317.936 317.937 317.939 317.94 317.941 317.943 317.944 317.945 317.947 317.948 317.949 317.951 318.158 318.159 318.161 318.162 318.163 318.165 318.166 318.167 318.169 318.17 318.171 318.173 318.174 318.175 318.177 318.178 318.179 318.181 318.182 318.183 318.185 318.186 318.188 318.189 318.19 318.192 318.193 318.194 318.196 318.197 318.198 318.2 318.201 318.202 318.203 318.205 318.206 318.207 318.49 318.492 318.493 318.494 318.496 318.497 318.498 318.5 318.501 318.502 318.504 318.505 318.506 318.508 318.509 318.51 318.512 318.514 318.515 318.516 318.518 318.683 318.685 318.686 318.688 318.689 318.69 318.692 318.693 318.694 318.696 318.697 318.698 318.7 318.825 318.826 318.828 318.829 318.831 318.832 318.833 318.835 318.836 318.837 318.839 318.84 318.841 318.843 318.844 318.845 318.847 318.848 318.85 319.094 319.095 319.097 319.098 319.099 319.101 319.102 319.104 319.105 319.106 319.108 319.109 319.11 319.112 319.113 319.162 319.163 319.164 319.166 319.167 319.168 319.17 319.171 319.172 319.174 319.175 319.177 319.178 319.179 319.181 319.499 319.5 319.501 319.503 319.504 319.505 319.507 319.508 319.51 319.511 319.512 319.514 319.515 319.661 319.663 319.664 319.665 319.667 319.668 319.669 319.671 319.672 319.673 319.675 319.676 319.678 319.698 319.699 319.701 319.702 319.703 319.705 319.706 319.707 319.709 319.71 319.711 319.713 319.714 319.716 319.717 319.853 319.854 319.855 319.857 319.858 319.859 319.861 319.862 319.863 319.865 319.866 319.867 319.869 320.185 320.187 320.188 320.189 320.191 320.192 320.193 320.195 320.196 320.197 320.199 320.2 320.201 320.203 320.204 320.206 320.207 320.208 320.21 320.211 320.212 320.214 320.215 320.216 320.218 320.219 320.502 320.503 320.505 320.506 320.507 320.509 320.51 320.512 320.513 320.514 320.516 320.517 320.518 320.52 320.521 320.522", "0 0 0 0 7241.27 19682.1 27785.8 23786.1 11817.8 0 0 0 0 0 0 0 0 13211.6 54540.5 99481.3 152403 159280 100901 44174.8 5942.52 669.91 19020 24047.2 29295.1 32228.6 28107.4 17978.6 8561.04 0 0 11118.5 22135 31201.2 30940.3 22511.4 13362.5 0 0 0 0 0 0 0 0 6274.15 15618.1 18945.5 13924.8 6489.34 0 0 0 0 0 0 0 0 7115.21 22347.8 38114 40847 28384.4 12714.9 0 9728.08 20270.1 30845.3 33839 25561.4 11791.7 0 0 0 0 2838.75 30794.9 110881 264181 433533 494283 346541 186229 58071.1 31575 56479.1 88848.2 99857.9 74113.7 27142.1 10370.1 0 0 0 0 0 0 0 0 4210.3 14196.8 29404.4 40223.1 40661.7 31569.1 18046.1 6584.65 0 0 0 0 0 0 9015.66 84507.7 303362 881869 1.56398e+006 2.1689e+006 1.89473e+006 1.1745e+006 506045 129958 8192.9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9526.5 50942.6 157815 283530 398647 363474 232571 106562 26483.7 2350.44 0 0 0 0 0 0 0 0 0 257639 990140 1.72868e+006 2.28545e+006 1.82081e+006 1.13244e+006 598491 488134 431208 425376 153198 0 0 0 0 0 0 31092.5 77243.6 92134.5 42742.4 20480.1 9110.67 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32241.4 201430 596658 1.01718e+006 1.32269e+006 1.07921e+006 674702 312270 150738 76963.9 26837.7 0 0 0 0 0 0 0 0 0 10405.6 18454.8 19731.5 14720 9263.62 0 0 0 0 0 0 0 0 0 30631.5 110156 256053 414666 490873 373001 223590 87841.3 20101.4 0 0 0 0 0 0 0 0 0 9320.82 22152.1 33638 38100.6 35254.2 26050.6 13168.7 0 0 0 0 0 0 0 0 13529.5 29369.4 47257.8 83492.8 58642.4 22383.5 6423.32 0 0 0 0 0 0 0 0 9006.56 21523.2 28310.6 22433.6 9918.16 0 0 0 0 0 0 0 0 5278.34 14654 21399.3 18021.8 7602 0 0 0 0 0 0 0 0 11153 59868.5 100026 127742 92760.2 45584.7 5273.03 0 0 0 0 0 0 0 0 7645.86 17039.9 21039.8 17552.4 11361 0 0 0 0 0 0 0 0 5561.98 14489.5 27837.5 40524.3 42870.9 31134.9 14509.6 4109.08 0 0 7191 20899.1 40191.3 78693.5 48652.2 35130.9 20294.4 8769.44 0 0 0 0 0 0 0 0 5084.17 17373 54040.9 90767.3 93585.1 56167.4 22545.6 8011.93 0 0 0 0", 318.169,3,5.0,4.0, 2,6,0,1,1.25,0,0}, { "415.179 415.181 415.183 415.185 415.187 415.189 415.191 415.193 415.195 415.197 415.199 415.201 415.203 415.205 415.832 415.834 415.836 415.838 415.84 415.842 415.844 415.846 415.848 415.85 415.852 415.854 415.856 415.858 415.86 415.862 415.864 415.866 415.868 415.87 415.872 415.874 415.876 415.878 415.88 415.882 415.884 415.886 415.888 415.89 415.892 415.894 415.896 415.898 415.9 415.902 415.904 415.906 416.116 416.118 416.12 416.122 416.124 416.126 416.128 416.13 416.132 416.134 416.136 416.138 416.14 416.142 416.203 416.205 416.207 416.209 416.211 416.213 416.215 416.217 416.219 416.221 416.223 416.225 416.227 416.229 416.231 416.233 416.235 416.237 416.239 416.249 416.251 416.253 416.255 416.257 416.259 416.261 416.263 416.265 416.269 416.271 416.273 416.275 416.543 416.545 416.547 416.549 416.551 416.553 416.555 416.557 416.559 416.561 416.563 416.565 416.565 416.567 416.569 416.571 416.686 416.688 416.69 416.692 416.694 416.696 416.698 416.7 416.702 416.704 416.706 416.708 416.71 416.712 416.715 416.719 416.721 416.723 416.725 416.878 416.88 416.882 416.884 416.886 416.888 416.89 416.892 416.894 416.896 416.898 416.9 416.901 416.903 416.905 416.907 417.189 417.191 417.194 417.196 417.198 417.2 417.202 417.204 417.206 417.208 417.21 417.212 417.214 417.216 417.217 417.219 417.221 417.223 417.231 417.233 417.235 417.237 417.239 417.241 417.243 417.245 417.247 417.25 417.252 417.254 417.256 417.258 417.684 417.687 417.689 417.691 417.693 417.695 417.697 417.699 417.701 417.703 417.705 417.707 417.709 417.711 417.713 417.715 417.717 417.719 417.721", "0 0 0 0 13068 30313.6 44327 42763.5 27143 10681.3 0 0 0 0 0 0 0 0 12861.9 23932.4 28395.7 23919.2 16205.1 0 0 0 0 0 0 12611.1 32209.5 48624.5 29001 9739.21 0 0 0 9396.9 94225.4 360072 829765 1.33793e+006 1.52372e+006 1.08989e+006 607260 198301 46043.7 894.783 0 0 0 0 0 0 0 0 12735.4 22188 27313.5 26983.9 21415.5 11976.7 0 0 0 0 0 0 0 0 0 22379.6 82187.5 223771 484210 773082 879781 626408 345808 101896 14446.1 0 0 0 0 0 0 0 0 20150.6 32063.4 35461 26247.8 12074.9 0 0 0 0 0 0 0 0 15138 102952 166212 231266 242733 165744 82543 6802.75 0 0 0 0 0 0 0 0 1200.84 44406.5 158943 424244 713443 903608 698826 411095 139820 33835.6 2461.56 0 0 0 0 0 0 0 0 9622.32 28799.5 112977 153068 136163 77972.9 25924.5 0 0 0 0 0 0 0 0 0 7630.18 50758.5 145197 263044 375578 339783 212564 93956.1 23367.7 5491.11 0 0 0 0 0 0 0 0 13068.6 27194.7 39076.3 39616.8 27151.2 11416.8 0 0 0 0 0 0 0 0 20127.6 35614.7 43645.7 33615.7 9873.6 0 21477.2 42504.8 42405.9 24642.2 8445.45 0 0 0 0", 415.888,3,50.0,102.6, 2,6,1,0,1.25,0,0}, { "300.703 300.704 300.705 300.707 300.708 300.709 300.71 300.712 300.713 300.714 300.715 300.716 300.718 300.719 300.72 300.721 301.177 301.178 301.18 301.181 301.182 301.183 301.185 301.186 301.187 301.188 301.19 301.191 301.192 301.193 301.491 301.492 301.494 301.495 301.496 301.497 301.498 301.5 301.501 301.502 301.503 301.505 301.506 301.655 301.656 301.657 301.659 301.66 301.661 301.662 301.664 301.665 301.666 301.667 301.669 301.67 301.671 301.672 301.674 301.675 301.676 301.677 301.679 301.68 301.681 301.682 301.684 301.825 301.827 301.828 301.829 301.83 301.832 301.833 301.834 301.835 301.836 301.838 301.839 301.84 301.841 301.843 301.844 302.149 302.15 302.151 302.153 302.154 302.155 302.156 302.158 302.159 302.16 302.161 302.163 302.164 302.165 302.166 302.168 302.169 302.17 302.171 302.173 302.174 302.175 302.176 302.178 302.637 302.638 302.639 302.64 302.642 302.643 302.644 302.645 302.647 302.648 302.649 302.65 302.652 302.736 302.738 302.739 302.74 302.741 302.743 302.744 302.745 302.746 302.748 302.749 302.75 302.751 302.753 303.145 303.147 303.148 303.149 303.15 303.152 303.153 303.154 303.155 303.157 303.158 303.159 303.16 303.162 303.167 303.168 303.169 303.17 303.172 303.173 303.174 303.175 303.177 303.178 303.179 303.18 303.182 303.183 303.184 303.186 303.193 303.194 303.196 303.197 303.198 303.199 303.201 303.202 303.203 303.204 303.206 303.207 303.208 303.452 303.454 303.455 303.456 303.457 303.459 303.46 303.461 303.462 303.464 303.465 303.466 303.467 303.477 303.479 303.48 303.481 303.482 303.484 303.485 303.486 303.487 303.489 303.49 303.491 303.493 303.494 303.495 303.657 303.658 303.659 303.661 303.662 303.663 303.664 303.666 303.667 303.668 303.669 303.671 303.672 303.673 303.674 303.813 303.814 303.815 303.816 303.818 303.819 303.82 303.821 303.823 303.824 303.825 303.826 303.828 303.829 303.83 303.831 303.833 303.834 303.835 304.142 304.143 304.144 304.146 304.147 304.148 304.149 304.151 304.152 304.153 304.154 304.156 304.157 304.158 304.159", "0 0 0 0 4021.59 14948.3 29089.3 36172.3 33002.6 23872.1 13677 5631.91 0 0 0 0 0 0 0 0 3857.72 12358.4 21296.1 23339.3 16310.7 6581.76 0 0 0 0 0 0 0 0 5103.45 14404.9 20128 17722.4 11071 0 0 0 0 0 0 0 0 5040.13 35337.3 92693 150038 188818 156826 95523.6 36488.8 1633.48 0 14570.6 13804.9 13959 16252.2 16043.7 10491.2 0 0 0 0 0 0 0 0 11491.4 23253.9 33391.5 38064.9 35915.8 26480.2 13339.6 3360.52 0 0 0 0 0 0 0 0 9994.41 18678.4 23105.4 23357.1 21846.8 17762.7 12243 1230.6 23060.6 60254.8 97465.7 113113 88507.4 54246.1 18156.2 6643.82 0 0 0 0 0 0 0 0 9123.52 17445.2 21036 16344.5 7770.44 0 0 0 0 0 0 0 0 8312 20822.9 29108.9 25567.8 13950.4 3781.06 0 0 0 0 0 0 0 0 9115.97 17822.3 25208.4 25012.8 16827.3 8086.82 0 0 0 0 0 0 0 0 3947.37 12745.8 24975.9 32592.2 31830.1 24391.1 13880.6 4732.84 0 0 0 0 0 0 0 0 6750.57 14914.3 18383.8 16081.2 11665.7 0 0 0 0 0 0 0 0 4826.25 12462.4 16962.6 13627.1 6053.79 0 0 0 0 0 0 0 0 7090.97 18737.1 29710.3 31932.3 24547.1 13431.4 4401.52 0 0 0 0 0 0 0 0 8864.78 24483.2 54372.2 81053.3 67322.2 27272.1 10297.5 0 0 0 0 0 0 0 0 11422.7 23786.6 33943.1 32175 18417.9 5897.95 6002.16 14535.1 18982.7 14518.1 6290.84 0 0 0 0 0 0 0 0 11744.6 23937.1 31048 29687.7 22535 13681.6 8906.82 14661.8 27257.5 43105 43170.2", 301.665,2,12.99,13.01, 2,6,1,0,1.25,0,0}, { "452.06 452.062 452.065 452.067 452.069 452.071 452.074 452.076 452.078 452.081 452.082 452.084 452.087 452.089 452.192 452.194 452.196 452.198 452.201 452.203 452.205 452.208 452.21 452.212 452.214 452.217 452.22 452.222 452.224 452.226 452.446 452.448 452.45 452.452 452.455 452.457 452.459 452.461 452.464 452.466 452.468 452.471 452.473 452.475 452.477 452.48 452.482 452.484 452.694 452.697 452.699 452.701 452.704 452.706 452.708 452.71 452.713 452.715 452.717 452.72 452.722 452.724 452.726 452.729 452.731 452.733 452.95 452.953 452.955 452.957 452.96 452.962 452.964 452.966 452.969 452.971 452.973 452.976 452.978 452.98 452.982 453.454 453.456 453.458 453.461 453.463 453.465 453.468 453.47 453.472 453.474 453.477 453.479 453.481 454.158 454.16 454.162 454.165 454.167 454.169 454.172 454.174 454.176 454.178 454.181 454.183 454.185 454.188 454.714 454.716 454.718 454.721 454.723 454.725 454.728 454.73 454.732 454.735 454.737 454.739 454.741", "0 0 0 0 9364.36 24041.2 38252.2 41150.4 31605.1 17604.6 0 0 0 0 0 0 0 0 3930.9 41824.5 95963.9 154164 152063 95638.9 43562 12495.1 0 0 0 0 0 0 0 0 0 28332.8 103440 204407 311126 307518 199724 97813.7 28554.9 2987.27 0 0 0 0 0 0 0 0 0 37076.2 121274 226216 331181 324273 217272 115224 35782.4 0 0 0 0 0 0 0 0 0 18286.8 60113.4 102915 133571 104506 59294.7 17472.9 0 0 0 0 0 0 0 0 10894.4 21954.3 28972.5 28655.5 21029.8 0 0 0 0 0 0 0 0 17264.7 32830.8 41807.6 38619.2 26607.2 12618.2 0 0 0 0 0 0 0 0 19933.8 29881.3 34532.2 30762.8 19924.3 0 0 0 0", 452.463,4,50.1,49.6, 2,6,0,1,1.25,0,0}, { "307.696 307.697 307.699 307.7 307.701 307.702 307.704 307.705 307.706 307.708 307.709 307.71 307.711 307.713 307.714 307.715 307.717 307.718 308.17 308.172 308.173 308.174 308.175 308.177 308.178 308.179 308.181 308.182 308.183 308.185 308.186 308.2 308.201 308.203 308.204 308.205 308.206 308.208 308.209 308.21 308.212 308.213 308.214 308.215 308.217 308.218 308.219 308.22 308.222 308.491 308.493 308.494 308.495 308.496 308.498 308.499 308.5 308.502 308.503 308.504 308.505 308.507 308.508 308.509 308.628 308.629 308.63 308.631 308.633 308.634 308.635 308.637 308.638 308.639 308.64 308.642 308.643 308.644 308.645 308.647 308.662 308.663 308.665 308.666 308.667 308.668 308.67 308.671 308.672 308.674 308.675 308.676 308.677 308.679 308.68 308.682 308.683 308.702 308.703 308.705 308.706 308.707 308.709 308.71 308.711 308.712 308.714 308.715 308.716 308.718 308.719 308.72 308.721 308.723 308.833 308.835 308.836 308.837 308.839 308.84 308.841 308.842 308.844 308.845 308.846 308.848 308.849 308.85 308.851 308.853 308.854 308.855 308.857 308.858 308.859 308.86 308.89 308.891 308.893 308.894 308.895 308.896 308.898 308.899 308.9 308.902 308.903 308.905 308.906 309.157 309.158 309.16 309.161 309.162 309.164 309.165 309.166 309.167 309.169 309.17 309.171 309.173 309.174 309.175 309.176 309.177 309.178 309.18 309.181 309.182 309.184 309.185 309.186 309.187 309.189 309.19 309.192 309.193 309.194 309.491 309.492 309.494 309.495 309.496 309.498 309.499 309.5 309.501 309.503 309.504 309.505 309.507 309.508 309.509 309.51 309.512 309.513 309.514 309.515 309.517 309.518 309.519 309.521 309.522 309.523 309.524 309.526 309.527 309.664 309.665 309.667 309.668 309.669 309.67 309.672 309.673 309.674 309.676 309.677 309.678 309.679 309.681 309.682 309.683 309.685 309.686 309.827 309.828 309.83 309.831 309.832 309.833 309.835 309.836 309.837 309.839 309.84 309.841 309.843 309.844 309.845 309.846 310.166 310.167 310.169 310.17 310.171 310.173 310.174 310.175 310.177 310.178 310.179 310.18 310.182 310.183 310.184 310.186 310.187 310.188 310.189 310.191 310.192 310.193 310.195 310.651 310.653 310.654 310.655 310.656 310.658 310.659 310.66 310.662 310.663 310.664 310.666 310.667 310.668 310.67 310.671 310.816 310.818 310.819 310.82 310.822 310.823 310.824 310.826 310.827 310.828 310.829 310.831 310.832 310.833 310.835 310.836 310.837 310.838 310.84 310.841 310.842 310.844 310.845 310.858 310.859 310.86 310.862 310.863 310.864 310.866 310.867 310.868 310.87 310.871 310.872 310.874 310.875 311.122 311.123 311.125 311.126 311.127 311.129 311.13 311.131 311.133 311.134 311.135 311.136 311.138 311.139 311.14 311.141 311.143 311.144 311.145 311.147 311.148 311.149 311.151 311.152 311.153 311.154 311.156 311.157 311.158 311.16 311.161 311.162 311.164 311.165 311.166 311.167 311.169 311.17 311.171 311.173 311.174 311.175 311.177 311.178 311.179 311.181", "0 0 0 0 9802.36 23098.1 80318.2 168123 260050 249021 153699 69134.6 15860.2 0 0 0 0 0 0 0 0 0 6603.17 16854.7 22242.6 17002.5 6384.9 0 0 0 0 0 0 0 0 3259.21 45522.7 136253 256874 378108 384887 264149 143498 38861.2 0 0 0 0 0 0 0 0 0 9568.38 16779.6 25703.4 34804.3 36903.4 27626.5 13210.8 0 0 0 0 0 0 0 0 6020.72 19418.9 41247.7 87139.4 101517 51696.3 31958.5 13406.6 0 0 0 0 0 0 0 0 8887.19 32368.8 88172.5 150448 183012 138562 83560.8 34576.6 9382.31 0 0 0 0 0 0 0 0 6136.98 17078.9 37706.1 99369.4 120669 89079.4 48058.7 16632.9 5690.8 0 0 0 0 0 0 0 0 13659 36722.7 21354.1 19439.5 43622.3 141202 361101 593217 725619 549023 320363 106084 18987.1 0 0 0 0 0 0 0 0 0 7044.94 21287 31346.9 27932.1 15042.7 0 0 0 0 0 0 0 0 12545.5 66956 196850 483967 796603 1.00996e+006 800685 478608 175846 31025.8 0 0 0 21565.5 116573 248949 372585 340360 208008 89705.4 16994.2 0 0 0 0 0 0 0 0 0 0 20664.3 76813.8 211847 360938 474556 391964 238310 96484.5 13402.4 0 0 15903.2 18823.3 38109.2 78987.2 115813 103941 60973.3 21474.4 8379.21 0 0 0 0 0 0 0 0 5010.87 39835 145701 261216 355012 297678 181623 70393.1 19551.4 9556.91 0 0 0 0 0 0 0 0 13098.9 30137.5 82208.8 121291 126226 84746 41315 13074.1 0 0 0 0 0 0 0 0 7583.31 24991.6 42441.5 47113.5 37361.7 22733.3 11295.4 0 0 15445.3 25939.6 29374.9 24399.7 16278.2 8806.05 0 0 0 0 0 0 0 0 13501.6 32925.8 78379.3 112170 101026 58511.2 22918.4 7815.47 0 0 0 0 0 0 0 0 0 16485.2 87297.2 250447 436618 588792 489043 298868 118211 35326.5 17949.5 28044.3 49970.6 30360.5 12383.3 0 0 0 0 0 0 0 0 12935.3 27576.7 33616.7 27724.5 17214.9 8642.67 0 0 0 0 0 0 0 0 4327.09 28941.4 100849 182836 253955 223430 137468 54432.1 7270.05 0 0 0 0 0 11368.6 20920.1 27685.4 29939.4 25376 15654.1 0 0 0 0 26913.6 134469 249526 300649 223246 136273 126863 259141 410598 488277 350133 183857 33436.7 0 0 0 0 0", 308.849,3,120.2,121.2, 2,6,1,0,1.25,0,0}, { "507.723 507.726 507.729 507.731 507.734 507.737 507.74 507.742 507.745 507.748 507.75 507.753 507.756 507.758 507.761 507.764 508.228 508.231 508.234 508.236 508.239 508.242 508.245 508.247 508.25 508.253 508.255 508.258 508.261 508.264 510.229 510.231 510.234 510.237 510.24 510.242 510.245 510.248 510.251 510.253 510.256 510.259 510.262 510.264", "0 0 0 0 20993.6 79292.2 151677 219202 191318 115566 45767.5 12062.2 0 0 0 0 0 0 0 0 10042.1 24206 34397.5 33192 22528.5 10434.2 0 0 0 0 0 0 0 0 9028.83 22351.6 35166.6 38509.2 29599.8 14844.1 0 0 0 0", 507.744,2,10.8,10.9, 2,6,1,0,1.25,0,0}, }; const size_t testChargeStateCalculatorsSize = sizeof(testChargeStateCalculators) / sizeof(TestChargeStateCalculator); vector parseDoubleArray(const string& doubleArray) { vector doubleVector; vector tokens; bal::split(tokens, doubleArray, bal::is_space(), bal::token_compress_on); if (!tokens.empty()) for (size_t i=0; i < tokens.size(); ++i) if (!tokens[i].empty()) doubleVector.push_back(lexical_cast(tokens[i])); return doubleVector; } vector parseCVTermArray(const string& cvTermArray) { static pwiz::data::CVTranslator cvTranslator; vector cvTermVector; vector tokens; bal::split(tokens, cvTermArray, bal::is_space()); if (!tokens.empty() && !tokens[0].empty()) for (size_t i=0; i < tokens.size(); ++i) cvTermVector.push_back(cvTranslator.translate(tokens[i])); return cvTermVector; } int test() { int failedTests = 0; for (size_t i=0; i < testChargeStateCalculatorsSize; ++i) { try { TestChargeStateCalculator& t = testChargeStateCalculators[i]; MSData msd; SpectrumListSimple* sl = new SpectrumListSimple; // create new spectrumListSimple object, s1 SpectrumListPtr originalList(sl); // create pointer (originalList) to s1 msd.run.spectrumListPtr = originalList; // create an MS1 (parent) spectrum SpectrumPtr sPar(new Spectrum); sPar->set(MS_MSn_spectrum); sPar->set(MS_ms_level,1); sPar->set(MS_profile_spectrum); sPar->scanList.scans.push_back(Scan()); Scan& scanRef = sPar->scanList.scans[0]; scanRef.set(MS_scan_start_time,t.MS1rTime,UO_second); scanRef.set(MS_preset_scan_configuration,1); vector inputMZArray = parseDoubleArray(t.inputMZArray); vector inputIntensityArray = parseDoubleArray(t.inputIntensityArray); sPar->setMZIntensityArrays(inputMZArray, inputIntensityArray, MS_number_of_detector_counts); sPar->defaultArrayLength = inputMZArray.size(); sl->spectra.push_back(sPar); // add ms1 spectrum to spectrumList // The MS2 spectrum SpectrumPtr s(new Spectrum); // create pointer (s) to spectrum object s->set(MS_MSn_spectrum); // set spectrum attribute, MS_MSn_spectrum s->set(MS_ms_level, 2); // set spectrum level s->set(MS_profile_spectrum); s->scanList.scans.push_back(Scan()); Scan& scanRef2 = s->scanList.scans[0]; scanRef2.set(MS_scan_start_time,t.MS2rTime,UO_second); scanRef2.set(MS_preset_scan_configuration,2); s->precursors.push_back(Precursor(t.inputPrecursorMZ)); // set precursor m/z in spectrum s s->defaultArrayLength = 10; // arbitrary non-zero value so that it can pass through the filter sl->spectra.push_back(s); // add ms2 spectrum to spectrumList // Run Turbocharger SpectrumListPtr calculator(new SpectrumList_ChargeFromIsotope( msd,t.maxCharge,t.minCharge,t.parentsBefore,t.parentsAfter, t.halfIsolationWidth,t.defaultMaxCharge,t.defaultMinCharge)); // Check results CVID outputChargeStateTerm = MS_charge_state; SpectrumPtr calculatedSpectrum = calculator->spectrum(1, true); // index 1 returns the MS2 spectrum BOOST_FOREACH(const CVParam& cvParam, calculatedSpectrum->precursors[0].selectedIons[0].cvParams) { if (cvParam.cvid != MS_charge_state && cvParam.cvid != MS_possible_charge_state) continue; unit_assert_operator_equal(outputChargeStateTerm, cvParam.cvid); // tests whether MS_charge_state was reported unit_assert(cvParam.valueAs() == t.trueCharge); // tests whether the correct charge was recorded } } catch (exception& e) { cerr << "Test case " << (i+1) << " failed:\n" << e.what() << endl; ++failedTests; } } return failedTests; } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; int failedTests = test(); unit_assert_operator_equal(0, failedTests); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/spectrum_processing/SpectrumList_Sorter.hpp0000664000175100017510000000622012664775615027175 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_Sorter.hpp 2971 2011-09-09 20:52:29Z chambm $ // // // Original author: Matt Chambers // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_SORTER_HPP_ #define _SPECTRUMLIST_SORTER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/SpectrumListWrapper.hpp" #include "boost/logic/tribool.hpp" namespace pwiz { namespace analysis { /// Provides a custom-sorted spectrum list class PWIZ_API_DECL SpectrumList_Sorter : public msdata::SpectrumListWrapper { public: /// client-implemented sort predicate -- called during construction of /// SpectrumList_Sorter to sort the underlying spectrum list struct PWIZ_API_DECL Predicate { /// return values: /// true: lhs < rhs /// false: lhs >= rhs /// indeterminate: need to see the full Spectrum object to decide virtual boost::logic::tribool less(const msdata::SpectrumIdentity& lhs, const msdata::SpectrumIdentity& rhs) const {return boost::logic::indeterminate;} /// return values: /// true: lhs < rhs /// false: lhs >= rhs /// indeterminate: need a more detailed Spectrum object to decide virtual boost::logic::tribool less(const msdata::Spectrum& lhs, const msdata::Spectrum& rhs) const {return lhs.index < rhs.index;} virtual ~Predicate() {} }; SpectrumList_Sorter(const msdata::SpectrumListPtr& inner, const Predicate& predicate, bool stable = false); /// \name SpectrumList interface //@{ virtual size_t size() const; virtual const msdata::SpectrumIdentity& spectrumIdentity(size_t index) const; virtual msdata::SpectrumPtr spectrum(size_t index, bool getBinaryData = false) const; //@} private: struct Impl; boost::shared_ptr impl_; SpectrumList_Sorter(SpectrumList_Sorter&); SpectrumList_Sorter& operator=(SpectrumList_Sorter&); }; class PWIZ_API_DECL SpectrumList_SorterPredicate_ScanStartTime : public SpectrumList_Sorter::Predicate { public: virtual boost::logic::tribool less(const msdata::Spectrum& lhs, const msdata::Spectrum& rhs) const; }; } // namespace analysis } // namespace pwiz #endif // _SPECTRUMLIST_SORTER_HPP_ pwiz/pwiz/analysis/spectrum_processing/SpectrumList_PrecursorRecalculatorTest.cpp0000664000175100017510000001020312664775614033072 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_PrecursorRecalculatorTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "SpectrumList_PrecursorRecalculator.hpp" #include "pwiz/data/msdata/MSDataFile.hpp" #include "pwiz/utility/misc/unit.hpp" #include "boost/filesystem/path.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::cv; using namespace pwiz::msdata; using namespace pwiz::util; using namespace pwiz::analysis; namespace bfs = boost::filesystem; ostream* os_ = 0; void verifyPrecursorInfo(const Spectrum& spectrum, double precursorMZ, int precursorCharge) { unit_assert(!spectrum.precursors.empty()); const Precursor& precursor = spectrum.precursors[0]; unit_assert(!precursor.selectedIons.empty()); const SelectedIon& selectedIon = precursor.selectedIons[0]; const double epsilon = 1e-2; if (os_) { *os_ << "[verifyPrecursorInfo] " << spectrum.index << " " << spectrum.id << " " << precursorMZ << " " << precursorCharge << ": " << selectedIon.cvParam(MS_selected_ion_m_z).value << " " << selectedIon.cvParam(MS_charge_state).value << endl; } unit_assert_equal(selectedIon.cvParam(MS_selected_ion_m_z).valueAs(), precursorMZ, epsilon); if (precursorCharge != 0) unit_assert(selectedIon.cvParam(MS_charge_state).valueAs() == precursorCharge); } void test5peptideFT(const bfs::path& datadir) { MSDataFile msd((datadir / "5peptideFT.mzML").string()); unit_assert(msd.run.spectrumListPtr.get() && msd.run.spectrumListPtr->size()==7); if (os_) *os_ << "original spectra:\n"; verifyPrecursorInfo(*msd.run.spectrumListPtr->spectrum(2), 810.79, 0); verifyPrecursorInfo(*msd.run.spectrumListPtr->spectrum(3), 837.34, 0); verifyPrecursorInfo(*msd.run.spectrumListPtr->spectrum(4), 725.36, 0); verifyPrecursorInfo(*msd.run.spectrumListPtr->spectrum(5), 558.87, 0); verifyPrecursorInfo(*msd.run.spectrumListPtr->spectrum(6), 812.33, 0); shared_ptr spectrumListRecalculated( new SpectrumList_PrecursorRecalculator(msd)); unit_assert(spectrumListRecalculated->size() == 7); if (os_) *os_ << "recalculated spectra:\n"; verifyPrecursorInfo(*spectrumListRecalculated->spectrum(2), 810.42, 2); verifyPrecursorInfo(*spectrumListRecalculated->spectrum(3), 836.96, 2); verifyPrecursorInfo(*spectrumListRecalculated->spectrum(4), 724.91, 2); verifyPrecursorInfo(*spectrumListRecalculated->spectrum(5), 558.31, 3); verifyPrecursorInfo(*spectrumListRecalculated->spectrum(6), 810.42, 2); } void test(const bfs::path& datadir) { test5peptideFT(datadir); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { bfs::path datadir = "."; for (int i=1; i1 && !strcmp(argv[1],"-v")) os_ = &cout; test(datadir); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/spectrum_processing/SpectrumList_PrecursorRecalculator.hpp0000664000175100017510000000377712664775615032262 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_PrecursorRecalculator.hpp 1191 2009-08-14 19:33:05Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_PRECURSORRECALCULATOR_HPP_ #define _SPECTRUMLIST_PRECURSORRECALCULATOR_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/SpectrumListWrapper.hpp" namespace pwiz { namespace analysis { /// SpectrumList wrapper that recalculates precursor info on spectrum() requests class PWIZ_API_DECL SpectrumList_PrecursorRecalculator : public msdata::SpectrumListWrapper { public: /// constructor needs the full MSData object for instrument info; /// SpectrumList_PrecursorRecalculator holds a reference to the original SpectrumListPtr SpectrumList_PrecursorRecalculator(const msdata::MSData& msd); /// \name SpectrumList interface //@{ virtual msdata::SpectrumPtr spectrum(size_t index, bool getBinaryData = false) const; //@} private: struct Impl; boost::shared_ptr impl_; SpectrumList_PrecursorRecalculator(SpectrumList_PrecursorRecalculator&); SpectrumList_PrecursorRecalculator& operator=(SpectrumList_PrecursorRecalculator&); }; } // namespace analysis } // namespace pwiz #endif // _SPECTRUMLIST_PRECURSORRECALCULATOR_HPP_ pwiz/pwiz/analysis/spectrum_processing/SpectrumList_ChargeFromIsotope.hpp0000664000175100017510000000762212664775615031306 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_ChargeFromIsotope.hpp 6389 2014-06-13 19:46:19Z frenchwr $ // // // Original author: William French vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_CHARGEFROMISOTOPE_HPP_ #define _SPECTRUMLIST_CHARGEFROMISOTOPE_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/utility/misc/IntegerSet.hpp" #include "pwiz/data/msdata/SpectrumListWrapper.hpp" typedef struct { int charge; std::vector indexList; int parentIndex; } isotopeChain; typedef struct { // three score types double mzPvalue; double intensityPvalue; double intensitySumPvalue; double overallPvalue; // ranks of chains based on different score types int mzRank; int intensityRank; int intensitySumRank; int sumRanks; // need index to the chain int chainIndex; } scoreChain; typedef struct { double rtime; int indexMap; } rtimeMap; typedef struct { double mz; double intensity; } pairData; namespace pwiz { namespace analysis { using namespace msdata; /// SpectrumList implementation that assigns (probable) charge states to tandem mass spectra class PWIZ_API_DECL SpectrumList_ChargeFromIsotope : public msdata::SpectrumListWrapper { public: SpectrumList_ChargeFromIsotope(const msdata::MSData& msd, int maxCharge = 3, int minCharge = 1, int parentsBefore = 2, int parentsAfter = 0, double isolationWindow = 1.25, int defaultChargeMax = 0, int defaultChargeMin = 0); virtual msdata::SpectrumPtr spectrum(size_t index, bool getBinaryData = true) const; void getMS1RetentionTimes(); void simulateSSE(const int,const int); void simulateKL(const double,const int,const int); void simulateTotIntensity(const int); void getParentIndices(const SpectrumPtr,std::vector &) const; void getParentPeaks(const SpectrumPtr,const std::vector &,const double,const double,const double,std::vector< std::vector > &,std::vector< std::vector > &) const; SpectrumListPtr instantiatePeakPicker( const std::vector & ) const; SpectrumListPtr instantiatePeakPicker( const std::vector &, const double, const double, const double ) const; private: bool override_; int maxCharge_; int minCharge_; double sigVal_; int nChainsCheck_; int parentsBefore_; int parentsAfter_; int defaultChargeMax_; int defaultChargeMin_; double defaultIsolationWidth_; int nSamples; // number of samples per simulation int maxIsotopePeaks; int minIsotopePeaks; int maxNumberPeaks; int minNumberPeaks; double mzTol; double massNeutron; double upperLimitPadding; std::vector simulatedSSEs; std::vector simulatedKLs; std::vector simulatedIntensityRankSum; std::vector MS1retentionTimes; }; } // namespace analysis } // namespace pwiz int nChoosek(int,int); double getKLscore( const isotopeChain, const std::vector &, const std::vector & ); #endif // _SPECTRUMLIST_CHARGEFROMISOTOPE_HPP_ pwiz/pwiz/analysis/spectrum_processing/SpectrumList_Sorter.cpp0000664000175100017510000001415112664775615027172 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_Sorter.cpp 2972 2011-09-09 22:42:04Z chambm $ // // // Original author: Matt Chambers // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_Sorter.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace analysis { using namespace msdata; using boost::logic::tribool; // // SpectrumList_Sorter::Impl // struct SpectrumList_Sorter::Impl { const SpectrumListPtr original; std::vector spectrumIdentities; // local cache, with fixed up index fields std::vector indexMap; // maps index -> original index Impl(const SpectrumListPtr& original, const Predicate& predicate, bool stable); void pushSpectrum(const SpectrumIdentity& spectrumIdentity); }; namespace { // sorts index vector by calling the indexed spectra with the predicate struct SortPredicate { SortPredicate(const SpectrumListPtr& inner, const SpectrumList_Sorter::Predicate& predicate) : inner(inner), predicate(predicate), detailLevel(DetailLevel_InstantMetadata) { if (inner->size() < 2) return; using namespace boost::logic; // determine the minimum detail level needed using the first two spectra if (indeterminate(predicate.less(inner->spectrumIdentity(0), inner->spectrumIdentity(1)))) { needDetails = true; // not enough info -- we need to retrieve the Spectrum do { SpectrumPtr spectrum0 = inner->spectrum(0, detailLevel); SpectrumPtr spectrum1 = inner->spectrum(1, detailLevel); tribool lessThan = predicate.less(*spectrum0, *spectrum1); if (indeterminate(lessThan)) { if (detailLevel != DetailLevel_FullData) detailLevel = DetailLevel(int(detailLevel) + 1); else throw runtime_error("[SortPredicate::ctor] indeterminate result at full detail level"); } else break; } while ((int) detailLevel <= (int) DetailLevel_FullData); } else needDetails = false; } bool operator() (size_t lhs, size_t rhs) { if (needDetails) return (bool) predicate.less(*inner->spectrum(lhs, detailLevel), *inner->spectrum(rhs, detailLevel)); else return (bool) predicate.less(inner->spectrumIdentity(lhs), inner->spectrumIdentity(rhs)); } const SpectrumListPtr inner; const SpectrumList_Sorter::Predicate& predicate; bool needDetails; // false iff spectrumIdentity is sufficient for sorting DetailLevel detailLevel; // the detail level needed for a non-indeterminate result }; } // namespace SpectrumList_Sorter::Impl::Impl(const SpectrumListPtr& _original, const Predicate& predicate, bool stable) : original(_original) { if (!original.get()) throw runtime_error("[SpectrumList_Sorter] Null pointer"); indexMap.resize(original->size()); for (size_t i=0, end=original->size(); i < end; ++i ) indexMap[i] = i; if (stable) stable_sort(indexMap.begin(), indexMap.end(), SortPredicate(original, predicate)); else sort(indexMap.begin(), indexMap.end(), SortPredicate(original, predicate)); spectrumIdentities.reserve(indexMap.size()); for (size_t i=0, end=indexMap.size(); i < end; ++i ) { spectrumIdentities.push_back(original->spectrumIdentity(indexMap[i])); spectrumIdentities.back().index = i; } } // // SpectrumList_Sorter // PWIZ_API_DECL SpectrumList_Sorter::SpectrumList_Sorter(const SpectrumListPtr& original, const Predicate& predicate, bool stable) : SpectrumListWrapper(original), impl_(new Impl(original, predicate, stable)) {} PWIZ_API_DECL size_t SpectrumList_Sorter::size() const { return impl_->indexMap.size(); } PWIZ_API_DECL const SpectrumIdentity& SpectrumList_Sorter::spectrumIdentity(size_t index) const { return impl_->spectrumIdentities.at(index); } PWIZ_API_DECL SpectrumPtr SpectrumList_Sorter::spectrum(size_t index, bool getBinaryData) const { size_t originalIndex = impl_->indexMap.at(index); SpectrumPtr originalSpectrum = impl_->original->spectrum(originalIndex, getBinaryData); SpectrumPtr newSpectrum(new Spectrum(*originalSpectrum)); newSpectrum->index = index; return newSpectrum; } // // SpectrumList_SorterPredicate_ScanStartTime // PWIZ_API_DECL tribool SpectrumList_SorterPredicate_ScanStartTime::less(const msdata::Spectrum& lhs, const msdata::Spectrum& rhs) const { if (lhs.scanList.empty() || rhs.scanList.empty()) return boost::logic::indeterminate; CVParam lhsTime = lhs.scanList.scans[0].cvParam(MS_scan_start_time); CVParam rhsTime = rhs.scanList.scans[0].cvParam(MS_scan_start_time); if (lhsTime.empty() || rhsTime.empty()) return boost::logic::indeterminate; return lhsTime.timeInSeconds() < rhsTime.timeInSeconds(); } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/SpectrumList_MetadataFixerTest.cpp0000664000175100017510000000757012664775615031301 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_MetadataFixerTest.cpp 4922 2013-09-05 22:33:08Z pcbrefugee $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "SpectrumList_MetadataFixer.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/data/msdata/TextWriter.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::msdata; using namespace pwiz::analysis; ostream* os_ = 0; struct TestMetadataFixer { // space-delimited doubles const char* inputMZArray; const char* inputIntensityArray; double tic; double bpi; double bpmz; }; TestMetadataFixer testMetadataFixers[] = { { "1 2 3 4 5", "10 20 30 40 50", 150, 50, 5 }, { "1 2 3 4 5", "50 40 30 20 10", 150, 50, 1 }, { "1 2 3 4 5", "10 20 30 20 10", 90, 30, 3 }, { "1", "10", 10, 10, 1 } }; const size_t testMetadataFixersSize = sizeof(testMetadataFixers) / sizeof(TestMetadataFixer); vector parseDoubleArray(const string& doubleArray) { vector doubleVector; vector tokens; bal::split(tokens, doubleArray, bal::is_space()); if (!tokens.empty() && !tokens[0].empty()) for (size_t i=0; i < tokens.size(); ++i) doubleVector.push_back(lexical_cast(tokens[i])); return doubleVector; } void test() { for (size_t i=0; i < testMetadataFixersSize; ++i) { SpectrumListSimple* sl = new SpectrumListSimple; SpectrumListPtr originalList(sl); // test once with no metadata SpectrumPtr s0(new Spectrum); sl->spectra.push_back(s0); TestMetadataFixer& t = testMetadataFixers[i]; // test again with existing metadata to be overwritten SpectrumPtr s1(new Spectrum); s1->set(MS_TIC, t.tic + 1); s1->set(MS_base_peak_intensity, t.bpi + 1); s1->set(MS_base_peak_m_z, t.bpmz + 1); sl->spectra.push_back(s1); vector inputMZArray = parseDoubleArray(t.inputMZArray); vector inputIntensityArray = parseDoubleArray(t.inputIntensityArray); s0->setMZIntensityArrays(inputMZArray, inputIntensityArray, MS_number_of_detector_counts); s1->setMZIntensityArrays(inputMZArray, inputIntensityArray, MS_number_of_detector_counts); SpectrumListPtr fixer(new SpectrumList_MetadataFixer(originalList)); SpectrumPtr fixedSpectrum = fixer->spectrum(0, true); unit_assert(fixedSpectrum->cvParam(MS_TIC).valueAs() == t.tic); unit_assert(fixedSpectrum->cvParam(MS_base_peak_intensity).valueAs() == t.bpi); unit_assert(fixedSpectrum->cvParam(MS_base_peak_m_z).valueAs() == t.bpmz); fixedSpectrum = fixer->spectrum(1, true); unit_assert(fixedSpectrum->cvParam(MS_TIC).valueAs() == t.tic); unit_assert(fixedSpectrum->cvParam(MS_base_peak_intensity).valueAs() == t.bpi); unit_assert(fixedSpectrum->cvParam(MS_base_peak_m_z).valueAs() == t.bpmz); } } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/spectrum_processing/SpectrumList_Filter.cpp0000664000175100017510000004043212664775615027142 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_Filter.cpp 6478 2014-07-08 20:01:38Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "pwiz/data/common/cv.hpp" #include "SpectrumList_Filter.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace analysis { using namespace pwiz::cv; using namespace pwiz::util; using namespace pwiz::msdata; using boost::logic::tribool; // // SpectrumList_Filter::Impl // struct SpectrumList_Filter::Impl { const SpectrumListPtr original; std::vector spectrumIdentities; // local cache, with fixed up index fields std::vector indexMap; // maps index -> original index DetailLevel detailLevel; // the detail level needed for a non-indeterminate result Impl(SpectrumListPtr original, const Predicate& predicate); void pushSpectrum(const SpectrumIdentity& spectrumIdentity); }; SpectrumList_Filter::Impl::Impl(SpectrumListPtr _original, const Predicate& predicate) : original(_original), detailLevel(predicate.suggestedDetailLevel()) { if (!original.get()) throw runtime_error("[SpectrumList_Filter] Null pointer"); // iterate through the spectra, using predicate to build the sub-list for (size_t i=0, end=original->size(); ispectrumIdentity(i); tribool accepted = predicate.accept(spectrumIdentity); if (accepted) { pushSpectrum(spectrumIdentity); } else if (!accepted) { // do nothing } else // indeterminate { // not enough info -- we need to retrieve the Spectrum do { SpectrumPtr spectrum = original->spectrum(i, detailLevel); accepted = predicate.accept(*spectrum); if (boost::logic::indeterminate(accepted) && (int) detailLevel < (int) DetailLevel_FullMetadata) detailLevel = DetailLevel(int(detailLevel) + 1); else { if (accepted) pushSpectrum(spectrumIdentity); break; } } while ((int) detailLevel <= (int) DetailLevel_FullMetadata); } } } void SpectrumList_Filter::Impl::pushSpectrum(const SpectrumIdentity& spectrumIdentity) { indexMap.push_back(spectrumIdentity.index); spectrumIdentities.push_back(spectrumIdentity); spectrumIdentities.back().index = spectrumIdentities.size()-1; } // // SpectrumList_Filter // PWIZ_API_DECL SpectrumList_Filter::SpectrumList_Filter(const SpectrumListPtr original, const Predicate& predicate) : SpectrumListWrapper(original), impl_(new Impl(original, predicate)) {} PWIZ_API_DECL size_t SpectrumList_Filter::size() const { return impl_->indexMap.size(); } PWIZ_API_DECL const SpectrumIdentity& SpectrumList_Filter::spectrumIdentity(size_t index) const { return impl_->spectrumIdentities.at(index); } PWIZ_API_DECL SpectrumPtr SpectrumList_Filter::spectrum(size_t index, bool getBinaryData) const { return spectrum(index, getBinaryData ? DetailLevel_FullData : DetailLevel_FullMetadata); } PWIZ_API_DECL SpectrumPtr SpectrumList_Filter::spectrum(size_t index, DetailLevel detailLevel) const { size_t originalIndex = impl_->indexMap.at(index); SpectrumPtr originalSpectrum = impl_->original->spectrum(originalIndex, detailLevel); SpectrumPtr newSpectrum(new Spectrum(*originalSpectrum)); newSpectrum->index = index; return newSpectrum; } // // SpectrumList_FilterPredicate_IndexSet // PWIZ_API_DECL SpectrumList_FilterPredicate_IndexSet::SpectrumList_FilterPredicate_IndexSet(const IntegerSet& indexSet) : indexSet_(indexSet), eos_(false) {} PWIZ_API_DECL tribool SpectrumList_FilterPredicate_IndexSet::accept(const SpectrumIdentity& spectrumIdentity) const { if (indexSet_.hasUpperBound((int)spectrumIdentity.index)) eos_ = true; bool result = indexSet_.contains((int)spectrumIdentity.index); return result; } PWIZ_API_DECL bool SpectrumList_FilterPredicate_IndexSet::done() const { return eos_; // end of set } // // SpectrumList_FilterPredicate_ScanNumberSet // PWIZ_API_DECL SpectrumList_FilterPredicate_ScanNumberSet::SpectrumList_FilterPredicate_ScanNumberSet(const IntegerSet& scanNumberSet) : scanNumberSet_(scanNumberSet), eos_(false) {} PWIZ_API_DECL tribool SpectrumList_FilterPredicate_ScanNumberSet::accept(const SpectrumIdentity& spectrumIdentity) const { int scanNumber = id::valueAs(spectrumIdentity.id, "scan"); if (scanNumberSet_.hasUpperBound(scanNumber)) eos_ = true; bool result = scanNumberSet_.contains(scanNumber); return result; } PWIZ_API_DECL bool SpectrumList_FilterPredicate_ScanNumberSet::done() const { return eos_; // end of set } // // SpectrumList_FilterPredicate_ScanEventSet // PWIZ_API_DECL SpectrumList_FilterPredicate_ScanEventSet::SpectrumList_FilterPredicate_ScanEventSet(const IntegerSet& scanEventSet) : scanEventSet_(scanEventSet) {} PWIZ_API_DECL boost::logic::tribool SpectrumList_FilterPredicate_ScanEventSet::accept(const msdata::Spectrum& spectrum) const { Scan dummy; const Scan& scan = spectrum.scanList.scans.empty() ? dummy : spectrum.scanList.scans[0]; CVParam param = scan.cvParam(MS_preset_scan_configuration); if (param.cvid == CVID_Unknown) return boost::logic::indeterminate; int scanEvent = lexical_cast(param.value); bool result = scanEventSet_.contains(scanEvent); return result; } // // SpectrumList_FilterPredicate_ScanTimeRange // PWIZ_API_DECL SpectrumList_FilterPredicate_ScanTimeRange::SpectrumList_FilterPredicate_ScanTimeRange(double scanTimeLow, double scanTimeHigh) : scanTimeLow_(scanTimeLow), scanTimeHigh_(scanTimeHigh) {} PWIZ_API_DECL tribool SpectrumList_FilterPredicate_ScanTimeRange::accept(const SpectrumIdentity& spectrumIdentity) const { // TODO: encode scan time in mzML index (and SpectrumIdentity) return boost::logic::indeterminate; } PWIZ_API_DECL boost::logic::tribool SpectrumList_FilterPredicate_ScanTimeRange::accept(const msdata::Spectrum& spectrum) const { Scan dummy; const Scan& scan = spectrum.scanList.scans.empty() ? dummy : spectrum.scanList.scans[0]; CVParam param = scan.cvParam(MS_scan_start_time); if (param.cvid == CVID_Unknown) return boost::logic::indeterminate; double time = param.timeInSeconds(); return (time>=scanTimeLow_ && time<=scanTimeHigh_); } // // SpectrumList_FilterPredicate_MSLevelSet // PWIZ_API_DECL SpectrumList_FilterPredicate_MSLevelSet::SpectrumList_FilterPredicate_MSLevelSet(const IntegerSet& msLevelSet) : msLevelSet_(msLevelSet) {} PWIZ_API_DECL boost::logic::tribool SpectrumList_FilterPredicate_MSLevelSet::accept(const msdata::Spectrum& spectrum) const { CVParam param = spectrum.cvParamChild(MS_spectrum_type); if (param.cvid == CVID_Unknown) return boost::logic::indeterminate; if (!cvIsA(param.cvid, MS_mass_spectrum)) return true; // MS level filter doesn't affect non-MS spectra param = spectrum.cvParam(MS_ms_level); if (param.cvid == CVID_Unknown) return boost::logic::indeterminate; int msLevel = param.valueAs(); bool result = msLevelSet_.contains(msLevel); return result; } // // SpectrumList_FilterPredicate_ChargeStateSet // PWIZ_API_DECL SpectrumList_FilterPredicate_ChargeStateSet::SpectrumList_FilterPredicate_ChargeStateSet(const IntegerSet& chargeStateSet) : chargeStateSet_(chargeStateSet) {} PWIZ_API_DECL boost::logic::tribool SpectrumList_FilterPredicate_ChargeStateSet::accept(const msdata::Spectrum& spectrum) const { CVParam param = spectrum.cvParamChild(MS_spectrum_type); if (param.cvid == CVID_Unknown) return boost::logic::indeterminate; if (!cvIsA(param.cvid, MS_mass_spectrum)) return true; // charge state filter doesn't affect non-MS spectra param = spectrum.cvParam(MS_ms_level); if (param.cvid == CVID_Unknown) return boost::logic::indeterminate; int msLevel = param.valueAs(); if (msLevel == 1 || // MS1s don't have charge state spectrum.precursors.empty()) // can't do much without a precursor return false; BOOST_FOREACH(const Precursor& precursor, spectrum.precursors) { if (precursor.selectedIons.empty()) continue; BOOST_FOREACH(const SelectedIon& si, precursor.selectedIons) BOOST_FOREACH(const CVParam& cvParam, si.cvParams) { switch (cvParam.cvid) { case MS_charge_state: case MS_possible_charge_state: if (chargeStateSet_.contains(cvParam.valueAs())) return true; break; default: break; } } } // at this point the charge state could not be determined; // these spectra can be included/excluded by including 0 in the chargeStateSet return chargeStateSet_.contains(0); } // // SpectrumList_FilterPredicate_PrecursorMzSet // PWIZ_API_DECL SpectrumList_FilterPredicate_PrecursorMzSet::SpectrumList_FilterPredicate_PrecursorMzSet(const std::set& precursorMzSet) : precursorMzSet_(precursorMzSet) {} PWIZ_API_DECL boost::logic::tribool SpectrumList_FilterPredicate_PrecursorMzSet::accept(const msdata::Spectrum& spectrum) const { double precursorMz = getPrecursorMz(spectrum); if (precursorMz == 0) { CVParam param = spectrum.cvParam(MS_ms_level); if (param.cvid == CVID_Unknown) return boost::logic::indeterminate; int msLevel = param.valueAs(); // If not level 1, then it should have a precursor, so request more meta data. if (msLevel != 1) return boost::logic::indeterminate; } bool result = precursorMzSet_.count(precursorMz)>0; return result; } PWIZ_API_DECL double SpectrumList_FilterPredicate_PrecursorMzSet::getPrecursorMz(const msdata::Spectrum& spectrum) const { for (size_t i=0; i(param.value); } } return 0; } // // SpectrumList_FilterPredicate_DefaultArrayLengthSet // PWIZ_API_DECL SpectrumList_FilterPredicate_DefaultArrayLengthSet::SpectrumList_FilterPredicate_DefaultArrayLengthSet(const IntegerSet& defaultArrayLengthSet) : defaultArrayLengthSet_(defaultArrayLengthSet) {} PWIZ_API_DECL boost::logic::tribool SpectrumList_FilterPredicate_DefaultArrayLengthSet::accept(const msdata::Spectrum& spectrum) const { if (spectrum.defaultArrayLength == 0) return boost::logic::indeterminate; return defaultArrayLengthSet_.contains(spectrum.defaultArrayLength); } // // SpectrumList_FilterPredicate_ActivationType // PWIZ_API_DECL SpectrumList_FilterPredicate_ActivationType::SpectrumList_FilterPredicate_ActivationType(const set cvFilterItems_, bool hasNoneOf_) : hasNoneOf(hasNoneOf_) { BOOST_FOREACH(const CVID cvid, cvFilterItems_) { CVTermInfo info = cvTermInfo(cvid); if (!cvIsA(cvid, MS_dissociation_method)) throw runtime_error("first argument not an activation type"); cvFilterItems.insert(cvid); } } PWIZ_API_DECL boost::logic::tribool SpectrumList_FilterPredicate_ActivationType::accept(const msdata::Spectrum& spectrum) const { CVParam param = spectrum.cvParamChild(MS_spectrum_type); if (param.cvid == CVID_Unknown) return boost::logic::indeterminate; if (!cvIsA(param.cvid, MS_mass_spectrum)) return true; // activation filter doesn't affect non-MS spectra param = spectrum.cvParam(MS_ms_level); if (param.cvid == CVID_Unknown) return boost::logic::indeterminate; int msLevel = param.valueAs(); if (msLevel == 1) return true; // activation filter doesn't affect MS1 spectra if (spectrum.precursors.empty() || spectrum.precursors[0].selectedIons.empty() || spectrum.precursors[0].selectedIons[0].empty()) return boost::logic::indeterminate; const Activation& activation = spectrum.precursors[0].activation; bool res = true; BOOST_FOREACH(const CVID cvid, cvFilterItems) { if (hasNoneOf) res &= !activation.hasCVParam(cvid); else res &= activation.hasCVParam(cvid); } return res; } // // SpectrumList_FilterPredicate_AnalyzerType // PWIZ_API_DECL SpectrumList_FilterPredicate_AnalyzerType::SpectrumList_FilterPredicate_AnalyzerType(const set cvFilterItems_) { BOOST_FOREACH(const CVID cvid, cvFilterItems_) { CVTermInfo info = cvTermInfo(cvid); if (std::find(info.parentsIsA.begin(), info.parentsIsA.end(), MS_mass_analyzer_type) == info.parentsIsA.end()) { throw runtime_error("first argument not an analyzer type"); } cvFilterItems.insert(cvid); } } PWIZ_API_DECL boost::logic::tribool SpectrumList_FilterPredicate_AnalyzerType::accept(const msdata::Spectrum& spectrum) const { bool res = false; Scan dummy; const Scan& scan = spectrum.scanList.scans.empty() ? dummy : spectrum.scanList.scans[0]; CVID massAnalyzerType = CVID_Unknown; if (scan.instrumentConfigurationPtr.get()) try { massAnalyzerType = scan.instrumentConfigurationPtr->componentList.analyzer(0) .cvParamChild(MS_mass_analyzer_type).cvid; } catch (out_of_range&) { // ignore out-of-range exception } if (massAnalyzerType == CVID_Unknown) return boost::logic::indeterminate; BOOST_FOREACH(const CVID cvid, cvFilterItems) if (cvIsA(massAnalyzerType, cvid)) { res = true; break; } return res; } // // SpectrumList_FilterPredicate_Polarity // PWIZ_API_DECL SpectrumList_FilterPredicate_Polarity::SpectrumList_FilterPredicate_Polarity(CVID polarity) : polarity(polarity) {} PWIZ_API_DECL boost::logic::tribool SpectrumList_FilterPredicate_Polarity::accept(const msdata::Spectrum& spectrum) const { CVParam param = spectrum.cvParamChild(MS_scan_polarity); if (param.cvid == CVID_Unknown) return boost::logic::indeterminate; return param.cvid == polarity; } // // SpectrumList_FilterPredicate_MzPresent // SpectrumList_FilterPredicate_MzPresent::SpectrumList_FilterPredicate_MzPresent(chemistry::MZTolerance mzt, std::set mzSet, ThresholdFilter tf, bool inverse) : mzt_(mzt), mzSet_(mzSet), tf_(tf), inverse_(inverse) {} boost::logic::tribool SpectrumList_FilterPredicate_MzPresent::accept(const msdata::Spectrum& spectrum) const { if (spectrum.getMZArray().get() == NULL || spectrum.getIntensityArray().get() == NULL) return boost::logic::indeterminate; // threshold spectrum SpectrumPtr sptr(new Spectrum(spectrum)); tf_(sptr); for (std::vector::iterator iterMZ = sptr->getMZArray()->data.begin(); iterMZ != sptr->getMZArray()->data.end(); ++iterMZ) { for (std::set::const_iterator mzSetIter = mzSet_.begin(); mzSetIter != mzSet_.end(); ++mzSetIter) { if (isWithinTolerance(*mzSetIter, *iterMZ, mzt_)) { if (inverse_) return false; else return true; } } } if (inverse_) return true; return false; } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/MS2Deisotoper.cpp0000664000175100017510000003314512664775615025641 0ustar teamcityteamcity00000000000000// // $Id: MS2Deisotoper.cpp 6389 2014-06-13 19:46:19Z frenchwr $ // // // Original author: Chris Paulse systemsbiology.org> // // Copyright 2009 Institute for Systems Biology, Seattle, WA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "MS2Deisotoper.hpp" #include "pwiz/analysis/peakdetect/PeakFamilyDetectorFT.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace analysis { using namespace std; using namespace msdata; using namespace pwiz::data; using namespace pwiz::data::peakdata; using boost::shared_ptr; namespace { struct PWIZ_API_DECL FilterSpectrum { FilterSpectrum(const MS2Deisotoper::Config& params_, const pwiz::msdata::SpectrumPtr spectrum_); ~FilterSpectrum() { } void DeIsotopeHiRes() { /* TODO: call peak family detector */ } void DeIsotopeLowRes(); void DeIsotopePoisson(); double getKLscore( const isoChain, bool ); // data const MS2Deisotoper::Config params; const pwiz::msdata::SpectrumPtr spectrum; std::vector& massList_; std::vector& intensities_; double precursorMZ; int precursorCharge; }; vector > GetPrecursors(const SpectrumPtr spectrum) { vector > precursorList; BOOST_FOREACH(Precursor& precursor, spectrum->precursors) { BOOST_FOREACH(SelectedIon& selectedIon, precursor.selectedIons) { double mz = 0; int charge = 0; if (selectedIon.hasCVParam(MS_m_z)) { mz = selectedIon.cvParam(MS_m_z).valueAs(); } else if (selectedIon.hasCVParam(MS_selected_ion_m_z)) { mz = selectedIon.cvParam(MS_selected_ion_m_z).valueAs(); } if (selectedIon.hasCVParam(MS_charge_state)) { charge = selectedIon.cvParam(MS_charge_state).valueAs(); } precursorList.push_back(pair(mz, charge)); } } return precursorList; } FilterSpectrum::FilterSpectrum(const MS2Deisotoper::Config& params_, const pwiz::msdata::SpectrumPtr spectrum_) : params(params_), spectrum(spectrum_), massList_(spectrum->getMZArray()->data), intensities_(spectrum->getIntensityArray()->data), precursorMZ(0), precursorCharge(0) { if (massList_.size() < 1) { //TODO: log encounter with empty spectrum? return; } if ( params.poisson ) DeIsotopePoisson( ); else DeIsotopeLowRes(); } static double PropogateNulls(double& arg1, double& arg2) { if (arg1 < 0) // indicates null return arg1; else return arg2; } struct indexValuePair { double val; size_t index; }; // Override "less than" with "greater than" for stl::sort to output in descending order bool operator < (const indexValuePair& lhs, const indexValuePair& rhs) { return lhs.val > rhs.val; } void FilterSpectrum::DeIsotopeLowRes() { vector indexValuePairs; size_t ix = 0; BOOST_FOREACH(double& intens, intensities_) { indexValuePair p; p.index = ix++; p.val = intens; indexValuePairs.push_back(p); } sort(indexValuePairs.begin(), indexValuePairs.end()); int curIxValPair = 0; BOOST_FOREACH(indexValuePair& ix, indexValuePairs) { ++curIxValPair; if (intensities_[ix.index] >= 0) { if (params.hires) { size_t i = ix.index + 1; while (i < massList_.size() && massList_[i] - massList_[ix.index] < (2.0 + params.matchingTolerance.value)) { if (intensities_[i] < intensities_[ix.index]) { intensities_[i] = -1.; } i++; } } else { for (size_t i = curIxValPair; i < indexValuePairs.size(); i++) { double massDiff = massList_[indexValuePairs[i].index] - massList_[ix.index]; if (-massDiff < params.matchingTolerance.value && massDiff < (2.0 + params.matchingTolerance.value)) { intensities_[indexValuePairs[i].index] = -1.; } } } } } transform(intensities_.begin(), intensities_.end(), massList_.begin(), massList_.begin(), PropogateNulls); intensities_.erase(remove_if(intensities_.begin(), intensities_.end(), bind2nd(less(), 0)), intensities_.end()); massList_.erase(remove_if(massList_.begin(), massList_.end(), bind2nd(less(), 0)), massList_.end()); spectrum->defaultArrayLength = massList_.size(); } // Poisson-based algorithm for deisotoping. Based on: // Breen et al., Electrophoresis 2000, 21, 2243-2251. // Bellew et al., Bioinformatics 2006, 22(15), 1902-1909. void FilterSpectrum::DeIsotopePoisson( ) { // xPeak stores m/z; yPeak stores intensity int nPeaks = massList_.size(); if ( nPeaks < 2 ) return; //std::cout << "Performing Poisson deisotoping!" << endl; double massNeutron = 1.00335; // massC13 - massC12 double mzTolppm = 100.0; double mzTolparts = mzTolppm / 1000000.0; int maxCharge = params.maxCharge, minCharge = params.minCharge; int maxIsotopePeaks = 5; vector chains; // build chains of potential isotopes for (int j=0; j massNeutron + mzTol) break; // subsequent sets of peaks will have spacing that is too large double recip = massNeutron / mzDiff; int possibleCharge = int(recip + 0.50); if ( possibleCharge > maxCharge || possibleCharge < minCharge ) continue; // Not going to generate chain extension if ( abs( massNeutron / double(possibleCharge) - mzDiff) < mzTol ) { // We have a hit // Start by checking if this can be connected to previous chains for (int w=0, wend=chains.size(); w < wend; ++w) { if ( possibleCharge != chains[w].charge ) continue; int nPeaksInChain = chains[w].indexList.size(); if ( nPeaksInChain >= maxIsotopePeaks ) continue; int finalIndex = chains[w].indexList[chains[w].indexList.size()-1]; if ( j == finalIndex ) // connect it and save previous chain { chains.push_back(chains[w]); // push back copy of previous chain with current size chains[w].indexList.push_back(k); // now extend the size of the chain } } // Also create a new chain of length 2 isoChain newChain; newChain.charge = possibleCharge; newChain.indexList.push_back(j); newChain.indexList.push_back(k); chains.push_back(newChain); } // end if peak is within tolerance } // end for loop k } // end for loop j vector KLcutoffs(5); vector SSEcutoffs(5); KLcutoffs[0] = 0.025; KLcutoffs[1] = 0.05; KLcutoffs[2] = 0.1; KLcutoffs[3] = 0.2; KLcutoffs[4] = 0.3; SSEcutoffs[0] = 0.00005; SSEcutoffs[1] = 0.0001; SSEcutoffs[2] = 0.0003; SSEcutoffs[3] = 0.0006; SSEcutoffs[4] = 0.001; // score chains, store indices that we want to remove vector removePeak(nPeaks,false); vector ::iterator it = chains.begin(); while ( it != chains.end() ) { double KLscore = getKLscore( *it, false ); int length = it->indexList.size(); // calculate average monoisotopic mass based on m/z positions in chain double average=0.0; for (int k=0; k < length; k++) average += massList_[it->indexList[k]] - double(k)*massNeutron/double(it->charge); average /= double(length); // calculate summed square error of m/z positions in chain relative to the average monoisotopic m/z double sse=0.0; for (int k=0; k < length; k++) sse += pow( average - (massList_[it->indexList[k]] - double(k)*massNeutron/double(it->charge)),2); int reducedLength = length <= 6 ? length-2 : 4; double thisKLcutoff = KLcutoffs[reducedLength]; double thisSSEcutoff = SSEcutoffs[reducedLength]; double monoIntensity = intensities_[it->indexList[0]]; if ( KLscore < thisKLcutoff && sse < thisSSEcutoff && monoIntensity > 5.0 ) { for (int i=1, iend=it->indexList.size(); i < iend; ++i) // do not remove first peak! removePeak[it->indexList[i]] = true; } ++it; } // remove peaks for (int i=nPeaks-1; i >= 0; --i) { if ( removePeak[i] ) { massList_.erase( massList_.begin() + i ); // remove this peak intensities_.erase( intensities_.begin() + i ); // remove this peak } } spectrum->defaultArrayLength = massList_.size(); } // end function DeIsotopePoisson double FilterSpectrum::getKLscore( const isoChain chain, bool printDist ) { if ( massList_.size() != intensities_.size() ) throw runtime_error("[MS2Deisotope FilterSpectrum::getKLscore] m/z and intensity vectors must be equal in size."); // First, convert from molecular weight of ion to Mstar, which is linear mapping double lambda = 1.0 / 1800.0; // parameter for poisson model double Mstar = lambda * massList_[chain.indexList[0]] * double(chain.charge); // from msInspect paper double Mexp = exp( -Mstar ); double poissonSum = 0.0; // sum up all the poisson values to normalize double observedIntensitySum = 0.0; // initialize this sum double KLscore = 0.0; vector poissonVals(chain.indexList.size(),0.0); // calculate poisson distribution and sum up the intensities for normalization for (int k=0,kend=chain.indexList.size(); k < kend ; ++k) { // probability of seeing isotope with k additional ions relative to monoisotope double poisson = Mexp * pow(Mstar,k); for (int w=k;w>1;w--) poisson /= double(w); poissonVals[k] = poisson; // store value // sums for normalization poissonSum += poisson; observedIntensitySum += intensities_[chain.indexList[k]]; } // calculate the K-L score for (int k=0,kend=chain.indexList.size(); k < kend ; ++k) { poissonVals[k] /= poissonSum; // normalize these values to use in the K-L score double normObservedIntensity = intensities_[chain.indexList[k]] / observedIntensitySum; KLscore += normObservedIntensity * log10( normObservedIntensity / poissonVals[k] ); if ( printDist ) std::cout << "mz: " << massList_[chain.indexList[k]] << " int: " << intensities_[chain.indexList[k]] << " model/obs. intensity: " << poissonVals[k] << "/" << normObservedIntensity << std::endl; } if (printDist) std::cout << std::endl; return KLscore; } } // namespace void MS2Deisotoper::describe(ProcessingMethod& method) const { //method.set(MS_ECD_ETD_Precursor_Mass_Filter); //method.userParams.push_back(UserParam("remove precursor", lexical_cast(params.removePrecursor))); //method.userParams.push_back(UserParam("filter charge reduced precursors", lexical_cast(params.removeReducedChargePrecursors))); //method.userParams.push_back(UserParam("remove neutral loss masses", lexical_cast(params.neutralLossSpecies.size() > 0))); //method.userParams.push_back(UserParam("selective removal of precursors (most intense peak in tolerance window)", lexical_cast(params.removeMostIntensePeakInWindow))); //method.userParams.push_back(UserParam("blanket removal of neutral loss masses", lexical_cast(params.useBlanketFiltering))); //method.userParams.push_back(UserParam("matching tolerance", lexical_cast(params.matchingTolerance))); } void MS2Deisotoper::operator () (const SpectrumPtr spectrum) const { if (spectrum->cvParam(MS_ms_level).valueAs() > 1 && spectrum->cvParam(MS_MSn_spectrum).empty() == false && spectrum->precursors.empty() == false && spectrum->precursors[0].empty() == false && spectrum->precursors[0].selectedIons.empty() == false && spectrum->precursors[0].selectedIons[0].empty() == false) { FilterSpectrum(params, spectrum); } } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/SpectrumList_Filter.hpp0000664000175100017510000002257412664775615027156 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_Filter.hpp 4352 2013-02-20 09:36:33Z mwilhelm42 $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_FILTER_HPP_ #define _SPECTRUMLIST_FILTER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/SpectrumListWrapper.hpp" #include "pwiz/utility/misc/IntegerSet.hpp" #include "pwiz/utility/chemistry/MZTolerance.hpp" #include "pwiz/analysis/spectrum_processing/ThresholdFilter.hpp" #include "boost/logic/tribool.hpp" #include namespace pwiz { namespace analysis { /// SpectrumList filter, for creating Spectrum sub-lists class PWIZ_API_DECL SpectrumList_Filter : public msdata::SpectrumListWrapper { public: /// client-implemented filter predicate -- called during construction of /// SpectrumList_Filter to create the filtered list of spectra struct PWIZ_API_DECL Predicate { /// can be overridden in subclasses that know they will need a certain detail level; /// it must be overridden to return DetailLevel_FullData if binary data is needed virtual msdata::DetailLevel suggestedDetailLevel() const {return msdata::DetailLevel_InstantMetadata;} /// return values: /// true: accept the Spectrum /// false: reject the Spectrum /// indeterminate: need to see the full Spectrum object to decide virtual boost::logic::tribool accept(const msdata::SpectrumIdentity& spectrumIdentity) const = 0; /// return true iff Spectrum is accepted virtual boost::logic::tribool accept(const msdata::Spectrum& spectrum) const {return false;} /// return true iff done accepting spectra; /// this allows early termination of the iteration through the original /// SpectrumList, possibly using assumptions about the order of the /// iteration (e.g. index is increasing, nativeID interpreted as scan number is /// increasing, ...) virtual bool done() const {return false;} virtual ~Predicate() {} }; SpectrumList_Filter(const msdata::SpectrumListPtr original, const Predicate& predicate); /// \name SpectrumList interface //@{ virtual size_t size() const; virtual const msdata::SpectrumIdentity& spectrumIdentity(size_t index) const; virtual msdata::SpectrumPtr spectrum(size_t index, bool getBinaryData = false) const; virtual msdata::SpectrumPtr spectrum(size_t index, msdata::DetailLevel detailLevel) const; //@} private: struct Impl; boost::shared_ptr impl_; SpectrumList_Filter(SpectrumList_Filter&); SpectrumList_Filter& operator=(SpectrumList_Filter&); }; class PWIZ_API_DECL SpectrumList_FilterPredicate_IndexSet : public SpectrumList_Filter::Predicate { public: SpectrumList_FilterPredicate_IndexSet(const util::IntegerSet& indexSet); virtual boost::logic::tribool accept(const msdata::SpectrumIdentity& spectrumIdentity) const; virtual bool done() const; private: util::IntegerSet indexSet_; mutable bool eos_; }; class PWIZ_API_DECL SpectrumList_FilterPredicate_ScanNumberSet : public SpectrumList_Filter::Predicate { public: SpectrumList_FilterPredicate_ScanNumberSet(const util::IntegerSet& scanNumberSet); virtual boost::logic::tribool accept(const msdata::SpectrumIdentity& spectrumIdentity) const; virtual bool done() const; private: util::IntegerSet scanNumberSet_; mutable bool eos_; }; class PWIZ_API_DECL SpectrumList_FilterPredicate_ScanEventSet : public SpectrumList_Filter::Predicate { public: SpectrumList_FilterPredicate_ScanEventSet(const util::IntegerSet& scanEventSet); virtual boost::logic::tribool accept(const msdata::SpectrumIdentity& spectrumIdentity) const {return boost::logic::indeterminate;} virtual boost::logic::tribool accept(const msdata::Spectrum& spectrum) const; private: util::IntegerSet scanEventSet_; }; class PWIZ_API_DECL SpectrumList_FilterPredicate_ScanTimeRange : public SpectrumList_Filter::Predicate { public: SpectrumList_FilterPredicate_ScanTimeRange(double scanTimeLow, double scanTimeHigh); virtual boost::logic::tribool accept(const msdata::SpectrumIdentity& spectrumIdentity) const; virtual boost::logic::tribool accept(const msdata::Spectrum& spectrum) const; private: double scanTimeLow_; double scanTimeHigh_; }; class PWIZ_API_DECL SpectrumList_FilterPredicate_MSLevelSet : public SpectrumList_Filter::Predicate { public: SpectrumList_FilterPredicate_MSLevelSet(const util::IntegerSet& msLevelSet); virtual boost::logic::tribool accept(const msdata::SpectrumIdentity& spectrumIdentity) const {return boost::logic::indeterminate;} virtual boost::logic::tribool accept(const msdata::Spectrum& spectrum) const; private: util::IntegerSet msLevelSet_; }; class PWIZ_API_DECL SpectrumList_FilterPredicate_ChargeStateSet : public SpectrumList_Filter::Predicate { public: SpectrumList_FilterPredicate_ChargeStateSet(const util::IntegerSet& chargeStateSet); virtual boost::logic::tribool accept(const msdata::SpectrumIdentity& spectrumIdentity) const {return boost::logic::indeterminate;} virtual boost::logic::tribool accept(const msdata::Spectrum& spectrum) const; private: util::IntegerSet chargeStateSet_; }; class PWIZ_API_DECL SpectrumList_FilterPredicate_PrecursorMzSet : public SpectrumList_Filter::Predicate { public: SpectrumList_FilterPredicate_PrecursorMzSet(const std::set& precursorMzSet); virtual boost::logic::tribool accept(const msdata::SpectrumIdentity& spectrumIdentity) const {return boost::logic::indeterminate;} virtual boost::logic::tribool accept(const msdata::Spectrum& spectrum) const; private: std::set precursorMzSet_; double getPrecursorMz(const msdata::Spectrum& spectrum) const; }; class PWIZ_API_DECL SpectrumList_FilterPredicate_DefaultArrayLengthSet : public SpectrumList_Filter::Predicate { public: SpectrumList_FilterPredicate_DefaultArrayLengthSet(const util::IntegerSet& defaultArrayLengthSet); virtual boost::logic::tribool accept(const msdata::SpectrumIdentity& spectrumIdentity) const {return boost::logic::indeterminate;} virtual boost::logic::tribool accept(const msdata::Spectrum& spectrum) const; private: util::IntegerSet defaultArrayLengthSet_; }; class PWIZ_API_DECL SpectrumList_FilterPredicate_ActivationType : public SpectrumList_Filter::Predicate { public: SpectrumList_FilterPredicate_ActivationType(const std::set filterItem, bool hasNoneOf_ = false); virtual boost::logic::tribool accept(const msdata::SpectrumIdentity& spectrumIdentity) const {return boost::logic::indeterminate;} virtual boost::logic::tribool accept(const msdata::Spectrum& spectrum) const; private: std::set cvFilterItems; bool hasNoneOf; }; class PWIZ_API_DECL SpectrumList_FilterPredicate_AnalyzerType : public SpectrumList_Filter::Predicate { public: SpectrumList_FilterPredicate_AnalyzerType(const std::set filterItem); virtual boost::logic::tribool accept(const msdata::SpectrumIdentity& spectrumIdentity) const {return boost::logic::indeterminate;} virtual boost::logic::tribool accept(const msdata::Spectrum& spectrum) const; private: std::set cvFilterItems; }; class PWIZ_API_DECL SpectrumList_FilterPredicate_Polarity : public SpectrumList_Filter::Predicate { public: SpectrumList_FilterPredicate_Polarity(pwiz::cv::CVID polarity); virtual boost::logic::tribool accept(const msdata::SpectrumIdentity& spectrumIdentity) const {return boost::logic::indeterminate;} virtual boost::logic::tribool accept(const msdata::Spectrum& spectrum) const; private: pwiz::cv::CVID polarity; }; class PWIZ_API_DECL SpectrumList_FilterPredicate_MzPresent : public SpectrumList_Filter::Predicate { public: SpectrumList_FilterPredicate_MzPresent(chemistry::MZTolerance mzt, std::set mzSet, ThresholdFilter tf, bool inverse); virtual msdata::DetailLevel suggestedDetailLevel() const {return msdata::DetailLevel_FullData;} virtual boost::logic::tribool accept(const msdata::SpectrumIdentity& spectrumIdentity) const {return boost::logic::indeterminate;} virtual boost::logic::tribool accept(const msdata::Spectrum& spectrum) const; private: chemistry::MZTolerance mzt_; std::set mzSet_; ThresholdFilter tf_; bool inverse_; }; } // namespace analysis } // namespace pwiz #endif // _SPECTRUMLIST_FILTER_HPP_ pwiz/pwiz/analysis/spectrum_processing/PrecursorRecalculatorDefaultTest.cpp0000664000175100017510000004764212664775615031703 0ustar teamcityteamcity00000000000000// // $Id: PrecursorRecalculatorDefaultTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "PrecursorRecalculatorDefault.hpp" #include "pwiz/data/msdata/BinaryDataEncoder.hpp" #include "pwiz/analysis/peakdetect/PeakFamilyDetectorFT.hpp" #include "pwiz/utility/misc/unit.hpp" #include "boost/filesystem/path.hpp" #include "boost/filesystem/fstream.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::analysis; using namespace pwiz::msdata; using namespace pwiz::util; using namespace pwiz::data; namespace bfs = boost::filesystem; ostream* os_ = 0; double testData_[] = { 818.0578, 0.0000, 818.0618, 0.0000, 818.0659, 0.0000, 818.0699, 0.0000, 818.0740, 554.0963, 818.0781, 676.5923, 818.0821, 560.7537, 818.0862, 0.0000, 818.0902, 0.0000, 818.0942, 0.0000, 818.0983, 0.0000, 818.1105, 0.0000, 818.1145, 0.0000, 818.1186, 0.0000, 818.1226, 0.0000, 818.1267, 391.2166, 818.1307, 697.9452, 818.1348, 593.9573, 818.1389, 0.0000, 818.1429, 0.0000, 818.1470, 272.1141, 818.1510, 693.6737, 818.1550, 727.4882, 818.1591, 411.9992, 818.1631, 0.0000, 818.1672, 0.0000, 818.1713, 0.0000, 818.1753, 0.0000, 818.3740, 0.0000, 818.3780, 0.0000, 818.3821, 0.0000, 818.3861, 0.0000, 818.3902, 220.8158, 818.3942, 649.2535, 818.3983, 1322.3580, 818.4023, 2346.6816, 818.4064, 5577.4443, 818.4105, 15628.4590, 818.4145, 28139.2852, 818.4186, 34538.0156, 818.4226, 29967.1211, 818.4267, 17854.7773, 818.4307, 6258.7852, 818.4348, 336.7964, 818.4388, 0.0000, 818.4429, 0.0000, 818.4470, 0.0000, 818.4510, 0.0000, 818.8811, 0.0000, 818.8852, 0.0000, 818.8892, 0.0000, 818.8933, 0.0000, 818.8973, 493.9565, 818.9014, 1365.4312, 818.9055, 2507.0815, 818.9095, 6813.2627, 818.9136, 13756.5684, 818.9177, 18748.5176, 818.9217, 18208.9883, 818.9258, 12877.9766, 818.9298, 6632.2642, 818.9339, 2455.7969, 818.9380, 518.3702, 818.9420, 0.0000, 818.9461, 0.0000, 818.9501, 0.0000, 818.9542, 0.0000, 818.9583, 0.0000, 818.9623, 416.6718, 818.9664, 835.6812, 818.9705, 899.3900, 818.9745, 565.6674, 818.9786, 0.0000, 818.9826, 0.0000, 818.9867, 0.0000, 818.9907, 0.0000, 819.3401, 0.0000, 819.3442, 0.0000, 819.3483, 0.0000, 819.3524, 0.0000, 819.3564, 537.5367, 819.3605, 666.3043, 819.3645, 707.9114, 819.3686, 560.4056, 819.3727, 0.0000, 819.3767, 0.0000, 819.3808, 0.0000, 819.3848, 0.0000, 819.3889, 0.0000, 819.3930, 0.0000, 819.3970, 0.0000, 819.4011, 248.0490, 819.4052, 983.9253, 819.4092, 2492.4019, 819.4133, 4937.9619, 819.4174, 7837.6245, 819.4214, 9702.0254, 819.4255, 9001.9619, 819.4296, 6028.9702, 819.4337, 2715.7598, 819.4377, 881.8906, 819.4418, 979.8033, 819.4458, 1142.8175, 819.4499, 901.4358, 819.4540, 509.0410, 819.4580, 0.0000, 819.4621, 0.0000, 819.4661, 0.0000, 819.4702, 0.0000, 819.8810, 0.0000, 819.8851, 0.0000, 819.8892, 0.0000, 819.8932, 0.0000, 819.8973, 38.7442, 819.9014, 719.8252, 819.9055, 1409.7166, 819.9095, 1759.1530, 819.9136, 1186.1797, 819.9177, 834.6477, 819.9218, 2120.9097, 819.9258, 2723.4282, 819.9299, 2148.7354, 819.9340, 951.6946, 819.9380, 0.0000, 819.9421, 0.0000, 819.9462, 0.0000, 819.9503, 0.0000, 819.9543, 0.0000, 820.1131, 0.0000, 820.1172, 0.0000, 820.1212, 0.0000, 820.1253, 0.0000, 820.1294, 283.9149, 820.1335, 685.0024, 820.1375, 841.5573, 820.1416, 831.9690, 820.1457, 724.9828, 820.1498, 478.1599, 820.1538, 0.0000, 820.1579, 0.0000, 820.1620, 0.0000, 820.1660, 0.0000, 820.3942, 0.0000, 820.3983, 0.0000, 820.4023, 0.0000, 820.4064, 0.0000, 820.4105, 0.0000, 820.4146, 733.8157, 820.4186, 1578.8794, 820.4227, 1832.4481, 820.4268, 1322.1443, 820.4308, 489.9802, 820.4349, 0.0000, 820.4390, 0.0000, 820.4431, 0.0000, 820.4471, 259.0050, 820.4512, 654.6262, 820.4553, 731.2765, 820.4594, 517.5179, 820.4634, 0.0000, 820.4675, 0.0000, 820.4716, 0.0000, 820.4756, 0.0000, 820.5205, 0.0000, 820.5246, 0.0000, 820.5287, 0.0000, 820.5327, 0.0000, 820.5368, 618.2869, 820.5409, 684.1355, 820.5450, 464.5241, 820.5491, 0.0000, 820.5531, 0.0000, 820.5572, 0.0000, 820.5613, 0.0000, 820.5654, 0.0000, 820.5694, 0.0000, 820.5735, 302.8770, 820.5776, 748.6038, 820.5817, 961.3633, 820.5858, 820.3262, 820.5898, 413.4973, 820.5939, 0.0000, 820.5980, 0.0000, 820.6021, 0.0000, 820.6061, 0.0000, 820.6102, 0.0000, 820.6143, 354.7731, 820.6183, 890.8882, 820.6224, 1160.5521, 820.6265, 1128.5698, 820.6306, 893.9106, 820.6346, 579.9231, 820.6387, 0.0000, 820.6428, 0.0000, 820.6469, 0.0000, 820.6509, 0.0000, 820.8589, 0.0000, 820.8630, 0.0000, 820.8671, 0.0000, 820.8712, 0.0000, 820.8753, 567.8625, 820.8793, 953.4827, 820.8834, 1072.7717, 820.8875, 1019.1711, 820.8916, 946.2395, 820.8957, 748.0505, 820.8998, 448.6019, 820.9039, 0.0000, 820.9079, 0.0000, 820.9120, 0.0000, 820.9161, 0.0000, 821.3365, 0.0000, 821.3406, 0.0000, 821.3447, 0.0000, 821.3488, 0.0000, 821.3529, 551.2963, 821.3569, 717.1707, 821.3610, 837.5309, 821.3651, 841.7739, 821.3692, 261.5813, 821.3733, 498.2640, 821.3774, 2032.2089, 821.3815, 2452.4067, 821.3856, 1783.2299, 821.3896, 696.4254, 821.3937, 955.2690, 821.3978, 3954.5977, 821.4019, 19850.8086, 821.4060, 46906.4688, 821.4100, 68569.3750, 821.4141, 68448.7812, 821.4182, 46811.6289, 821.4223, 19901.8672, 821.4264, 3090.5479, 821.4305, 862.4839, 821.4346, 326.3895, 821.4387, 0.0000, 821.4427, 0.0000, 821.4468, 0.0000, 821.4509, 0.0000, 821.8556, 0.0000, 821.8597, 0.0000, 821.8638, 0.0000, 821.8679, 0.0000, 821.8719, 633.9686, 821.8760, 1388.3333, 821.8801, 1965.9994, 821.8842, 1568.3851, 821.8883, 617.3872, 821.8924, 471.6464, 821.8965, 2934.9033, 821.9006, 6675.8296, 821.9047, 23122.4727, 821.9088, 47305.5195, 821.9128, 62059.1055, 821.9169, 55725.9336, 821.9210, 33587.5078, 821.9251, 11589.8770, 821.9292, 368.7498, 821.9333, 725.5962, 821.9374, 80.9717, 821.9415, 0.0000, 821.9456, 0.0000, 821.9496, 0.0000, 821.9537, 0.0000, 822.3548, 0.0000, 822.3589, 0.0000, 822.3630, 0.0000, 822.3671, 0.0000, 822.3712, 106.4319, 822.3752, 698.2700, 822.3793, 1279.7435, 822.3834, 1498.7074, 822.3875, 1715.3507, 822.3916, 2368.6270, 822.3957, 2623.0996, 822.3998, 570.4650, 822.4039, 5261.7271, 822.4080, 15413.5098, 822.4121, 23855.4492, 822.4162, 25214.1484, 822.4203, 19019.5293, 822.4244, 9904.5566, 822.4285, 3034.5713, 822.4326, 13.8116, 822.4366, 0.0000, 822.4407, 0.0000, 822.4449, 0.0000, 822.4490, 0.0000, 822.8710, 0.0000, 822.8751, 0.0000, 822.8792, 0.0000, 822.8833, 0.0000, 822.8874, 635.9196, 822.8915, 1131.2902, 822.8956, 1693.5773, 822.8997, 1612.8446, 822.9038, 1345.5366, 822.9079, 3657.9766, 822.9120, 6275.4512, 822.9161, 7365.7505, 822.9202, 6641.2046, 822.9243, 4600.4551, 822.9284, 2155.3687, 822.9325, 336.5125, 822.9366, 0.0000, 822.9407, 0.0000, 822.9448, 0.0000, 822.9489, 0.0000, 823.3468, 0.0000, 823.3509, 0.0000, 823.3550, 0.0000, 823.3591, 0.0000, 823.3632, 506.6892, 823.3673, 877.7867, 823.3714, 1072.1282, 823.3755, 1128.3158, 823.3796, 1120.0167, 823.3837, 939.9150, 823.3878, 394.1900, 823.3920, 113.9174, 823.3961, 787.8625, 823.4001, 978.4752, 823.4042, 616.5432, 823.4084, 0.0000, 823.4125, 0.0000, 823.4166, 0.0000, 823.4207, 269.5316, 823.4248, 978.9325, 823.4289, 1613.0895, 823.4330, 1762.3575, 823.4371, 1326.9281, 823.4412, 624.3387, 823.4453, 0.0000, 823.4494, 0.0000, 823.4536, 0.0000, 823.4576, 0.0000, }; // testData_ const size_t testDataSize_ = sizeof(testData_)/sizeof(double); const MZIntensityPair* testDataBegin_ = reinterpret_cast(testData_); const MZIntensityPair* testDataEnd_ = reinterpret_cast(testData_+testDataSize_); void test() { if (os_) *os_ << "test()\n" << flush; // instantiate PeakFamilyDetector PeakFamilyDetectorFT::Config pfdftConfig; pfdftConfig.cp = CalibrationParameters::thermo_FT(); shared_ptr pfd(new PeakFamilyDetectorFT(pfdftConfig)); // instantiate PrecursorRecalculatorDefault PrecursorRecalculatorDefault::Config config; config.peakFamilyDetector = pfd; config.mzLeftWidth = 1; config.mzRightWidth = 2.5; PrecursorRecalculatorDefault pr(config); // recalculate PrecursorRecalculator::PrecursorInfo initialEstimate; initialEstimate.mz = 821.92; vector result; pr.recalculate(testDataBegin_, testDataEnd_, initialEstimate, result); // validate result unit_assert(result.size() == 1); unit_assert_equal(result[0].mz, 821.41, 1e-2); } void test2() { if (os_) *os_ << "test2()\n" << flush; // instantiate PeakFamilyDetector PeakFamilyDetectorFT::Config pfdftConfig; pfdftConfig.cp = CalibrationParameters::thermo_FT(); shared_ptr pfd(new PeakFamilyDetectorFT(pfdftConfig)); // instantiate PrecursorRecalculatorDefault PrecursorRecalculatorDefault::Config config; config.peakFamilyDetector = pfd; config.mzLeftWidth = 4; config.mzRightWidth = 2.5; PrecursorRecalculatorDefault pr(config); // recalculate PrecursorRecalculator::PrecursorInfo initialEstimate; initialEstimate.mz = 821.92; vector result; pr.recalculate(testDataBegin_, testDataEnd_, initialEstimate, result); // validate result unit_assert(result.size() == 2); unit_assert_equal(result[0].mz, 821.41, 1e-2); unit_assert_equal(result[1].mz, 818.42, 1e-2); } vector readData(const bfs::path& filename) { // data stored as 32-bit big-endian zlib m/z-intensity pairs (mzXML with zlib) bfs::ifstream is(filename); if (!is) throw runtime_error(("[PrecursorRecalculatorDefaultTest::readData()] Unable to open file " + filename.string()).c_str()); string encoded; is >> encoded; BinaryDataEncoder::Config bdeConfig; bdeConfig.precision = BinaryDataEncoder::Precision_32; bdeConfig.byteOrder = BinaryDataEncoder::ByteOrder_BigEndian; bdeConfig.compression = BinaryDataEncoder::Compression_Zlib; BinaryDataEncoder encoder(bdeConfig); vector data; encoder.decode(encoded, data); unit_assert(!data.empty() && data.size()%2 == 0); vector result(data.size()/2); copy(data.begin(), data.end(), reinterpret_cast(&result[0])); return result; } shared_ptr createPrecursorRecalculator_msprefix() { // instantiate PeakFamilyDetector PeakFamilyDetectorFT::Config pfdftConfig; pfdftConfig.cp = CalibrationParameters::thermo_FT(); shared_ptr pfd(new PeakFamilyDetectorFT(pfdftConfig)); // instantiate PrecursorRecalculatorDefault PrecursorRecalculatorDefault::Config config; config.peakFamilyDetector = pfd; config.mzLeftWidth = 3; config.mzRightWidth = 1.6; return shared_ptr(new PrecursorRecalculatorDefault(config)); } struct TestInfo { double mzInitialEstimate; double mzTrue; int chargeTrue; TestInfo(double _mzInitialEstimate, double _mzTrue, int _chargeTrue) : mzInitialEstimate(_mzInitialEstimate), mzTrue(_mzTrue), chargeTrue(_chargeTrue) {} }; void validateRecalculation(const MZIntensityPair* begin, const MZIntensityPair* end, PrecursorRecalculatorDefault& pr, const TestInfo& testInfo) { // recalculate PrecursorRecalculator::PrecursorInfo initialEstimate; initialEstimate.mz = testInfo.mzInitialEstimate; vector result; pr.recalculate(begin, end, initialEstimate, result); // validate result if (os_) for (vector::const_iterator it=result.begin(), end=result.end(); it!=end; ++it) *os_ << " " << it->mz << " " << it->charge << endl; unit_assert(result.size() >= 1); unit_assert_equal(result[0].mz, testInfo.mzTrue, 1e-2); unit_assert(result[0].charge == testInfo.chargeTrue); } void test5peptide(const bfs::path& datadir) { if (os_) *os_ << "test5peptide()\n" << flush; vector data = readData(datadir / "5peptide.b64"); unit_assert(data.size() == 19914); shared_ptr pr = createPrecursorRecalculator_msprefix(); const MZIntensityPair* begin = &data[0]; const MZIntensityPair* end = begin + data.size(); validateRecalculation(begin, end, *pr, TestInfo(810.79, 810.42, 2)); validateRecalculation(begin, end, *pr, TestInfo(837.34, 836.96, 2)); validateRecalculation(begin, end, *pr, TestInfo(725.36, 724.91, 2)); validateRecalculation(begin, end, *pr, TestInfo(558.87, 558.31, 3)); validateRecalculation(begin, end, *pr, TestInfo(812.33, 810.42, 2)); validateRecalculation(begin, end, *pr, TestInfo(810.75, 810.42, 2)); validateRecalculation(begin, end, *pr, TestInfo(837.96, 836.96, 2)); validateRecalculation(begin, end, *pr, TestInfo(644.06, 643.37, 2)); validateRecalculation(begin, end, *pr, TestInfo(725.68, 724.91, 2)); validateRecalculation(begin, end, *pr, TestInfo(559.19, 558.31, 3)); validateRecalculation(begin, end, *pr, TestInfo(811.41, 810.42, 2)); validateRecalculation(begin, end, *pr, TestInfo(674.64, 674.37, 2)); validateRecalculation(begin, end, *pr, TestInfo(882.45, 882.47, 1)); } void runSpecialTest(const bfs::path& filename, size_t pairCount, const TestInfo& testInfo) { if (os_) *os_ << "runSpecialTest: " << filename << " " << testInfo.mzInitialEstimate << " " << testInfo.mzTrue << " " << testInfo.chargeTrue << endl; vector data = readData(filename); unit_assert(data.size() == pairCount); shared_ptr pr = createPrecursorRecalculator_msprefix(); validateRecalculation(&*data.begin(), &*data.begin()+data.size(), *pr, testInfo); } void runTests(const bfs::path& datadir) { test(); test2(); test5peptide(datadir); runSpecialTest(datadir / "special_1a.b64", 12118, TestInfo(484.2727357, 484.28, 0)); runSpecialTest(datadir / "special_1b.b64", 17767, TestInfo(930.0000218, 929.99, 2)); // noise floor calculation issue (due to big neighbor) runSpecialTest(datadir / "special_2a.b64", 4802, TestInfo(705.0000091, 704.32, 2)); // charge state determination (window must be > 1.5amu to the right) runSpecialTest(datadir / "special_2b.b64", 8897, TestInfo(961.0000167, 960.9639, 2)); // monoisotopic peak threshold must be lenient runSpecialTest(datadir / "special_2c.b64", 7006, TestInfo(731.090919, 730.36, 3)); runSpecialTest(datadir / "special_2d.b64", 12512, TestInfo(730.3599854,730.36, 3)); // charge state calculation issues due to small 1-neutron peak runSpecialTest(datadir / "special_3a.b64", 5721, TestInfo(560.3636411, 560.28, 2)); runSpecialTest(datadir / "special_3b.b64", 5342, TestInfo(820.6363762, 820.47, 2)); // charge state calculation issues due to small 1-neutron peak runSpecialTest(datadir / "special_4a.b64", 4142, TestInfo(791.5454722, 791.37, 2)); // charge state regression due to generous acceptance of charge 2 scores runSpecialTest(datadir / "special_5a.b64", 12324, TestInfo(445.0000073, 445.12, 1)); runSpecialTest(datadir / "special_5a.b64", 12324, TestInfo(407.9090971, 408.31, 1)); runSpecialTest(datadir / "special_5a.b64", 12324, TestInfo(462.0000078, 462.14, 1)); runSpecialTest(datadir / "special_5a.b64", 12324, TestInfo(536.0909191, 536.16, 1)); runSpecialTest(datadir / "special_5a.b64", 12324, TestInfo(519.0909186, 519.14, 1)); // lonely peaks runSpecialTest(datadir / "special_6a.b64", 12358, TestInfo(1682.636408, 1683.39, 0)); runSpecialTest(datadir / "special_6b.b64", 12280, TestInfo(1565.636404, 1563.74, 0)); runSpecialTest(datadir / "special_6c.b64", 12245, TestInfo(1668.545498, 1667.55, 0)); runSpecialTest(datadir / "special_6d.b64", 12386, TestInfo(1851.545504, 1849.69, 0)); runSpecialTest(datadir / "special_6e.b64", 12221, TestInfo(1444.636401, 1442.54, 0)); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { bfs::path datadir = "."; for (int i=1; i // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PRECURSORRECALCULATORDEFAULT_HPP_ #define _PRECURSORRECALCULATORDEFAULT_HPP_ #include "PrecursorRecalculator.hpp" #include "pwiz/analysis/peakdetect/PeakFamilyDetector.hpp" namespace pwiz { namespace analysis { class PWIZ_API_DECL PrecursorRecalculatorDefault : public PrecursorRecalculator { public: struct PWIZ_API_DECL Config { boost::shared_ptr peakFamilyDetector; std::ostream* log; double mzLeftWidth; double mzRightWidth; enum SortBy {SortBy_Proximity, SortBy_Score}; SortBy sortBy; Config() : log(0), mzLeftWidth(0), mzRightWidth(0), sortBy(SortBy_Proximity) {} }; PrecursorRecalculatorDefault(const Config&); virtual void recalculate(const MZIntensityPair* begin, const MZIntensityPair* end, const PrecursorInfo& initialEstimate, std::vector& result) const; private: class Impl; boost::shared_ptr impl_; PrecursorRecalculatorDefault(PrecursorRecalculatorDefault&); PrecursorRecalculatorDefault& operator=(PrecursorRecalculatorDefault&); }; } // namespace analysis } // namespace pwiz #endif // _PRECURSORRECALCULATORDEFAULT_HPP_ pwiz/pwiz/analysis/spectrum_processing/SpectrumList_PeakPicker.hpp0000664000175100017510000000427712664775615027747 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_PeakPicker.hpp 9035 2015-10-24 18:58:07Z pcbrefugee $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_PEAKPICKER_HPP_ #define _SPECTRUMLIST_PEAKPICKER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/utility/misc/IntegerSet.hpp" #include "pwiz/data/msdata/SpectrumListWrapper.hpp" #include "pwiz/analysis/common/LocalMaximumPeakDetector.hpp" #include "pwiz/analysis/common/CwtPeakDetector.hpp" namespace pwiz { namespace analysis { /// SpectrumList implementation to replace peak profiles with picked peaks class PWIZ_API_DECL SpectrumList_PeakPicker : public msdata::SpectrumListWrapper { public: SpectrumList_PeakPicker(const msdata::SpectrumListPtr& inner, PeakDetectorPtr algorithm, bool preferVendorPeakPicking, const util::IntegerSet& msLevelsToPeakPick); static bool accept(const msdata::SpectrumListPtr& inner); virtual msdata::SpectrumPtr spectrum(size_t index, msdata::DetailLevel detailLevel) const; virtual msdata::SpectrumPtr spectrum(size_t index, bool getBinaryData = false) const; private: PeakDetectorPtr algorithm_; const util::IntegerSet msLevelsToPeakPick_; int mode_; }; class PWIZ_API_DECL NoVendorPeakPickingException : public std::runtime_error { public: NoVendorPeakPickingException() : std::runtime_error("[PeakDetector::NoVendorPeakPickingException]") {} }; } // namespace analysis } // namespace pwiz #endif // _SPECTRUMLIST_PEAKPICKER_HPP_ pwiz/pwiz/analysis/spectrum_processing/SpectrumList_PeakFilterTest.cpp0000664000175100017510000033355212664775615030613 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_PeakFilterTest.cpp 4922 2013-09-05 22:33:08Z pcbrefugee $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/data/msdata/MSData.hpp" #include "PrecursorMassFilter.hpp" #include "ThresholdFilter.hpp" #include "MS2Deisotoper.hpp" #include "MS2NoiseFilter.hpp" #include "SpectrumList_PeakFilter.hpp" #include "SpectrumList_ZeroSamplesFilter.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/data/msdata/examples.hpp" #include "pwiz/data/msdata/TextWriter.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::msdata; using namespace pwiz::analysis; ostream* os_ = 0; ostream& operator<< (ostream& os, const vector& v) { os << "("; for (size_t i=0; i < v.size(); ++i) os << " " << v[i]; os << " )"; return os; } vector parseDoubleArray(const string& doubleArray) { vector doubleVector; vector tokens; bal::split(tokens, doubleArray, bal::is_space()); if (!tokens.empty() && !tokens[0].empty()) for (size_t i=0; i < tokens.size(); ++i) doubleVector.push_back(lexical_cast(tokens[i])); return doubleVector; } //////////////////////////////////////////////////////////////////////////// // ETD/ECD Filter test //////////////////////////////////////////////////////////////////////////// struct TestETDMassFilter { // space-delimited doubles const char* inputMZArray; const char* inputIntensityArray; const char* outputMZArray; const char* outputIntensityArray; double matchingTolerance; bool usePPM; bool hasCharge; bool removePrecursor; bool removeReducedChargePrecursors; bool removeNeutralLossPrecursors; bool blanketRemovalofNeutralLoss; }; #define PRECURSOR_CHARGE 3 #define PRECURSOR_MZ 445.34 TestETDMassFilter testETDMassFilterData[] = { { "100 110 120 130 415.8215 422.337 422.8295 423.3215 427.3295 427.8215 428.3135 429.327 431.3425 436.3345 445.34 831.632 844.674 845.659 846.643 854.659 855.643 856.627 858.654 862.685 872.669 873.653 890.68 1000.0", "10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 260 270 280", "100 110 120 130 415.8215 422.337 422.8295 423.3215 427.3295 427.8215 428.3135 429.327 431.3425 436.3345 445.34 831.632 844.674 845.659 846.643 854.659 855.643 856.627 858.654 862.685 872.669 873.653 890.68 1000.0", "10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 260 270 280", 0.1234, false, false, false, false, false, false }, // do nothing { "100 110 120 130 415.8215 422.337 422.8295 423.3215 427.3295 427.8215 428.3135 429.327 431.3425 436.3345 445.34 445.35 831.632 844.674 845.659 846.643 854.659 855.643 856.627 858.654 862.685 872.669 873.653 890.68 1000.0", "10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 260 270 280 290", "100 110 120 130 415.8215 422.337 422.8295 423.3215 427.3295 427.8215 428.3135 429.327 431.3425 436.3345 831.632 844.674 845.659 846.643 854.659 855.643 856.627 858.654 862.685 872.669 873.653 890.68 1000.0", "10 20 30 40 50 60 70 80 90 100 110 120 130 140 170 180 190 200 210 220 230 240 250 260 270 280 290", 0.1234, false, true, true, false, false, false }, // remove precursor only { "100 110 120 130 415.8215 422.337 422.8295 423.3215 427.3295 427.8215 428.3135 429.327 431.3425 436.3345 445.34 445.35 831.632 844.674 845.659 846.643 854.659 855.643 856.627 858.654 862.685 872.669 873.653 890.68 1000.0", "10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 260 270 280 290", "100 110 120 130 415.8215 422.337 422.8295 423.3215 427.3295 427.8215 428.3135 429.327 431.3425 436.3345 831.632 844.674 845.659 846.643 854.659 855.643 856.627 858.654 862.685 872.669 873.653 890.68 1000.0", "10 20 30 40 50 60 70 80 90 100 110 120 130 140 170 180 190 200 210 220 230 240 250 260 270 280 290", 0.1234, false, false, true, false, false, false }, // remove precursor without charge state { "100 110 120 130 415.8215 422.337 422.8295 423.3215 427.3295 427.8215 428.3135 429.327 431.3425 436.3345 445.34 668.01 831.632 844.674 845.659 846.643 854.659 855.643 856.627 858.654 862.685 872.669 873.653 890.68 1000.0", "10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 155 160 170 180 190 200 210 220 230 240 250 260 270 280", "100 110 120 130 415.8215 422.337 422.8295 423.3215 427.3295 427.8215 428.3135 429.327 431.3425 436.3345 445.34 831.632 844.674 845.659 846.643 854.659 855.643 856.627 858.654 862.685 872.669 873.653 890.68 1000.0", "10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 260 270 280", 0.1234, false, true, false, true, false, false }, // remove charge reduced precursors only { "100 110 120 130 415.8215 422.337 422.8295 423.3215 427.3295 427.8215 428.3135 429.327 431.3425 436.3345 445.34 668.01 831.632 844.674 845.659 846.643 854.659 855.643 856.627 858.654 862.685 872.669 873.653 890.68 1000.0", "10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 155 160 170 180 190 200 210 220 230 240 250 260 270 280", "100 110 120 130 415.8215 422.337 422.8295 423.3215 427.3295 427.8215 428.3135 429.327 431.3425 436.3345 831.632 844.674 845.659 846.643 854.659 855.643 856.627 858.654 862.685 872.669 873.653 890.68 1000.0", "10 20 30 40 50 60 70 80 90 100 110 120 130 140 160 170 180 190 200 210 220 230 240 250 260 270 280", 0.1234, false, true, true, true, false, false }, // remove precursor and charge reduced precursors { "100 120 445.34 667.51 668.01 1335.02 1336.02 1400.", "10 20 30 40 50 60 70 80", "100 120", "10 20", 0.01, false, true, true, true, true, false }, // remove precursor charge reduced precursors, and neutral losses { "100 120 445.34 667.51 668.01 1335.02 1336.02 1400.", "10 20 30 40 50 60 70 80", "100 120", "10 20", 0.01, false, true, true, true, true, true }, // remove precursor charge reduced precursors, and neutral losses -- blanket removal of neutral losses (60 Da window) }; const size_t testETDMassFilterDataSize = sizeof(testETDMassFilterData) / sizeof(TestETDMassFilter); void testPrecursorMassRemoval() { for (size_t i=0; i < testETDMassFilterDataSize; ++i) { SpectrumListSimple* sl = new SpectrumListSimple; SpectrumListPtr originalList(sl); SpectrumPtr s(new Spectrum); sl->spectra.push_back(s); TestETDMassFilter& t = testETDMassFilterData[i]; vector inputMZArray = parseDoubleArray(t.inputMZArray); vector inputIntensityArray = parseDoubleArray(t.inputIntensityArray); s->set(MS_MSn_spectrum); s->set(MS_ms_level, 2); s->setMZIntensityArrays(inputMZArray, inputIntensityArray, MS_number_of_detector_counts); s->precursors.resize(1); s->precursors[0].activation.set(MS_electron_transfer_dissociation); s->precursors[0].selectedIons.resize(1); s->precursors[0].selectedIons[0].set(MS_selected_ion_m_z, PRECURSOR_MZ, MS_m_z); if (t.hasCharge) s->precursors[0].selectedIons[0].set(MS_charge_state, PRECURSOR_CHARGE); MZTolerance tol(t.matchingTolerance, t.usePPM ? MZTolerance::PPM : MZTolerance::MZ); SpectrumDataFilterPtr filter; if (t.removeNeutralLossPrecursors) { PrecursorMassFilter::Config params(tol, t.removePrecursor, t.removeReducedChargePrecursors, t.blanketRemovalofNeutralLoss); filter.reset(new PrecursorMassFilter(params)); } else { PrecursorMassFilter::Config params(tol, t.removePrecursor, t.removeReducedChargePrecursors, t.blanketRemovalofNeutralLoss, 0); filter.reset(new PrecursorMassFilter(params)); } SpectrumListPtr peakFilter(new SpectrumList_PeakFilter(originalList, filter)); SpectrumPtr pFiltered = peakFilter->spectrum(0, true); vector outputMZArray = parseDoubleArray(t.outputMZArray); vector outputIntensityArray = parseDoubleArray(t.outputIntensityArray); vector& resultMZArray = pFiltered->getMZArray()->data; vector& resultIntensityArray = pFiltered->getIntensityArray()->data; unit_assert(resultMZArray.size() == outputMZArray.size()); unit_assert(resultIntensityArray.size() == outputIntensityArray.size()); for (size_t ii=0; ii < outputMZArray.size(); ++ii) { unit_assert_equal(resultMZArray[ii], outputMZArray[ii], 0.001); unit_assert_equal(resultIntensityArray[ii], outputIntensityArray[ii], 0.001); } } } //////////////////////////////////////////////////////////////////////////// // Thresholder test //////////////////////////////////////////////////////////////////////////// struct TestThresholder { // space-delimited doubles const char* inputMZArray; const char* inputIntensityArray; const char* outputMZArray; const char* outputIntensityArray; ThresholdFilter::ThresholdingBy_Type byType; double threshold; ThresholdFilter::ThresholdingOrientation orientation; }; TestThresholder testThresholders[] = { // test empty spectrum { "", "", "", "", ThresholdFilter::ThresholdingBy_AbsoluteIntensity, 0.1, ThresholdFilter::Orientation_MostIntense }, { "", "", "", "", ThresholdFilter::ThresholdingBy_FractionOfBasePeakIntensity, 0.1, ThresholdFilter::Orientation_MostIntense }, { "", "", "", "", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensity, 0.1, ThresholdFilter::Orientation_MostIntense }, { "", "", "", "", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensityCutoff, 0.99, ThresholdFilter::Orientation_MostIntense }, { "", "", "", "", ThresholdFilter::ThresholdingBy_Count, 5, ThresholdFilter::Orientation_MostIntense }, // test one peak spectrum { "1", "10", "1", "10", ThresholdFilter::ThresholdingBy_AbsoluteIntensity, 0.1, ThresholdFilter::Orientation_MostIntense }, { "1", "10", "1", "10", ThresholdFilter::ThresholdingBy_FractionOfBasePeakIntensity, 0.1, ThresholdFilter::Orientation_MostIntense }, { "1", "10", "1", "10", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensity, 0.1, ThresholdFilter::Orientation_MostIntense }, { "1", "10", "1", "10", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensityCutoff, 0.99, ThresholdFilter::Orientation_MostIntense }, { "1", "10", "1", "10", ThresholdFilter::ThresholdingBy_Count, 5, ThresholdFilter::Orientation_MostIntense }, // test two peak spectrum with a zero data point { "1 2", "10 0", "1", "10", ThresholdFilter::ThresholdingBy_AbsoluteIntensity, 0.1, ThresholdFilter::Orientation_MostIntense }, { "1 2", "10 0", "1", "10", ThresholdFilter::ThresholdingBy_FractionOfBasePeakIntensity, 0.1, ThresholdFilter::Orientation_MostIntense }, { "1 2", "10 0", "1", "10", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensity, 0.1, ThresholdFilter::Orientation_MostIntense }, { "1 2", "10 0", "1", "10", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensityCutoff, 0.99, ThresholdFilter::Orientation_MostIntense }, { "1 2", "10 0", "1 2", "10 0", ThresholdFilter::ThresholdingBy_Count, 5, ThresholdFilter::Orientation_MostIntense }, // absolute thresholding, keeping the most intense points { "1 2 3 4 5", "10 20 30 20 10", "1 2 3 4 5", "10 20 30 20 10", ThresholdFilter::ThresholdingBy_AbsoluteIntensity, 5, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5", "10 20 30 20 10", "2 3 4", "20 30 20", ThresholdFilter::ThresholdingBy_AbsoluteIntensity, 10, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5", "10 20 30 20 10", "2 3 4", "20 30 20", ThresholdFilter::ThresholdingBy_AbsoluteIntensity, 15, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5", "10 20 30 20 10", "", "", ThresholdFilter::ThresholdingBy_AbsoluteIntensity, 30, ThresholdFilter::Orientation_MostIntense }, // absolute thresholding, keeping the least intense points { "1 2 3 4 5", "10 20 30 20 10", "", "", ThresholdFilter::ThresholdingBy_AbsoluteIntensity, 5, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5", "10 20 30 20 10", "", "", ThresholdFilter::ThresholdingBy_AbsoluteIntensity, 10, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5", "10 20 30 20 10", "1 5", "10 10", ThresholdFilter::ThresholdingBy_AbsoluteIntensity, 15, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5", "10 20 30 20 10", "1 2 4 5", "10 20 20 10", ThresholdFilter::ThresholdingBy_AbsoluteIntensity, 30, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5", "10 20 30 20 10", "1 2 3 4 5", "10 20 30 20 10", ThresholdFilter::ThresholdingBy_AbsoluteIntensity, 50, ThresholdFilter::Orientation_LeastIntense }, // relative thresholding to the base peak, keeping the most intense peaks { "1 2 3 4 5", "10 20 30 20 10", "1 2 3 4 5", "10 20 30 20 10", ThresholdFilter::ThresholdingBy_FractionOfBasePeakIntensity, 0.1, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5", "10 20 30 20 10", "2 3 4", "20 30 20", ThresholdFilter::ThresholdingBy_FractionOfBasePeakIntensity, 0.34, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5", "10 20 30 20 10", "2 3 4", "20 30 20", ThresholdFilter::ThresholdingBy_FractionOfBasePeakIntensity, 0.65, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5", "10 20 30 20 10", "3", "30", ThresholdFilter::ThresholdingBy_FractionOfBasePeakIntensity, 0.67, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5", "10 20 30 20 10", "", "", ThresholdFilter::ThresholdingBy_FractionOfBasePeakIntensity, 1.0, ThresholdFilter::Orientation_MostIntense }, // relative thresholding to the base peak, keeping the least intense peaks { "1 2 3 4 5", "10 20 30 20 10", "", "", ThresholdFilter::ThresholdingBy_FractionOfBasePeakIntensity, 0.1, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5", "10 20 30 20 10", "", "", ThresholdFilter::ThresholdingBy_FractionOfBasePeakIntensity, 0.32, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5", "10 20 30 20 10", "1 5", "10 10", ThresholdFilter::ThresholdingBy_FractionOfBasePeakIntensity, 0.34, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5", "10 20 30 20 10", "1 2 4 5", "10 20 20 10", ThresholdFilter::ThresholdingBy_FractionOfBasePeakIntensity, 0.67, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5", "10 20 30 20 10", "1 2 4 5", "10 20 20 10", ThresholdFilter::ThresholdingBy_FractionOfBasePeakIntensity, 1.0, ThresholdFilter::Orientation_LeastIntense }, // relative thresholding to total intensity, keeping the most intense peaks { "1 2 3 4 5", "10 20 30 20 10", "1 2 3 4 5", "10 20 30 20 10", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensity, 0.1, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5", "10 20 30 20 10", "2 3 4", "20 30 20", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensity, 0.12, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5", "10 20 30 20 10", "2 3 4", "20 30 20", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensity, 0.21, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5", "10 20 30 20 10", "3", "30", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensity, 0.23, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5", "10 20 30 20 10", "", "", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensity, 0.34, ThresholdFilter::Orientation_MostIntense }, // relative thresholding to total intensity, keeping the least intense peaks { "1 2 3 4 5", "10 20 30 20 10", "", "", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensity, 0.1, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5", "10 20 30 20 10", "1 5", "10 10", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensity, 0.12, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5", "10 20 30 20 10", "1 5", "10 10", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensity, 0.21, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5", "10 20 30 20 10", "1 2 4 5", "10 20 20 10", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensity, 0.23, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5", "10 20 30 20 10", "1 2 3 4 5", "10 20 30 20 10", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensity, 0.34, ThresholdFilter::Orientation_LeastIntense }, // threshold against cumulative total intensity fraction, keeping the most intense peaks (ties are included) // intensities: 12 2 2 1 1 1 1 0 0 (TIC 20) // cumulative: 12 14 16 17 18 19 20 20 20 // fraction: .60 .70 .80 .85 .90 .95 1.0 1.0 1.0 // at threshold 1.0 ---------------------------^ cut here // at threshold .99 ---------------------------^ cut here // at threshold .90 ---------------------------^ cut here // at threshold .80 -----------^ cut here // at threshold .65 -----------^ cut here // at threshold .60 ---^ cut here // at threshold .15 ---^ cut here { "1 2 3 4 5 6 7 8 9", "0 1 2 1 0 1 2 12 1", "2 3 4 6 7 8 9", "1 2 1 1 2 12 1", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensityCutoff, 1.0, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5 6 7 8 9", "0 1 2 1 0 1 2 12 1", "2 3 4 6 7 8 9", "1 2 1 1 2 12 1", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensityCutoff, 0.99, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5 6 7 8 9", "0 1 2 1 0 1 2 12 1", "2 3 4 6 7 8 9", "1 2 1 1 2 12 1", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensityCutoff, 0.90, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5 6 7 8 9", "0 1 2 1 0 1 2 12 1", "3 7 8", "2 2 12", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensityCutoff, 0.80, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5 6 7 8 9", "0 1 2 1 0 1 2 12 1", "3 7 8", "2 2 12", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensityCutoff, 0.65, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5 6 7 8 9", "0 1 2 1 0 1 2 12 1", "8", "12", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensityCutoff, 0.60, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5 6 7 8 9", "0 1 2 1 0 1 2 12 1", "8", "12", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensityCutoff, 0.15, ThresholdFilter::Orientation_MostIntense }, // threshold against cumulative total intensity fraction, keeping the least intense peaks (ties are included) // intensities: 0 0 1 1 1 1 2 2 12 (TIC 20) // cumulative: 0 0 1 2 3 4 6 8 20 // fraction: 0 0 .05 .10 .15 .20 .30 .40 1.0 // at threshold 1.0 -----------------------------------^ cut here // at threshold .45 -----------------------------------^ cut here // at threshold .40 -------------------------------^ cut here // at threshold .35 -------------------------------^ cut here // at threshold .25 -------------------------------^ cut here // at threshold .20 -----------------------^ cut here // at threshold .01 -----------------------^ cut here { "1 2 3 4 5 6 7 8 9", "0 1 2 1 0 1 2 12 1", "1 2 3 4 5 6 7 8 9", "0 1 2 1 0 1 2 12 1", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensityCutoff, 1.0, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5 6 7 8 9", "0 1 2 1 0 1 2 12 1", "1 2 3 4 5 6 7 8 9", "0 1 2 1 0 1 2 12 1", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensityCutoff, 0.45, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5 6 7 8 9", "0 1 2 1 0 1 2 12 1", "1 2 3 4 5 6 7 9", "0 1 2 1 0 1 2 1", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensityCutoff, 0.40, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5 6 7 8 9", "0 1 2 1 0 1 2 12 1", "1 2 3 4 5 6 7 9", "0 1 2 1 0 1 2 1", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensityCutoff, 0.35, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5 6 7 8 9", "0 1 2 1 0 1 2 12 1", "1 2 3 4 5 6 7 9", "0 1 2 1 0 1 2 1", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensityCutoff, 0.25, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5 6 7 8 9", "0 1 2 1 0 1 2 12 1", "1 2 4 5 6 9", "0 1 1 0 1 1", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensityCutoff, 0.20, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5 6 7 8 9", "0 1 2 1 0 1 2 12 1", "1 2 4 5 6 9", "0 1 1 0 1 1", ThresholdFilter::ThresholdingBy_FractionOfTotalIntensityCutoff, 0.15, ThresholdFilter::Orientation_LeastIntense }, // keep the most intense points, excluding ties { "1 2 3 4 5", "10 20 30 20 10", "3", "30", ThresholdFilter::ThresholdingBy_Count, 1, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5", "10 20 30 20 10", "3", "30", ThresholdFilter::ThresholdingBy_Count, 2, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5", "10 20 30 20 10", "2 3 4", "20 30 20", ThresholdFilter::ThresholdingBy_Count, 3, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5", "10 20 30 20 10", "2 3 4", "20 30 20", ThresholdFilter::ThresholdingBy_Count, 4, ThresholdFilter::Orientation_MostIntense }, // keep the least intense points, excluding ties { "1 2 3 4 5", "10 20 30 20 10", "", "", ThresholdFilter::ThresholdingBy_Count, 1, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5", "10 20 30 20 10", "1 5", "10 10", ThresholdFilter::ThresholdingBy_Count, 2, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5", "10 20 30 20 10", "1 5", "10 10", ThresholdFilter::ThresholdingBy_Count, 3, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5", "10 20 30 20 10", "1 2 4 5", "10 20 20 10", ThresholdFilter::ThresholdingBy_Count, 4, ThresholdFilter::Orientation_LeastIntense }, // keep the most intense points, including ties { "1 2 3 4 5", "10 20 30 20 10", "3", "30", ThresholdFilter::ThresholdingBy_CountAfterTies, 1, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5", "10 20 30 20 10", "2 3 4", "20 30 20", ThresholdFilter::ThresholdingBy_CountAfterTies, 2, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5", "10 20 30 20 10", "2 3 4", "20 30 20", ThresholdFilter::ThresholdingBy_CountAfterTies, 3, ThresholdFilter::Orientation_MostIntense }, { "1 2 3 4 5", "10 20 30 20 10", "1 2 3 4 5", "10 20 30 20 10", ThresholdFilter::ThresholdingBy_CountAfterTies, 4, ThresholdFilter::Orientation_MostIntense }, // keep the least intense points, including ties { "1 2 3 4 5", "10 20 30 20 10", "1 5", "10 10", ThresholdFilter::ThresholdingBy_CountAfterTies, 1, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5", "10 20 30 20 10", "1 5", "10 10", ThresholdFilter::ThresholdingBy_CountAfterTies, 2, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5", "10 20 30 20 10", "1 2 4 5", "10 20 20 10", ThresholdFilter::ThresholdingBy_CountAfterTies, 3, ThresholdFilter::Orientation_LeastIntense }, { "1 2 3 4 5", "10 20 30 20 10", "1 2 4 5", "10 20 20 10", ThresholdFilter::ThresholdingBy_CountAfterTies, 4, ThresholdFilter::Orientation_LeastIntense } }; const size_t testThresholdersSize = sizeof(testThresholders) / sizeof(TestThresholder); void testIntensityThresholding() { // default msLevelsToThreshold should include all levels for (size_t i=0; i < testThresholdersSize; ++i) { SpectrumListSimple* sl = new SpectrumListSimple; SpectrumListPtr originalList(sl); SpectrumPtr s(new Spectrum); s->set(MS_ms_level, 2); sl->spectra.push_back(s); TestThresholder& t = testThresholders[i]; vector inputMZArray = parseDoubleArray(t.inputMZArray); vector inputIntensityArray = parseDoubleArray(t.inputIntensityArray); s->setMZIntensityArrays(inputMZArray, inputIntensityArray, MS_number_of_detector_counts); SpectrumDataFilterPtr pFilter = SpectrumDataFilterPtr(new ThresholdFilter(t.byType, t.threshold, t.orientation)); SpectrumListPtr thresholder(new SpectrumList_PeakFilter(originalList, pFilter)); vector outputMZArray = parseDoubleArray(t.outputMZArray); vector outputIntensityArray = parseDoubleArray(t.outputIntensityArray); SpectrumPtr thresholdedSpectrum = thresholder->spectrum(0, true); //if (os_) cout << s1->defaultArrayLength << ": " << s1->getMZArray()->data << " " << s1->getIntensityArray()->data << endl; unit_assert(thresholdedSpectrum->defaultArrayLength == outputMZArray.size()); for (size_t i=0; i < outputMZArray.size(); ++i) { unit_assert(thresholdedSpectrum->getMZArray()->data[i] == outputMZArray[i]); unit_assert(thresholdedSpectrum->getIntensityArray()->data[i] == outputIntensityArray[i]); } } // test that msLevelsToThreshold actually works for (size_t i=0; i < testThresholdersSize; ++i) { SpectrumListSimple* sl = new SpectrumListSimple; SpectrumListPtr originalList(sl); SpectrumPtr s(new Spectrum); s->set(MS_ms_level, 1); sl->spectra.push_back(s); TestThresholder& t = testThresholders[i]; vector inputMZArray = parseDoubleArray(t.inputMZArray); vector inputIntensityArray = parseDoubleArray(t.inputIntensityArray); s->setMZIntensityArrays(inputMZArray, inputIntensityArray, MS_number_of_detector_counts); SpectrumDataFilterPtr pFilter = SpectrumDataFilterPtr(new ThresholdFilter(t.byType, t.threshold, t.orientation, IntegerSet(2))); SpectrumListPtr thresholder(new SpectrumList_PeakFilter(originalList, pFilter)); SpectrumPtr unthresholdedSpectrum = thresholder->spectrum(0, true); //if (os_) cout << s1->defaultArrayLength << ": " << s1->getMZArray()->data << " " << s1->getIntensityArray()->data << endl; unit_assert(unthresholdedSpectrum->defaultArrayLength == inputMZArray.size()); for (size_t i=0; i < inputMZArray.size(); ++i) { unit_assert(unthresholdedSpectrum->getMZArray()->data[i] == inputMZArray[i]); unit_assert(unthresholdedSpectrum->getIntensityArray()->data[i] == inputIntensityArray[i]); } } } //////////////////////////////////////////////////////////////////////////// // Markey Deisotoper test //////////////////////////////////////////////////////////////////////////// struct TestDeisotoper { // space-delimited doubles const char* inputMZArray; const char* inputIntensityArray; const char* outputMZArray; const char* outputIntensityArray; MZTolerance tol; bool hires; }; TestDeisotoper TestDeisotopers[] = { // Markey method { "101 102 103 104 105", "10 20 30 20 10", "101 102 103", "10 20 30", 0.5, false }, }; const size_t testDeisotopersSize = sizeof(TestDeisotopers) / sizeof(TestDeisotoper); void testDeisotoping() { for (size_t i=0; i < testDeisotopersSize; ++i) { SpectrumListSimple* sl = new SpectrumListSimple; SpectrumListPtr originalList(sl); SpectrumPtr s(new Spectrum); sl->spectra.push_back(s); TestDeisotoper& t = TestDeisotopers[i]; vector inputMZArray = parseDoubleArray(t.inputMZArray); vector inputIntensityArray = parseDoubleArray(t.inputIntensityArray); s->setMZIntensityArrays(inputMZArray, inputIntensityArray, MS_number_of_detector_counts); s->set(MS_MSn_spectrum); s->set(MS_ms_level, 2); s->precursors.resize(1); s->precursors[0].activation.set(MS_electron_transfer_dissociation); s->precursors[0].selectedIons.resize(1); s->precursors[0].selectedIons[0].set(MS_selected_ion_m_z, PRECURSOR_MZ, MS_m_z); s->precursors[0].selectedIons[0].set(MS_charge_state, PRECURSOR_CHARGE); SpectrumDataFilterPtr pFilter = SpectrumDataFilterPtr(new MS2Deisotoper(MS2Deisotoper::Config(t.tol, t.hires))); SpectrumListPtr deisotopedList(new SpectrumList_PeakFilter(originalList, pFilter)); vector outputMZArray = parseDoubleArray(t.outputMZArray); vector outputIntensityArray = parseDoubleArray(t.outputIntensityArray); SpectrumPtr deisotopedSpectrum = deisotopedList->spectrum(0, true); unit_assert(deisotopedSpectrum->defaultArrayLength == outputMZArray.size()); for (size_t i=0; i < outputMZArray.size(); ++i) { unit_assert(deisotopedSpectrum->getMZArray()->data[i] == outputMZArray[i]); unit_assert(deisotopedSpectrum->getIntensityArray()->data[i] == outputIntensityArray[i]); } } } //////////////////////////////////////////////////////////////////////////// // Moving Window MS2 Denoise test //////////////////////////////////////////////////////////////////////////// struct TestMS2Denoise { // space-delimited doubles const char* inputMZArray; const char* inputIntensityArray; const char* outputMZArray; const char* outputIntensityArray; double precursorMass; int precursorCharge; double windowSize; int keepTopN; bool relaxLowMass; }; TestMS2Denoise TestMS2DenoiseArr[] = { { // basic test "101 102 103 104 105", "10 20 30 20 10", "102 103 104", "20 30 20", 500.0, 2, 10.0, 3, false }, { // verify removal of precursor and masses above parent mass minus glycine "101 102 103 104 105 500 945", "10 20 30 20 10 10 10", "102 103 104", "20 30 20", 500.0, 2, 10.0, 3, false }, }; const size_t testMS2DenoiseSize = sizeof(TestMS2DenoiseArr) / sizeof(TestMS2Denoise); void testMS2Denoising() { for (size_t i=0; i < testMS2DenoiseSize; ++i) { SpectrumListSimple* sl = new SpectrumListSimple; SpectrumListPtr originalList(sl); SpectrumPtr s(new Spectrum); sl->spectra.push_back(s); TestMS2Denoise& t = TestMS2DenoiseArr[i]; vector inputMZArray = parseDoubleArray(t.inputMZArray); vector inputIntensityArray = parseDoubleArray(t.inputIntensityArray); s->setMZIntensityArrays(inputMZArray, inputIntensityArray, MS_number_of_detector_counts); s->set(MS_MSn_spectrum); s->set(MS_ms_level, 2); s->precursors.resize(1); s->precursors[0].activation.set(MS_electron_transfer_dissociation); s->precursors[0].selectedIons.resize(1); s->precursors[0].selectedIons[0].set(MS_selected_ion_m_z, t.precursorMass, MS_m_z); s->precursors[0].selectedIons[0].set(MS_charge_state, t.precursorCharge); SpectrumDataFilterPtr pFilter = SpectrumDataFilterPtr(new MS2NoiseFilter(MS2NoiseFilter::Config(t.keepTopN, t.windowSize, t.relaxLowMass))); SpectrumListPtr filteredList(new SpectrumList_PeakFilter(originalList, pFilter)); vector outputMZArray = parseDoubleArray(t.outputMZArray); vector outputIntensityArray = parseDoubleArray(t.outputIntensityArray); SpectrumPtr filteredSpectrum = filteredList->spectrum(0, true); unit_assert(filteredSpectrum->defaultArrayLength == outputMZArray.size()); for (size_t i=0; i < outputMZArray.size(); ++i) { unit_assert(filteredSpectrum->getMZArray()->data[i] == outputMZArray[i]); unit_assert(filteredSpectrum->getIntensityArray()->data[i] == outputIntensityArray[i]); } } } void testZeroSamplesFilter() { const char* RawX = "300.000066203793 300.000611626572 300.001157051333 300.001702478078 300.058437690186 300.058983325233 300.059528962264 300.06007460128 300.06062024228 300.061165885264 300.061711530233 300.062257177186 300.062802826123 300.063348477046 300.063894129952 300.064439784843 300.064985441719 300.065531100579 300.066076761424 301.055887660805 301.056436929468 301.056986200136 301.057535472809 301.058084747485 301.058634024166 301.059183302851 301.059732583541 301.060281866235 301.060831150933 301.061380437635 301.061929726342 301.062479017053 301.063028309769 301.063577604489 311.869088211176 311.869677645283 311.870267081618 311.870856520182 311.871445960974 311.872035403993 311.872624849241 311.873214296717 311.873803746421 311.874393198353 311.874982652514 311.875572108902 311.876161567519 311.876751028364 311.877340491437 311.877929956739 311.878519424268 311.879108894026 311.879698366013 311.880287840227 311.88087731667 311.881466795341 311.882056276241 315.73174362051 315.732347745926 315.732951873654 315.733556003694 315.734160136047 315.734764270711 315.735368407687 315.735972546974 315.736576688574 315.737180832486 315.73778497871 315.738389127246 316.901416544052 316.902025153901 316.902633766087 316.90324238061 316.903850997471 316.90445961667 316.905068238207 316.905676862081 316.906285488293 316.906894116843 316.907502747731 316.908111380957 316.90872001652 316.909328654421 326.293591849569 326.294237069432 326.294882291847 326.295527516814 326.296172744332 326.296817974402 326.297463207024 326.298108442198 326.298753679923 326.299398920201 326.30004416303 327.074882186811 327.075530500256 327.076178816272 327.076827134858 327.077475456014 327.07812377974 327.078772106036 327.079420434903 327.080068766339 327.080717100346 327.081365436923 327.082013776071 327.082662117789 327.083310462077 327.083958808935 341.007109159311 341.007813880848 341.008518605298 341.00922333266 341.009928062936 341.010632796124 341.011337532225 341.012042271238 341.012747013165 " "341.013451758004 341.014156505757 341.014861256422 341.01556601 341.016270766491 341.016975525895 341.017680288212 341.018385053442 341.019089821585 341.019794592642 341.020499366611 341.021204143493 341.021908923288 341.022613705997 341.023318491618 341.024023280153 341.024728071601 342.01359244987 342.014301337525 342.015010228119 342.015719121651 342.016428018122 342.017136917532 342.01784581988 342.018554725167 342.019263633392 342.019972544557 342.02068145866 342.021390375702 342.022099295682 342.022808218602 342.02351714446 342.873501341248 342.874213798035 342.874926257782 342.87563872049 342.876351186159 342.877063654789 342.87777612638 342.878488600932 342.879201078445 342.879913558918 342.880626042353 342.881338528749 344.97306118134 344.9737823902 344.974503602076 344.975224816967 344.975946034874 344.976667255797 344.977388479735 344.978109706689 344.978830936658 344.979552169644 344.980273405644 344.980994644661 344.981715886693 355.063935356091 355.064699374529 355.065463396255 355.066227421269 355.066991449572 355.067755481162 355.06851951604 355.069283554207 355.070047595661 355.070811640404 355.071575688435 355.072339739754 355.073103794361 355.073867852257 355.074631913441 355.075395977913 355.076160045673 355.076924116722 355.077688191059 355.078452268685 356.064553240471 356.065321571195 356.066089905234 356.06685824259 356.067626583261 356.068394927249 356.069163274552 356.069931625172 356.070699979107 356.071468336359 356.072236696926 356.07300506081 356.073773428009 356.074541798525 356.075310172357 356.076078549505 356.076846929969 356.07761531375 356.078383700846 356.079152091259 356.079920484988 356.080688882034 357.062327559534 357.063100202372 357.063872848555 357.064645498081 357.065418150951 357.066190807165 357.066963466723 357.067736129625 357.068508795871 357.069281465461 357.070054138395 357.070826814673 357.071599494295 357.072372177261 357.073144863571 357.073917553225 357.074690246224 357.075462942566 357.076235642253 " "357.077008345284 357.077781051659 357.078553761379 357.079326474442 357.08009919085 359.023183355092 359.023964507385 359.024745663078 359.02552682217 359.026307984661 359.027089150551 359.027870319841 359.028651492531 359.029432668619 359.030213848107 359.030995030994 359.031776217281 359.032557406967 359.033338600053 359.034119796538 359.034900996422 359.035682199706 360.023491974674 360.024277485921 360.025063000597 360.0258485187 360.02663404023 360.027419565189 360.028205093575 360.028990625389 360.029776160632 360.030561699301 360.031347241399 360.032132786925 360.032918335879 360.03370388826 360.03448944407 361.021491400285 361.02228127251 361.023071148191 361.023861027329 361.024650909923 361.025440795974 361.026230685481 361.027020578444 361.027810474864 361.02860037474 361.029390278072 361.030180184861 361.030970095107 361.031760008809 371.095690561049 371.096525130684 371.097359704072 371.098194281215 371.099028862111 371.099863446762 371.100698035166 371.101532627324 371.102367223236 371.103201822902 371.104036426322 371.104871033497 371.105705644425 371.106540259107 371.107374877543 371.108209499734 371.109044125678 371.109878755377 371.11071338883 372.078066820464 372.078905814551 372.079744812421 372.080583814075 372.081422819513 372.082261828735 372.083100841741 372.08393985853 372.084778879103 372.08561790346 372.086456931601 372.087295963526 372.095686490895 372.096525564444 372.097364641778 372.098203722896 372.099042807799 372.099881896485 372.100720988956 372.101560085211 372.102399185251 372.103238289075 372.104077396683 372.104916508076 372.105755623254 372.106594742216 372.107433864962 372.108272991493 373.076623237254 373.077466740653 373.078310247866 373.079153758894 373.079997273735 373.080840792391 373.081684314862 373.082527841147 373.083371371246 373.084214905159 373.085058442887 373.08590198443 373.086745529787 373.101086384495 373.101929998517 373.102773616354 373.103617238007 373.104460863474 373.105304492756 373.106148125853 " "373.106991762765 373.107835403493 373.108679048035 373.109522696393 373.110366348566 373.111210004555 415.030543316388 415.031587197383 415.032631083628 415.033674975125 415.034718871873 415.035762773872 415.036806681123 415.037850593625 415.038894511378 415.039938434383 415.040982362639 415.042026296147 415.043070234906 415.044114178917 415.045158128179 415.046202082693 415.047246042459 416.004675140758 416.005723927765 416.006772720059 416.007821517642 416.008870320513 416.009919128672 416.01096794212 416.012016760856 416.01306558488 416.014114414193 416.015163248794 416.016212088684 416.030896402465 416.031945321688 416.032994246201 416.034043176002 416.035092111093 416.036141051473 416.037189997143 416.038238948102 416.03928790435 416.040336865888 416.041385832715 416.042434804832 416.043483782239 416.044532764935 416.04558175292 416.046630746196 416.047679744761 417.027651705639 417.028705657034 417.029759613757 417.030813575807 417.031867543184 417.032921515889 417.033975493922 417.035029477282 417.036083465969 417.037137459984 417.038191459327 417.039245463997 417.040299473995 417.041353489321 426.357976566382 426.359078206359 426.360179852029 426.361281503392 426.362383160449 426.363484823198 426.36458649164 426.365688165776 426.366789845604 426.367891531126 426.368993222341 428.935877697296 428.936992699323 428.938107707146 428.939222720767 428.940337740184 428.941452765398 428.94256779641 428.943682833218 428.944797875823 428.945912924226 428.947027978426 429.083108101101 429.0842238687 429.085339642101 429.086455421305 429.087571206312 429.088686997122 429.089802793735 429.090918596151 429.09203440437 429.093150218392 429.094266038217 429.095381863845 429.096497695277 429.097613532512 429.09872937555 429.099845224392 429.100961079037 429.102076939486 429.134439417209 429.135555451783 429.136671492162 429.137787538345 429.138903590334 429.140019648128 429.141135711726 429.14225178113 429.143367856339 429.144483937353 429.145600024173 429.146716116797 " "429.85101025753 429.852130022341 429.853249792985 429.854369569464 429.855489351777 429.856609139924 429.857728933905 429.858848733721 429.859968539371 429.861088350855 429.862208168173 429.863327991326 429.864447820313 429.865567655135 429.866687495792 429.867807342283 429.868927194608 429.870047052768 429.871166916764 429.872286786593 429.873406662258 429.874526543758 429.875646431092 429.876766324261 429.877886223266 430.081805059062 430.082926026641 430.084047000064 430.08516797933 430.086288964439 430.087409955392 430.088530952189 430.089651954829 430.090772963313 430.091893977641 430.093014997813 430.094136023828 430.095257055687 430.09637809339 430.097499136937 430.098620186328 430.099741241563 430.100862302643 430.101983369566 431.078404724764 431.079530893455 431.08065706803 431.081783248489 431.082909434832 431.08403562706 431.085161825172 431.086288029168 431.087414239049 431.088540454814 431.089666676463 431.090792903997 431.091919137416 431.093045376719 431.094171621907 431.09529787298 431.096424129938 431.09755039278 431.098676661507 431.099802936119 432.079633824813 432.080765230898 432.081896642908 432.083028060844 432.084159484704 432.085290914491 432.086422350202 432.087553791839 432.088685239402 432.08981669289 432.090948152304 432.092079617643 432.093211088908 444.61606065115 444.617258663358 444.618456682022 444.619654707142 444.620852738719 444.622050776751 444.62324882124 444.624446872186 444.625644929587 444.626842993445 444.62804106376 444.629239140531 444.630437223759 445.111389571898 445.112590254911 445.113790944402 445.114991640371 445.116192342817 445.117393051741 445.118593767143 445.119794489023 445.120995217382 445.122195952218 445.123396693532 445.124597441324 445.125798195595 445.126998956343 445.128199723571 445.129400497276 445.13060127746 446.092099627601 446.093305607359 446.094511593638 446.095717586437 446.096923585757 446.098129591598 446.099335603959 446.100541622841 446.101747648245 446.102953680169 446.104159718614 " "446.10536576358 446.106571815068 446.107777873076 446.108983937606 446.110190008657 446.111396086229 446.112602170323 446.113808260938 446.115014358075 446.116220461733 446.117426571913 446.118632688614 446.119838811837 446.121044941582 446.122251077849 446.123457220638 446.124663369948 446.12586952578 446.127075688135 446.128281857011 446.12948803241 446.130694214331 446.131900402774 446.133106597739 447.092888369096 447.09409976606 447.095311169589 447.096522579682 447.09773399634 447.098945419563 447.100156849351 447.101368285703 447.10257972862 447.103791178103 447.10500263415 447.106214096762 447.10742556594 447.108637041682 447.10984852399 447.111060012863 447.112271508302 447.113483010306 447.114694518875 447.115906034009 447.11711755571 447.118329083975 447.119540618807 447.120752160204 447.121963708167 447.123175262696 447.12438682379 447.125598391451 447.126809965677 447.128021546469 447.129233133828 447.130444727752 447.131656328243 449.794778250235 449.796004332987 449.797230422424 449.798456518544 449.799682621349 449.800908730839 449.802134847013 449.803360969872 449.804587099415 449.805813235643 449.807039378556 449.808265528153 476.291926493584 476.293301287096 476.294676088545 476.296050897931 476.297425715253 476.298800540512 476.300175373707 476.30155021484 476.30292506391 476.304299920917 476.305674785861 476.307049658742 487.815419569054 487.81686169142 487.818303822312 487.819745961732 487.821188109678 487.822630266151 487.824072431152 487.825514604679 487.826956786733 487.828398977315 487.829841176424 489.047206755368 489.048656169973 489.050105593169 489.051555024957 489.053004465336 489.054453914307 489.05590337187 489.057352838025 489.058802312771 489.06025179611 489.06170128804 489.063150788563 489.064600297678 489.066049815385 489.067499341685 494.497639238354 494.499121140501 494.500603051529 494.50208497144 494.503566900233 494.505048837908 494.506530784465 494.508012739904 494.509494704226 494.510976677431 494.512458659517 " "503.097384350016 503.098918243574 503.100452146485 503.10198605875 503.103519980368 503.10505391134 503.106587851665 503.108121801345 503.109655760378 503.111189728765 503.112723706507 503.114257693603 503.115791690052 503.117325695857 503.118859711015 503.120393735528 503.121927769396 503.123461812619 503.124995865196 504.057895208494 504.059434964655 504.060974730222 504.062514505197 504.064054289579 504.065594083369 504.067133886566 504.06867369917 504.070213521182 504.071753352602 504.073293193429 504.097931926196 504.099471926969 504.101011937151 504.102551956742 504.104091985743 504.105632024154 504.107172071974 504.108712129204 504.110252195844 504.111792271893 504.113332357353 504.114872452223 504.116412556503 504.117952670193 504.119492793294 504.121032925805 504.122573067726 504.124113219059 504.136434768509 504.137975004541 504.139515249984 504.141055504838 504.142595769105 504.144136042783 504.145676325873 504.147216618374 504.148756920288 504.150297231614 504.151837552352 504.153377882502 505.094736580555 505.096282677762 505.097828784435 505.099374900573 505.100921026176 505.102467161245 505.104013305779 505.105559459779 505.107105623245 505.108651796177 505.110197978574 505.111744170438 505.113290371768 505.114836582564 505.116382802826 505.117929032555 505.11947527175 505.121021520412 505.12256777854 506.095491214212 506.097043444127 506.098595683563 506.100147932522 506.101700191001 506.103252459003 506.104804736527 506.106357023573 506.107909320141 506.109461626231 506.111013941844 506.112566266978 506.114118601636 517.627784100423 517.62940787711 517.631031663984 517.632655461045 517.634279268294 517.635903085731 517.637526913356 517.639150751169 517.64077459917 517.642398457359 517.644022325736 519.117811946194 519.11944508466 519.121078233402 519.122711392419 519.124344561713 519.125977741282 519.127610931128 519.129244131249 519.130877341647 519.132510562322 519.134143793272 519.1357770345 519.137410286004 519.139043547785 519.140676819843 " "519.142310102177 519.143943394789 519.145576697678 519.147210010844 519.148843334287 519.150476668008 519.152110012007 519.153743366283 520.107741759837 520.109381132867 520.111020516231 520.11265990993 520.114299313963 520.115938728332 520.117578153035 520.119217588074 520.120857033448 520.122496489157 520.124135955201 520.125775431581 520.130693922735 520.132333440458 520.133972968517 520.135612506911 520.137252055643 520.13889161471 520.140531184113 520.142170763854 520.14381035393 520.145449954343 520.147089565093 520.14872918618 520.150368817604 520.152008459365 520.153648111463 520.155287773898 521.127785814089 521.129431623767 521.131077443839 521.132723274308 521.134369115172 521.136014966432 521.137660828088 521.13930670014 521.140952582588 521.142598475432 521.144244378673 521.14589029231 521.147536216343 531.114696350534 531.11640584546 531.118115351391 531.119824868327 531.121534396267 531.123243935212 531.124953485163 531.126663046119 531.12837261808 531.130082201046 531.131791795019 531.179664894929 531.181374808109 531.183084732298 531.184794667495 531.186504613701 531.188214570917 531.189924539141 531.191634518375 531.193344508618 531.195054509871 531.196764522133 531.198474545405 539.793121824335 539.79488764215 539.796653471517 539.798419312438 539.800185164913 539.80195102894 539.803716904521 539.805482791656 539.807248690344 539.809014600586 539.810780522383 544.657227988968 544.659025773986 544.660823570872 544.662621379626 544.664419200249 544.66621703274 544.6680148771 544.669812733329 544.671610601426 544.673408481392 544.675206373228 544.677004276933 544.678802192507 544.68060011995 544.682398059264 544.684196010447 544.685993973499 544.687791948422 544.689589935214 544.691387933877 564.063114662872 564.065042838848 564.066971028006 564.068899230347 564.07082744587 564.072755674577 564.074683916467 564.076612171539 564.078540439795 564.080468721235 564.082397015858 564.084325323664 564.086253644655 577.113045862246 577.115064289413 " "577.1170827307 577.119101186105 577.12111965563 577.123138139273 577.125156637036 577.127175148919 577.129193674921 577.131212215043 577.133230769285 577.135249337647 577.137267920129 577.139286516732 577.141305127455 577.143323752299 578.095668254573 578.09769356096 578.099718881538 578.101744216308 578.103769565269 578.105794928421 578.107820305765 578.1098456973 578.111871103028 578.113896522947 578.115921957059 578.117947405363 578.119972867859 578.121998344549 578.124023835431 578.126049340506 578.128074859774 578.130100393235 578.13212594089 578.134151502738 578.13617707878 578.138202669016 578.140228273445 578.142253892069 578.144279524888 578.1463051719 579.112127291178 579.114159725986 579.116192175059 579.118224638399 579.120257116005 579.122289607877 579.124322114016 579.126354634422 579.128387169095 579.130419718034 579.132452281241 579.134484858716 579.136517450457 579.138550056467 579.140582676744 579.142615311289 593.146836106552 593.148968246848 593.151100402472 593.153232573424 593.155364759706 593.157496961317 593.159629178256 593.161761410526 593.163893658125 593.166025921053 593.168158199311 593.1702904929 593.172422801818 593.174555126067 594.334675871054 594.336816559592 594.338957263551 594.341097982931 594.343238717732 594.345379467954 594.347520233598 594.349661014664 594.351801811151 594.35394262306 594.356083450392 594.358224293146 602.991717202929 602.993920708033 602.996124229242 602.998327766555 603.000531319973 603.002734889497 603.004938475125 603.007142076859 603.009345694699 603.011549328644 603.013752978696 603.015956644853 603.018160327117 603.020364025487 603.022567739964 603.024771470548 603.026975217238 647.653798614949 647.656340625328 647.65888265566 647.661424705948 647.66396677619 647.666508866388 647.669050976542 647.671593106651 647.674135256716 647.676677426738 647.679219616716 647.681761826651 647.684304056543 647.686846306392 647.689388576198 647.691930865962 647.694473175684 647.697015505364 647.699557855003 " "651.129472007141 651.132041374488 651.134610762114 651.137180170017 651.139749598198 651.142319046658 651.144888515396 651.147458004413 651.150027513709 651.152597043284 651.155166593139 651.157736163274 651.160305753689 651.162875364383 651.165444995359 651.168014646615 652.130488515969 652.133065789459 652.135643083321 652.138220397554 652.140797732159 652.143375087136 652.145952462485 652.148529858207 652.151107274301 652.153684710768 652.156262167609 652.158839644823 652.16141714241 652.163994660372 652.166572198708 652.169149757418 652.594726156514 652.597307100729 652.599888065358 652.602469050403 652.605050055862 652.607631081738 652.610212128029 652.612793194736 652.615374281859 652.617955389399 652.620536517356 653.126832071549 653.129417226335 653.132002401586 653.134587597302 653.137172813482 653.139758050129 653.142343307241 653.14492858482 653.147513882864 653.150099201375 653.152684540353 653.155269899798 653.157855279709 653.160440680089 653.163026100936 660.922514101737 660.925161337446 660.927808594361 660.930455872483 660.933103171812 660.935750492348 660.938397834091 660.941045197042 660.943692581201 660.946339986568 660.948987413144 660.951634860928 660.954282329921 660.983405888706 660.986053612226 660.988701356959 660.991349122903 660.993996910061 660.996644718431 660.999292548015 661.001940398812 661.004588270823 661.007236164048 661.009884078488 661.012532014142 664.411346114577 664.414021372197 664.41669665136 664.419371952069 664.422047274321 664.424722618119 664.427397983461 664.430073370349 664.432748778782 664.435424208761 664.438099660286 664.440775133357 664.443450627975 664.44612614414 664.448801681852 664.451477241112 664.454152821919 664.456828424273 664.459504048176 664.462179693628 664.464855360628 667.159443330433 667.162140764336 667.164838220052 667.16753569758 667.170233196922 667.172930718076 667.175628261044 667.178325825826 667.181023412421 667.183721020831 667.186418651055 667.189116303095 667.191813976949 " "667.194511672619 667.197209390104 667.199907129405 668.145457833561 668.148163246605 668.150868681559 668.153574138422 668.156279617196 668.158985117879 668.161690640472 668.164396184977 668.167101751392 668.169807339718 668.172512949956 668.175218582105 668.177924236166 668.180629912139 668.183335610025 668.186041329824 668.188747071536 668.19145283516 668.194158620699 668.196864428151 668.199570257517 670.158915513485 670.161637256666 670.164359021956 670.167080809353 670.16980261886 670.172524450475 670.175246304198 670.177968180032 670.180690077974 670.183411998027 670.186133940189 670.188855904462 670.191577890846 677.272020770102 677.274800597507 677.277580447732 677.280360320776 677.283140216641 677.285920135325 677.28870007683 677.291480041156 677.294260028303 677.297040038272 677.299820071062 677.302600126674 677.305380205108 677.308160306364 677.310940430444 677.313720577346 677.316500747072 677.319280939622 677.322061154995 677.324841393193 677.327621654214 677.330401938061 677.333182244733 677.33596257423 684.185792158615 684.188629030244 684.191465925398 684.194302844078 684.197139786283 684.199976752015 684.202813741274 684.205650754059 684.208487790372 684.211324850212 684.21416193358 684.216999040475 684.2198361709 684.222673324852 684.225510502334 685.302497766186 685.305343905889 685.308190069232 685.311036256217 685.313882466843 685.316728701111 685.319574959021 685.322421240572 685.325267545767 685.328113874604 685.330960227085 685.333806603209 685.336653002977 685.339499426388 685.345192344145 685.34803883849 685.350885356481 685.353731898117 685.356578463399 685.359425052328 685.362271664902 685.365118301123 685.367964960991 685.370811644507 685.37365835167 685.376505082481 686.165961086862 686.168814403222 686.171667743312 686.174521107133 686.177374494685 686.180227905968 686.183081340982 686.185934799728 686.188788282207 686.191641788417 686.19449531836 686.197348872036 699.464091765658 699.467056750447 699.470021760373 699.472986795436 " "699.475951855637 699.478916940975 699.481882051452 699.484847187067 699.487812347821 699.490777533714 699.493742744746 699.496707980919 699.499673242231 699.502638528684 699.505603840277 699.508569177012 699.511534538887 699.514499925905 707.540962759248 707.54399661424 707.54703049525 707.550064402278 707.553098335324 707.556132294389 707.559166279473 707.562200290576 707.565234327699 707.568268390842 707.571302480006 707.574336595191 707.577370736396 707.580404903623 707.583439096872 707.586473316143 707.589507561437 707.592541832753 707.595576130092 712.253358999635 712.256433401729 712.259507830364 712.26258228554 712.265656767258 712.268731275519 712.271805810321 712.274880371667 712.277954959555 712.281029573987 712.284104214963 714.637817537752 714.640912559113 714.644007607282 714.647102682261 714.650197784048 714.653292912646 714.656388068053 714.65948325027 714.662578459298 714.665673695137 714.668768957787 714.671864247249 725.142802571441 725.145989253758 725.149175964084 725.152362702418 725.155549468761 725.158736263113 725.161923085476 725.165109935848 725.168296814231 725.171483720624 725.174670655029 725.177857617445 725.181044607873 725.184231626314 725.187418672767 725.190605747233 725.193792849713 725.196979980206 726.144799061961 726.147994557046 726.151190080255 726.15438563159 726.15758121105 726.160776818635 726.163972454346 726.167168118184 726.170363810149 726.17355953024 726.176755278459 726.179951054806 726.183146859281 726.186342691885 726.189538552617 727.133547186777 727.136751390037 727.139955621536 727.143159881275 727.146364169255 727.149568485475 727.152772829936 727.155977202638 727.159181603583 727.162386032769 727.165590490198 727.16879497587 727.171999489785 727.175204031944 727.178408602347 727.181613200995 727.184817827887 727.188022483024 728.144269729676 728.147482846893 728.150695992466 728.153909166398 728.157122368687 728.160335599336 728.163548858343 728.16676214571 728.169975461436 728.173188805523 728.17640217797 " "728.179615578778 728.182829007947 728.623337067404 728.626554414027 728.629771789064 728.632989192515 728.63620662438 728.639424084659 728.642641573354 728.645859090464 728.64907663599 728.652294209931 728.65551181229 728.658729443065 739.579801260267 739.583116094462 739.586430958371 739.589745851995 739.593060775335 739.596375728391 739.599690711162 739.603005723651 739.606320765856 739.609635837779 739.61295093942 741.174345003278 741.177674146565 741.18100331976 741.184332522862 741.187661755872 741.190991018791 741.194320311618 741.197649634355 741.200978987002 741.204308369558 741.207637782025 741.210967224403 741.214296696693 741.217626198894 741.220955731007 741.224285293032 742.067626706004 742.070963878878 742.074301081766 742.077638314671 742.080975577592 742.08431287053 742.087650193485 742.090987546457 742.094324929448 742.097662342457 742.100999785484 742.104337258531 742.107674761597 742.111012294683 742.11434985779 742.117687450917 742.121025074066 742.124362727236 742.127700410428 742.131038123643 742.13437586688 742.137713640141 742.141051443425 742.174431127655 742.177769261226 742.181107424826 742.184445618454 742.187783842111 742.191122095798 742.194460379515 742.197798693263 742.201137037042 742.204475410852 742.207813814694 742.211152248568 742.214490712474 742.217829206413 742.221167730386 742.224506284392 742.227844868433 743.1470966977 743.150443586686 743.153790505819 743.157137455098 743.160484434525 743.1638314441 743.167178483823 743.170525553695 743.173872653716 743.177219783887 743.180566944208 743.183914134679 743.187261355301 743.190608606074 743.193955886998 743.197303198075 743.200650539304 743.203997910686 743.20734531222 743.210692743909 743.214040205752 743.217387697749 743.220735219901 743.224082772208 743.227430354671 743.23077796729 744.176009584717 744.179365747906 744.182721941368 744.186078165103 744.18943441911 744.192790703391 744.196147017945 744.199503362773 744.202859737876 744.206216143254 744.209572578908 " "744.212929044837 744.216285541042 744.219642067524 744.222998624283 758.202410978174 758.205894849435 758.209378752713 758.212862688007 758.216346655318 758.219830654647 758.223314685994 758.226798749359 758.230282844744 758.233766972148 758.237251131571 758.240735323015 758.24421954648 758.247703801965 758.251188089473 758.254672409002 759.203597733713 759.207090811794 759.210583922019 759.214077064387 759.2175702389 759.221063445557 759.22455668436 759.228049955308 759.231543258401 759.235036593642 759.238529961029 759.242023360563 759.245516792245 759.249010256075 760.200427521877 760.203929778783 760.207432067959 760.210934389405 760.214436743123 760.217939129111 760.221441547372 760.224943997905 760.228446480711 760.231948995789 760.235451543142 760.238954122768 760.24245673467 760.316019040799 760.319522362853 760.323025717192 760.326529103815 760.330032522725 760.33353597392 760.337039457402 760.340542973171 760.344046521228 760.347550101572 760.351053714205 760.354557359126 760.358061036338 760.361564745838 777.189954415057 777.193614963706 777.197275546837 777.200936164451 777.204596816548 777.208257503129 777.211918224194 777.215578979744 777.219239769779 777.2229005943 777.226561453308 777.230222346802 777.233883274784 777.237544237253 799.160490663856 799.164361099883 799.1682315734 799.172102084408 799.175972632907 799.179843218898 799.183713842382 799.187584503358 799.191455201828 799.195325937792 799.19919671125 799.203067522204 799.206938370653 799.210809256599 799.214680180041 799.21855114098 800.16418774129 800.168067905512 800.171948107365 800.175828346849 800.179708623967 800.183588938718 800.187469291103 800.191349681123 800.195230108777 800.199110574067 800.202991076993 800.206871617555 800.210752195754 801.158739593593 801.162629409414 801.166519263006 801.170409154372 801.174299083511 801.178189050424 801.182079055111 801.185969097572 801.18985917781 801.193749295823 801.197639451613 801.20152964518 801.205419876525 801.209310145647 " "801.213200452549 810.055165196855 810.059141881054 810.063118604297 810.067095366586 810.07107216792 810.0750490083 810.079025887728 810.083002806202 810.086979763725 810.090956760296 810.094933795916 810.098910870585 810.102887984305 810.106865137076 815.189564537267 815.19359179245 815.197619087424 815.20164642219 815.205673796749 815.209701211101 815.213728665248 815.217756159189 815.221783692925 815.225811266457 815.229838879786 815.233866532911 815.237894225833 815.241921958555 815.245949731074 815.249977543393 815.395005298192 815.3990345835 815.40306390863 815.407093273582 815.411122678358 815.415152122956 815.419181607379 815.423211131626 815.427240695699 815.431270299597 815.435299943322 815.439329626874 816.169358934812 816.17339587673 816.177432858584 816.181469880374 816.1855069421 816.189544043764 816.193581185365 816.197618366904 816.201655588382 816.2056928498 816.209730151157 816.213767492455 816.217804873695 816.221842294876 816.225879756 816.229917257066 816.233954798077 816.237992379031 816.24202999993 816.246067660775 816.250105361565 816.254143102302 817.183885871236 817.187932855536 817.19197987992 817.196026944389 817.200074048944 817.204121193585 817.208168378313 817.212215603128 817.216262868032 817.220310173024 817.224357518104 817.228404903275 817.232452328536 817.236499793888 817.240547299332 817.244594844868 817.248642430496 817.252690056218 818.164426363991 818.16848306611 818.172539808458 818.176596591035 818.180653413842 818.18471027688 818.18876718015 818.192824123651 818.196881107384 818.200938131351 818.204995195551 818.209052299986 818.213109444656 818.21716662956 818.221223854701 818.225281120079 818.229338425694 818.233395771546 818.237453157638 818.241510583968 818.245568050537 818.249625557347 819.18392233678 819.18798915515 819.1920560139 819.19612291303 819.200189852541 819.204256832432 819.208323852706 819.212390913362 819.216458014401 819.220525155824 819.224592337631 819.228659559823 819.2327268224 819.236794125363 " "819.240861468713 819.24492885245 820.193731546341 820.197808397262 820.201885288712 820.205962220691 820.210039193201 820.214116206241 820.218193259813 820.222270353916 820.226347488553 820.230424663722 820.234501879425 820.238579135663 832.21883436359 832.223031634984 832.227228948716 832.231426304787 832.235623703196 832.239821143946 832.244018627035 832.248216152466 832.252413720239 832.256611330353 832.260808982811 832.265006677613 832.269204414758 832.273402194249 832.277600016085 832.281797880267 832.285995786796 832.290193735673 832.294391726897 832.298589760471 833.218980432568 833.223187798465 833.227395206852 833.231602657731 833.235810151102 833.240017686965 833.244225265321 833.248432886172 833.252640549516 833.256848255356 833.261056003692 833.265263794525 833.269471627854 833.273679503681 834.221533310184 834.225750807043 834.229968346546 834.234185928695 834.238403553488 834.242621220928 834.246838931015 834.251056683749 834.255274479132 834.259492317163 834.263710197844 834.267928121174 835.218046494203 835.222274073065 835.226501694725 835.230729359182 835.234957066438 835.239184816494 835.243412609349 835.247640445004 835.251868323461 835.256096244719 835.26032420878 835.264552215644 835.268780265312 835.273008357784 835.277236493061 873.174235302306 873.178855854748 873.18347645609 873.188097106335 873.192717805482 873.197338553533 873.201959350488 873.206580196348 873.211201091114 873.215822034786 873.220443027366 873.225064068854 873.229685159251 873.234306298558 873.238927486775 874.17804253512 874.182673717335 874.18730494862 874.191936228976 874.196567558404 874.201198936904 874.205830364477 874.210461841124 874.215093366845 874.219724941642 874.224356565516 874.228988238466 874.233619960494 874.238251731601 874.303101680785 874.307734188164 874.312366744634 874.316999350196 874.321632004851 874.3262647086 874.330897461442 874.335530263379 874.340163114412 874.344796014542 874.349428963769 874.354061962094 875.174876842222 875.179518592457 " "875.184160391931 875.188802240643 875.193444138596 875.198086085788 875.202728082222 875.207370127898 875.212012222817 875.216654366978 875.221296560385 875.225938803036 875.230581094934 889.200602342844 889.205394064883 889.210185838565 889.214977663891 889.219769540862 889.224561469479 889.229353449744 889.234145481656 889.238937565216 889.243729700426 889.248521887286 889.253314125797 889.25810641596 889.262898757776 889.267691151245 889.272483596368 889.277276093147 889.282068641582 889.286861241673 889.291653893423 889.296446596831 889.301239351898 889.306032158626 889.310825017014 889.315617927065 889.320410888778 889.325203902155 889.329996967196 889.334790083902 890.02073813417 890.0255386994 890.030339316416 890.03513998522 890.039940705812 890.044741478193 890.049542302364 890.054343178326 890.059144106079 890.063945085625 890.068746116964 890.073547200097 890.078348335025 890.083149521749 890.174381911812 890.179184134627 890.183986409256 890.188788735699 890.193591113957 890.198393544031 890.203196025921 890.207998559629 890.212801145155 890.217603782501 890.222406471667 890.227209212653 890.232012005462 890.236814850093 890.241617746547 890.246420694826 890.25122369493 890.25602674686 890.260829850616 890.2656330062 890.270436213613 890.275239472855 890.280042783927 891.198426546905 891.203239824931 891.208053154948 891.212866536959 891.217679970964 891.222493456964 891.22730699496 891.232120584952 891.236934226942 891.24174792093 891.246561666917 891.251375464905 891.256189314893 891.261003216882 891.265817170875 891.27063117687 891.27544523487 891.280259344875 892.200708915166 892.205533025772 892.210357188546 892.21518140349 892.220005670603 892.224829989886 892.229654361341 892.234478784968 892.239303260768 892.244127788742 892.248952368891 892.253777001215 892.258601685716 892.263426422395 892.268251211251 892.273076052286 893.142398272161 893.147232571559 893.15206692329 893.156901327355 893.161735783755 893.166570292491 893.171404853563 " "893.176239466974 893.181074132723 893.185908850811 893.190743621239 893.20041331912 893.205248246574 893.210083226371 893.214918258513 893.219753343 893.224588479834 893.229423669014 893.234258910542 893.239094204419 893.243929550645 893.248764949222 893.25360040015 893.25843590343 893.263271459063 893.26810706705 893.272942727391 894.197514830975 894.202360559179 894.207206339903 894.212052173146 894.21689805891 894.221743997196 894.226589988005 894.231436031336 894.236282127192 894.241128275573 894.24597447648 894.250820729913 894.255667035874 894.260513394364 894.265359805383 894.270206268932 906.234202718878 906.239179781027 906.244156897845 906.249134069332 906.25411129549 906.259088576319 906.26406591182 906.269043301994 906.274020746843 906.278998246366 906.283975800565 906.288953409441 906.293931072995 906.298908791226 907.235692252254 907.240680320926 907.245668444448 907.250656622821 907.255644856045 907.260633144123 907.265621487054 907.270609884839 907.27559833748 907.280586844978 907.285575407332 907.290564024546 907.295552696618 907.30054142355 908.234398692328 908.239397749042 908.244396860787 908.249396027565 908.254395249375 908.25939452622 908.2643938581 908.269393245016 908.274392686968 908.279392183959 908.284391735988 908.289391343056 922.842856257044 922.84801742175 922.853178644185 922.858339924351 922.86350126225 922.86866265788 922.873824111245 922.878985622344 922.884147191179 922.88930881775 922.894470502059 934.042623867136 934.0479110658 934.053198324322 934.058485642702 934.063773020941 934.069060459041 934.074347957002 934.079635514825 934.084923132512 934.090210810063 934.09549854748 934.100786344763 934.106074201913 934.111362118932 962.94815872668 962.953778232548 962.959397804004 962.96501744105 962.970637143686 962.976256911914 962.981876745735 962.987496645149 962.993116610159 962.998736640765 963.004356736968 963.00997689877 963.217969011729 963.223591667127 963.229214388169 963.234837174856 963.240460027188 963.246082945167 " "963.251705928794 963.257328978069 963.262952092996 963.268575273574 963.274198519804 963.279821831688 963.285445209227 963.291068652422 963.296692161274 963.302315735784 963.307939375954 963.313563081784 963.319186853277 963.324810690432 963.420425969611 963.426050988895 963.431676073865 963.43730122452 963.442926440862 963.448551722892 963.454177070612 963.459802484022 963.465427963124 963.471053507919 963.476679118408 963.482304794592 964.21420252401 964.219836816216 964.225471174269 964.23110559817 964.236740087921 964.242374643523 964.248009264976 964.253643952283 964.259278705443 964.26491352446 964.270548409332 964.276183360063 964.281818376652 964.287453459101 964.293088607411 964.298723821583 964.304359101619 964.309994447519 964.315629859286 964.321265336919 964.32690088042 964.33253648979 964.338172165031 964.343807906143 964.349443713128 964.355079585987 964.36071552472 964.36635152933 964.467810878442 964.473448134917 964.479085457292 964.484722845568 964.490360299745 964.495997819824 964.501635405808 964.507273057696 964.512910775491 964.518548559193 964.524186408804 964.529824324324 965.201207199106 965.206853032182 965.212498931307 965.218144896483 965.223790927711 965.229437024992 965.235083188328 965.240729417718 965.246375713166 965.252022074672 965.257668502236 965.26331499586 965.268961555546 965.274608181294 965.280254873106 965.285901630983 965.291548454925 965.297195344935 965.302842301012 965.308489323159 965.314136411377 965.319783565667 965.325430786029 965.331078072465 966.212864647697 966.218522322157 966.224180062874 966.22983786985 966.235495743085 966.241153682582 966.246811688342 966.252469760364 966.258127898651 966.263786103204 966.269444374024 966.275102711111 966.280761114469 966.286419584096 966.292078119995 966.297736722167 966.303395390612 966.309054125333 966.31471292633 966.320371793604 966.326030727157 967.215306113877 967.220975534084 967.226645020755 967.232314573891 967.237984193494 967.243653879564 967.249323632103 " "967.254993451112 967.260663336592 967.266333288544 967.272003306969 967.277673391869 967.283343543245 967.289013761098 967.294684045428 967.300354396238 967.306024813528 967.3116952973 967.317365847555 967.323036464293 967.328707147517 967.334377897227 967.340048713424 967.345719596109 967.351390545285 980.194309595126 980.200132191883 980.205954857816 980.211777592926 980.217600397214 980.223423270681 980.229246213329 980.235069225159 980.240892306172 980.24671545637 980.252538675753 980.258361964323 980.264185322081 980.270008749028 980.275832245166 980.281655810496 980.287479445018 980.293303148735 980.299126921648 980.304950763757 980.310774675063 980.31659865557 980.322422705276 989.849128120579 989.855065986618 989.861003923897 989.866941932417 989.872880012179 989.878818163186 989.884756385438 989.890694678936 989.896633043682 989.902571479677 989.908509986923 989.91444856542 1024.22504311064 1024.23140056509 1024.23775809846 1024.24411571076 1024.25047340198 1024.25683117213 1024.26318902121 1024.26954694921 1024.27590495616 1024.28226304203 1024.28862120684 1024.29497945058 1024.30133777326 1024.30769617489 1024.31405465545 1024.32041321495 1024.3267718534 1024.3331305708 1024.33948936714 1024.62571693597 1024.63207936544 1024.63844187393 1024.64480446143 1024.65116712796 1024.6575298735 1024.66389269807 1024.67025560165 1024.67661858427 1024.6829816459 1024.68934478657 1024.69570800627 1024.80389483394 1024.8102594764 1024.81662419793 1024.82298899851 1024.82935387816 1024.83571883686 1024.84208387463 1024.84844899146 1024.85481418736 1024.86117946232 1024.86754481635 1024.87391024946 1024.88027576163 1024.88664135288 1037.17792520177 1037.18444447285 1037.19096382588 1037.19748326088 1037.20400277783 1037.21052237674 1037.21704205761 1037.22356182045 1037.23008166525 1037.23660159202 1037.24312160075 1037.24964169146 1037.25616186413 1037.26268211878 1037.2692024554 1037.275722874 1037.28224337457 1037.28876395712 1037.29528462166 1037.30180536817 " "1037.30832619667 1037.31484710715 1037.32136809962 1037.32788917408 1038.22205208364 1038.22858448726 1038.2351169731 1038.24164954113 1038.24818219137 1038.25471492382 1038.26124773848 1038.26778063535 1038.27431361443 1038.28084667573 1038.28737981924 1038.29391304497 1038.30044635292 1038.30697974309 1038.31351321548 1038.32004677009 1038.32658040693 1039.22901160479 1039.235556686 1039.24210184966 1039.24864709577 1039.25519242432 1039.26173783531 1039.26828332876 1039.27482890466 1039.28137456301 1039.28792030381 1039.29446612706 1039.30101203278 1039.30755802095 1039.31410409158 1039.32065024467 1039.32719648023 1039.33374279825 1039.34028919873 1039.34683568169 1040.22481095549 1040.23136858588 1040.23792629894 1040.24448409469 1040.25104197312 1040.25759993424 1040.26415797804 1040.27071610453 1040.27727431371 1040.28383260558 1040.29039098014 1040.2969494374 1040.30350797735 1040.3100666 1040.31662530535 1040.32318409339 1040.32974296414 1041.2290907215 1041.2356610201 1041.24223140163 1041.24880186607 1041.25537241343 1041.26194304372 1041.26851375694 1041.27508455308 1041.28165543215 1041.28822639415 1041.29479743909 1041.30136856695 1041.30793977776 1041.3145110715 1041.32108244817 1041.32765390779 1041.33422545035 1041.34079707585 1041.3473687843 1041.35394057569 1041.36051245003 1041.36708440732 1041.37365644756 1041.38022857076 1041.3868007769 1041.39337306601 1041.39994543807 1041.40651789309 1041.41309043107 1041.41966305201 1088.79279195134 1088.79997622919 1088.80716060185 1088.81434506932 1088.82152963161 1088.82871428871 1088.83589904063 1088.84308388737 1088.85026882893 1088.85745386531 1088.86463899652 1098.12539546821 1098.13270343459 1098.14001149825 1098.14731965918 1098.15462791738 1098.16193627285 1098.1692447256 1098.17655327563 1098.18386192294 1098.19117066753 1098.19847950941 1098.20578844857 1098.21309748502 1098.22040661877 1098.2277158498 1098.23502517813 1098.24233460375 1098.24964412667 1098.2569537469 1098.26426346442 " "1098.27157327925 1111.23703980607 1111.2445233295 1111.25200695373 1111.25949067876 1111.26697450458 1111.27445843121 1111.28194245863 1111.28942658687 1111.29691081591 1111.30439514576 1111.31187957642 1111.31936410789 1111.32684874018 1111.33433347329 1111.34181830722 1111.34930324196 1112.25572512581 1112.26322237607 1112.27071972739 1112.27821717979 1112.28571473327 1112.29321238783 1112.30071014346 1112.30820800018 1112.31570595798 1112.32320401687 1112.33070217685 1112.33820043792 1112.34569880008 1112.41318860905 1112.42068798226 1112.42818745657 1112.43568703201 1112.44318670856 1112.45068648624 1112.45818636504 1112.46568634496 1112.47318642601 1112.48068660819 1112.48818689151 1112.49568727595 1112.50318776154 1112.57819818028 1112.58569977849 1112.59320147786 1112.60070327839 1112.60820518009 1112.61570718295 1112.62320928699 1112.63071149219 1112.63821379856 1112.64571620611 1112.65321871484 1112.66072132475 1114.26108654592 1114.26861085524 1114.27613526618 1114.28365977874 1114.29118439293 1114.29870910874 1114.30623392618 1114.31375884525 1114.32128386596 1114.32880898829 1114.33633421227 1115.25517475482 1115.2627124958 1115.27025033867 1115.27778828344 1115.28532633011 1115.29286447867 1115.30040272913 1115.3079410815 1115.31547953577 1115.32301809195 1115.33055675004 1115.33809551004 1115.34563437195 1130.2815779083 1130.28932013803 1130.29706247383 1130.30480491569 1130.31254746363 1130.32029011764 1130.32803287773 1130.33577574389 1130.34351871613 1130.35126179446 1130.35900497886 1147.66276619636 1147.67074837394 1147.67873066254 1147.68671306219 1147.69469557288 1147.70267819461 1147.71066092738 1147.7186437712 1147.72662672607 1147.73460979199 1147.74259296897 1147.750576257 1147.75855965609 1147.76654316625 1147.77452678746 1182.98466783959 1182.99314891893 1183.00163011987 1183.01011144242 1183.01859288659 1183.02707445237 1183.03555613976 1183.04403794878 1183.05251987942 1183.06100193168 1183.06948410557 1183.07796640108 1183.1712796801 " "1183.17976343539 1183.18824731234 1183.19673131095 1183.20521543123 1183.21369967318 1183.22218403681 1183.23066852212 1183.2391531291 1183.24763785777 1183.25612270812 1183.26460768015 1183.27309277388 1183.68052043171 1183.68901149146 1183.69750267303 1183.70599397643 1183.71448540165 1183.7229769487 1183.73146861758 1183.7399604083 1183.74845232085 1183.75694435525 1183.76543651148 1183.77392878956 1188.27493289966 1188.28349000304 1188.29204722968 1188.30060457956 1188.30916205269 1188.31771964907 1188.32627736871 1188.3348352116 1188.34339317776 1188.35195126718 1188.36050947987 1209.74923184622 1209.75810103042 1209.76697034466 1209.77583978896 1209.78470936331 1209.79357906772 1209.80244890218 1209.81131886671 1209.82018896131 1209.82905918597 1209.83792954071 1209.87341226042 1209.88228326555 1209.89115440077 1209.90002566609 1209.9088970615 1209.917768587 1209.92664024261 1209.93551202832 1209.94438394413 1209.95325599005 1209.96212816609 1214.99579864251 1215.00474492341 1215.01369133607 1215.02263788047 1215.03158455663 1215.04053136455 1215.04947830422 1215.05842537566 1215.06737257887 1215.07631991384 1215.08526738058 1215.0942149791 1215.10316270939 1215.11211057146 1240.4233010027 1240.43262565993 1240.44195045736 1240.45127539499 1240.46060047282 1240.46992569085 1240.47925104909 1240.48857654754 1240.4979021862 1240.50722796507 1240.51655388417 1240.52587994349 1240.53520614303 1240.5445324828 1243.04905650569 1243.05842068214 1243.06778499968 1243.0771494583 1243.08651405802 1243.09587879883 1243.10524368075 1243.11460870376 1243.12397386788 1243.13333917311 1243.14270461945 1243.15207020691 1243.16143593548 1243.17080180517 1243.18016781599 1243.18953396794 1250.94602927114 1250.95551280543 1250.96499648351 1250.97448030538 1250.98396427106 1250.99344838053 1251.00293263381 1251.0124170309 1251.0219015718 1251.03138625652 1251.04087108505 1251.05035605741 1261.31128248752 1261.32092383336 1261.33056532659 1261.34020696722 1261.34984875525 " "1261.35949069069 1261.36913277353 1261.37877500379 1261.38841738147 1261.39805990657 1261.40770257909 1261.94792763215 1261.95757871339 1261.96722994224 1261.97688131873 1261.98653284283 1261.99618451457 1262.00583633394 1262.01548830095 1262.02514041559 1262.03479267788 1262.04444508782 1262.05409764541 1262.06375035065 1262.07340320354 1262.32442921749 1262.33408605841 1262.34374304707 1262.35340018349 1262.36305746766 1262.3727148996 1262.3823724793 1262.39203020678 1262.40168808202 1262.41134610504 1262.42100427584 1262.43066259442 1262.44032106079 1263.28117374346 1263.29084522825 1263.30051686113 1263.31018864211 1263.31986057118 1263.32953264835 1263.33920487361 1263.34887724699 1263.35854976847 1263.36822243806 1263.37789525577 1263.3875682216 1263.39724133555 1263.40691459763 1265.31544052296 1265.32514318102 1265.33484598788 1265.34454894355 1265.35425204803 1265.36395530132 1265.37365870343 1265.38336225437 1265.39306595413 1265.40276980271 1265.41247380013 1265.42217794639 1273.46930606141 1273.47913417338 1273.48896243705 1273.49879085242 1273.5086194195 1273.51844813829 1273.5282770088 1273.53810603102 1273.54793520496 1273.55776453063 1273.56759400803 1273.57742363715 1273.58725341802 1273.59708335062 1273.60691343496 1273.61674367105 1273.62657405888 1281.32087896611 1281.33082864257 1281.34077847355 1281.35072845906 1281.3606785991 1281.37062889368 1281.38057934279 1281.39052994644 1281.40048070464 1281.41043161738 1281.42038268468 1281.43033390653 1281.44028528294 1281.45023681392 1281.46018849946 1281.47014033957 1281.48009233426 1293.16997731079 1293.18011185941 1293.19024656688 1293.2003814332 1293.21051645839 1293.22065164243 1293.23078698534 1293.24092248711 1293.25105814776 1293.26119396729 1293.27132994569 1293.28146608298 1409.30396671911 1409.31600329167 1409.32804006984 1409.34007705362 1409.35211424301 1409.36415163802 1409.37618923866 1409.38822704493 1409.40026505684 1409.4123032744 1409.4243416976 1409.43638032645 1439.81291838247 " "1439.82548173949 1439.83804531576 1439.85060911129 1439.86317312607 1439.87573736013 1439.88830181346 1439.90086648606 1439.91343137795 1439.92599648913 1439.93856181961 1439.97625912687 1439.98882533458 1440.00139176163 1440.013958408 1440.0265252737 1440.03909235875 1440.05165966315 1440.0642271869 1440.07679493 1440.08936289247 1440.10193107432 1456.39679555874 1456.40964999523 1456.42250465864 1456.43535954896 1456.44821466621 1456.46107001039 1456.47392558151 1456.48678137957 1456.49963740459 1456.51249365655 1456.52535013548 1456.53820684138 1456.55106377425 1456.5639209341 1456.57677832093 1469.49643693345 1469.5095236508 1469.52261060125 1469.5356977848 1469.54878520145 1469.56187285121 1469.57496073409 1469.58804885009 1469.60113719922 1469.61422578149 1469.6273145969 1469.64040364545 1477.46994793765 1477.48317705841 1477.49640641608 1477.50963601066 1477.52286584217 1477.53609591059 1477.54932621596 1477.56255675826 1477.5757875375 1477.58901855369 1477.60224980685 1477.61548129696 1477.62871302405 1477.64194498811 1477.65517718916 1477.6684096272 1477.68164230223 1477.69487521426 1477.7081083633 1477.72134174936 1478.91331787051 1478.9265728516 1478.93982807029 1478.9530835266 1478.96633922051 1478.97959515204 1478.99285132121 1479.006107728 1479.01936437244 1479.03262125452 1479.04587837426 1480.17360285036 1480.18688043216 1480.20015825217 1480.2134363104 1480.22671460685 1480.23999314153 1480.25327191444 1480.2665509256 1480.279830175 1480.29310966266 1480.30638938858 1480.31966935276 1480.33294955522 1480.34622999596 1480.35951067499 1480.37279159231 1480.38607274793 1480.39935414185 1480.41263577409 1480.42591764464 1480.73146645809 1480.74475405022 1480.75804188082 1480.77132994991 1480.78461825749 1480.79790680357 1480.81119558816 1480.82448461126 1480.83777387287 1480.85106337301 1480.86435311168 1480.87764308888 1480.89093330463 1480.90422375893 1480.91751445178 1480.9308053832 1480.94409655318 1480.95738796174 1480.97067960888 1480.983971494 " "1480.99726361894 1481.01055598187 1481.0238485834 1481.03714142355 1481.05043450231 1481.06372781971 1481.07702137574 1481.34294261915 1481.35624118796 1481.36953999554 1481.38283904191 1481.39613832706 1481.409437851 1481.42273761375 1481.4360376153 1481.44933785567 1481.46263833486 1481.47593905287 1481.48924000971 1481.50254120539 1481.51584263992 1481.5291443133 1481.54244622554 1481.55574837664 1481.56905076662 1481.58235339547 1481.5956562632 1481.60895936983 1481.62226271535 1481.63556629978 1481.64887012311 1481.66217418536 1481.67547848654 1482.36763154258 1482.38094851586 1482.39426572841 1482.40758318025 1482.42090087136 1482.43421880177 1482.44753697147 1482.46085538047 1482.47417402879 1482.48749291642 1482.50081204337 1482.51413140965 1482.52745101526 1482.54077086022 1493.62532276273 1493.63884277381 1493.65236302966 1493.66588353027 1493.67940427566 1493.69292526583 1493.70644650079 1493.71996798055 1493.73348970511 1493.74701167448 1493.76053388867 1493.77405634768 1511.59045068974 1511.60429789207 1511.6181453481 1511.63199305785 1511.64584102131 1511.65968923849 1511.6735377094 1511.68738643405 1511.70123541244 1511.71508464459 1511.72893413049 1599.95476419777 1599.97027768381 1599.98579147069 1600.00130555844"; const char* RawY = "0 0 0 0 0 0 0 0 0 193.855026245117 641.106506347656 877.26220703125 700.196716308594 274.883911132813 0 0 0 0 0 0 0 0 0 0 224.89469909668 511.670349121094 595.136657714844 452.148010253906 234.596389770508 74.6820220947266 0 0 0 0 0 0 0 0 119.225784301758 185.543075561523 200.134750366211 188.900192260742 160.073196411133 0 0 0 0 0 0 0 172.296859741211 200.144027709961 165.512985229492 0 0 0 0 0 0 0 0 83.4415893554688 208.525405883789 177.816024780273 100.466018676758 0 0 0 0 0 0 0 0 93.3426513671875 177.81330871582 221.383926391602 233.153823852539 185.899673461914 84.1839904785156 0 0 0 0 0 0 0 0 126.048049926758 184.371139526367 97.8295288085938 0 0 0 0 0 0 0 0 25.8681793212891 261.258850097656 531.637878417969 574.53076171875 413.904724121094 218.982650756836 112.732650756836 0 0 0 0 0 0 0 0 94.0497131347656 191.148391723633 161.991897583008 0 0 0 0 0 0 0 402.995788574219 1600.27600097656 3017.67749023438 3685.970703125 3078.0078125 1699.85888671875 531.254028320313 44.9793395996094 0 0 0 0 0 0 0 0 3.05120849609375 326.982971191406 918.194396972656 1295.37927246094 1141.49755859375 577.818969726563 26.3272705078125 0 0 0 0 0 0 0 0 125.907791137695 264.531921386719 266.280029296875 158.506088256836 0 0 0 0 0 0 0 0 45.1534271240234 245.012252807617 337.062133789063 230.558639526367 35.3934326171875 0 0 0 0 0 0 0 0 21.4011077880859 269.609924316406 302.905334472656 3843.85766601563 9906.61328125 14627.65625 14086.5751953125 8667.4873046875 2666.59497070313 152.549850463867 452.571411132813 21.2885437011719 0 0 0 0 0 0 0 0 0 242.630386352539 1476.34033203125 2982.52856445313 3656.2958984375 2926.99194335938 1440.77648925781 378.651611328125 617.814758300781 1036.13317871094 1038.09765625 677.166748046875 273.266662597656 106.01123046875 0 0 0 0 0 0 0 0 0 644.765441894531 1669.39282226563 2428.14697265625 2279.11108398438 1350.7001953125 456.782958984375 195.992416381836 144.774459838867 138.42707824707 203.370742797852 302.340209960938 350.181884765625 " "314.466613769531 225.259658813477 125.442489624023 0 0 0 0 0 0 0 0 0 229.676986694336 1286.525390625 3076.466796875 4448.58984375 4288.94775390625 2695.29956054688 856.980102539063 0 0 0 0 0 0 0 0 0 0 297.09423828125 790.947937011719 1078.3701171875 895.997009277344 377.297119140625 0 0 0 0 0 0 0 0 0 54.2761840820313 380.800170898438 604.678894042969 530.256896972656 239.020004272461 14.5890960693359 0 0 0 0 0 0 0 0 0 315.951721191406 1584.78002929688 3584.27490234375 4964.8896484375 4550.10595703125 2648.34790039063 761.737854003906 336.893249511719 327.000427246094 103.404342651367 0 0 0 0 0 0 0 0 137.308151245117 232.669479370117 225.336959838867 131.02082824707 0 0 0 0 0 0 0 0 0 309.901550292969 806.588073730469 1159.07531738281 1105.30993652344 695.416931152344 245.27473449707 13.4951171875 0 0 0 0 0 0 0 0 114.433959960938 215.006851196289 272.628845214844 187.665817260742 12.0498352050781 0 0 0 0 0 0 0 0 127.550247192383 182.018173217773 211.423233032227 191.385147094727 141.782333374023 0 0 0 0 0 0 0 0 0 745.767456054688 2422.9541015625 3720.92529296875 3568.47998046875 2088.86743164063 510.764953613281 183.886978149414 136.265151977539 0 0 0 0 0 0 0 0 171.257888793945 188.640060424805 192.395614624023 154.632247924805 0 0 0 0 0 0 0 0 130.887710571289 642.11865234375 1160.51184082031 1294.43505859375 977.964050292969 544.39794921875 308.192199707031 211.437362670898 76.1909332275391 0 0 0 0 0 0 0 0 0 229.855178833008 543.525207519531 586.220275878906 314.952575683594 0 0 0 0 0 0 0 0 0 154.422073364258 196.758010864258 149.831283569336 0 0 0 0 0 0 0 0 123.318832397461 188.429489135742 169.386795043945 0 0 0 0 0 0 0 0 2959.08642578125 8616.0419921875 13691.96484375 14140.76953125 9577.6708984375 3752.03759765625 393.419616699219 324.138061523438 232.52278137207 0 0 0 0 0 0 0 0 0 133.11164855957 205.964584350586 199.730422973633 139.437789916992 0 0 0 0 0 0 0 0 101.496200561523 185.133193969727 259.655029296875 244.710922241211 160.866897583 0 0 0 0 0 0 0 0 " "171.158157348633 209.737930297852 216.904006958008 153.206130981445 0 0 0 0 0 0 0 0 0 1064.01928710938 2744.22631835938 3925.62744140625 3728.50854492188 2484.57104492188 1484.09924316406 1184.474609375 801.294799804688 276.304870605469 0 0 0 0 0 0 0 0 0 0 300.0966796875 1263.98876953125 2300.80615234375 2527.240234375 1658.1162109375 416.934509277344 362.052856445313 510.349609375 422.890075683594 293.749877929688 96.1615142822266 0 0 0 0 0 0 0 0 277.112182617188 552.278137207031 634.911743164063 465.758728027344 230.118118286133 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 338.728454589844 100.444885253906 1113.40734863281 4002.13525390625 6734.62841796875 7179.69189453125 4943.12939453125 1888.85778808594 87.8339996337891 0 0 0 0 0 0 0 0 166.607498168945 203.203231811523 88.5599517822266 0 0 134.797103881836 252.799118041992 321.236206054688 317.407653808594 177.626174926758 0 0 0 0 0 0 0 0 420.235168457031 1400.63110351563 2127.62890625 2036.72399902344 1375.9619140625 1018.35345458984 909.901550292969 528.322021484375 118.658309936523 0 0 0 0 0 0 0 0 6.52516174316406 184.584854125977 399.570495605469 472.823852539063 311.700012207031 67.0648040771484 0 0 0 0 0 0 0 0 4.97833251953125 518.760131835938 1195.45788574219 1522.00109863281 1192.40087890625 457.996826171875 236.555740356445 455.735107421875 494.134094238281 419.947204589844 169.757431030273 0 0 0 0 0 0 0 0 158.202651977539 249.356582641602 255.182876586914 181.06364440918 0 0 0 0 0 0 0 0 173.365737915039 243.861038208008 222.755081176758 104.503341674805 0 0 0 0 0 0 0 0 127.732864379883 184.066452026367 159.648910522461 0 0 0 0 0 0 0 0 0 216.264389038086 564.540100097656 758.490661621094 593.172241210938 186.406509399414 0 0 0 0 0 0 0 0 0 57.8870544433594 189.093154907227 180.032363891602 0 0 0 0 0 0 0 0 107.181259155273 588.624389648438 3296.2294921875 6859.40966796875 8629.48046875 6954.76904296875 3204.29370117188 530.406066894531 701.101257324219 446.318359375 172.379989624023 0 0 0 0 0 0 0 0 " "106.025817871094 219.603103637695 171.653244018555 0 0 0 0 0 0 0 0 66.6060028076172 816.289489746094 2058.00170898438 2839.88916015625 2264.32885742188 887.272766113281 1098.07897949219 1184.8994140625 515.840759277344 0 0 0 0 0 0 0 0 0 107.923675537109 213.511978149414 238.096145629883 157.005569458008 0 0 0 0 0 0 0 0 84.7611541748047 279.91943359375 997.471740722656 1668.52087402344 1678.548828125 1062.6884765625 456.879150390625 261.066772460938 414.542724609375 400.814636230469 181.47590637207 0 0 0 0 0 0 0 0 162.703384399414 402.678283691406 606.938415527344 584.632751464844 322.495727539063 0 0 0 0 0 0 0 0 203.609512329102 221.824447631836 103.749816894531 0 0 0 0 0 0 0 0 139.273239135742 246.041458129883 237.826309204102 138.225112915039 0 0 0 102.917053222656 540.358703613281 1507.14807128906 2255.67041015625 2121.10278320313 1207.01428222656 254.796005249023 0 0 0 0 0 0 0 0 0 180.893783569336 216.125747680664 186.408401489258 92.5867767333984 0 0 0 0 0 0 0 0 67.1141357421875 314.660339355469 430.744506835938 249.505142211914 110.873168945313 311.952087402344 298.573059082031 158.444198608398 0 0 0 0 0 0 0 0 0 203.841903686523 330.667297363281 305.950500488281 171.00895690918 0 0 0 0 0 0 0 0 150.461807250977 187.074295043945 122.066360473633 0 0 0 0 0 0 0 0 128.328475952148 228.142013549805 224.649185180664 115.597442626953 0 0 0 0 0 0 0 0 121.621292114258 209.864395141602 180.903396606445 0 0 0 0 0 0 0 0 180.190689086914 221.191635131836 230.223587036133 203.161819458008 163.631942749023 0 0 0 103.920654296875 254.635330200195 239.919662475586 117.75276184082 0 0 0 0 0 0 0 0 127.274429321289 277.754516601563 418.050842285156 364.745910644531 108.102828979492 0 0 0 0 0 0 0 0 122.235366821289 204.649490356445 1283.6416015625 2732.66333007813 3403.52026367188 2677.83666992188 1189.97729492188 91.4230346679688 0 0 0 0 0 0 0 0 179.184860229492 218.383316040039 188.207290649414 103.431289672852 0 0 0 0 0 19.3411254882813 320.543273925781 708.724914550781 " "746.338012695313 324.464965820313 498.983642578125 805.302062988281 584.451416015625 150.821365356445 0 0 0 0 0 0 0 0 18.6659393310547 273.791931152344 556.722961425781 580.784423828125 324.137634277344 118.86296081543 192.937911987305 133.19303894043 0 0 0 0 0 0 0 0 156.306106567383 528.205383300781 857.985168457031 865.72802734375 528.765258789063 126.998458862305 0 0 0 0 0 0 0 0 141.282363891602 213.537307739258 188.727676391602 83.9633941650391 0 0 0 0 0 0 0 0 53.5650329589844 300.0869140625 496.208679199219 543.627502441406 469.730163574219 370.066101074219 289.648376464844 183.115615844727 57.3272399902344 0 0 0 0 0 0 0 0 128.359512329102 282.553894042969 428.125305175781 518.781311035156 625.49609375 722.9619140625 704.251159667969 596.822631835938 501.902587890625 382.079040527344 159.27229309082 0 0 0 0 0 0 0 0 65.7273559570313 820.538696289063 2162.48120117188 3311.76513671875 3299.95263671875 2090.16650390625 672.241455078125 0 0 0 0 0 0 0 0 0 0 308.417297363281 836.372497558594 1054.75146484375 828.995056152344 520.746643066406 281.113220214844 0 0 0 0 0 0 0 0 0 135.923385620117 224.629806518555 176.55793762207 0 0 0 0 0 0 0 0 0 243.977737426758 679.087585449219 930.161682128906 790.303100585938 379.179931640625 152.314804077148 0 0 0 0 0 0 0 0 136.929214477539 317.641784667969 361.6630859375 256.365356445313 53.1949462890625 0 0 0 0 0 0 0 0 79.8312377929688 199.234237670898 225.433242797852 110.191116333008 0 0 0 0 0 0 0 0 88.5470733642578 328.809631347656 486.254577636719 566.095397949219 679.935241699219 807.850219726563 851.315795898438 785.165161132813 654.703979492188 527.893920898438 423.899841308594 256.051086425781 0 0 0 0 0 0 0 0 0 0 325.090454101563 1122.31469726563 1884.14013671875 2005.18811035156 1370.16577148438 511.172485351563 0 0 0 0 0 0 0 0 0 144.137466430664 222.952560424805 139.711410522461 0 0 0 31.4209136962891 456.088439941406 906.362609863281 992.082092285156 640.056396484375 191.88249206543 0 0 0 0 0 0 0 0 0 142.481643676758 " "248.23698425293 361.091796875 321.38818359375 84.5967559814453 0 0 0 0 0 0 0 0 68.5481414794922 229.667556762695 342.556030273438 233.595016479492 12.875 284.913818359375 586.492919921875 765.540771484375 846.076843261719 837.908752441406 736.949829101563 570.628051757813 422.32958984375 338.351196289063 265.928649902344 102.936645507813 0 0 0 0 0 0 0 0 111.217437744141 194.165725708008 498.359680175781 810.423156738281 786.201354980469 424.384338378906 32.8225250244141 0 0 0 0 0 0 0 0 126.047775268555 188.677780151367 216.424392700195 207.760787963867 193.143905639648 173.67204284668 0 0 0 0 0 0 0 0 230.711318969727 263.243713378906 218.297134399414 121.326461791992 0 0 0 0 0 0 0 0 85.8698425292969 222.64518737793 225.071212768555 111.491928100586 0 0 0 0 0 0 0 0 158.272689819336 319.939025878906 405.672607421875 543.889831542969 709.350402832031 762.2890625 669.657836914063 464.710327148438 230.338363647461 135.231704711914 0 0 0 0 0 0 0 0 112.85188293457 340.410949707031 556.054382324219 649.1904296875 642.006286621094 595.709777832031 552.84423828125 532.100952148438 509.958984375 393.80126953125 147.021102905273 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 163.031021118164 257.087280273438 222.833755493164 69.1905975341797 0 0 0 0 0 0 0 0 0 193.01008605957 1283.4189453125 2651.75854492188 3263.72827148438 2533.265625 1061.58337402344 237.298934936523 292.41845703125 36.6092681884766 0 0 0 0 0 0 0 0 0 412.251708984375 1201.08520507813 1691.83618164063 1483.95202636719 787.549011230469 140.731460571289 0 0 0 0 0 0 0 0 155.059463500977 197.582107543945 226.128463745117 389.715087890625 812.975402832031 1328.24084472656 1494.00390625 1091.52282714844 416.5791015625 13.3121490478516 0 0 0 0 0 0 0 0 30.8641204833984 259.902893066406 398.201293945313 307.794982910156 89.9954833984375 0 0 0 0 0 0 0 0 250.239639282227 294.914489746094 240.247360229492 36.3681182861328 0 0 0 0 0 0 0 0 168.141342163086 211.644943237305 185.341293334961 0 0 0 0 0 0 0 0 0 1255.41430664063 " "4270.45751953125 7186.3505859375 7656.57861328125 5270.84912109375 2048.24633789063 131.94660949707 0 0 0 0 0 0 0 0 171.324295043945 234.151138305664 188.494430541992 85.8521118164063 0 0 0 0 0 0 0 177.790451049805 196.738876342773 191.143508911133 173.924301147461 0 0 0 0 0 0 0 0 27.4716339111328 870.664428710938 2696.56469726563 4313.33056640625 4373.56005859375 2848.65014648438 1105.826171875 363.445678710938 95.8519592285156 0 0 0 0 0 0 0 0 165.054183959961 190.630477905273 212.371444702148 119.549850463867 0 0 0 0 144.282302856445 1497.27661132813 3014.11791992188 3372.33959960938 2141.125 440.955444335938 486.9052734375 473.754028320313 237.800888061523 10.4761962890625 0 0 0 0 0 0 0 0 187.649795532227 717.752685546875 1004.04693603516 895.356262207031 611.759887695313 231.517959594727 0 0 0 0 0 0 0 0 0 0 380.191772460938 1166.65649414063 1580.28991699219 1321.69921875 695.5244140625 219.708572387695 60.3770294189453 0 0 0 0 0 0 0 0 168.744674682617 496.461608886719 797.966979980469 819.004150390625 524.868408203125 148.768051147461 0 0 0 0 0 0 0 0 114.591278076172 230.604568481445 404.740417480469 400.008056640625 149.154037475586 0 0 0 0 0 0 0 0 102.017929077148 332.576171875 431.327087402344 395.180480957031 291.81103515625 179.464797973633 0 0 0 0 0 0 0 0 328.818298339844 432.372192382813 513.603515625 524.003845214844 455.190307617188 323.07763671875 0 0 0 0 0 0 0 0 0 500.822875976563 1250.17626953125 1691.61279296875 1446.947265625 741.710021972656 242.135177612305 131.856307983398 0 0 0 0 0 0 0 0 106.934600830078 416.481811523438 591.3037109375 471.31884765625 154.692947387695 0 0 0 0 0 0 0 0 58.2242736816406 451.217834472656 867.215209960938 952.283020019531 683.782348632813 327.990234375 53.9348297119141 0 0 0 0 0 0 0 0 112.282455444336 194.305465698242 247.864517211914 283.480651855469 251.062362670898 154.861434936523 0 0 0 0 0 0 0 0 0 2550.76782226563 7417.4248046875 11472.3154296875 11331.73046875 7126.333984375 2372.173828125 154.968887329 0 0 " "0 0 0 0 0 0 171.941879272461 235.122146606445 189.759658813477 86.6224975585938 0 0 0 0 0 0 0 0 161.515548706055 191.835342407227 263.086181640625 280.552551269531 146.46711730957 354.734191894531 1819.36071777344 4197.60791015625 5904.71484375 5515.97998046875 3378.09521484375 1216.07165527344 240.816360473633 160.06672668457 0 0 0 0 0 0 0 0 168.925979614258 417.149658203125 1732.84704589844 3627.1572265625 4610.03076171875 3790.7890625 1980.00671386719 757.338623046875 314.47314453125 0 0 0 0 0 0 0 0 0 151.324813842773 253.94270324707 329.051940917969 266.352722167969 111.870147705078 0 196.40153503418 1169.40258789063 2201.71215820313 2499.97778320313 1842.07995605469 847.819702148438 294.143676757813 154.02375793457 0 0 0 0 0 0 0 0 0 263.716003417969 663.424133300781 945.621276855469 900.181091308594 586.183349609375 242.737838745117 0 0 0 0 0 0 0 0 0 87.7988586425781 273.416259765625 275.446044921875 122.881698608398 0 0 0 0 0 0 0 0 139.006607055664 632.857299804688 1046.19299316406 1076.18725585938 721.538818359375 282.741760253906 33.4364013671875 0 92.9069519042969 201.903335571289 216.809951782227 66.0712280273438 0 0 0 0 0 0 0 0 0 262.810607910156 583.060974121094 697.79833984375 522.555419921875 181.537673950195 0 0 0 0 0 0 0 0 258.55615234375 289.532775878906 243.079086303711 173.991165161133 0 0 0 0 0 0 0 0 37.7136077880859 214.55876159668 243.370010375977 18.9360961914063 35.8999176025391 191.428115844727 166.77082824707 0 0 0 0 0 0 0 0 0 258.869323730469 651.99658203125 911.448181152344 810.898193359375 421.798156738281 54.3055572509766 0 0 0 0 0 0 0 0 60.1159057617188 292.62109375 475.166442871094 465.994323730469 265.969482421875 59.4075927734375 0 0 0 0 0 0 0 0 129.671829223633 203.134628295898 214.902053833008 142.065078735352 0 0 0 0 0 0 0 0 68.9898071289063 258.451477050781 349.82421875 288.4658203125 184.60481262207 0 0 0 0 0 0 0 0 60.4415130615234 757.99267578125 4146.55859375 8593.078125 10882.390625 9079.6171875 4740.5390625 1125.72338867 " "0 0 0 0 0 0 0 0 0 102.086837768555 209.562088012695 285.004333496094 167.125106811523 0 0 0 0 0 0 0 0 153.054061889648 218.63932800293 227.450668334961 199.439254760742 191.222061157227 179.493179321289 0 0 0 0 0 0 0 0 136.84049987793 243.085250854492 175.279190063477 0 0 0 165.884048461914 1627.97961425781 4570.39892578125 7233.904296875 7538.84521484375 5242.4697265625 2183.01293945313 247.249221801758 94.0259094238281 0 0 0 0 0 0 0 0 0 708.975402832031 2684.54736328125 4892.7626953125 5664.70263671875 4346.48974609375 2153.0361328125 792.776916503906 328.806335449219 26.2600402832031 0 0 0 0 0 0 0 0 0 600.651245117188 1863.01184082031 2856.58935546875 2825.29223632813 1829.23559570313 678.683837890625 156.775985717773 0 0 0 0 0 0 0 0 177.269912719727 213.871047973633 146.206100463867 0 0 0 0 0 0 0 0 0 438.628295898438 1067.17602539063 1423.88037109375 1322.46948242188 846.637451171875 222.935501098633 8.62030029296875 0 0 0 0 0 0 0 0 1.40678405761719 204.166915893555 495.588256835938 711.029602050781 672.086486816406 440.136291503906 197.460708618164 25.0921783447266 0 0 0 0 0 0 0 0 181.639419555664 454.123840332031 630.59228515625 540.996643066406 248.280014038086 0 0 0 0 0 0 0 0 0 0 272.537475585938 507.36669921875 482.3701171875 228.514022827148 0 0 0 0 0 0 0 0 0 173.016799926758 282.362365722656 239.30632019043 89.6678161621094 0 0 0 0 0 0 0 0 163.693313598633 238.812973022461 181.945022583008 0 0 0 0 0 0 0 0 154.68586730957 251.716812133789 301.325927734375 285.520263671875 212.902420043945 125.696426391602 0 0 0 0 0 0 0 0 144.465744018555 280.485534667969 282.486389160156 171.469833374023 0 0 0 0 0 0 0 0 168.80158996582 1852.96484375 4451.087890625 6223.240234375 5698.3251953125 3317.40869140625 947.944641113281 0 72.4445648193359 222.517288208008 190.692306518555 8.54414367675781 0 0 0 0 0 0 0 0 173.518569946289 287.66455078125 315.665649414063 180.375747680664 0 0 0 0 0 0 0 0 22.9653015136719 377.313659667969 1943.11608886719 3810.626464843 4614.140625 " "3648.7470703125 1708.49145507813 216.385025024414 180.797805786133 220.440505981445 66.8912200927734 0 0 0 0 0 143.90119934082 216.902420043945 185.753768920898 98.3815460205078 0 0 0 0 0 0 0 0 162.759536743164 215.904861450195 208.337875366211 127.708084106445 0 0 0 0 0 0 0 0 105.314514160156 217.56315612793 204.984756469727 103.096450805664 1431.53564453125 2977.5546875 3651.64916992188 2931.84326171875 1398.70080566406 87.1452484130859 320.6357421875 384.557983398438 269.201110839844 237.787063598633 238.22102355957 131.059158325195 0 0 0 0 0 0 0 0 82.7467803955078 540.114013671875 1467.232421875 2395.43090820313 2641.54028320313 2010.16149902344 989.484558105469 192.628158569336 0 0 179.865524291992 275.410278320313 175.700149536133 0 0 0 0 0 0 0 0 59.9419708251953 485.762634277344 988.358093261719 1207.15466308594 963.307312011719 438.903381347656 31.6091766357422 0 0 0 0 0 47.9591827392578 196.635208129883 252.011154174805 211.016983032227 150.474960327148 0 0 0 0 0 0 0 0 168.648544311523 212.75212097168 246.239303588867 241.005111694336 180.050369262695 0 0 0 0 93.9449157714844 308.76171875 510.256713867188 547.370849609375 379.794067382813 126.207992553711 0 0 0 0 0 0 0 0 165.212295532227 203.172348022461 187.95915222168 180.575973510742 0 0 0 0 0 0 0 0 75.0355987548828 196.667404174805 286.693542480469 310.418090820313 283.288269042969 260.312194824219 292.165649414063 351.78125 356.774780273438 261.874694824219 112.601119995117 0 0 0 0 0 0 0 0 147.65412902832 199.247695922852 206.355667114258 137.159103393555 0 0 0 0 0 0 0 0 153.178085327148 250.377090454102 305.382019042969 294.765869140625 215.430770874023 81.4587097167969 0 0 0 0 0 0 0 0 89.8516693115234 217.64045715332 309.367736816406 283.979248046875 149.045394897461 0 0 0 182.38005065918 418.089721679688 1096.13757324219 1732.892578125 1712.91027832031 1019.67010498047 253.890274047852 63.1096954345703 0 0 0 0 0 0 0 0 146.927871704102 197.823593139648 450.705383300781 1247.59985351563 " "2147.16479492188 2419.29248046875 1796.34436035156 783.829040527344 106.181396484375 0 0 0 0 0 0 0 0 0 334.013916015625 997.858215332031 1538.47912597656 1550.04187011719 1073.02502441406 532.429992675781 248.089309692383 200.781692504883 213.394241333008 177.545181274414 0 0 0 0 0 0 0 0 26.6942443847656 209.29020690918 520.969909667969 869.404174804688 1070.1162109375 975.004333496094 655.297485351563 316.672058105469 99.7084808349609 0 0 0 0 0 0 0 0 79.5495910644531 288.576049804688 554.977966308594 746.154174804688 740.367309570313 521.067321777344 227.974136352539 72.0663757324219 0 0 0 0 0 0 0 0 171.190017700195 314.421569824219 429.333374023438 416.543640136719 251.908309936523 31.249267578125 0 0 0 0 0 0 0 0 180.657669067383 192.169876098633 162.963485717773 0 0 0 0 0 0 0 0 155.606674194336 333.596923828125 371.658142089844 244.003341674805 111.538848876953 0 0 0 55.3578186035156 199.379867553711 277.664733886719 246.347457885742 148.267105102539 0 0 0 0 0 0 0 0 90.9604797363281 198.196731567383 372.608276367188 566.121337890625 624.478515625 473.921447753906 201.671371459961 0 0 0 0 0 0 0 0 0 120.198684692383 400.147033691406 571.140441894531 478.692626953125 229.758438110352 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 152.600845336914 225.899429321289 240.899063110352 190.175918579102 0 0 0 0 0 0 0 0 225.349227905273 261.482971191406 145.197463989258 0 0 0 0 0 0 0 0 64.5845184326172 213.417953491211 267.813903808594 201.623031616211 117.913467407227 0 0 0 0 0 0 0 0 182.848587036133 203.188278198242 155.740859985352 0 0 0 0 0 0 0 0 184.153060913086 247.411849975586 282.429565429688 316.498046875 347.890441894531 314.713134765625 179.080673217773 0 0 0 0 0 0 0 0 115.904327392578 226.538375854492 215.979263305664 129.574813842773 0 0 0 0 0 0 0 0 129.243606567383 308.855651855469 363.072937011719 252.200698852539 36.5062561035156 0 0 0 0 0 0 0 0 168.485580444336 221.236099243164 203.256454467773 118.937698364258 0 0 0 0 0 0 0 0 135.065872192383 197.25260925293 " "164.043045043945 0 0 0 0 0 0 0 0 101.22346496582 199.961135864258 181.580459594727 0 0 0 0 0 0 0 0 171.627029418945 216.893325805664 165.188735961914 0 0 0 0 0 0 0 0 184.577438354492 315.924865722656 400.736938476563 401.748779296875 309.456359863281 177.526077270508 0 0 0 0 0 0 0 0 71.3968505859375 196.379440307617 317.622741699219 323.017578125 218.84977722168 108.977661132813 0 0 0 0 0 0 0 0 143.710311889648 248.819686889648 318.435913085938 338.807861328125 306.490661621094 239.977798461914 197.418716430664 128.426620483398 0 0 0 0 0 0 0 0 126.655654907227 226.479202270508 229.53288269043 179.628677368164 0 0 0 0 0 0 0 0 144.30647277832 214.861099243164 189.256454467773 0 0 0 0 0 0 0 0 188.085342407227 308.395935058594 374.08056640625 337.305053710938 193.459030151367 33.2561950683594 0 0 0 0 0 0 0 0 101.20735168457 200.764785766602 247.183944702148 206.08268737793 87.9416961669922 0 0 0 0 0 0 0 0 95.3595581054688 225.91584777832 248.077072143555 250.59260559082 257.277648925781 180.943740844727 0 0 0 0 0 0 0 0 155.655776977539 238.868362426758 250.283981323242 157.468978881836 0 0 0 0 0 0 0 0 165.849624633789 341.285217285156 449.087829589844 465.197448730469 414.669006347656 350.80908203125 287.216369628906 202.29280090332 102.295700073242 0 0 0 0 0 0 0 0 122.961654663086 216.524826049805 227.398483276367 197.743057250977 252.932815551758 368.044921875 412.497924804688 332.376770019531 189.94221496582 0 0 0 0 0 0 0 0 110.821487426758 205.431838989258 197.784744262695 165.351150512695 0 0 0 0 0 0 0 0 148.747482299805 197.384048461914 222.412368774414 130.84407043457 0 0 0 0 0 0 0 0 186.619369506836 231.119979858398 185.139663696289 0 0 0 0 0 0 0 0 129.717819213867 224.055252075195 180.142196655273 0 0 0 0 0 0 0 0 176.265243530273 223.66975402832 295.446105957031 361.572326660156 360.102111816406 244.047714233398 41.8561553955078 0 0 0 0 0 0 0 0 160.23698425293 238.57145690918 249.646987915039 191.794631958008 0 0 0 0 0 0 0 0 177.559341430664 308.058898925781 " "348.306823730469 288.753173828125 157.469802856445 0 0 50.9171905517578 233.195449829102 366.537780761719 333.827880859375 112.628784179688 0 0 0 0 0 0 0 0 146.29948425293 221.006973266602 185.588424682617 0 0 0 0 0 0 0 0 169.829788208008 298.886840820313 375.022705078125 349.165283203125 326.073608398438 321.16162109375 301.307739257813 280.400939941406 268.34130859375 250.299697875977 206.922592163086 161.804183959961 0 0 0 0 0 0 0 0 106.515991210938 216.509872436523 174.441055297852 0 47.4068908691406 197.185470581055 263.215942382813 352.870300292969 434.091491699219 407.799926757813 297.367797851563 209.839736938477 246.22785949707 378.100463867188 491.783874511719 505.840270996094 403.557006835938 229.298934936523 54.6394348144531 0 0 0 0 0 0 0 0 50.5400085449219 198.851058959961 280.1474609375 285.830627441406 210.564895629883 50.8290405273438 0 0 0 0 0 170.184860229492 335.466613769531 475.362731933594 547.797119140625 496.642517089844 292.609191894531 4.42018127441406 0 0 0 0 0 0 0 0 386.298461914063 549.150512695313 612.910278320313 599.075317382813 479.97314453125 260.072143554688 0 0 0 0 0 0 0 0 157.101547241211 216.543563842773 210.621841430664 151.346878051758 0 0 0 0 0 0 0 0 163.830764770508 225.50910949707 155.86100769043 0 0 0 0 0 0 0 0"; SpectrumListSimple* sl = new SpectrumListSimple; SpectrumListPtr originalList(sl); SpectrumPtr s(new Spectrum); sl->spectra.push_back(s); vector inputMZArray = parseDoubleArray(RawX); vector inputIntensityArray = parseDoubleArray(RawY); s->setMZIntensityArrays(inputMZArray, inputIntensityArray, MS_number_of_detector_counts); s->set(MS_MSn_spectrum); s->set(MS_ms_level, 2); s->precursors.resize(1); s->precursors[0].activation.set(MS_electron_transfer_dissociation); s->precursors[0].selectedIons.resize(1); s->precursors[0].selectedIons[0].set(MS_selected_ion_m_z, 1000, MS_m_z); s->precursors[0].selectedIons[0].set(MS_charge_state, 2); // should be no change if we specify MS3 SpectrumListPtr filteredList2(new SpectrumList_ZeroSamplesFilter(originalList,IntegerSet(3),SpectrumList_ZeroSamplesFilter::Mode_RemoveExtraZeros,0)); SpectrumPtr filteredSpectrum2 = filteredList2->spectrum(0, true); unit_assert(filteredSpectrum2->getIntensityArray()->data[9] == inputIntensityArray[9]); SpectrumListPtr filteredList(new SpectrumList_ZeroSamplesFilter(originalList,IntegerSet(2),SpectrumList_ZeroSamplesFilter::Mode_RemoveExtraZeros,0)); SpectrumPtr filteredSpectrum = filteredList->spectrum(0, true); unit_assert(filteredSpectrum->getIntensityArray()->data.size() == filteredSpectrum->getMZArray()->data.size()); unit_assert(filteredSpectrum->getIntensityArray()->data[0]==0); unit_assert(filteredSpectrum->getIntensityArray()->data[1]!=0); unit_assert(filteredSpectrum->getIntensityArray()->data[filteredSpectrum->getIntensityArray()->data.size()-1]==0); unit_assert(filteredSpectrum->getIntensityArray()->data[filteredSpectrum->getIntensityArray()->data.size()-2]!=0); unit_assert(filteredSpectrum->getIntensityArray()->data[1] == inputIntensityArray[9]); // now add missing zeros int nzeros=10; SpectrumListPtr filteredList3(new SpectrumList_ZeroSamplesFilter(originalList,IntegerSet(2),SpectrumList_ZeroSamplesFilter::Mode_AddMissingZeros,nzeros)); filteredSpectrum = filteredList3->spectrum(0, true); unit_assert(filteredSpectrum->getIntensityArray()->data[0]==0); unit_assert(filteredSpectrum->getIntensityArray()->data[1]==0); unit_assert(filteredSpectrum->getIntensityArray()->data[filteredSpectrum->getIntensityArray()->data.size()-1]==0); unit_assert(filteredSpectrum->getIntensityArray()->data[filteredSpectrum->getIntensityArray()->data.size()-2]==0); unit_assert(filteredSpectrum->getIntensityArray()->data[nzeros] == inputIntensityArray[9]); } void test() { testIntensityThresholding(); testPrecursorMassRemoval(); testDeisotoping(); testMS2Denoising(); testZeroSamplesFilter(); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/spectrum_processing/SpectrumList_ChargeStateCalculator.cpp0000664000175100017510000361670012664775615032133 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_ChargeStateCalculator.cpp 6826 2014-10-22 17:12:14Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_ChargeStateCalculator.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/IntegerSet.hpp" #include "pwiz/utility/chemistry/Ion.hpp" #include #include #include #include #include #include #include #include #include #include #include "svm.h" #include #include using namespace pwiz::msdata; using namespace pwiz::cv; using namespace pwiz::util; using namespace pwiz::chemistry; namespace { bool mzIntensityPairLessThan (const pwiz::msdata::MZIntensityPair& lhs, const pwiz::msdata::MZIntensityPair& rhs) { return lhs.mz < rhs.mz; } struct MZIntensityPairIntensitySum { double operator() (double lhs, const pwiz::msdata::MZIntensityPair& rhs) { return lhs + rhs.intensity; } }; } // namespace void etdPredictCharge(double, const set&, const vector&, vector&, double); namespace pwiz { namespace analysis { PWIZ_API_DECL SpectrumList_ChargeStateCalculator::SpectrumList_ChargeStateCalculator( const msdata::SpectrumListPtr& inner, bool overrideExistingChargeState, int maxMultipleCharge, int minMultipleCharge, double intensityFractionBelowPrecursorForSinglyCharged, int maxKnownCharge, bool makeMS2) : SpectrumListWrapper(inner), override_(overrideExistingChargeState), maxCharge_(maxMultipleCharge), minCharge_(minMultipleCharge), fraction_(intensityFractionBelowPrecursorForSinglyCharged), maxKnownCharge_(maxKnownCharge), makeMS2_(makeMS2) { } PWIZ_API_DECL SpectrumPtr SpectrumList_ChargeStateCalculator::spectrum(size_t index, bool getBinaryData) const { SpectrumPtr s = inner_->spectrum(index, true); // return non-MS/MS as-is CVParam spectrumType = s->cvParamChild(MS_spectrum_type); if (spectrumType != MS_MSn_spectrum) return s; // return MS1 as-is if (!s->hasCVParam(MS_ms_level) || s->cvParam(MS_ms_level).valueAs() < 2) return s; // return peakless spectrum as-is if (s->defaultArrayLength == 0) return s; // return precursorless MS/MS as-is if (s->precursors.empty() || s->precursors[0].selectedIons.empty()) return s; // use first selected ion in first precursor // TODO: how to deal with multiple precursors and/or selected ions? Precursor& precursor = s->precursors[0]; SelectedIon& selectedIon = precursor.selectedIons[0]; // get activation types set activationTypes; BOOST_FOREACH(const CVParam& cvParam, precursor.activation.cvParams) if (cvIsA(cvParam.cvid, MS_dissociation_method)) activationTypes.insert(cvParam.cvid); // if overriding, erase any existing charge-state-related CV params; // otherwise: // * keep track of existing "possible charge state" // * return as-is if there is a "charge state" vector& cvParams = selectedIon.cvParams; IntegerSet possibleChargeStates; for(vector::iterator itr = cvParams.begin(); itr != cvParams.end(); ++itr) { if (itr->cvid == MS_charge_state || itr->cvid == MS_possible_charge_state) { // some files may have a bogus "0" charge state if (override_ || itr->value == "0" || (maxKnownCharge_ > 0 && maxKnownCharge_ < itr->valueAs())) { selectedIon.userParams.push_back(UserParam("old charge state", itr->value)); itr = --cvParams.erase(itr); } else if (itr->cvid == MS_possible_charge_state) possibleChargeStates.insert(itr->valueAs()); else if (itr->cvid == MS_charge_state) return s; } } double precursorMZ = selectedIon.cvParam(MS_selected_ion_m_z).valueAs(); vector mzIntensityPairs; s->getMZIntensityPairs(mzIntensityPairs); sort(mzIntensityPairs.begin(), mzIntensityPairs.end(), &mzIntensityPairLessThan); bool singleCharge = true; if (!makeMS2_) { double tic = accumulate(mzIntensityPairs.begin(), mzIntensityPairs.end(), 0.0, MZIntensityPairIntensitySum()); // accumulate TIC from the right until the cutoff fraction or the precursor m/z is reached vector::iterator mzItr = lower_bound(mzIntensityPairs.begin(), mzIntensityPairs.end(), MZIntensityPair(precursorMZ, 0), &mzIntensityPairLessThan); double fractionTIC = 0, inverseFractionCutoff = 1 - fraction_; if (mzItr != mzIntensityPairs.end()) for (vector::reverse_iterator itr = mzIntensityPairs.rbegin(); itr != mzIntensityPairs.rend() && &*itr != &*mzItr && fractionTIC < inverseFractionCutoff; ++itr) fractionTIC += itr->intensity / tic; fractionTIC = 1 - fractionTIC; // invert singleCharge = fractionTIC >= fraction_; } else { // Use MakeMS2 behavior vector::iterator cutoff; // sum all intensities where m/z < precursor m/z - 20 cutoff = upper_bound(mzIntensityPairs.begin(), mzIntensityPairs.end(), MZIntensityPair(precursorMZ - 20, 0), &mzIntensityPairLessThan); double leftSum = accumulate(mzIntensityPairs.begin(), cutoff, 0.00001, MZIntensityPairIntensitySum()); // sum all intensities where m/z >= precursor m/z + 20 (if none, assume charge state +1) cutoff = lower_bound(mzIntensityPairs.begin(), mzIntensityPairs.end(), MZIntensityPair(precursorMZ + 20, 0), &mzIntensityPairLessThan); if (cutoff != mzIntensityPairs.end()) { double rightSum = accumulate(cutoff, mzIntensityPairs.end(), 0.00001, MZIntensityPairIntensitySum()); // compare ratio to threshold //double highMass = s->cvParam(MS_highest_observed_m_z).valueAs(); double highMass = mzIntensityPairs.back().mz; double correctionFactor = (precursorMZ * 2 < highMass || precursorMZ <= 0) ? 1 : highMass / precursorMZ - 1; singleCharge = rightSum / leftSum < fraction_ * correctionFactor; } } if (singleCharge) { // remove possible charge states if overriding if (override_ && !possibleChargeStates.empty()) cvParams.erase(boost::range::remove_if(cvParams, CVParamIs(MS_possible_charge_state))); // set charge state to 1 cvParams.push_back(CVParam(override_ || possibleChargeStates.empty() ? MS_charge_state : MS_possible_charge_state, 1)); } else { // use SVM for multiply charged ETD activated spectra (except when using MakeMS2 behavior) if (!makeMS2_ && activationTypes.count(MS_ETD) > 0) { vector predictedChargeStates; etdPredictCharge(precursorMZ, activationTypes, mzIntensityPairs, predictedChargeStates, 0.98); if (!predictedChargeStates.empty()) { if (predictedChargeStates.size() == 1) cvParams.push_back(CVParam(MS_charge_state, predictedChargeStates[0])); else BOOST_FOREACH(int z, predictedChargeStates) cvParams.push_back(CVParam(MS_possible_charge_state, z)); return s; } } if (maxCharge_ - minCharge_ == 0) { // remove possible charge states if overriding if (override_ && !possibleChargeStates.empty()) cvParams.erase(boost::range::remove_if(cvParams, CVParamIs(MS_possible_charge_state))); // set charge state to the single multiply charged state cvParams.push_back(CVParam(override_ || possibleChargeStates.empty() ? MS_charge_state : MS_possible_charge_state, maxCharge_)); } else { // add possible charge states in range [minMultipleCharge, maxMultipleCharge] for (int z = minCharge_; z <= maxCharge_; ++z) if (!possibleChargeStates.contains(z)) cvParams.push_back(CVParam(MS_possible_charge_state, z)); } } return s; } } // namespace analysis } // namespace pwiz namespace boost { namespace serialization { template void serialize(Archive& a, svm_parameter& param, const unsigned int version) { a & param.svm_type & param.kernel_type & param.degree & param.gamma & param.coef0; } template void serialize(Archive& a, svm_node& node, const unsigned int version) { a & node.index & node.value; } template void load(Archive& a, svm_model& model, const unsigned int version) { a & model.param & model.nr_class & model.l; model.SV = (svm_node**) malloc(model.l * sizeof(svm_node*)); for (int i=0; i < model.l; ++i) { vector nodes; for (int j=0;;++j) { nodes.push_back(svm_node()); a & nodes.back(); if (nodes.back().index == -1) break; } model.SV[i] = (svm_node*) malloc(nodes.size() * sizeof(svm_node)); copy(nodes.begin(), nodes.end(), model.SV[i]); } model.sv_coef = (double**) malloc((model.nr_class-1) * sizeof(double*)); for (int i=0; i < model.nr_class-1; ++i) { model.sv_coef[i] = (double*) malloc(model.l * sizeof(double)); for (int j=0; j < model.l; ++j) a & model.sv_coef[i][j]; } int numRho = model.nr_class*(model.nr_class-1)/2; model.rho = (double*) malloc(numRho * sizeof(double)); model.probA = (double*) malloc(numRho * sizeof(double)); model.probB = (double*) malloc(numRho * sizeof(double)); for (int i=0; i < numRho; ++i) a & model.rho[i] & model.probA[i] & model.probB[i]; model.label = (int*) malloc(model.nr_class * sizeof(int)); model.nSV = (int*) malloc(model.nr_class * sizeof(int)); for (int i=0; i < model.nr_class; ++i) a & model.label[i] & model.nSV[i]; a & model.free_sv; } }} BOOST_SERIALIZATION_SPLIT_FREE(svm_model) // SVM charge prediction for ETD spectra: // "Precursor Charge State Prediction for Electron Transfer Dissociation Tandem Mass Spectra" // V. Sharma, J. Eng, M. MacCoss, W. Noble, et al. // http://pubs.acs.org/doi/full/10.1021/pr1006685 class ETD_SVM : public boost::singleton { public: svm_model* m2() const {return m2_;} svm_model* m3() const {return m3_;} svm_model* m4() const {return m4_;} svm_model* m5() const {return m5_;} svm_model* m6() const {return m6_;} svm_model* m7() const {return m7_;} svm_model* m24() const {return m24_;} svm_model* m36() const {return m36_;} svm_model* m57() const {return m57_;} ETD_SVM(boost::restricted) { m2_ = load2(); m3_ = load3(); m4_ = load4(); m5_ = load5(); m6_ = load6(); m7_ = load7(); m24_ = load24(); m36_ = load36(); m57_ = load57(); } ~ETD_SVM() { svm_free_and_destroy_model(&m2_); svm_free_and_destroy_model(&m3_); svm_free_and_destroy_model(&m4_); svm_free_and_destroy_model(&m5_); svm_free_and_destroy_model(&m6_); svm_free_and_destroy_model(&m7_); svm_free_and_destroy_model(&m24_); svm_free_and_destroy_model(&m36_); svm_free_and_destroy_model(&m57_); } private: svm_model* m2_; svm_model* m3_; svm_model* m4_; svm_model* m5_; svm_model* m6_; svm_model* m7_; svm_model* m24_; svm_model* m36_; svm_model* m57_; svm_model* decodeModel(const string& encodedModel) { stringstream encoded(encodedModel); stringstream decoded; bio::copy(bio::compose(bio::zlib_decompressor(), bio::compose(bio::base64_decoder(), encoded)), decoded); boost::archive::text_iarchive a(decoded); svm_model* model = (svm_model*) malloc(sizeof(svm_model)); a & *model; return model; } svm_model* load2() { const std::string model = std::string("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") + "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"; return decodeModel(model); } svm_model* load3() { const std::string model = std::string("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") + "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"; return decodeModel(model); } svm_model* load4() { const std::string model = std::string("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") + "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"; return decodeModel(model); } svm_model* load5() { const std::string model = std::string("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") + "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"; return decodeModel(model); } svm_model* load6() { const std::string model = std::string("eNqEvWmuJcuuHjaVMwFdBJvoNBvBEGABhg3Ihn949CYzg8xFBvfRNWA81am9a63MCLZfg/jP//3f/+f/+G//x//4//7b//M//q//87/+1//2P/+3//1//L///Z/5T/P/D//Zc/LqQPuf9h/A/g/9Z+y+JgFih0k04b//FwD9m4Tw/Iz8//+Dm5HW9v9N+e/tP621hbP9/o//If0P3Abx99f3+oefv78bhL8+/unv7+GB4T+Afuz/NJiwZvjj9f59gn/2839NwBE/AND7V5DpHzi/HvbY4X//4PMFaEH4h+EffH4axmSOf3+8v2ly/MLyBP3fmOnfYHg/ovwjs38/sv75L/A8V3ifIuFE/vmV9DzDvqnLP/o8N6YxIPxq/TdRnvHvS1nvM2u4G8Zn+TwqHGPF7wrnpSwKn7zbY4Ml37s9/+daG3p8UPrZiXEu+v0I7/Pj0ZDiX39/pXxisGfZCdKro/cfw8bpMLzPmKCt3w8hZ1R/k7xCbDM8eLR/bMXfw+/Z4Dlptu8HxvdGzuGhTeFdrnNQO3eOf34+M0/G9B+en5Brwyu8uvjy99r4+4Pz+QQkL5z5vPy+wyWj96PMuXiHh/G+fZAvF4/hc2XkXXI/d2Zh7+mFvydBAsOOh/uchDl2eCVys953iEhoZ2TD3My/P/2cESB5oXjfsc2Tdnj97xkBlCgUz854377eaDp3qnV5V++nBnnEdguhDU5H5zkiS66QvP73g/a1eIRHd86F3NP9+1AhvixElg/3+2j1x6D1timcsufFy61v152FLheGn1clzwXGumIbj4k9HIgnVD+H9h+A90SAfP/fz2/vb4XX1zwAYgtfWO/+eE/nDuFMftNzilDudRsh/j2PTj6DfJJw3/F9ZyCf7sRO4LHPu0Q5pbt4lxPlQO3fC4jP0Vxyu36vA73XS+790tuu3x6Aurxuej9mH79nxQNFk1gXL+N7XIdEq3/oTS0kUfcfekOjJKsVD0R7/87uHe6QLmljS3Z8w4zERfmy7wmS/3vEs3sOkByeJs+oh0f6/NON4mU8EajL8TlJs3EMh/Lx3re6aYQfpX/ebwmS7kY4p29oYHl9rcimuBfE2LVPsts7BeL3AMrHm3IS4hG0tNv9ODainn/+JEvc0MqAIu+O05c94UWOpITFEC/eMI+zU0ru5zpLAvgHz2dBlIMTj/Qbbrpc33MsAQbLUXyfFknIm+Ep4nksnRl+U6knLvnoV+Y6D0yyb0ooFr3atNPZpZhJ+aqdjyWX4pw9GAMhBSYpkhZyPkRywDes32f8/Iuzxec1z2mSqEtFCaZB8ZwTGN1SiGbicxgm8AII2cQe/+T4Xs65AJjphdmxYKJWxSmpoVbIanLGnrDIa8mVtyKly11av38J36cPU4LqKVlal9Tawvc/cUuK1m3HRWJQ7/M+LfoRVy4lTyrk3uPBPaeCdqi7tL477xt2+F3DKkY5uOO3NoJcNHQMj2NZ2bJgpXL8/dRyLkN1Ym90SD0b//77KIcGlp+HZLlZwxKkL8n2T890b99vCXKqqSqA2n+W3qNYMLxXUo7zfkMz7ym39ve3xoMvCVke20nDklz/sXw3+0mnEItM9JQo9VC8kO9X74St97tVAP3muwgHg6n9FjJ4kpAEe/BLu/Rq3yWqpMr8asfgu6FiqdB/v8d7laEzheLy/fZLY8q+wr+ULnOdYpDltL43WW5cSpXPrUZpB2Pifi810NC/8r7zQaEn8HIDJUxjvN8n/UJPpwfOM+zxJtjLkMzXdw939XntXQIOn3v7XPq715Dcg8D3PdUI0c+7k6JlhWLLrqyUwV5q9gFQRm4JyuB1p/ytou7UP+d4auhkF4QRf6sVp5LHV9FGghQKg6212T2m1q+1kQ5lrj9DB0hXGb7O6delPbgbTPn0CKvoyiVu4blejXePR+B9alIi4W8p5EWBHONRBn8cknjttUttvEINcDo6iq3qsrg0CbmMyoxgb1s6iMXxW1rDSfHS4akv5RT3EIjtbkvb1kcV7eT1UTrJb4kp/QDO32ecpwByPZd1/pqg7yBOzL0q3yTCkaVAkkIB4C7QJTH81k5teKLj1SeGHziFmISRXXW0IG14DOjPV0f9huHgPV9cmnyCGXIcnk465nrKgbDxii3Ce9vH6vstZIBzjHo7LApVGLxFsbRMM8bKU/vOifHgvJEB17B2S4qPIf3T70c5wbBzmi/4GR8WCnesIT0USkeT69y39ZIqUBpgunMySL/Swxc71Q3tsRaGZuqdK3WiOCE4dfHQsvhtlKQNi9OH02trWxJj6jwzJIb452ekIA3H7xf65iJ7phxBVpOt+RUPO97e4VO1NIfZViyjhBeuAqt8u5lr8PeVLhzQivkcolYvIZai/arVyjPa/iOJA367fnpO7cYRamGd5sCJpQgpKc4zwGQb0QwpGc6sTjIc3SdLbrqkPRu9SHBOIa+9za+kFirOCUr/Fxq9k0yHNHP7ntVJI7ah6N11BrdiLU6nTWnamcMJkKHZlY9t7zoMDN9ndGKqZAZLm3Ki4/k7r4SBUi198p40gVtCWoghUhzywLcXkh/8PS9v08O0JVxcM7SlmT301euZ10iOOf2Pdr9UTJ1B46lPY1ouxk9MkPY8DsffNyp/3NKw5M2GQ2pSvrPh1HlCeBYnpnepn8fd6koglvN85UgAnHJfLUdK+mrj7mK0QMOis5VQ12fVEAy/xH0hVrXR2O334eu7fEci3FJuPcMVkrw4visoNQul7/MsNRZJb/r8hL7eWUxxceQp4fvecYTK/7x3KZa13zzV4Gyap23aMcfO7/ikgIVcjT40Ak27wpTHzJbGUY5rzFanANppkTF9mN6utvSU1pJFfxvTM1KTy40zjqrsgsaH+oTW89jgqm3G6WJwW50jzx/l73snu8OCxi+yFOHxA3/vlYaON+Vlnmn8Xi1MUvuZi6/B/Ur/cw8Kf/t9tTQmxjZnvWVRh7h62e+oeSybtUpaG+GBv69eHl6f52XLHSAs3vWiGRYQ/t5nnC1oQXHWXRu89ZFk8Vs4TetDJUvMYmWFPQ0mTjQAxDlOvn/a0LtKlnJeaqk7q8ujDosrPzrIodqeJxb0MWYcXb9HSmJzW/c+h6Ti7/te5zCP2e7Mrscq7RThHbRv7EVvLbniGq+cJ9I1jX5xRML5+Dlv0titdc9bpXsIr9lqKMlt4e2PcyWXdDEQ/tzCHq5dhD25dzlkxNZNarJxJj1SVP++MJ8I92t4anMetCkZSIeC9fwKygml/ADAXe9LJONJfs8n7Fm9BIw56hvgSGsgZeZvkOtnpNPjfPLU/RKu1hXK5TRL/3IXVUO+zPnqK1YSzcaWkgR2hx7S8AndcgCtKdUdZYy3Vn0xleMjiX6SXa5FqY4R6vupaTBEXOtppV357afsXEkZwvG425gx/f71NrEgL38Nnzb3b2YxNnE5s0DNn+/WSSqGXFTJ4cF3S9nm0///vsHTIUppP21Wngf9NktGKnsnHZe2cmLX1hypS3ieuVxn+O1/vmS5vsEl+DmXxn36KJ+GlAI+9SG0df7qPbx4u7zye3JsOHMb6B2n32U5WPhvd1lC2eJ768OU9wcn8+aXa483DdK9rZXUk069NQeSW+NU7CwoiOV/lmR0zpdez1noDQjbKPAgoYt9GxC0FGG+1I5jplf1Vr5S75x7LrVuWsW9mbHPch+/xrITRXF5bQgROcN+59vuMSr3b2+F167rHMjRqazj5bfx9V+su9+59rcBDQ/6bausmAeKyzZL67py5VTx2Ywb0jbPAznlevusp0bc8+mxO+F7QS9LPuhffmpj5h2W7c0B1srIBql9qMUO8E2XeS/+1ggKk7mHOVPXvdcwh3RVM6/6vTPG3vI9GQo6irOvd/Kt048YZ956ostxLLbrLNXNrJbrPFa9tHpK0Zh6rOfHDXh3eiR/HmO7JQ+KYZTsdMzZdjEQlac2PGFMprgNfmc5UkAgjXCw9qnm98b7+EjZxLPoACUkhNXGyTuKh+rW20vr/E1unn3JXd/pbAPKuY2GvmIrirqffQsQ0CHmF3wHjmo4jlr5WRWoIyvu9XBnaNCAcHufyaK86j") + "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"; return decodeModel(model); } svm_model* load7() { const std::string model = std::string("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") + "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"; return decodeModel(model); } svm_model* load24() { const std::string model = std::string("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") + "L1Eo7A8ih+gVoVEOa+hCC2gFS73czsI9qO4iBrcOOE0txLlmH9rHSroWVvpSZL7vanzrMaf3172osu2IfZ0urSp9QyezTitJuwr3dCdvhqnkI+V0rQMTOnHUI0tjSz3EpuOT6J6/ZnOc6FS5XGii+t+QHnra9R6HcDeiAPhbs4ouelcyaioi/drApuHdSxGs9RQhs0gt04Z8zm2jJ5WnymXMks89nBx6I9IB4+66uMoGDm9JJX0Pw2VH02Vck+h//Fi7fDnDXZTnY3Y1wG4xDtDqzXaT+C7AcTEBFZRtjZxjlJXK0b5AO6tNNutvF13C3Zh6UNE1/oqWGgYyxvj0ZDhj0ThYpzm33RgwHeMmdO4AbVXH0O9adh4v813lF4GfgYsjbGDa8vEiJziVjfnOIQA99VL1wVBttgro561g6bowF6ojcGtLlKkDu4qM5kIUknHvA/KBdPtzjs/f5jnW/33Ne0OEMpCmyndCsUrLu6IiexWtYgUJdHixxUQuEEXgPsAX/Jme287r5mqYUsuOUuyEru7u7JyogPnSv4FWZoK8sPAojTNUz5+7va47bYtqby0VCo0PQlOHB6s/laZ2VqtbyIhk4e1zple5BHVHQXO5f4shLwiL8FAF3YoLngd+LDt9eW75J8uLqw+GU9dzWPFk12httTypRnAOj4lC+Tm65sYbx7D8CXvdwuPO+tsQ50HiShHMzVXHreB1N+khbO3S3mmgYgDufZdKmSqUZaMzi+hO1kfwsaRJIeTHuw1e0R1AbocF/Q5ILS9px2DgCZ3v4NkBNBkCLztwiAsIcUccXCb7TeChgwoGicU12TvXTjwd1HN9Pfog3tqDap69ptzGancBJ+avPgP+mdcueycwYz240QmV8rv25uyU/HrkuxalPg77RkmiWzgkK4Fqp40LoyH26o84EXabpNynkUlJpbDHygYa6cfjfT7SQvzmiz+Z4ev7h1ByWWSMGtkqnM+lmgAYUnCzT+kSMH+P/azVzkZhu+PrMGF70PklUUJzY7UTlIOM6Ta77Ts5oMJFYLhba4CbKz1zNaSm5Bqr1vBqZYO9xqctr+oV1WUQb9ORT8dnb3JiifU9yBOXnLjNp8J6B5ifh4my2Ky0vvXltOT7cgsJ92eS7uGu3UYpez1AxLRbJLNSAMKXi5wg6gSpzju8U1nfofDJX+dNgdF/SUsFyyJyrv1JdTOp8BWVfN2fMbGFBM1/rWprUOD77c35I76RZgMmlVgxSW/hcNx++AX2Yxk6s3Cxw6e9A1i2t0TkPX0HC+Z3Ui0tNFuo0UQTixu3Wwwlrjn6r1brF0hTuOIUunSfVi4KpFIigoBDjuEgS3AeS5baQ2XHgA0SDVMogONslaRHnf6Jffb7V3WrlYqISsMFc9BdfkJyzcp1LnqAE8sz9N4tnsJbvZHycvLf6N2eRm2etzHx8xT/Bj3MhZcqPFXd8SB01+jxgTAxWi3Y6d4IEBYIRI4Qp0/D4ywaN3kM/m22yVPaCQZAiKxBjPsJE6ZjNyqHP/3dfirO9+tS+umjUTTsSVYDfBf2XkqELCHtFVSPKJRneDaCnj3dnKCrhbY9KDMwY2ctwBDie5ZtdXMtweycylFFrMRyjb+vBL0h3kI4+lGxzvp5mx7QEQcfP+BMnSq5mYntzed9PIB7o9J5fjJHg2WYEZpizv387Drs5I5zutU7Ag46qurRJU3qWT9v0DgbI/uZnzTmrtLbnQIEYIKMoWBjQuRjhTfTHCtVLJ9CT2xnf6dy1DMgDAtMUyUM7Ba8stshRWQimnF11QMdVqbyrHNMAFxxMECdXaO0XkTGeRoXeWNGy1323cIyzSDoGu4qjTP+3WntHeo9hHty7qrdIM8eK469kTLWWxSHlGHf/Abk8LL35wIyLB1eJR7DpvW+UPKmLnhzR6QAF4Rw/7GQkBLI13So/4OhwJTzCUpdS4FwX84OeTCaWVI0Yx2e4CRkej+6SKn7fL0edDe1ctFZVufeeac2FF9FJ8kpsNf4uW9yfpQnDUcH+buQBpf+/x+UHVcg4Zd6icTv7RIUweF1vZ6GNTTrf1l679Rfno9rga9u83Dh4K/8HYjdzCRvbe/F2LrUIktfYQ97Nx5j1ssgB2sysx3XI+KdQN79e0l3eH8dqqncweEhk/g2F+yUHNbDys9vGrCy6fv7WZxizpkPhZpgcHUQAakAvNNbkBEOiKcqzmoH4S18vsgh7MudBPMO/rd2w/5Ex3vqX9BTAVBNt3yg+ItA2Twl3ij2nZCPttA0efFYWP+zUekCAn595+Dy3dqd8cJZj6od/XhRC32Re6SnyA7HBZI/icOhHh4sLgUTTy8O0FS1L2X7n+K14RCsnhu3TuCWcydZSckekmSifDtfmLCS7/CB+wm33pOTjoT8uDjW64FcXPgwsXIbM8oHmQbubHJ7KXRs8TP+9cIogbv1euis4hIi6rfieR805huMUzWDCZExPHNnq6rcIdMvaTcnRmWQHtjcCcUd4kF0alP9mHjy7ZHa3w7g1482u4Bt/C8eKyCNE0PUMAvkp8xTQKrTbdcuQcu96Hb8MEvUDd7TCH7nibbhE4Yo6gvR9ASNaAeI9OaDXXS+5KE8XLQ+XA5QvYbhzkLQj5HEs+wKbJEsDfmvT7gqZ06Wm4VvfsKTjmCb+N79EMJCJ6zfMXj6uAe4AYLtTUFio/BUkZwdYhNy9qcQvPFm2y28KxfArPuXZlbg+ZRCmcJzcxFtAtH0zlE+2pTAqKzsINeQnwO/wZyoxKpFJ6ly1kBspMN86gtKVCQfcMzDK54ewFW6Xe59OH8Eef58XTKq727bun8fjO8+IxMXxGfWjPiF5EH6XhKHhahYH6YA6bjHZw6YMBMAdBUwUo2QxIhwiQw39eRzAWAklb0TijFzful1X59KiqE4SAjtMxY+USXZA2tH+XHAguFSwB+5wNzvPFtSknQHIvLuUe9j9ulXleU89DD0wAgDhIh1kNKkUh0FxR2bXWaY43NyMk+/AJ1uUBTcsq0VTJp8kOsEkRDjWbOPGDwxk4artRxo2sHkLPrVc2vEXFlFq64PwZOHP/2pMHH2MmbHQ0DqccS6CAU15Qqkla5LJ+RhoXnGFajnhDtfnVo8yzqwHbYA4kwjvJwfDOeUSj0q6AwKrf5souEMttmoGCf4AVSPy2ezkJso98UV/Eh+13sHTDFnhIdue8DydX+dWegHMIwbcp796c3+CwMARJeKnmYK+JUbhVlpDzBYDeellDpXIQc/X6HokVuyk7JaLdNemeauTpqFiimsP9jK6pHExmfbzDhp7bAAqFd+jakG8oiHcYgpMzN0RaOq3S2zuQ5p+//47QKlejK/4znJTSJ9jDB9pNUxekA/ZDabX1YqY2ZxgFirSvBLg5NJAF6WE4Xo7+rPb40lW7HTsDOA6W9F464rA5SwDN7bZSvs+KK2VTzPU79y9lBfNTDqEb0CTCIDMXXQikj1jMNUjXm8bPheoLVdqRuT83in8g2endie/gZih8ra9CtjM8/TxxJC8X1Nvt579aQGiDLVX73KOaATY7iyQiC4koF7/Nn84xRLLQUdbv7OF2xJRaDxVh0KxpbM8YY/bftWF3ILNy4kVUhHJmKm8PhBVHd0voi/T1ky29gXx77QDljrZsPftBmjiz1EjagBtjr6lRtMxPFoNSFMz6aHx1XfVeEu7In14XMEoyj+BcxR3SB6W3M5rfIo5fU67Pk+WsTMWEHjm5Fq8oTWduRkVgT8qykHem46uc+qU0E6eUfdssQ+FUdHPavyyiXBwyuN6/TeYs0ldWrKvnc633wKsG4+dqj6/Wc5ljT7+CFRyc9Fa3Oah+fUCVwQPx/2zvkp9fu2OQngXdnPxOLrV2pHFnc9AySIFGQEHFq1OI9KEMu9W/+3ZpGaMg0q3LqGmES9gCLTaLZ0Dw7iWV+u4XqmHwC9Z08pefT/ZD+2qFlnaRjyX6PgWZ6giYOtgaRlifmqrb9N6cZxA9H1MO4JEVVPB84XsoF4ECNNF7d8ccmYI2sJIVOLmlVPrI+NhbDhkqzDLr6g5eKCeCuK6wIxpZK6w56z0CXYfdBdB+vd8cwB1qVLZK" + "HPwNBNXlak6krfvSmJ/9GG/vNrh07Y8kCGZF9aHRE596wQvyV7KtzW3HuDn5LYC/tdJqM0rLuZv0/illJeBV5Z7O5oVZdGNZrf6Q6jG2byyEOjei27SRc7CI4IQ+bBCTkc8qC6h1LQccAbAqJ2SlaJcu/1ozdvJjCdUCKVdJgR8/2ct3q+Ch2buB2Etv9s4AjOdAc6bnTCko+GqtOZRM4vdp59i2bAbKa7zKH73aGYfuoCCZ5CUzFIBJxRK/NSOX4RlmciZSGR4kqIcip0VBIUyLPNm9K8fHyyFKGZQXZJMiLCVf7FTj1W7mT/CRZdH/2hrnVIWj0tQVE+rtkyt7HY64ITo6xf25cjIgWfd+V1rdcduFY/agp04642rPwnBVEKJWigDxYOPNq3zU3GdTiNpCEvsToYEr1JpHaHQ8VSsvutMz0Bxn6N1RfTzjbTS9+eU6oDSuEccdm9GsW57WmgrBVSI36lCCKBogBbjnkUN6g+mMfvUUCuhz0p6jrg9WH8TXkyLi5+Dj0ayIwBkjdepNCTM9V2XDNHR8ERWQDGv4B9CTzUjpbkI4hrgZmrxxFEURA2LWpwm4gB7qFMCfsYFAMoxo5hiHWUhGOxVcExAaGEYhAaHNMSPpsow51q3cOZ3d+9KTB38J5nsOvSODo914RmalFFpXIoJ/xvxDV7UA6jU94GPWZMRuRG0VSK8UEOxb6e/umq+Lo06ez9uMVoe0RdzHU3sGXugy6grKMByMEcytyryVNv+F7giSotKF+YnKtHZqXyCezREmlDHWa3vFQrgcqYFuLrf/Zq4sIDnsmocg4HI3dcyHedtU+fdkj9kMqr7dg20/2AVvQJsF3NcjgYmjXN/eOE9yDRCppK6DHNkF4aBRyKNnwcu2q6qz5IKO9rNEhh7BNCH2DNiwdReZt4ZhmFBD+Aj8CbJVyJcTY5TpJraLb3HH/fe4exmuMVYw0MROMc1AM5D//ggaa3B5Lt21zRFR5fmwJYt8O2BL/vVEDw2I+BE56cFxAGFzBhzEgXqyvGvmkbuhqGuDxw0AOQxvk4nwqu/YhmNrrwGyFzKISdfMXE+YqkRxaBk9/6UTgZfznCmMAP2Z4mqffgtX4bP26W7JmekRZ6MLsW2O+nlIrM1Ijy8hG+Jf9qC4wSZcCfT8ze1Qo10mxyRH6lEsTSo1Uk7h3qalF/qdwcUqmnMLZVIKERSUAy4qgWesXQD3S8mI4wkqnPOh1YVRpmFLUaMA1NwMkDrvz1eC/motGvLVYQfXt03gVrUHsqmEM31JaQihweg8l7Ki0XnHnUyBxi+iLqVkpVIQT5tRy0kqH8PBJVgn88+wRLpv3sTJrLyARhQiXY0H1nIR+kSy2Wd594YNPYIpqRT1VslPj0VDpcyQYPSCoSV+ZasWdqUoO3ioOlCYSmArXCkXHQ23VNwkfyc2YGa6SJIjh1s50+tQ0EVW/P0rJ75kx1q5cILVohUf52RtKysaOD07a1k2iJ6dlknhB+iQrFK5bp8hiNb/5MPyw25VSLCrNjvfEwEIRw+S0nBaVVFpDfajPTmu0ghmkQD2mj7nciG5Z7SkBYW0rUQhTHum7p0DZLIDhwDZ4RGfZgoEdLlBbW5oLHA8jrRvMuSn20ZT+AuksaJlM4gXEso4WPRAMyoDTLeC9s9BfNCiZUUr5Ah0zc2ypwYo+HH5zkh6CUgy3aDVart2Es0CZe6mwXYSH9gF6vqfqDMfm5b/lBvJrY9KD0Wq5tTf9TEGlP1FjGI50969A4YsNSDdQ8VQYhKVFO4SOPdNikoekysQA5Sg0UMhmeZFd8VdpDayEu36+lFzfNYSVvlXezjaJCI3AKpAhLxUs4asFMiDnWuKBEdWFWXIJi6vQNsVXJsVb3IAFrTzDx035l4/reE1wruattCAiBG01AIxAuIOM8R2OBmpT2Q9Q39cV38W4qIvYnDlP02MKCr+Apb1izfD0N7ZI8jKmLbVRKBYwGfw8nJWSm5irvskLmZzgM3g/zAUxrg1PvuvqOFWAioCYuQCUGh93M10uTE4mOddg/1izS0OohVTNVNJqG9ItDvgCofoJa1jZVHfehIss9/zr4ggIEs+vjBlRVTgw/RKTwoH82v1YI74msMcvsHkU03xGqDyW3V8Y51DUXpRPnjg/EEPnIf2zrRq52YmHtqfdgtwuewVLvDqRcU7aO26bF0uLulndwghRkecUAAYDcpnDYQ5edHX5kWsDyYZ9ccpw3DaLSFFy61EXnWtS4jMTcF6KLzMo5OtCb/lojU92H5ax6O6fG9d6b3MgNCZt+yCNnH8xqVG5z7JBHKFURXQqs4tA6Su/XA1R40uWZ+rfUIACLW/r9DRN2pSYD3e6Qc4GcvJRUnAcAqeU0F0tNotYbjk/7SMR0lRfUtOMe92V2W0Hk3Zc4Z6i27MsHKKtAjaMgHwYvT3GlOJidxsDOUcYk542QnJEZE/E6tCnhNy9ad9qKsy0Wir9m96z23BrAHITMoDzh5Z5i25UY/oIpncN5M34pYSuv6cr2mCfBbQdKwWru4+mh0m/sxGpmHtXCUmcLc/t6k+I/Vn9MVeFlob6QaBRyWTlJRC/tykHI378+YoaP6wLgFP3YA1YX10IDmdjy4uX/wT6mWqp/oL3uDAos+I89SgkOafaw7XRrl4HpSo9UGZ1RjDSLQf4w89xsoHqKioGlA4mt6BxftYt14T7J5tm0Q+C6/8nG2B3sxB6ecJe4iwPcEDaoLC0CFSISEQXV91TTx1izUdl56j7XW3YBql+bRXHVPKd665aAT4rPzVX+Sk+K46HlcYetazJXt82kBwReyBmOZKFkDc7rAw04reY0LeTvkZO6dHrVShOjV7uS1JJSXDvUIuEJw5bjXW27wWbdlvwiWJVyotJGMR7KT0mpXKFcFN6XaG+NtIV9XSmkH0wmInVJUplouEUymJA3UPBdKR4Bn7gyxXDc8v/7095m4ka67Ldv+i+Y0LB9WKASjsZyvsBUm1pKeqExhOpdNpmEsI2dAFCrQ+lvV5SZfeDDkRu7/SI8Lt0l0jv59KbRqhk2IlEW4iS+1e/Efr45NU6GRMiA4IuqHnfylEozuixYF/c4KfjzYzF75Wc/Uw31ttr4zPmKaUVykIrv2s3JJyz+DxsKMBFKnbq22fQCvL79KptWp0V2+8aC5mXgr83kYJMMUq5kwtIvtyKg5FWPhKZ+cu25C7parnUqpYIxYRck7NkhoO3KdaaUjltXOwduIASmu3aH5dUKHOjgggcLKJ5sAV0mAUkITq8G5tChY26F8F6/fd7F3CyLBcKQVQz2KHUQLch9bS/LOmgibSBRyOYia98zp7TjfpEDGg6ST3rrWnFYv+8k/pxRRo+QNZ22XiZ/oKel8JxL5z6lETz69irFDmB9WlUTa8mk9AszgK6G3kn3+j1J7i32ARfyb6FwxdUH7X1dBNPaCdPio/TQRIu+jmoq0zWV8p447BprKCwIt+mIo1W3lVSjNZnuodqCZXMaa7ESq0KLr1AOcoxA+yPK2MO0ftFxbfCpkbqd55tJz9pVQJHI9rMEXFHLuq3yLC1ksWbJNP733VAJ5A3ycLmC3njwB4az3+sa3fVTLmPwHUCJLSZNwiFHI9rDScbgFhMjAsaJVU/3kS/RBqsPrsJaR6TSo2YG6kAV/Eqrs/fq4C3F+DrGzYEmnXKzeBKdVcQQZYtChCcMxqL7aO0aHlHKxbIK/Y78wuW8/MOwnncCYlXEXP3z5zOH7yir+fpSswsyfr36WvkA8OBewpDFiT07lR4dc2/6CLy1TAiZio3RUHnw8KtykIMgPPs4aMdf74pXSL6FeKqBNQMfEClJt8RnZ8wszX/jBMzaktiBUfLAokKPIB7uqvwtm0lr9FT9FtlcfyFX2yo6PfR96FXZqNGMppvDn2kJVQ3bEKMgXrDVV1TMc9y9J/UrecRMU3rBZ4JGYUjAo/XmTJQiqhzN32cGtoIfItVdjB6FS5ptWRt1XCdLb6ywfrgl3gKF7KW28MTALoYZdwT0ymPNJygzrdw92rMxYRfnIyK7svhnEdUaJ2ZqxeIswMJqFlPWd323Pe2FYnVLUPnZG77P" + "oGMwK5NYfkB0jrWLmvcoDrMx1FZQwNRvKA91xplAepCeWaWh/tSuCmS7RJdECyoWM4IA7vemLk0iORHf47Di+QBRmMedQFGXrPrSxs9ZxckbuHyag56lvYbMZrBHPvpd1txsitvNZiG489n9MI2bJhcCQSYIEyd+6/SXZKZQQYmJ7c3kRi2OImUEHwE5oU/wKajHC5XoIoZJ6efhi8UeXw1bxqNFJdOfWocIE4RtSKQsegh4yhZFZW86LiciqhoGt5zNe0Ah1++qv8oW4BoN/CqNTeWjRRTW458OPxkduItG7T1j4dQcVSV3KaecpYMsFqGXPJnruxYD8tbm/DyP/IghF0ZPXHalReDYKBuV31yDfCFPbBkRTK2SK95iHF8Nc7chhc6eTbWZB3NpFSZgzHZhXZZDj+6NoJBO8ANwy82rSgJ4FQdsfrVwm3rWhxVkXJIYmKcAfHGhY0fJbJPbXICpWAqw40DrAMch5ImxcFDW7bZ3+cF1qptqf94ddR+quwxY3PsMMBwc2t0T79davjv7TG6PYu6cgMUrNWEfJfA5u4+OmUY502DiO/jUIXYFM3rmwYY101BIOHPRGGoE6aPWE4g0U2X6gANwgyXy2zt8CLDXio8S3RikU768njxzTnlVrqK2yimpUlX9d6hB+5mzid1wKHvoBdsdrI0di1tlYiJW9uLptgnzp30vUdsXBpZba+TXdE8B6rAfikt0KRsgrU4S7rua05I17dHkG6/7A0Hdby4CFgnJnvNJ4vz69bEWB1BsT3j3iBQLPXlNbaFTdPp5KBiMFqXUlGfNW63hV0IMKkmsLTLaaUcrSMiEqqt+scddTxZ/XOvU4y/USXQW7LJlkp9Yec7aUOeFO3TILVL+jDVo/XrAlEQwv71slOcwZZ7Q6F65PbpKWZw0im1ZuLH5cgnfG+FKa70Cn9UuvbA5xSxEWq7qzbxxqIVR16B7RblIrsdRCmgiG/neIiAFulRGmPpdh5MK2TI3iex4JTNALbIRjuOTqQzsdn3Yw7+fp5Pbo7MsSHt+/Vi0jVaXHfMkX/nq4YnI5Pue0u9yTTDhb+f8nR2nPX0leg48q19SyhsNV4rK30e/idb7s70YoZyMd1mcnoEE+RbFx5WKTmESniHKb+H0BhXtESTod+rT6VfhK5YOeMBWDW/rKPFwxFe2kWuTjU7r1CVIfEaShdddnudKzkUA3IQ8a0PO9TJ7Ohzc6moxbnaqszeqBi9OrllrZVc7Yg7amNpCy7t9eBgGZhWWiZsbV+f10XeBYCeEc+/Kmc8YCmEwCMBHO9toGWmAN5/6YPneNdRBTWmG1690hGDvgpoGBa6tTQRsfAHi+Qujlv7XsX6orF9kGDgHyeNkHkPXFu3+rID8renCOHTLnBxfjv7qlfW+xe+oWVlBaHZ8TGeyuni5PtC9Xul3/LTLfL/JZzxQL5P4ktADvX3xxZrOKaGrhky1mVQfywiMshHGziM3TKRK6EqSmmatkG5lTWJdurpTOH2T/oD35KUCZCqFf5cVxzDwr00rgWzMH2bE+vVXwveZzkxsQN6D8+G3T+ymuYkbZQbmim8VBuCpRwhVHBkcwTJ45aLi0rSiN4uW0Jud8UTC9TfiUbSwYDitTYrdolzDXo4ljzxfHBRfCydcP2fK2OYn9E00AXfdYv6Ov6JTjwua3i37SlRiIAcUolEEZDH1YjcGxz67tbJ81K44/89tFwXhyA9guWffaxbWa2VG2l4uP52kpVFi21UaCWAzJPvTjZ4SR7zqYF/r6tXsNj7MLKKxkOV4Uco8d68/9BptfF+YNei8ti8P53TDkRlNSNnkpdf3Bce65OAPsknlllI8pHZNj7o9xfckXKSXx8CUwkEaAvFNbbL37hKKM6AcVTLmSAF9aDqi38ZnoEVAOb6tujluZJmYq2TtlPJ5U0TTPCeiLo+jIwXz2tduEcMMLuD2gjd29roNwa+GZJedrcwFURPhDBVEgieEJqecl/d1OrpaKpMM8O6BEZtHHNKctRv+mjbvUWDtZo5RnhfbYKfipvV5axcw44N9DSczHgQ44U0CtNqBXbDQcjEAUuWm+oysVJdLazBm12pite8xH+EaS7rrBtsqTcj2vThyarzVrRE1Vmr1H7wtVJu4Dh3f0shZWFG34+Bf3GpWon2D8O8/ihiiRevQaMQKzSIhsfLKEv/qsCJxFR//bHfjvxDOeWO6V4xHIUI5ZHv0iwxX3d3fmSNT13/XpHdBm+x+B4NedrrwtAjzVh2MMLpKjs+S5Y81pI+l4J849tj4AiNBDrCGjFfOxUZ4FfnknwKvtT+3QkauFVgSumQj9lUo0cL9qjnyegz8ml5mtpCk7S1Y+pbTi3ojMAXa04a95d2QAD0yLN9my6n65A/21p8izkZrHkunYVomyYuQKw3H0Hphap80ec30Ku6Q4Om87x+5w/UIElpn6gAu7GzB7Tr3OpKHAd9A9nmaWTC5EbAM3KWmNfQk+zSNSPq+Pgsh9CPTW7Hrn3HWJ1w7L3iuqocVBsF/PoXOiu2SBUC6jeNYw13PqAQHwG74CD0wz3vxfV01cuhV5ljb0ov9Oiouxc4GxzqREjJznSiZ8c8dPv8/UQ5QcAtOghpvX+hnFIzY0IeuBqryuoAsPGd8SQuA3+BtKuaey3wqzrJ3j7MZbCelK7EbtZx9zrRLbsQ7qE2uapgar11HsPNmhgbFhNdCU+li+zc1QJBbv3KCWeCRTPjpSxzaifR/AsJUepvPstoNy/MrnRLHF5OZab6ZRjdJLrI/aXW87l5ea1MR1QQqdN4DTZCdvZjkF7ygMruE2y+4or1pmcJYMOo5wjssL6Zw3d+/qpQA8SKFlmnhaNWw06R9kfYJpgUTbzsAlHAGKULjaU00dsZd25AnzX443bglGe48YtX7eq8WLf1QE6ekAcYBeND7hhtKRldMX5zmmb6YrE/0T1mVtusX5OLFx2RzDc4MOyshaffUNWHjgoaErZTC9JNUFsMfjjwVKKtygV1JfbvWtNyanWpuCpGokuz0jrixXtfFrfrYlW3mFU5beSIzB8dkOqi/rmWHuBftxcld+ISFc7y4kE32UmnyVnqUeiIGI9heh6B3Oy/BvqgGXgqk8tz/fQ4r3PPZ+lHm0YTg3Ttn8yuHQ+T/qwZ7Jj2qZGL3P85Y9DBqR2s0CpdcSAzl6vmnGd/epxTqcwpEOn8vSNEu67NQXTxQSXr9XKpmi4z5br1K83npv6ffRafFTVbHysyYZ+z0iwehNInR2PrKcHtRDTu725y6iPXcOy6JMp8GqYSglujqP0qd45JVWzse5HJMIZ1ZxCeq30mjKAJWM/tgxgnHOTXDf+wfX3Buj7RzepcyauCCkoAjBKIgVBUK8myumkeG00qkRxEOLsq72GSt9CgVuvgKWI6PW7Cao/UAZ0xCNo/TtEqS2eP4u2corWrBA3VDo2vhsF5wV6PTVAj9Y8Rw/EGbneM4v/cZFRMG78AflylePoTQfAAQeDs11ca7waG527o3N20MvRI7lXYFhS/CEpELE91QAKjSLhAAvC6x0DXhmFkKk6Ii3Q7SYceTAQKFZiCV8MeugS9VEV93d1tCkpbzGPY2SxiYKnxKJUXj6s4snIfJ13DzRdRPWDoV6kolehCfypqVAd7xqzpOwS8w8whQ/hM4Pe8T172FuplJ2Bs+hkjZfbysGWD9bBS3HHmE9igOGFYuEgfhKYyEMepr6TQ3DNmgyZcUcvCZ8//eiBkG9zcqTa3u/UnQM6LMQP80P0KuiytKPHZvR2CXUruQq8CVVysLeordYng4xcvdPHfjag2ZWr1QBDgpf8gQtnpSpUCbjXHFGAIKRrQ0yNf75aegyHITnMIC6GLBHmoG1pFnr7D/7bZn17OT8L5PkTYDigrvy3/DAkppwuij51V+vLLq+lFnkpQJM0xH9Acv1HH7atPxTbF3063w+zUuRTW/epRbqwQZ5fni7IQlv49iwRhR26PCrzmKtzsU6R+O4o/Q/a31iAWPo7vudt2bf6tWeneCMFnz8WRzZ98J/fii8UEShpOfn3sx8Y1fGh1HE9hVVdTlcyoHpZ4mPiBcnFwF82" + "wwIqqO74MfrJ7dkWoR24umsjJq/jaa5XXW84RefmJbXXCNxmcFPeJ15Gzi+xqqw60+smDNGi/IJ5HIpK1cz2SQlqbUyFrcK5yuDUtKJdX2mP7obUY/CfVJy5q0bvWmbALqW+jRT3HIWu/tk0IGRl32LwFajybfxppAnKRRtEepQEkqvua0qzo2vtpqHlagD710KYw+kMAi0HilGDJjr6QSpF2F0/ohNWA7T/tJMyh9pyzdqGZ3jYQV4la7Z2bjeMmbqf1Oc8lp23HEYOufmT0NY4Ap1cDpRZf3c0S1c0q9gG6tK4RnUCWVmlt6oM8DMsx8p7sib3/DNaKL9u1MJmACRlvQCjzby1C2WJ5XDwNXn33I2GulrKAK5zi7YD/AgczutsoEERWK/aLMTl8qM2u8fSoSd7anQZZgQ5speOs5fpts+SNqI8YnxybQdF7UWmqjvsPqxpR9Gzyb/qjnVGqlb9TDil1WotfKI1qxrClOIiAOt0nos/KFiuiPNTn0LiJVvR7xM3qVqa4xKLy+wuyxAUm1PHnzrJmW/Kotqd5vE1jyumd9UlFPSwA75XIk7iNahM+cpaPcJrEleHNCgFkq3tQblxnO9OwF0OoVsDiDkB5Cbf9oSGVw6Q8wUNo8inoLjQrqcHlh+RNgVEX1aEfoIo5QpW0gXaKMEYuzRoC8TFToU2tR9xAB6YRBUbONb66oZWMxm5i40yHOZYsW6m+/7AkyMb5G0iBdhYYuFldHF4siXgDxJ5PvIUqv3RKSpEN7Ihcu+CwE25mnO2Z72ob2rD7GRUpyQ7eRA9LsAzdWdSrsbLPYSJ41/MEMSQnftU/qTQs9O2msD8ND+t4tZiqTwNn1Yn6L6hcHxxyEAYRP7bSt8K1mUYzwHBk7dlLUlla8W/uNfg1XLrZZBcsq+ADGcd2slyOhYaKMbW+a18ub2fTjv90I0WcCMKd0zD7oVlRdkwiHh5Ftz7DMceO8g1p14hcQSBb/Snj90LivEIEBaY+tYX2DBh60nP3BQCEXaqINmLO5EV+gw4erSerjkonpBQ6SWYlJEDhCtpoYN2EZiTlTadeeiF1q4fy6QKRYUR6d6BNWWqFxLhfe4ZxlPTT4uiSQLdhAnwY28H2C85NIzs25OZhV02A7DiNZia8KFtJQI59M551eyg1buulvICG2C451RI9ygInPdgrMGxd+R3QkoceNp4K5vk6Weaeciqnl9FEsBrq048YbEXI+z4bzUnvLIn1tZcStWGuJrpRghVgLDOzliM2KvRSDjRJ1dIukgxQkYoXjAODW0OBYtyaiVSLOHaNFtRIj0INbcQUAdpsag/Azoy5YDtUrIbzGisAezi7tbhHx40YoDQ6dSMC44y66uHxEewraIxphmoLokSJlzRXhnGDHLAeDPS9iwW4BQftBoVvy1FXrY7M93OrFDLIXx7wvctvy1bhTvqW9gUrtfrhebzFyn5oaZztuIY7ZZ0HdFMMBml22enS0U/yVJpk3JdtNJydkifdeG0tcEHnBq1hugYfMxyd51pWZWV9GHqnTH5V0XAw3IEjTOni0kj2JohYAajMbyeavzufm42kD/F7dEEZkLJlR7nC2dH/bli8UThohKqg7//qXw4Fq/trkqy3HBdrZnmqQ8KMirg6AWEl0LpygbmR9xGpOQauqer+tRqOM7CyC17ZtTh/NPqIyJMNedD6KXXa2/5lRTr0Eb4R0do7dJDpteKVvj4O19a+h/UcbFseVhV86NugGeqdALg3pW05HAX6vFlZ6L8qas9yFF1V5z+J9lKFSseIW3kZKTXj90tYOrWhWWHP8iZ0aMIDiRVeZBUGQs2SQpci9cZzbq5Q/3B5zsOZ78WmNO60J+CgGp1ChVZypNlBqikHrfIAvJueuuVrmOBm2pJQuCDYnZTUj8UbtLUyADjjSt1zAWn/Y4S4bMBEn2VwrK2YsgDpLj+sEnZ4BEhftRsfDTW9b5NDiepyhKu/NB2lU+4nWYJIaTPNuI2FsSvbPRpijD/rMa0CKFhoKmK9c6GRskhpVOxR/C8R35J4y0zOxoqOVbc8yi6mptrvg0nsgHhT3KsAH2c8xl1VC6GTRmgSgXF2iuriPaCpXML1C5gEBPY+GCUOyLxEfiey0ECQ7y97D6YlZZnB1exhNOalBCwrrwwZyMd9XImUcLuX+VEsmvV61QwsQENmo4MlGKA2IQiUY7W9gVQ4FAL6vD5VqmPLFLbZqi+Mc4Ybr4tMKjsJWIIwxVzBRQiyGKsYNybuIrvobxu/hPCM68DCvzaYa4jPwqop4BTXLdszYuxqhx0aoDhgdiBg2OrFGAGaCioUxpGK9G0g8vhD6r7/nMNN24NdcNNGc5w4/I6fIqV5MuRtM/0p0IihjUO4y4QhjJLkB3QD7VP3p6oKzQGeiKuk1Ux4+ZmWTqIpjH/hVYX2Jft2UlgQUjKEZnOQG9fYf4b1p/1SMf1KrZz2y/k3XO17XAVqAf2Va7wDncXP2Di7iYC6hplx6gfxd2OlC6yuEI3S2MR6g3V/6vbv/HEQKsee88T7VZVIk0r3iGWlA2Uo1oFuiH0kU1XCZlBnJidC7aKzNeyHHVHGWrdez9IOwfz9RxyhmCHWqpPYShIKXBz4h/jyNmC/2zlPRENBlcvcw0AJTvvPlkFuvIvLRngu4gKadEsP/IanCpnIN8GY0EKKCV2O6JzO5gsYlIpgoPgnb1oYigT5RTUsalp3YQsRJGieAYYWjVRgN32yU/NJDjIpvLIDHfuRNw/EVXq0q1X+efu47Vks7LBRff5/ZlVmJl2FH1VVKZp7j+xqLGgNWH4JpIkFlaH6vnjpK4UBtXnWCPixvMp7m5Xj0RDQQcz2+oPv3I5yZgm1DZbneiuHmjLlxEB6uZ4NQaBTTzHj49lvaL+vTTfU4qbUFpWTyWrvJ6nY0qD2Ka28vBWInphLMFQWOSOHvq8QDjmtApNYiiUS414cJkbG4UxTacSJlZRGbvv/oY7yNRcslu+RpuYx6cIMrvtIOmtsqhkik4G1OFDb03UUhxEpxl+Y/tElpsvBLlNrHs2Tj1bGw3ZU3Sc/t8/lTXAcB9xiGMnDdWW498tUh0tqzExB/pul675wK+mNeFU8GQecUk26/L7q3Ocuf7NKvcEf5rfi96uMmVx6o7nCLWcqQWsuAGBAsd8UCztPsuvOvomg5EKZfMPLekhOmDg6FcEkk97WiFCu6wcWYRktNH93Sns8/UGLjTL3QCDLvnSes2JZjZ3Ff1Gp8KXUlflY87xy3382TtAYMpaXuveAWKuVoqVzgJpWdzRcVqyzLm7El/X1dXtQ+8ADMzqGcA6AD+t1wjYTtv0eAHt1O50p3vXjaKSn7m1V0wMFJFNtD7Pjk/keFvCuoYb4p+jBvwrOdg2IHNUil2oiQbOgLfIWVxVKOvU02RWc950fkDUsgYlzzBvKqIOnbZXyBSqUs1pat0BThneogHj9jsCTh4+PrQ58eQ/IWV0b7itVOTsHXlVFGE64iBXwvl3hXusWKAzb3smscJr9hOePRjVWQzT7Ggsz2xvmowt7FjqjC2Ie4L8bEvg0pVfIg+0aqKCjt9IMclS2wCwPe3CRzYlfCgTvUC2macTghCQeU05AqnxK+z93b4Sx9cs2qgd7JP2GAZgbDH0rVVs2N5KDVvKgCTcMYypAUho7U2DsKaNEd/V4M0NvC7bfY5lgaIyouL81R3xR9hXyUsiCRALESuwMeQfQ+u9x2kT2W/UflCkSrJJjvj8AY1GdYvVPcJtWO371V9HLfwA4Qu8oF6x80JGfU/kWSAGGngelwKgq8AgyU2WspRCw43UDugBt1sPMPKwzdVdVurFBneBxPMdy5fmDmy9DVTqbYQIFjUrmez3Fi3QOZw8tk52OYiqm1odbsc41ViC0kuOIOQYmbUEf0ecpZrz2D0IdmDMAkds+FD38gj60IZXBL1CbVPGt+DrlRlKR3O1AzmgUxHujs+Tq7DUcYYMMnxOfnksEQ8y1adz5bwzLTHx5CYLtP4xxgZ8THVV3ChO9ntcn0w7JVWhnuqHfYI+KVZrVrcxHNnbe2kx48rRnLakmTURc1csx4KTebkTf1" + "BAyUUo9Xb/rBFqGh9AxNWwH7ehTx2OtGUNh2TjxbHz+rvxVWl/UKU5xPEXOkOtNcu2yFLh1kkH1rGt1vOTuKgth6wU3NhaI5qqTofhVkM+wGCMXePd7mYg3XSaN0uP+sTULM3/e+Hdbpmu8B5asBmod81lkVJKqlzkYP/ig4PuPNBCGfB7Vn+Tma1yJH2+1PRBxkbvEcgQzIkRESaz98zSGdbcQpfhi0YU6I/UIhgSS1AgUI0SfcUtPPZyU0bxPg/SktdZr1z4nD1Fal29KYAQ4EkFUPMrsjIsWRG2qYRyStjRh+iPSr3EGMNZrn4SrsoM1rD8RPs1chxbFjGrwmd1ckFFHBM8X05eQWnOXFfFM0rvVh9IBvvD+gXoEhdiHc74QFyBs1NVU1mmZvm/V/eLkgfMKOp11KsBWB6RoOvI1a9xbk7kFR6uy6OytvkLdScuJTMLftH9d0NHnx2Ir7SkQUCXWFs8lAUEzUrcbVwJ2S2EJCnUYOVFymLhsZ4kdZDFTkddRl4plUCLDi/RPT2JeWu0CNzER7XYJkNDXvHzQiGowIgj2jxhrKwnnaw22h3UckfDiUd7T0zAA44XPEDsCFM3kKRTf6qt2hH52UC25dY4hwWIHfI9ncTXotYgEv7hsAddequrrYo/jk50JdHXg6Xph8w7LRT9zDHIHMUfnedena2H0tJymn9oinGDPSzu6TCK4d36KNBAyHJdLppTaz+oiUYGK366xwxNRLWFHis6hX1lh0xSSUTyozC1UhrNakAe8VsObj2abfBz7G8JVWEhNl5EFad7yqpvyB+OPNR7FxecjOl3KjbHujsgo8dnVJzM9xmfwsAfjoGXipmvO7fX21FNJpgcyJTBwnbvc67zM14kO73+oVsmuuNoql5tJ18j90rt7auhEXnF+rYLo2tLVJ01f6JL2+hRVr+YRfYa5Ahs+anUYA+Xj4nz+neHuqP//Lc95VPDCquGlch7WPIlLA/ZFZ3uL4frLEmxcrRIgSae07NHuD/y5scSe7tKb8CCK4L8QbyQQszfgi1cN7PvIkV1OOatqdXADg3UwFwDLSy4roxb841cQjIBV7DXPQgcHB1KlJXt4ODEqNHBSgjy6Pa4l+6Oy/cal/wc57ntkhlHtx6dV33TzqRUfROOJAHCkLDI/0cpFn29Hnl8IPUlcS/tXNcV27UGJqcSLRSPA+6B0w3UzLeat3mQNDiTg06rdS46Fr18FfV7Dhgmtdbo1WfI+lyv45aNWroKaIJkTcE5QMdr002RSM4R4E5kiZOkonQ4mX/AL6uPc4Ff+VFgU/W7+qF+iftYPSDAQoVidhnSm5fFBhHA3MN5AOSyHez9CBUjbG5kDqH9O2OkjFb/5LRknY2kc+CyrF7WdZ8OdDPVpvUVZQXzT/tHCOSm+gxFM+SBVWOlYhKvnN596V+NldQs+eVHLDEKHorXPCw+NL1v7bT44dsl5rGLSofx8iU94ro6h1CdVrNxrZHjUVdvN6543Z9TQRFGuUGoh6XfDT0YPbje4DwM6BtpWm1ORl9qKOKbnukdROW6zSHPAghD0a5KLCCVx0tIRcrvig06WRKI+nSNKOkKv9xaHRlgZXolE7ikDXFfw9ZXl4qQl98DC1awV6e3daCCIGncHLOcROm4hF6nzn413wGl1Rnxqn3aabjcfUjA5F8FY7Et2jIC0nJaXGjSKAVoooXsq6R0cY41e4IJmVNh8eZs0ZnXuBlcmBZsk2qGv+yLqQBxrAQccwy/FWn2/sxrvNdX1JH2B0wtM/HirZxUSGjojoqAoaWXVcMnDsCoAAiblsMtHRM+7jyddL1sBcds+bFeqy2yhqndqW/J3hqxQd1gbG8kVBqwNOxa4CNE9P45sY0VOrFx8PRCjVc61M5Ur/tRAk2VgiUGMNI1RVuM1oaT7BVwOrw3voFotQLOMrLoy2wG1i/WeYY1FHSEL1ysNi80JuzcMYyW/A8NgJ9Vsnvtoj68/pH8yJFUo5XYBLHqXqw0HKOMQOMvg0l+pwgjjD/QuDEU2oueocd6WIjZKP9WoPzL4Tfyi4Xyi3UeunyD5tptXVLVRyRWqq/sOflXCtZ7bVzY6Zyx+0T5QKQ4Tq50kQNoDfx+i5XKfdQG653VcoXZnSg6U3Jp70AGClmPuL2p5JK2mrGVDlWcF93ZaAygd1T/KY+PWr9qq8+Qu3BC7Pl9gb16kbN8nOg5auSXwwB5OGsRf2oUtBYvyBhDYodKEZDQ8Nbep3gbs73ke8ga9fwQ2miNbnUOhAW7gU0BYmVabOuqGs6bNwFT0OcE4DHQiu0le5hovUSZWcLCA74b1mZ6F3TNO3zUI9aQcvfcF2B0zJTvs7HgnILB6BHtdDal0r72ZWik/I8F92MxE/1KeeY0A0gnd765BtQsbiFzpBwLCcEaScsNM+6+i1W+uc0y5HXH6kT6FA+KS60qIxAkW8FatVmDb3UxAg9PRou5JiemefomfuAmzFyY8chuaF5/wNF6rmA8KztTblxyCSArZRoO1XWN5uRcvqYJtmZvEVAxiPD2WjBN7DeoUqrrT9x7LZZxKoNDJ0J5bestfviw0ibGwum3thiCvKT8wsuhclSudFI2xldXziqDpae7lkkjYtpmfm4f+gnY5gj9tMcar/IwJ+bmYLwi5+ppg1WBXPVFDcPjJM93zNht1ahr+wn1QvHDQmUipQk3nbUqfx+WqysQRIK6c48x7WN8otjkFVO7WmqMABhcCO3JRcz14VBHsg1wjgTuAMG++uCWJjfyVP0kB2ZYttc9LirJ2W+eKwjFdJFBHRH8vIHY/LZTWJ2VQP4QffM1EofguPblhYpOmgeQG+e41FKISqBmOMmKLZxYU3uJIL4AFDp1LNKmXzUOKzb3gk6ibuhbMq8B79SSo6Ud7z3UlaEygPIQWvZjQazdtRfjOwv80kruLxGbuKjvM5AkdBj07P39aOUUspr49RWK5tOQ63DiGqpYzBG4xlyJ0ozaw+FKVJgBTT8WhrH6qJpELblNCDM4/u8seObsUBhHUcK6uKjaUa6RZyxOIRUrBKtyrBxVr/K6gSZ88/1Ru6eXywCXz+sVhiNu4AKFTgLCSk8scBb0nlia3rFO9sW5OdaJAA+4WVa9flAnayTHS1w66XlMy43BLtmmOpKwoA5mssNiLbsgYLQCsij4IAbj6/Rv+H1RP8mN0ygX62dquCfEYg87UjA1xAjyda3eg9seIA9gkBosvzK1YvUh99uHdKrbzIrUFR/R847r2rgvUWPmz0LjVWPuhe/vCPR3q9FI/NC7HFzpkcjnhJ37OzeG8EeUeQqU4e8mITmAskrrcsnz6zPOPU+yS10NGZxL8xTsX8u/ILKDaOVwOYZ5vypQncqrmN6S+ocDCpC9P6KAbZpLJYd9y+fDBvv98NGDOv8cYfjk0bQD2vuhojaqo14+URr1mU5wN1DoJdPC/9WiAYRYC139ESj+8BMqYWUw/ITxXEZ+BVQjYv6yKlhL9tQFULiXZAtiV5s/nGwrL/UZDhxtfXOwdDbOWUm81nOjaBha+K3XABxfne9MudqaywHxFf9KK7gJANnjuZ82iJ9XyYF0ElkdekW9cWxoKwVCD2VBq+53CQaslE1T59TzhSbLlBEK1EovIa9NT2o+rpTFOPCdU0/FbgPu4guT41BEcq1IWJYrx3LnPOT93iUL8QfTTqx0I8+tk7sF1lNANIbySOANU6BTGMGOytYG08RD1jde570dUoEpoj3lT6lx+rGu0oQH36Y7kIM4bpht4KxenXAFDvGU/gk2ql2VjVqjQASYWwSd7lCaAbeNT0Fvb6nbE1TpZB2FiF2jBgrATm2gQLhQQlt1NkTiMbqcOap4P8D4xkyNJa9gJ3LXk2gi6GmCthdxC7Bm3Mjm9nlSt0iRSAhE77B2FAsv0V4cfXZ611J7omoWl3Qr5JYiNxa8/x5JePLH9EVY1dZzUjEiVXKWgGD+HTrcY1Wmt1oxBwlO9fnpydvadVwTwa31eAIkiH/MoFIdgAsfUwAqFpsrx6jBGPlWpDRaEApAUm+X75Y57ovUCXU3m1R/d74hr6oMhsX5Fd3EkzLzjaqbor4o" + "mNrT1ZUoY8YkNOp2I6fIwgVCeXD3QT2OnEHqfCb8EjNLCgGwCgAij+s4hc5WrnuyIcbrNdBibxBWffvgMmhSOL4Hm+dCG8B3TiG2FeOou4rJ89IVoGdjxtIyRmop0yecRJ9C1fJGK5/Rc49RnhDpS4HKB4rVEru2cJ+XegRDKWmUPwTcJ7XsQZsn7QICml7TjZEMcl2FBmnbfDtmaS/8/+PRhcl817pOKrolLMmgvll0htzBNoqZnt/buNfb+501mP2YcCLj++k12QVBV1aPnDvqcEFACCkFHBBd+TajCJfoAtR3tSvtautO82MvNhBx7aLq2DdgznJK3MYBsNtDJjt+Jzpfpazm5HQpzQtJXIE7qVkrQ8n0TnvqBvds3tkHKeYE7C0/BeUFmc357gX4RYyZA1XLCavdd0yL6GkGra522PCg10EQlLfXvhrGSP0Zw3KV0a1t5XHz4U/6poo6s1v57IUSB+HWfcWxM3ENmlrQtunlVOXxGcVxpB2RnEOp+A9vN8U11JCuNs+ZS6DKyzfMlaqCmVobM3V6efglPw1XJ/ssFDsMSvp6VcS5Z5slvccUiJFZ0iPkUlCFlKdB40DBdfuHHK4tGNEWLO3yO6FFtbTIOH8K7gVzSvph6AM4rSqJsFgRU3WYaNb3PC7i01t/UMWbGOM3U/xzjW+VEPkKmJ7tER3BBjS/UtDZKMPfwQpikGWk72JlbAHbQCeQyzIyNFftBJ0D2kXm8QesAfAA5UfWTTRqDkqBfuCYYwUTXy52K7mGpcYoaUmVSN4rkFKCXm5WYF4CPV3eeEbQpkAsEzvwOt8Z7cGBRLOySV7d35GPy8z9wWNuJEwgKUPdybuf3U+fKRiPcZdWXzBUXc3pR+UzYFjD7nzPu8WDaIGBBm2h6XdOyh+858gFBRBD3RqVbEEGOiXF2y4BS76sWrNipZFxSkRCzhDF0ZlCtYabOjSFOVcNzAr4PHbtabk69qQXle6dXuKj/v5rsSKgW0oNy7peCrDD7bokethzmXWHnJzRPbadNONyjjb0C5n/bMek39prQd75QOxoG/co1Q/wgZOxgN0bgYQa9D0iwj1GfYExCzdg1ELKAVL3vH4sefkfKzOOnJxc/h27pxyN3VFH6EgW9yKtHqjKD+SgHsQWDPga6QqpzRnpLkD6IlpXl29bDdp7BLtvvReiF8eJuswRhPRwPYqcog1eZijhSc1uEe56KQ//DxQMxRXquAionPgjBrJ98HyfV7CBRhn97+jVpzG/PIz5Cq+8JzVlKN1V0YlBGe3lEgj6go9BEL/ZZhuIKQMYOXrcXFXr7yU2LDD4OqeIK+T5m4DpxqTuLdUPI6Ua1ew7V8uA+kkBVO3c+mqC1pSdOQvtcXpuIz+jzwqk0dLaPC23lNsfZiWD2NXdNdA/L4AYWO0WjGwwahl3TDPUS+39KaI7z3lXlaOhdqtjFu7y+zLITRK5PataJDURiFX0UqvahBBEJFk0rXDxOYVc4OY6QyzPwOF7wOmd24JJvmBqHb4XfjHOGQMNVzt092Zbu34U1Dk+HtcgyNjOp1rCWPkwXbFh6yp2MMBjEGQ6H7NZo6A3Q3VJ4FdVbhScrcBwJfO9jCTO+dGmab6ENJacTZrCc7hp6DfItVXlNG4rmPHihPljLluG7YOJJfJ4Y9/CZKk9hXmu1v1NekkAQi19RGbDaXuZiRFSoyEnjQs25/Iu+J02qvUrFHms2RyDWcUQALUNoDwotiNxUugqlDke0h8cILYdmiwzUWg/QIuCOUQ5vSAn+/rm27pKsODGkNfioWR+sbrnxivurddwJdPp0iFwW2dEnMYrusCeDJLyBatjkRyA1fNq6dPNxwY7QmKQlw8VtPqaKpmc+rBIvqZHrzvTL0Grl/XJKlNy5iPqUGs/jZKguUwZzrlWhjzTqUVX6aiSG60qT3rcaWap/jWpGiB5mVhpMIgv1aV9NUgHX6/rvE/7GfgBrPZhGpupCD8PKigVvWdWUGhVceabtRUMN+Eb2GxZq7OF5hZJytXq1aueX06hGhvvzj05+QcxzEgjdBt3G74dzknJA91i1HRzOIYD/wjTgr+3o+KSriJWKCyKcGC8BdvdRmHGkgOCcO7FT5DgirE86iXRaPlVy0u7IAqfY6qTYpZp8F9k0g+USH2Zpah0y8cZzco34ztTRojBfn+DDoZXMivlmu0bLiri1byE0RAu7lwBtSHgIEjrgKBljTEVBV+8QvU5WlyGTEdpV/Pb3i6Jds0c2zmgPJ5PJNnAsxbU05DQSQG5gAZ/7BxoCUNN7xjlCrwzyzoCyxsL8tWmSEwHOp/BVD1QHR/MuTWfdUWZpb7rCj6bbueyn3OHnEd+O38QQMbb+feZjAqurDgLwTn3MjKfUHOI49uz8gUVY3JGL0mhcsq1o1DZZLdmxlkK9wC/uAS6shAPz/NBVg0O28789iPobaMumQ6AI9A/YWPyYF2Z8uVqNYMFogMkaoAAgZnispx2QYBYp7krLZuB4Jb8wSenR5rrMM0iHQfAt8drnAGh1QIJ48U1gVzfMdKI0gT/QwvhGXqB6TECzjoVy+2TeHGQgK86Scn+4B/UOt71ZdUDGmLeoiTJnHLw1tFSl+KULzQTph4OBFN/vPGUYs8HepYRdPTQp0jRWGhrEC6K1nLFhbwfVlNVwPB2bY633XXvDgJa0z6BkQp2sUZiRj4umeZEdVUm/AQeFeFClIUF0Xqf6fFrkFBfnRP8PMauzilrXSqLqf0UJlPpyqTUNHt0dFAJz4APBavXFqE1aX5lbW9mOTyuKhyq2rdAgejFCpce1XFWRehiLjv2P54gDRWeOZRLVyd2EKcGUNQpmEbWbuE8gpQCHHUoMY6f98hhXdqbE8o7JwuuiHSBg3VWq0cqE6KZR0CRBCFv2Ebxp1EH/saDhPmUUFNLsh0PHwUCrmlyeWoMTiKY/inmNgWUyQwLWQqwwVOiU4EYKQXFxXBS+jJE4jajjBKcKM6qwRCJ4FlynWX6dO9QNNS5sBxRx2R9fmTwOKB6WxyYJ3/uMra2vUbgtUWEXGiQ9UhKYEG5QTjh1QH/TuGzBgL7M+3BOIO6VscFnIUIsAHVuR8t6onfYaV/9+S6/+YU2YoAkNZecvgYw8mtHDqWQrhqSwLb4gY+RbKpyfdvusDqrU+LRtCJM3dGF/nbqvcdVCsFZwAg+/viDO00YXFb1Kz284EKc5CqrwoT356exwNdrdDyDNBcqI1WZALC4aJHKvg5WQqd5ig4a91lPuSeVSUYJk7pUYrmst9StG77lKldHTu+c7+dnNcITsDPBz0Fgt2MlCNRhLf1N+Uq74HRgwuqhWp5tvqbZe31vlSAqIW6xKmPp5dNavcN5Q3tzlabkRVCg7j4exRScoz3PSo51T0ftmoW6yI2+v65lke/aKDpg6gC6xrYeQEaaIt1NfO+Px4uNEjmIxrChZJ169klBRqNHMBvy9Vlmm5ML/RpPnrcHi1Z/d2pPvSye8Rp53PYHa1VO3wqVN8+A1bvkYQVILMOhSvqP9jVr4AuVLKbU8gonhP0T3vdFVGVO4yDnDox/8JXVKCWSe+iOIPPeFIlh442TNIQ7C0ASAJj479BgYpYxXZc93Yp+Zmh7BzXvCOfTD0UROa3W+uLSIaPlaMFHqmFCufkoqL+7n6dxVtxS2DZ4kOJ1V0bZWYb7eXrvdbLXcBxEnHyoTIAnNaHraiyBLcjF2ZKmOVE/NFmp96aBqGFPYzdgEWf4tEUDwtYeRrp5TMm4P7H8YlOiQTfg4fEjpn9izniF7eMm4GmS2vsdYEgsHK3G1NFsCePNNpD8U3oDNIuzp2b/EgP7PTe6TOb9P9BKimAB54UDIeqGlTsoGK2FymCW9pkWMY5t7gSJEnb3uZluEMORq09iwWzSw2+HZyvXh0ZK8UNoZTSaYRJEowlCqsoLE7smWmALA9/Zgpolo+0N9LQyq/6EqpfL6h/yXMlO+DWfvIHY1DUDjtAFWNxGipHtJGdkoPUsr2sGjHVQMD+oDgZqmZ6/4YdQvy4S2SOyW69v+Fpy8xlRKMlgz0h4mcV6hHK7K9Qh66vPihHq/aAbMoYZgIoVI" + "HClXOhyKHEcg9Sv5z6Vm9XCmm4HAjQ1mXHBCJNtlCX1melwkkkW524I+IABm55XwVgZpF3EhAkFxeDHUekzwOFlci+3C7sf+Ya0GPqAYoqc41ff6TLjN+QcqQztmw/RUgrXEJYiYxz9/ukR7AQJolZyCJpOjd2UW5ZzoNCUikGGKnROxezPd+XV6F3Fau+jO584z+mVbgowMMNUTMgGIWombrIbcUksHYron51YjiL1EQUgLK4Bzcnj66tuhm6/RzU8cd6B0Vhzh/dtQVeS9yM1CaYCEQvcoQrRdHY3/3xxyCkEmrOvCy2z4PujvpHLdXVAHdF4Q1qhCNrgcCfNAnqjE7j786klS4K3RWI5fzIjzTnaKdArryMKZwUz6tPh0GT8VpuTrUoq6b4g+QSemFLkbIIyEeOSaPJevgNoO6TWy+vCioMtOYlQyfD4R7XoYtuET63ZurR/J3N+juoap737ZKXDkMqV+up2Rh9QKqePZBK5Ktp5D+Gqa1AhNBjeAGhaeNhw/Ofpvm83uFUUvo3V+VGTot2CJb0l5gG55HIpQjbtxyJGu7n8PREXKf0HLkhpDku2rI15Z/xSeoB/azB6yabtLaRTlyrFXo7WL7TfdBVN+dL/js+0f19BXFlPX0uB7ZmvYjEqG9axd6rcTjK8m4v23FnDKfx4iYRNY0eJAfsMFIo5gV2Xb9EwJI9IvpbDgJKUgzT7/THw+LbREtnlvrOS0uyf3w+Har7bLqT00QBdy0eftgVvUATSO+RyxciPjGIgklaxa25s/ZWesA7SLsl6u8aEP1GfskyIDikwDkXhXUk/cGVu6Nlldurzn00pYvcssNm5X92f91SoOaViOHu6dPjdII4NV8rYTdIIZ2m3ZRDXrb7nNXpzAr0SM5kcHFTG9BpjEwE8gRkvbNppuPzNbweA/+yPOpTC718EQFbYDc1/wR3yFiogGSUI+m60sofytlzBGMDtEStBeMaBOkWCfnCBynqM0B1VduHXnIkSUdbUkrVfGoPl3Mre0sSNTw2KOBfZtz0YxOX62cOrDrLmjWKMMbu7dvr45HXcP+K6r3UYGpjUVU/dWOZkVswuqLriAhqvTu+qgCZaiwRyG+4RRKBhPVuJIML7RoDlFbx0Pdf1AuZiZeldcEI8xUO2HKs2JZbJSUOQLmK/hZlC0c9UvmL+6qDBwVj9/TNqEUsCG3tF1mbk6uQQOQYDN88xFzHdEeaq1ih836NT7sRGbxy5s56eH4uziQuzoCx94gKkZ1yko7QhvVBE3t5LjrN8FgJV3xkSn5REu9PVyETq3x6WYR59E/udVzmVS0GhHLVW7lb+dG4Bn7E5+9MtV/8VaboPs1lUQCXiQixqf633QAEnKxm3rnOtq1Tt6Xep7jt9pG7OmVNmuqqS06D+OTI/NhQStQqVCNUZ1oO0FUuYgw+R0EYzXXEUvh0C74EYGIpz9ABF8begxMBuF4u1hFSJj1gEuZgO5mWuyECqZjbbOs9P9vxRNNoHh6NeQ2pDDi33XF7D4e04GRgvP0DASYI/W2QeeVfWP2KEjs5q+B/a3f0Vcueqnn4HdmUWP3uoZt1br8y0nC2TBGAsszhYS1qnQaf50DUtT228fq+uundrolob7CHl+F5G/XWNESzRXRyzKzqhbPC8dfex627+XcJrYpOed0vaTO4v4MZa613sceReCqqrnj/sFMi15UfwSNwsJNtYbbTOMe8/rpYEQ5Ye0of4uxnxYTOzZzDGopp34zG95IjC/dZOlnpO3O8qvOlthpFez7VNkgeiSk+ceudAOJUNVlYYbKTZ8CAG27feSXm+WPqGx+NZtRxrfGoXB7+zuj54pfmMjTKS22bddpk5aI6BKRXMM8uDkpx15fgWFiEsK6lVy//grCZsf8WXC9XAp0CXO+mlg2FBqkIPVd6F6eP2PGJQFj5tW89AlbDBb8Nk1rUxIlzVXNeEVevufULa1vFaxGq2rX1PX6mUalDWehhH8OlW1tO2Hq+7ULhmGpNwQQpzxG8XEShDfJ3CdEst2X1Ozn1lfmdnCbPRq23LFzR4jL16lXv9KmvVleYSa2SzA/4OqMdb6+cA74e9RG0rq0YWk//hirzwkFgoZdebQcwWGt7BZtSsTE73WkpgQVg521Tv2reaDFd6Wd/iSTt3r8oqWmVEqqKlN5mOEztOVFEhEBTtTubQLsd/+QuWDnsW5egKw9VvdUPKWQkkbUoEL4EnDvp7xvOEWg0a+F4hhO++ZLllld5H9fjMsT2cxNXw9Umh+sStMGU+77JsgjJ/UJBKk0KduP73PhGk4vJIboryOBPOYqNgSNMH7DPLGQv1snqxcoclcsaphnBYTiFhkZllLyWu0qUQggmRVIsNC5smEOX07ZX+6fHB0Sxen30C+HizONmnElaDq7Y77ABWIzxbpahnBBs4zhAzPku4zZ1PDB9hEfkrC+OAT8mR5r6HJpSu0T16k2oNE3XmSMow3amsGMb3axOUjJnxvcKKHYYvZvn7dbPsJBbfqFa0Ma8Kj8tWySOrDAmh7Cjo76ws31u1XBmmwcIBA06a1G0zhSL5rUAgmNpsA/jCqyNCN8Hm+LfcbKuLjpCJAWRnvhE1Jd6AieBGiqlcJeicvtofl98H5A75a3TCkzgtCmf2aJ7pDTnQpYrMlHr4XAzg44b1cQIplx8g6+iKKVLwuQeYrrxnVDZ0HW0V3YUKtFuuKirsTFDQT9I8A03j8FGOL8wdLRr9ABBYXo8nxCd+eFO3daTUwYWr9pCWmJ4q5lbYuRmFuGfJFvvOeCuoI6srvoWIx+bZC95hU9ce1HkaD80wa9uq7V6Ffy2KmowR9v8/BGoDYDStt4tSvSj1Jq6kWsuq+xra9j4QRfxLluorhJqEnAIrm2++1MYZOdofZon30DfRIKsGtgXA6cUb9phMjWNoo/kVIDCfz+oV+qnOn6T56mG+VyU/uxiIOjYRdQapOJH1JovDgX6xdWZb4y72WspWi9hrK7lroOv3qqjc9CysgS6FsztL3sY7294Jlx5Od0yQWYb5zFl2mz+qs4bUysjsqjkAieX/AwWj4NsuGOZqfj01gRxYSuiO6Dn2EXh+eNeb1kGnepGcrKzkDgllFs1vwtL4UaMLOb1Yz9wse82GRgicOQe89F1WtwiyaQC3c5wKoWCRup9WWbcYZGP4WSDZH4yhsa3TfKP5oc1e7vWkzoBZVpBioRah9t0J4WH/x52GUnX/YRe0aZaxxwrkKKcuTshjX6saYaTDhrncC1Nio1v9syPFvrWxVqR4nJNWvrgOhibYAlHBSSP/LYSA1yb/LegHDLmOw+umDtLHVRtRB8ig76SRTgd1nvuuq5tHKVtC7iEeWqqTAXvFXgJR8CiNrJThdbSmiwMUPfXnGLdilIray6N5AQsrEUCPgTovE5dVHhDpQWWU7BFWy9/KndIrCqpoQ0vo33KtGx8q5ciNgdwEwE8qK4+I+s5LNAu14EPdgnIVJiXX/Y+/PeCvQR8iinUcmrJce+twA5MT4qfMkNiyg7BRZJrpNdRAWKR2eienAsDOQEpn8uwcol7LNe7U8WWdDNdIaiAAOdfpXGlbpeNt0fjYOPKpnOQmhWkW1fjiTP5dLYgSZw+h8tUB/VJnF21WZtk9VeUiDNcSXdgwOT2lVKPcw6nebdkgPepaDk3IKM+VXjaNDWbp46/TIZpji7E9g9Sg9c5Y8fgkh/Lz64IpxVALPPJImK/Q4OCCh2PZVCAb+oPPZauI26uV3aiet7oj7lnBXtDpV4xsf/Fe5211xi1duPAJ8ZT5FpfUVhfQzBOIw1HA7v6hL03q/MkOSZ7A1h1xHDcOFVTHjlQ6Mas1DiLKE8EMK7ARg3r3zRf7sJmbUmjBknffEWUYbxTdY7Qh779zPe6By+fcguHalvhaQbiyttaN5ih0fQLBFdfcynmhIqqOtHe5XVy1Gk/V4OWgx2Z7I0ZdyjZigqf9G89RkgKaUNh43QlGK9hNMKqiv96mPGVZ0ZQut8BFho6OHqMYrVOrvVK46CzKW/hA0Gm1qPRAJrKrk581UhsK96xFVvtzk/ZfZBVRTszgz7ISSPsGNWm0aJX" + "22k+Tc4dXODd6Gm14AaV51IbsqXj3j0rute783Poys+7sXgHXG393UH+0fJqC27YHqYPDn0eD0QJrZ2PlII/m7UFPEHq5GQLFXy0Nd3E8zRbLOTlgeUH8FlUSmk5D2sdwU4Xoj6VV1qtTv89CdS0Z84BZJS45Gy+w3qWTcBmW1EgES2bqzzj2UI0Ao8D/GHgccDF1+iByBR3cfr0MDVMAdqU6+ViF2Pn6sDIogaKw9yfZjdEOAIgjchJExSVJlE1bNgC1gBVDjFQZ32wMak0e/cYJRmtQTIoMkLgp1lrftlj2+4r0JgC4aZ+DrZlhabtrXhPPUWT1axTt0bW9UVl0ICMS0Hb2rtRLvxmbhiG/gsgGmqxF7kCf7H6kgu5thAPBKpm7SWnr1nGkST2vMW3D1oKRKun4twiYC1Y4sGKMgcrPACtg7TOn+9ToiGgdVW/kcvHqmGYz4zGXi7rxwg4uIAwWYX6k9ahC/piXPhJUKV3rU5zuOu+xFKh3SLAcgF1zgGbOAoUQfnWDZ1sDGw0rJDDkDLd2XqK2mxPbb7+ChlGLkWtrlGQniIPHX7o+yYzf8yt3wYXOe6d+XPplN5eFzPfEvS6vfXDo4FPdxOpT84QJdSY5UhVolCV/NhRsTUl52hzhNK/BQGtjZ4jZmuDqU5EjsFeoSsarxbrW6KNb0Yf/6aVvMqcsiCqjvpzCa2g+Zc3JA0O2lZG45ylWaxtq0xvS+sOWnyUH9pc9pQIcYusSuFVsOsQMY6maHB/CCwj8A+ifrhu22cPkoX4y7FqgqWysF7PGOBMGeHVpYT8PEa0aeTXSprnCZA8YxZzhpsd41MtyMiqelw3vmalqhTjCsnYGqimAfBY/wUCuOYu1MNaqa1Ae6A4IcP7TXsdCnIhJ3yu42A4BF5NuewlDKQTHyPreosbCgIFQ/AA26m5vfDSAoh4MLTbLNE/hI2araw/hx5cdQfiItSZw+sKb/G+/HIeoL5dZdbRjQWtSLjChCM9w1JYhSvWElE0mI/xX5kBy6Gs8ql/cA40QzQVU52zW+6WWOlAuOedXxb+LAHNspTiZLHr9VmgT60e63KR3J3TXDgpAADeaPQvQHPgSqrUxl2XIbBWJ22lkl+J/pD8ws35WqsZx1/ugWMAenJ02ttdVRjDRFBxrgS71ZQTgUNXHdxVN0jVHgwl7T2CZEDyg85kypfaB3zFY/bcK91uIdceYl1K+zFi1Lq/VqfOscWDOAC/niNw7eoPRqPihavwVrGb/0sW89KskkSQZK8p3az1I5wmiuS2+Bw5isWV1arXITzPESbLDO/Ey+KoUP1S5ng/KsT1s40sCgsn6zwlshAPrE9GKyOXQEMLh2FEGjdogCmKVxhYzauGnfsfzVzaRGgZkuz69u7QVZ4K5rLX4qvXeWMLpUKRosZI4bAqQdRR7DMGGTj1nTTkAl2AD9ybXQrTVa6bn91VbpppBFsyCBZbUWSZJ2Eq0sIHw1Eo9UdUjvb58c08qGktP7IWXIfO8uGnG1rKc5w5YTmvPtl+LKehLAaWtA3afXrMu0kJkIFgGEorsWZCNDuldrHc6SaepKdU3S+mdKC5n5MPDG+9JNdar4cfkuh1cqpcLIm714DwRn/QQuAJrFe5NCfkmicCAupuizIZM3KbO1UsrluQuapvw/01YL5yPE8/Zr/4rUFvsJ3d+clqizCb6HeV0VzZIFDMNsddbULnVBGiGCMEcDKYOAf+41jWXPFAjuYWkSk9YzN704+EtoalT8jMF/Yn/a10IK253tEuCNi/f73LXGGllXMgwTSXLzLVADE5C2NRQk9eulbXSKORZb/+hKjWPS3g+FphFSw1JiBvQY2JVvoGr8G5kQKZWL69V4+Ar1qJMLWcttT6Z2XnL6b5YM8HAgFjK9m2dQZUqLR600GxZRplBSB1wDByEPa2Xm4K2hoIfq4WDtIzdsZF/vfsP4GP21kiL2g3FnqOlwC+ujWc0mjHOX1YpZDdCnNMsOvmHXQ4BI/gxWRodUaAJRRf17aumSVfvQM8Y7f3AZ2htx3wwivQdhEDoXifyWMtyyH2nYmAd9WpPum7QH47mI/Mnhxz5rzPzmcsB/Ra2L9RCmYf/Ji82lYvBtSmrOsxrP6QSqu3rIPmZCWIPwjsbJ5XoIzZCafxwA94b1RWXCaP7jkD4v9A09lHK3C4jnzpmEZV+5d2yRGhWKrKR6/0Bb82dh5r2y7BEo1yu/DR7Wl6EwlfUbceKt3JWFVRdhiyEwKv+4X39WSXtbJGhE9Xe6AwHfqK02eOPDcx6byPgdnEeJHHhF8fyWLk7DYO5x3B+2QFkFPu85wmRb6arJMse2ipZG2PZk9ERvz7ip03YxizPnwhyguS7+uQFXsUx0HH6vOeEVSfU2WQoWec5ovV4kpgtnfTDQ5Ksvxmmdm34Saep+QbQ4MyxHmDS8yxa1kZpqoKq7l9tnz5jqDgw2fN0dRsprZS/+yINzN+ejGtikKyPgUMHEtfN1nwEnJ9ljD8Yw1GR1rqTlbIWHy1oOmSg103nC97eycWpVcMM7WQvboTs9hSql4bLbrGDJsQHWlWEqYQdmmptJtSAqvxAruhACUI4fT6ztRgMONIMsdc6/ETWUoyqM7kSH2mu8HF6AoGwpPay1mDY5VYAA9qO3q8mxbob/QAPMERJjsFtjxhrPwkjQ7s9HM8UsDCFzp/oxXOViB13qKqdnsRxBwysn71dwjKibk6BUVJFOWjCyRXFH8lU85eT1xnJRxJH9l5jHXno/w5uY2zXc5ZCPRq1R0kPGaPUZjCSpb2j/vvdq0jKmj/N0RPtF/aRgOWLId/NCfadykgILi8ZQ7ei32TsqXnq15LIBQ6q11gCr8W++RSrihFJy+0K+BUKt5vULSbVy7BW8Eb/ViYzS3HFJa/+CPNm4fL+NA9lr3jIuIqY7zeJhywh1XF3mIj3ZoknF01d3mjvj6VnHFnCu7BKE7qVraErjS9cxN+5ZEDM//4GsqLcDC3mlFHlBS+5PSkz7xdJ5XkzmWEvEkAB0sJUc1ICyYWJTmLHnh/itkx3QpLoPNtxnbchS8EXepEpVYe8Kl1FDz1FKc1BZ+iGHrrqQHZanqEQ/fWf24BQcPwv4nK6T2sTzdylRZohXKLUbUNyQR7uiyLlE4lGgAD/xDBa/g8zxT4QoxipQUu3BT1TAA37TCqUupNnyXQyoac6HxX9hl7k1v2Ii/8Dt6uIjp3Jf0OT7JFBfwSmpPuBilk7A4rBfJrLzNWGW5fs6dJFr9St1vZuZGg4z7AKQKwJ5ivzVVG8IorcX1q7FVkGjCSA+eKRlSr6Q6OuX1Q3DD3Zwb2XOQNw0xZ1QVB2nMCE3QlEq3EmjAQhhMKPNeW7GpYxU8KzJ5aIH7CR2Z8vIQVoT729LVqD9qT86WQsGxs3+9uoPAFyIHFOTdj86bWxTXzb/b/PIa75YAPPWXIguVnFtRbzZHqOS06s4epeq3KWxzUq8MXiKEkZ7ArmJTjpR9UrNcryQP1eytcZXtvaNo4kqK4GlF/0CjQc3GCKILcHk7paYjmy+qhxASQjOszXbsAx1JC+njddbPQTpw4/VdclxoKYgNx3YPiC8c/tDY+HiMBAg0Kx0NX0Ny22sgs9DC+PiNyBUUj2u8m5OOABX9fqr41WohC5ooiX9nENj6NpQmDhxlsfcF7vWUIrHYvb7t2QJ7OmRDyZrNFu7xKbiZGRB7O2GJHypbVCWfel8mV43AwPvXTscW4IjTGhL66pPoGHff2th38EEeM5uZvU1KK5Yq54jbyNfPCqPmadevPeUgoy7iupC7635ms40o/TLUxX8MwjK1fzDU2cU4zcum78+rcwg2AMlskN0ZOJFnhgyuFJj1reTPopTifGjSoBWDL8s6UC7SeXqG4zMndKioKic3tbaU95SaFbDEgYv9cXtnB08Harn383hkJ8a+1/neSNoCFiXb80Li9IXbkFO4pZ6Zo1pn76nb8pTTe5C0NZIACR0BlDBBBZPbt7vAWaw8YA6NRiRYTHMghXkBKIc3ZFgqufR6pv2p4MxnzBAn73JTP9qBlKm6maGnxL+7t3YUXzBqiXXhyCFQ50w" + "Ta7ed86R0OpNQpy0EI/w9f53YlSY4jUVVagd1Dgm+BVn8VFkYC9ACIrM/p6c6qjHAn8TC7lmUfz5/XCC4ASBbyO7urhea8UdKjBQokFPDpndKhGbCOeZJ07Ew9ION28jlwZ640raRVV1XEf+hNquj2eL0PFzcXTp9Q1W7bdmyYEJxcDOFNG+dyvc64ssXNb/VuJ3x31FA1Xe7MuDqzuYAGsmnO5EapCGINRgzZnndSDkN1NcKOB2KaSI61ip+76wgZm26dT4y2InR3fh4xGQN3rJfvHqZ/6kI4K4OSgR/h3APNOgAOPfDSYZLSA0nh7m+jlQAqFT2HMItut5Ut1Y1wlAtG/a6V+UM1tmgPaKzL3OJHGoa69vd5lm8fmOf1rGv4eyPj15ZLkJ/Kj73noA1LWtAxo8Fcy4Pmem2UYFjG+1DyFGAZPO1i/na20IgMcyHtp36u6XIWykmfMekCKjnjvhnbDR2eAp3Y3tuJn9mZgwMBFoTPhYbE26Ibwp4/lvJ0l8p58duE+dCzutYwQJV1c2OnPYLlwEb5dysASk/EjPzHa9Rwp8WfVo16edRNjuZqtc2rDpsofvZRZO1psgFA3/2MUubqbisi2e2uX9Lojd495V/7yl4ueHlmf9OIiOLZhmeFIPjSQboTO4j6XBpAk9guUT98hxG7FkyENQXZwy+yQA2/vfTI811tnEHTRUBfTlUzNW66tUD6d0Iei2qifEKYdDnBfy37cRO1e73AmHCpPrrDkqC3Ht/y8/NljB5FJnKDdBEWE7HGZsNYZb+JgdyPioYPD3KdAERA/MvNp4fn8y8H2ho3yFY425hmR3igO4i9SD2AMfG9mK0hVi80R1KsV9/ZfujOXjovTxmaY43vwTtxe12qDrOmhU+zlA+hybeWpPSu+GDyAw2GaKq99xQfYDaGVa+sbjFvUiHDtpkFFICQiU+/XDtCJY+WgB+eVd46mGuzNvsD5c6Ln6QSw+BnMW3d0ZEA62tpVAKDt7QkqZERHTqS15ccSXROq746Ua6VumY/rVaubhHAJm3a+AC8rn/kel5bJP/m5YW67+jWcMnS+bd5l4cYpvYfFX7u78KFqz6TlTrVuM01ojwWOx65vULr9fR+WxewUBIGu8bpxPc6xofzJQdF0U7+CfoxFL3uFNait3DPbECytinqlFoPnFmr1ecL7/xR92fTiOe/Cs908jnx21aooLuX8QdZERKeHBSzzaY9/uwiQb9UoHVaUQ44dl5kq9B7xxQXjax3DHcmvT47aLRCAcQ4Y1alt01z2MaPr0jFmWJldFiTJvr1Ya1Z4wLa+AEoIXEJ7cL7wCAe062h9IKqxVv7r3o+2TmWjFVtcO1HueHDQcM4sVxZkQY9N+jVghbe4V8+CDIyDZNV/958rNrb33NcoE1e625BdPV7VvEdM0fAH8zeOnUOnsbn/NvAZf66tJrq5FMFzhON8Bm3QxdHcR8jmg4SNxfz+sOaGx5kbYmHG5XJg974hSta3vcFzaKm2M9UgjhpKr7bPIZvKMtexSk/q85pqzwcFN5SJ1UsugPvBFFr5ScCofrceeneh4VKfRjQUSiifcKzWqPhE6waIYbWzck/YWve8eC/w+C1nMNVmzevqpKri6a9kKWMrnneLm1yUX9PrO7PH1VhtXz94G5Zs/qXgFB9PKFsR6GsD2Z8/IfZmkZ4NMlFql3CleXafPqnZkOQdQJfkBlp2mWV7nf+G53PVUm57eKLb7Y2KuGoVeFGOMWUvP23eEpFcOE/fnnrYRrEMebNeZ09NH1WQDH/nkJT+BK4FpuBhIMA9LUJDg7NI39lzNzSnw49mmWWZyrZIETLj8IB8JLXadbncN7AI3Aodp96w+75mfUhbbomdzHiukRN7oaTT5rLgQs3mM0GokuThnEfXUoprOfvaAgThNW/CUIuti2ROZEj8V6GUnXsmntK1Jt/yZ9ZTb9KQU2G3ijSv2V6YC+lKdpc1+aKfxJqwHV9Ay4wSIW2w1ksr4QOj5Zqbid5oev9mO3hr/gCQhjYFVb157i/nknPTSGNlaESnSYb8JLu59h9iydBVpNyjtxs0MjlEkkLyqM39gQXA8s7Fzq3o4Ynf2ZvkDdUrT8b9DIyIubzWxSPcEWIsqAaPtBVMwKj0O6QtFKkJiBAf24/ghzBrJHQPQiTgtMou5D1s3zgqiDS/ZTv9QCBbQbAZXgTV2BE2Kb6iGC4UbrfHIIIO27FSa8LHHuUxeLCztMB17W2Q8MXSIUG0j2DrrRAYVX/xv5gL+pySZue4G7YNvRa6F9QuRm9/kzzL1neToHE5IthapDPAPS16iNLD82JfC33Eo7AMKt0teA1j7ZoogWf+QyyUY4JTc+11qNPext86+VFYt6ZwhYfSOLxeOQG4qbfuWNekEhJl2flOTJsLNZcdUjdA8ageum3RU9C/uL7u6Lgo9o5LVRDNylFn1PfMS2G0qh0bHtn3txll053hOf8R7bmYEYaTMsN+NBVO1+uZAEt4vWdRrL/CSWLK5euCgdzi10Z8Atq1PX3RoIprayATJuvwGYPZtvb03NRbXhwv3UWF4Kk6HjMIiLTVZ139Nud6OU2Kw83UE49yq0G7EX+pnzqiUpXO7eKRgOmCkYwgiNZA2hgWl5yveDKLU0eg43SXdaE/dr5GLCGbq8meq+Hg4OFyuyBqcZRZ+/Slj9i/q1acBJsIoI8u2WZANT55ctNG0Gr4+w/2O65XTkoamd/1OiifqSP8JPqihZhyIpM/7iA05zF9GLCg5yWAqhIf/Ll4tl9DrIi9SEnHr1+mbw6H8civE2USyC3gc0hB9ie5CER2lAX2PBUC1jsXOxiIMdyQGE5sWuxbX25evY03LzvqEBbMX/AxW1jzBuwV5D6q8OfhU8lBbkZ/LmSG0UfAxt3c9OkBSnGod59hAM2foDt/sCqNazWJR59oRrkac/aZ0/vDpP1BPcD1nh3zQzULt+gG2fJD+J4wQbefxd3/v1OtbwOrlytGeTMe+iYfrcchwu3M9cpO9Tz1ScVA+NXOyS6kvwoOYJw3/tA1lD/VYDTuUkBXH1oOdlWuzcd//YlCCGd/DhSwPaZmao68TEGC+pGTP9d9u5xusOH1d8VLaqYHFWT2L+pbWqkNqJnhcoqkce1bXrEOw+s2MZa1ooErSHa3pdyC6mvGgwbMCrw3nY3GRG/JFm5w4/bZUBPYlbVN9Qnl9gXiWj7aHrMp0al/G4oQXQdL7d8wxb0RKcLXcLwdCaluwIi39xuQCbg076XX1Bobo+Y/7Ze6y9VN1IguiknTi2ajYToBtmX0V50SN741HPC9bleCSB/1I79oMktflmtUqj8RVjV6geBOi6dK3/pSY75opujNMZ0Wi5xG3Pxl1Xnz6UQjNYKIMrlSmNH0nRwpD2b6fa8ofLk9RZdt1zRCQ9YeI9sHQBp1dHv+M7/ayqUneSH/WpGGZ4NI++BA2NeDUV6INcfiGZRi6em8G21H/UU/zi3RtuO2zXX48pKWEKvl7IUkLXUfmvhSv1UJHPQQ3VDdk0Wnu+Chf5Q3Zo30IrLiVuwN2QPoVBzRczy4vxC35Fux4h6vCNnt72HBexYtubWqLXcfFjiLSXEWZtqy9mqRn7jpi1WQ+CsfNQ0u0aRcNx9+gXoNwisxIxAUPwUDXrhe0YFo2UMN1E5O+8K6ULAnBzVSpV1j1TGs1kWY8KknN7mdwcByqnW8VrXd6NENC2kTtsmfFMlHBjIBYh1+X34e/PFcW1uuyATHAxbxCDH5+jFp3kjlkwXbGP1TReQrxpOF1J2AzyducLSNQJ8KcKNc8CWS84cco8pjMI/+8mYTialqnI/bbqCzR2J6m7/rCFr1ILrH2s/PxL9ELaj5PXkWfDB22w00imEiokZVmkeitf2HicFYh969n0NcJzmIfZolxyn5uBFq3kSBA/Tcgmx4fCo1GBF5GBzP3L2upwL7FDh5iYNPdN5KI79Suki7Y2fdOrYuAzHiBMdTs1lrgCR0p8gNDmZKixnZ39Yl8lAoV/uLR/MdQQjgMbX6e+aVZ9BBJTf/XXtyfctehn7LZm2v7XcvUyp6VqcMFBzZlIdXtjV7Pzi" + "E1axJEe7u6nk4yG2eqQaHFj7T1lIVhN8CFBtctVxpkalmNGkjtWa0X5q5TRcsvHHG190Y8mQna2PSWl+xqZBdXXncMlkcnC1H9xO/IJnTZGEbsCFzUnPZXFnqigHNljFohUcyqAngYApuKRQVpW7l9jT60CQB9ARWWuFPjyOwK9Tcfm52hp337yIy2EX5yoidm6bj43kjlvVLwAQ+Gu8/im50aP3Imjk3qewEUue7quuWtUVz+bW1rWVHtTVfFhoJE9FJRTIPgG+6/TupKDmDd008BbfM6ekHD1MfBZbpY/ODZNnp0nbC4qlcQPLWTSAyh6Pg2EjIy9yhLsd3SySDRyTEQvXyWSf5lPWFHjqXq0MDrEaDNcINAyRZvKZ8yNMfiTqcuws9Ir5PWr4ErOg7JsmykeTTYuUfris6Ym1rVnc9pnStQrEh7HCHdHrSv3VqHPD2t+ATYAUgoCnUqzuQPXqW0wuTxOiC+lFJPNb0F1mlvRuyUvUpWoefmqtT5YJGfmKoGazdTQIgcwUUlcEGdGd7VW/IDxajqi6g87fuhh20+Gy4SUMyMaCXePVJNfyykZucdm7TE68urBA/rwp12brekEi/AC1qeLQAW9GfoMQqA63DJaniS/N5AUI3Jm3/kATcaA+tqjcZnkvscI3juU3yrpu5kjdwW/tWK/DH6FKXlGlvpYau6JGLtHKdveX0bMFekqUG7C5lMPUf7rAG17drbnpfHbmt4bKZXq6gPBxk+2L6EKfdLaA8IKUXw4dfyyVgukeDCkU4WugQCuBQhDONbXW9OlaTUV3rhJbSmvPLboiK/aY0cBhmknwdwLSsB3ivS47v3TWFGjbr4rwlGcexT/KbIiEELJN5sGWt3JxNp8t5s6ZsVIgyQpqtWuGZ3HY1PVvUwVfu5fFCqN8iUr92YdZtX8yMaRhq8Svj2KJGT9mlWhryn+pZJgY5a6eGh8raubKa4coad4J5Uhyxo2Onz9Lsm12/CwSR2JPLq506shqjlv5d4CEy1v5IwX1CgNxqrh+UzqnUToF1gqw0ENwTfKGX1FAtL7CaZlr9K8MDkr4ZOsbTRPnC8SS7S7Dtq/AsbFxMteSDpBqf98JxL217scQLnSgyxii2S7wqhpc/OH4g0ss41gLBv2mE8k1W1c0tvU+KcJ6LdAh6oPBh2DB/gaXuJlriecTmbx8XBUwM+doWAEDxQi+8YePc7/Aiky/HuxMN7Y4pT8PprKTjn0TWPsY5Q2pgOyyPtUYXzLLduRd0jG6zQOTU8mGSperPpNJRE4UTyIKMu6u0Wtl/XZB4ajmkZIarRQXPKZy5PLkqgv+gr9wu+5RIkWb420r0fHSq4pKbYyR373J1iK/VnkC+9L6wyTdBpzzd+7Ap+6skWWPLMvlwpO2wtItXIqu0to9fUpzdFrpHsqa0bNI5PfX55DBtc4Hg0Zc4Did70oHLoAS3KMwVFj9+U80VHWhWyTM4jVeoRTAbvQ2o3l4dZhUKTbZmFRIXyGvUVQ5f4vzxt9qYmx/ECiiC0c6TgCeRWyEU5L/oM2DehBpWRRYxIBtJyc5WEow7Td2bRSrc9S7tBRMlsQYjS47AqusaeumuzEaNj1O79XKv5ttJkjsbBP0ny93O1kmldZ4blh8Kz6YtbXIW84R8uUbT4v5uwNepEG4H6tfqQ+fqurpw6A1kqBwZ/+p71eb421TTkhj/lM5WMAem08bMloPJu58ofUcIbmbDfu7404IUWoE27MxZjeGMwPsEdTMgLvYBaq9N+DVeObZBIHVawDmHtPJUvZ5uOrsS+KvdpCyu9Aho2+vhKEjjzHQNaFmbkGjxQ96b+E+fHljtnp/a3LEG3nlOre+NnFBhTfuj7hJ4R0elEBGVRFMbvulY80ag9TfR5glKKkrO1+OYFaSibJLqkPnY6l31Z43xP4F0oiaWpqhdGb4CHFdiED/cfMKc6nhhhV+XovK1WkQJmZeHdGfW0uk7b0ESgmblfpp4DY3LfDHQ6Hg/4+7mRr3mESIxXjnxsWiJO/LtOfUd+sNg2mpr+Z/467/JISmWOrQnM7ph56ecU1VURMNx3OUQZwFc98ZbK7yAa5u/42qCVAdT7nyOvMfuzwnk7kFEtrbYjtT0vpzeEiq3C2p2006xGdy8qQcxJcA+5RKIBsoiD4OenXUYU54cT/KNWyo65C8qWY6iLxZgAcK3ekV7gAPbIXQB3jIh9alGXjR+ZT0yFIDTCTWIhFDEEDjFmxL5vRAcznyRhsf5DZdC0DZCOR3qY9lm1J2ukOFag4gkg3ftezWiKdndL21A+1x3oF37zwSsjDnXkvzn/FmBNMd8oGqWqCSXcbea78VqhEbNCNoRQ8x7rhbjZZnwA2s+pjSMcKvy6pnXSBbdj2EsPH7sDysexDEZoHiZ/PquVnp1gAg40fWGohwVm/B/oHsZ/uZMZI98X8R9jYXYG8E6fqXw6NK4tn5ShQ/2LIgriIqx2HQpIo4brPn/sxjuZXr50yviNgcfp5PA/1SIJQBzUi3Q5VmydHMFY65cOZaRy6fnN8oNu62B+EVdMGqzSoQ2r3MEZJFIoFP85uQ7mj6F0yzrQOvD5BKrhSY8XGi5Le+o1KjZVGGE7tEm0X/09V5U/nCU/d0atrg4We0dcM+SrsyFq6gUg0bOTjO3aL+VsZlWBfe2T3zx3WejYld7Hpn9dwRn2cDRfHqHspXMpm/DH3+123HLzemQsVSBqb7PSfDQTFULDU2weAZIiFUtXwC+TJ0Bw03SnCYwjBepZeCUvS3JNHKDueLjUVRg2Elutkf9h7RVTH/8B7AW5CgrhtCgM+a4pX5mLyapoxStunXPpPVkv5QVBf/yvbvvW1wxcQ3nC4diQatPdUKl0AuYf5894msCXLfKIh57/6C3QmWxYtc4Hn/sB1cpQ797vPy6nLpybHjCJ4DhHF/K79RtEGokFvOV5hfphUeK2Ub5UOIZiTwRUQP1ckN/UVDnSwjQkV23LR3I+qXYXiFBbW/hBgo7IppRKZ0zWT0Q00ewI5EXjldCiza/Sby8vl4MUH8QCqRIXktk6BkWnL51eep4wYruwJgyUin8h8sEEZuuWaohrFTF+XnZdDC4gyoWXqzUWB6HkGxQbKS4XeT3hgLfsi61QCdqOxkp0L7oSyNn5rzJNY8x3h1w5QHlREgWJdN4LwjTn5TWhBcgUCp1oItdB3JBQYmyTTO/VXv91VcOqucXmR/up5e/FbUqacX1WayRuX0mkQ67uETxCdOZXkuVo48IPzYqVbc0wXXHemAXKAwf+4tf5mCqo6kmWuJZAwgT9mgUZlK5tL7j2IYyB678Tix2R7Cgp+6qrNsyp2WKYuYIdndhAaw5pxK0DkAmbEe+V7pdkMr9qMNiMg38oqfufNEZbzdOgfpxZZhOgYp3I30aEy+EL5tViMqk6mpq0yYz/a7uGsTmVMPhD5DPNQveB6gsP0gTW4mKz2kszYss7+rHJ0fhRHI0Wvltqm9a5fR7EZEz6/Kd5+bJOubr7XwKsNBcI+sBsOcETyNbZg2D+6IdeBaJY9AeJMRH6CX7B75zGAHPb9HFtj/OgzjHtyAo4zohuE3NNiuBCItpLK+c/FtYK2+v0VE4pBV3Eg12MQBsDKfCh1b6DJeLfvgm6mZlb9mIIwRZIAuiHWKAUOcAWe/ufZ4jXukwtlmkYirlFfk4M0I9tSRHYItWr9W572Jlsq+XsMoYTpVf2TtvYPeeaTssI7RZeY3I/PW7TA2UDai+Dx6AFa7ku4MAPkJsQJiDSNH9Mu5OLn2Iic1T3JAIgcm2Nwu0D7/NFoiFwUs/1Ph1qrL2uY8g3IiJzfnkcFcnd4wcKXk9Ff8ce/h+InP/KITVGw2hkLfMZvLfgIn27JWRqgVWVbF+E1F+fH9qRpwk9oIE9HU5vloahM/j8kaequYlFZ+C12EW2QPJ+fX2Vk4x86oqEZLcNVIf3y4yDxw/1yoWd0FAkhxu7N6hWG3UWkKiuBLOr0SIsSGjzc3Bo3TijZMfPX0/pYSeGnoHQGuwTVpf2QbXIzM1N9NaYbAjCK4qcU4Xz5dqd1z644EGL3EeQx2vEs18QtnW5uboy" + "NXVSSPXl9vQevZDNnLN1RJNwcFmPpcXxZ0H9Vs+4eH8jQzmT9aI0IRqZOXYszdMnnh8lBJeGMWs02TaTq3TLkGLmf+Ems3o0itOR684d3NO02mPG/JKRw0ubGVTKb5UwrwzEb7oxTgZXnyKqDEvzlezAzf66bjrEp9HtX3bYdZVPas4ylv4bxbFAHF2w3g5HetlmjrmLn1zmH1mZzR2ulprbPiHMy12pRyGWOX6YD4Z/WIcFGN+jDWtCuW5W+XAqMjQJNRjCrxcTIi7YXPa7pXcLOK13vQ7AOlPqsZfhi6XMDo0op2vxhlWwi/uoxXra84Bw1ei+i5OIIp4H0jd6hHPMLgP2jqC/+BOrmAeM3Xq8vExPSr66n2JNfjA0rAFIeLt871djfPpkZk1Gzt/hIWwF3+OQC4gVkWlbAlxRP4wZeJwP+wmTHDaXKt8naJi3FDoJ/FRq3DOMrKRRt1p8vUGLNx1T3TmvK0ayFgxoIHDIk3TrIggrRiFmK3H0k7bOCM5Wi4wLv9uaxpPi0R7sCm5licknHLhXu3wPKTVz/TegPKuVQ0JGPpUnaBmQNZ9vvT1Wj0qJ10B8mN0BXzNLfsLx/sOnDGDecGkrjnDGhZDxbC6M/GW2fixTOSR1dnQvBzumiU0dSeyTC/Bb09DA+MGsujGnxnt/PcCN1m2JzesTsD5JX1dD4fyRgCihoCrpIne4iFajYsMePjYBJGvSPgulIiS7IVxj3ZVCklCPVslKJF6ZhWcCLVcaFJM+B04HNeJVjSUXcQbaH6ZkvW13kNf7OjB8qxOorLiZQJMxeYRZ+wAhVNehfkI1mHjqLwENh54auwzVlRo8vQauSzsY85hg4FALoIl/YwdNMThpLWrnBvRyT6DaW2KUr3O+Z3JlMLVufN6nJ0tYpia9QUE9VWDs2GOdNHWXhUG+cS2pmULXDBYpo4IiIeHyDFQ9H4QZ7e7CUYyru2rH+D9KSoKC2g3fInaI26rhCCYteFN+ziJvfZH4X9qlbpffax3BCP8gw8Ml6e/j4N073nFxedm7OLq4tsRVJBYGZrwPfbqvawQwabPxRokPXy3HiUVPMjU9RG0T4yIlwiWGXG+1CC3JCjPs6llE5dRvDHnAsFCpqKudV5oPnAdkJdUmPLlvnK/TmQHWlCiNWIm0Gbe98HGGYi3RNwsxS1/vxFx2CKNT055bKEfO6u1vKZnBDuzI1gk/1BTzQbCXZkKAMCyfocTwjtm+/krsNhdxh3yahKjoiV667yO+ORBHjuD9y0Zu/NWin92ZuB9lZHoLibcOvOgEGzip1pq1S7tzIjjSvkoT14boEk0Euy8Jdc6o+1SR7V3OayQ3tSHUkqgSSJUne2eLWDF4fQ3E8qhAGzx/g9ZCuOICgTMIyRyzuRKBA6zmcaxV8t1ywaMpWt/v36Rt4fKsIYp9fSBIeaisvbPhPDXpILrRQTc3YzgYqHdD/PfBfbWBa9jZvVAWtM4Vgt22BRtUktwGZ+NynZxqacdN6RKz3JVWWLlMSNPscZO7ZmV92XfUDO8DTlgS1WhXO+lk363o8omIg5OFobjJcBiq0v68KR/UehbBLrdQ7WuObWMxNbjhFAB5G/1F8rXcE/ru+DOHU+4rqbJVCQSfPdgWzaoO7bko1s1QaB+745X05TBgo+v7aj5SY9/SpBFuLNPukd5WYv5C0QAE61vf64bo9kDS7jR/jgVhd5dtHptDeJ6LmyW7ZtqOiCEOhn/VxyLI20bhz6TN5MKUuFObOVI8k2LKfRg2E1wPYu9U6MRSs7DMBVDrWHjazUHCKDCJOsF6jy8quzaw2SAfOP83nmp3vdmiZEkoY486eiu4W0qr/tZTNVytIanDuzYrH6Vj/OX3h5XnHaZDiZUWarWj6V5E4gfypzqIUVHjDdm6oggdqcelTzo9YXaFu638WqhDxPigourGXCgotPvx6NsxB5H8Y407TZHnpgtL0zOn6dltd81cjwtllhjDjBucRqgZeR/2n99cbI8JKwsReaHv9tRg0QA3jxixG3SYPB/3p3NBOZ89YVScy5zPBxevJoDVMIfHhFbp+KRbTYmTc+j+K3nZCy2iicY1wt1c0a9/ibb+cl8Zh4o4Pte65zqVbXQczoWmd7a3fd0hFvcaWE44I60b/rgBN8wP4aDSk5P5ceByW7Va1ySqYqpbnBbra5UQRJaWahcFfi0yZftwtPHPSNi3q5uYU0r4mm1BmbaFDV9BoA2LiMqXmEumx+GdvIzzWAGW13/lBF88F78SJEkDVWosUDLi91By8fX3NjYFywkZ9LQWzxLPmydSZcSGAaNp063cDU5EQs9+KBxXisyB3NF1vPFFCOIM52u9F6GZK1vVxp/MWqZ/br2nTYNeEH18eMyUAC1KA/p4+IVf2wS4X9IfRxZ+jnB9V62q62ZLNHwn1t8qEf65dU0+vUwJ3S3DN0qjBw4V8HPvR6zlLe5NHPFjc4NII4sm9tIJn728nvM6iGZE/cHP16MfjAd+ehAiNz/8mL4n9LzxPUr/Qmh2GW24NEnQhiKUlPYM4FPgxsoqMwzJTcN3QVNHic79dlbab7QdECy36P13Uk6/3LdYQIUF4gGpv0GR0lGLbayQPMHGfBXo3JlG62Wr/Y6taLg7GLcRWEoZ8/ZBYaj9oVlstR/SlWGvrl9zKatb5ZzbWAAHn2Cc2aNuTJasvX26dX56KrR8aB0kjKFm7ayqpvLwMhY5TTBKFeC9QxrY8ewLaQMhPJBom7HYog6wWwOylmCjbJXqV6I5kmJDiBkb7H4I+8zbY39JsvY32I8P3b1/UTdgCbYduv/feyHBfxyWM90n2N2pHn8/akLVvk9zgLCP6pl2hfqPpwUfEGV+dSEW/witNL86o18PlsFPEsb/WZQSG8JWcaLq5c4N8EdI9k3uyeTlCcEzi3FznEV7ZJLL9R71x+SX3I31ppWfvK5ICr4tCprZbAocOfyex/D/n5njLw9DNEA6XeER1Pp9Pzy5/gC7FTQG9tdsYtdcgs+dX8AgS8xGPHHSnMBvvY4Feh9btDb6u8byx/tcWyY0V73oxe+5uVZco3PjQD0aSNaFsKyMuQxvUraMOdrXlrnWaPbHrTBfso8YevnFr66wfrGPI9u6aGdb39t4V5u0YQwM4fOzlpeFZs4Ai8YaX1VKIdZy1lRNBPPnCW3ijgZIY21sHPV/MFCoiH62WS5A06fE/pQfqdQ+JAdVDAy6H56NpuPKxHvCSd56c/+KOr8RNq1bMHGocc1tNHcqU4X4ZxhvjpWbsgomVNP1XOoJy+bThQws1/CAjYO00TN6oVIs2tFCsIG3oVJXV0p6DLwr9tLtdFMhJam4HSBKAHW6PLm8G3qfVD6RaOW49p3BQitrW7Fq2ayDX4Oi2uRA6lfqfFBJa/FtJ8CtlK93yzddRsvQhnQtP4yenvipUQbhFBO+r0Kb0i5zNqlys8xq067xSnYVt43oGGLJXxuiCxOjZl95NuOYc+bdMjs8RRxrWTFs/PjSPUJXpcefImFRu994sPDVFVyWIEP+EjVhUjXMuOUoPVOz9vJtbzW2ghJuLmnDg/Uf8hpLdBIyiRi4MQ393TjgILoT+58lvYLrOC+8KcQocL/y131t0WiNeMVYMaqnsM5kzwO1tn8ZR8n1Ze+wFs+XFCLt8whpGtjisI7soK+J3F8QD01ss97oNA4In4TUj7LfPV+4DNPKPxCVIuJNnElm/67WXot9QsgJNyXHNk8lFkAuzzimihavF/TBcpwn+YZzoJHzTn8vcAFb9GlsYCPM2p6xATPimlJ5jP+X3B9oYsebfkLtTVJcdPSL3a4e5WIzLQ7lZVqDFXCI9620rkdAylAEIEH9TzlbhwVHUJZFbBEYeEGintYU0kHd7s2Mj2Rnnw8c4VkqpvgYmd794KhrRGfwRNLGxgn3sVzo/84IdaMT3E5fqN4mSUx/GM68TvMPg8yeIFApCkB3ALOwr6hXNbT+SdYydsUyIOWl3+9NHXi0sgOwgSpyPMQabzuVi/J0xiV55ckF5DEAG13O4Nu2bULmKMIUgI7r1WzW5OJbcq113dMVFPqZH7kNlUBf+H3mpy60zs" + "LblXgNN2Dhc0kPygU6ah/CJaPZOI57gJu86eXuwk5w43JjZx5YWg1tIcIuI7FqYKwQHdnPVn4DUrzWl3ASeilNtqmVKu5lw19YNFn43aKGSEh10sDFRevjdXRzN4MuEX7+/UizsdJyG7Sxjs888yrnVMnaXBHT4eVbdxuap7cW7T07P/L8Rt1RvpmjCGsV+XKIfLbL3/7NZGNfw13a2BmmNNM2JDmxC6iHgTDUx6iWv67wjTfD7NiQIc7aTynm2w8OXXZIC63eJrNDgWtUr6vcXl0hk22eV7uiBc0TQjxEPXv+WZkLn28ozBu7uqRb3FDZKeZlxuesbNVIisFzwpd4ivuG9LRx5yoyOu0moovuOvdoRFAt8cylzmbru65ALSbJdsDDm3PeP70AFmpP5by1ZzdwHD3wjegUAmbrelvzCmmXoIYwIHd9mEUp1u1Tn/AN/MZBZiP+pwrDT6czc1JNK33z/9iGmze3bF95eGES2K+DvzMaFFhFOMXAVQp6iNw8ZNYQobI6YzqpXjtBkoY9+ig2vuVCzM87zhazlhrOC8cF6+IWNc+tYZXCTAXeVo7s01ik9/OFdGdZgn3Tzx4cT/n3rcqZmMWzU282HpiICaSlZmWLxoQPGs40V98ik3XzZL7z2/yDYu18hWO+rYp6JSWKeQlZO/uH2Hrkv5yeimwMvfW16vYrRXSlEVsh8n59+QMJzR+jUJcc1lkAj1PkXT435Pc9KXR7Io5Zpvwf6QPTMWClLSwvChq/beIO4NKNd8Htl1lha+dblZ57k33h+ki5VmUV2pXrJ1Gy0oShLUNxG3k98/Y/FR0AJf+jVsYuAgC/KLUu7cPV0WYkXISP2TEbSjM9q7lQOdZjyPH2i2LhxUTaZEPdy9OqXKNyngt+gJxNJb5A6FMiZ20bI10YhWZnhywig1fjcrxZM8+y5/tANo3PRygF0vHA5w+RcGF+7EOvpmAxV+KecbwwzP8D22yrTB2nxUdgQCzelQJuAhz8cOLUFAN+OGyL1Wp/jjm6eEG88KRrh5u8U8CMS3cq/GzKGTkGaqkSyLu0KrwNXYKS4KgxUIiCLN+uUFfo+EopvZwd2GXCl8Q4xXnb/gdbHimrlvmu7ngku2z4tG4LXIybPuNJUBwS/HzbXcIEPh0daXNb9c3eRTzNZJc8kup/k4V6FwCeJQ+ZnhX+VcOWB8NLVgAP6q8q8MsWbzki/+47vnY3ToBqdX+EG3aEkle7paUrMRPV2IdfnN7OUf0C7+vrvKbmlwtwPDiiIfkSmfhXVlHYEM53GnL56oRXINjIyuoKfuSah5BkQtXckdyfu6qThl2jNp5COpjhcFWvbz+4jo+fEdLpl1KsPFqjhVoWzF8RfWMvxfXkOGSuuvm4Svpfz7nbSbaAUGUwugfBD3lqemQeRHC0LE+wSX/k8HNF+YdkkmhxvmAG/aLjrC8k6ooZfo5mfIHnmtIC8Ez5g8boCQleBx4wNpRPgCODn7DCCxecdkvFKOOq3PS5d1e/R3Qz1tULH2Ji3ZdLp5zRb8t6YekBIyV6H3IlrkMsW10wR1KtjeAoL9JCGXNYqob7ChC+xCXN+HmNfltCr6goM3GVWXtPY0873kQXvz13/7/sICORhbHHplDXQTcIuDyHz3fPKo4w9e1CO+In9nTp2lbwrZVOBfYhUmaCMi6FUsltoz3Rmtun3JmfTwvzs9aGJyp27FK4e/CFSIJEuvbA+gdWA+cmJCgPTBZNf4LLvUxrjxonlFamouFpPDOJ6ZNDaHKdrbjTbGy6EozYdKnxTG5ENNz2PIZXdU8I9VzXBOEbXNwfKF2VeRAmP/MuPkvTan+D5KZXRE+RXZYSZvza4yVLJdpog0wUVwSuoS/3QB/bdKKs/lJqGEcP9lA1JVnosOYZwHdBu7cnCQw7k53oOAC3FqwZoD0Qq/abx8wZZqM2K3pKaPOux5LgxeZNLTVeH5yZD4cQalQCtFPiP++pdsSkD6mZ/b/qNdITiZ127d/dTyIkvNF6nVGI8vTXTBvFyM4OJcadXS6q89oJCLUlAOYOFSIT0Kjcxff5PbgC9JYx+4Sc4API5rFuE/uEc+umITbO90w0G6r7i7p+m+hi9/Js+At48z+sqGQWtPfy/EwPDWzebqfGlptnrzCsqpGI4RriyB05hW/X57EK/TEA0CuXDZK8W0sW86mt5o6k7zaTYAK58z8vxmC175Rgk7b/U2inzJjMiPeLKxZg5VshNygeU3W+j4SnkoMq012xJrFNR8+3XiynO8aeqEfvRtG8ma6dSKj0tD/YMwet7Gj7/BcjFFzdm9RPo0WvjF9Jyyk6yRkLuvPat3I5VLmilF8OfpsIePAw1SQLRdpFnKW7yqUYxeGilVNBJmbvaYC94mgcZBaTpemRIUqSP9LcVYvZtcDHGTVhqWOiFTeq45dUzvJ3k6pi+rz8j6AIdit0YiHbbYhdqvLqN6uPRlzZOuDjPG/7q+z8PNiaUim8NuNst1y7tH44pGa2+3OqOa52eQn3eMUoA6XIG5YUCPbvZ5bjeSNn9tSw6L8+0Jo2CMYzrPg3p+eRV5JyVOQVeY1aPYFrnTrzmC8iDwJJps5Zko3I90t5YbV1Po506qxn90NnLi8VmUA3Mbss5HJKNayYf6HFxPbcnZKqXVR7byFdPw//odLrarB3Yuovsu1nlD4DEuz9HoFNuT625ZpmHcjax0FoXvmEvqylyd1BTeTUWqota1t5nWD/IDvuszakkyPU4glRz9nOJj0iwGBXcmNMOknHwq+MoFtW2GRSDn4qTlcG4uYk/H+vzGK8wHjKgcQ5Q/uZWFnadrr2y9lgBEAK+WKcZUx9O4jRSxPqgA6nrjB7D0yPCKEDbNvcK8vtwSePVgXMY1u7cgn4EdUoaiA6HjfaYHiYMD66rpDiclphBDDGkzd88lzB8pPU5okG3Lw5TlD9AaUY8YHTlsXr+ZAAuywbMCNLCTkNtgd++y+gucuZ+FPsnEHcj2j7CPHq+pCYmq1qUsTVw3JKt1nbKuyb7jWSQzihCzcWlLjyly1JmbGTWfDm0A06Uug7wLKjkwPLJUzgj+vq2vUbST/P9cbht/8PNvjWTvS6Oz0Ya3+uzgJqxWT9e+sck5oJHYjb7WubCNp1exxzdEu7sQfMoppPE9HiVZuyFsoL/dOKFtaM83lmF7jXhFjUySa7/UkOomqnotNC8HEcXeXC7EWLyuFRd1EJaHnOZwvl6SLSO+cOPP0VYfvouu6lddYX/TYHofAfIvWdSNbnLRgN9DA3q5HOWMETK345yxY1Oc0yU+71U4CHYvRgRxA2fHuybZMPvT1PWR62N7yAhGpNcnuzXmz3ExxpzW6qQj9tQoqg5fb6neFvlJcF+3GNYiv1Ft8zHWdqhMyhPQkfnstNfhWfPwlz2mJjXCKCvz0gXC1HwH5cBkudGgrm5Q0aral1oJ3YwFwrhLnfFTiHLzT73//gyS4Rw0w3u9d1bLdgyqMu40lEcjD9uweaFV+U0rNxUjluYlgerTQyxVJEesw93tCkrL/WMX5ax0F4y5HI5TCtjdKWn5w49yCU2qaIjGTY6GjCJyJSIkon0TCCILMK1nuIY1wHNhyzKQ2ivmRBfUSzS75t5PAySrDbi4H2HFFLW+2+rWnvegykzoJ1B5I3FIQQahpzNvZpc0o30VeXIAeugiLMrVxq+7MUv2jtbTTvJn16WzyYvfchX5I2BUFkV81Lfg2nJTmKHSVhut+mObvfbp18T38bFmCODjLvseIVtZdD+6FOnDkN5lOzMF2q/amgpYR7KL5kuQpOHmGerInluBGHgIulsj6v0GAfelYgHCW3KgWuIPZA4nE7lcea9D0hjQ7DWtSu2u7iPUFwVzgc/jz4WA64/lArPsGDNu6khm8BpVvo4LTZkxgfL3zJi4j54eXnufomHnskeGCo+JPDjYPeS3UMVEaY+RqgymvmRo7mMp7FS4OlQmFcizuQciA7IIbxEZFBQ282XZIiuhvs3xcCjTplsJYNheQBB+kSKLKD7xKNm/gLiGUW70YI44+aOi+t5nnX9OvUnCFtOVRIqA/UNx/7GmldUc3XMEyHtkme" + "jFxVuI8rUXI7y6KqSKl+YDCvS5/uY2jOIFnkWFwimIRKiWSCze8dpSrl4djZzgUR73P5eeI9DCUVm+3JH5GRyV9IIiYBEekXmpvPMZGWG4CkHdb5ia3lMPSkNpwFqdqorDjKRphT5dCyOPIACU9FKWaVNMX2nCQGP2rJwz5ohaqc+Md/53fCe9em9V3cLoQkcwPt3hzfM9xLjnJ+3bub1a2dBwbtQvrqbXCrIghTC5SKpo418yjT9BNBiI0AMHAXHH7mJOhwfR7VNCoOaw5jpB9tlBrpp4AJJ/H7KKKi14yPhGLlYQolMaU/5+UVdc+I8QzZfHlWFCKv+FD/Jd8/ujZGLDT4GzjgmSveU+okfJmTBOCY5F+vwGgHBnmiXaObQW99M35Zb/hB61dC5T6Q7pcYxcKMV4SldxpS+/YJZpPP/2NYK414X88G/cg35q+HEPPzlVBvT43N0e9QzcjExGFi1I+Ta74SOMQvrcM1jeAj+zSp0iETAnsoj2OpQ0ETZrppbD1WkbfsCnltTcAycHtdnDGUPnByZ/wKSL1ttBRyUA5hKAxlG9VQcZmrNa1Qd/PPXXSjSX1WJo58a/gfg3GrqJLw0op8hczseUA/af86jnUu2UosgspvzIZbyyVPnGvbX1jwHzrrSnEpFuV9XpqSj1rqSfaGE0xSQT4zFLc2S2cyVCKJge3HbxL5hKdVzotMyjKtqgdx614Qm3kewu11YH4XO6UGh5hopJdfiEVc2q0bU9wlbyAxyU5mLjZdbUa9dDx/l51fHDNaL2nIQCYAb63ulCxi81G2GBER0bvrUINVuefbU8MnNvJeQpKN0C0Z0sjr8Spy8/LR0XHtK9YgKcgvaVr/ARENGwni3hGn3nJdVgGgC7bNTMglN7PaVbJ/jukSjnHLHG8ch8ibUv1+qu9nKLrdRAsNXAQQUNeLW9miZ1r+YRXV+Lw9e3hY/sN2t1e2iK4povxhdJgoegP/yp7NB1+uVkjJIleksIdUgicSGA+UowLTA3X7RVJG6lXkrEjs5gI0RvHf8BLTDeda5jS+C2QEqPs1ufysMFHglKhD9ZsGekO1nLvBX9OnIqRaCQ1Kb/0i77udWrae0toj3DwhJoXbG6Gs5CI0vi3kfrL/kMlsUaYHP3SKr/HbxFE+5PX1vylzac9PI8E1xynHqyo2UPTujlV26y65mRd5NLHocy06EVrsX+8stLJZ/QccCe3BtHsGf+CpA1pQIkBd4tm6csJ0FdiJR9emZ+EUBTEpAuXovyCqD26SKTlYkOx1alUxrLPEs0Shk/05Ne/YNS/viPZTA1l7NrqPvPjVvuLhr28mDPxM8cOS3xz2ASU5n/RAVc3MRd5ha1RtBEzMeCbxhGg5He0AuILIcmSqLVP98elwO9q1SWNh3qlZhxy1xrQIcCPuhV0H42yVX/QLR3G2ugM3G+levvh66NXwY2W99HsGGfJIPZb3jB8DeWeS25pHFxh+JhsvkXd8Xazcv/CdJoXcMrH91mAUYf4OSq0SjNHqYAlEU1YM/CvOLGTOdc7lbsOa68oLcaipzp8dmSBjy6pAh9aaimcN0RuJ+EerKcaucKL0bjN8JMv/RC7imtEIok/pOBSPLn+uXKtL+K6Q2+efqs6Qy/RTKom5PCzj3mnGTt0UtAWCs/c0ji8r0H4LdeUwm6KZgNSrnh40golbqJn7hf5bywvjCEs5WHGAlGnSNk4VPWaWPd9JjnFG1tGnSX6K2w6VwvXJgLU/6IBMdgTex6nJZkr1dSvXKhet0mNfv0Usl8nEW4cBhxteI1cKjVzSNeJFg+ad1Lz0ZO6a32kvx1ENpC+Ucnmpfyngl78hmsEBCuPa6808bJ/dJNu80Y+YqLTUCKInJSKX45+uMc6Cb3cn7hYEBevlPQQcm9oGdHbJuEJihD7NDEDVBW0Yof+MooJI5/eL+odcie5YGGv0k3MNvw9ur4W7MBhvrcUhoRBLfQEwcohVG1jPIzr9xIyhdoSOAEjpBW193Q+oQvY1Wm6Q0F6+j7TM+UtSmZqGft1S8NFxj36guvSBp/G5eKzbmfi99ZFPDL81da32bpXiHG39Ssgq1BAepoSvIYYrs3VUmcvWRTtmJ8p9N6C8G9stLmoFY3qVInq41z++nAerLI9+qb2pR9SXC+c4MxEa7qniutaD2bs1u+ySIyz35zTZLj6nw2lxea+a2RPKng1LUFXVvgLfY15ccOa6UOsiWTsNGXNZjcxwasiRo1r5jGhUeEeIOXpecd+1yv05j9To25M9alpdgTrrej4JrA4KdumYNR+TBABV3ElfYtOV4eqWhN20auHcIN/5xrfUO+++vO2ZB6G3Qhn2xfLpLq1i0zh3ULpvP6/gLcVgNYS87DktsM5TwVeynsGoAvyUfrl1rubhgmHxEFuI4K8XI509/WXHDm8YMuB4GYZxRKqz56nbVzwxTUwF+tDcK52oSWoi08xFoRa2pmm0ati1U45HSjMOAbI6Pm3rkEqAWCOgbHYwpGC9spmQLYzwkA1luAz+byPC4AAxb7jzf+BwmA6uCi3otjbUt8IO1xwgkRX84Nem4HfJTttW29P/KgjLHhuhjHJ51AQr+LN1ZIAHirYyjPAbDkGti6YTxq0UIDwDYNBufGxJapH2MQNSn9lBP824mOkbgmfFNn+bYw4grZpPIXHLgPkdDrDoEzNuZ/OUz14Fvx6hthZtLTBJjWGirKaLkEC13xt1TLc/pQN0nUH0kZsSXvin/7xldMOWsBdGj/CIGfdfscinVrtumimPfjydeNObnvfJrvwhy1ZtbW/cnVUElRNKqYlEeofpzFyh/Ht4adOrfgu9dOTXWrCmHuGjG9ckDO9NiTwBsovpsrQHPJchVrzvyckAgJrEJy3m3IUwk0PgzLe4l1sh+4eghLIoqEJXxV2xmQFMP8bd6wSFolgl22bglXWhg3KGB0lb9QjWqVjCC2qMlo/DxeD0Yabh53RmalcfchEhKqTvz/sx3jJzuMSuaSrjpe3onAKimoijdlw8VKlb9+jmK2vKBOl7PPrlF2JcPWmJ8QF3kwWllyr2zSZ9u32vXEGwklXqvGgFUoY0eVFMo5LEZEOhPcGprIa1852kImiRQ2X8DUNBrUoFPcZC5s9Txu/P6Yp/bjqaZ78WaA1G9+RJlXNIv5hRRViZ8wM4BTZiPq6VGCXAkYzIad1OhmrXV3IFC72r5grsRHl9s1k+CluFIOBG/Y099zDG/tCh438GdvTBFoi9cq6U6+S0jinrN/61h/7aj2mm/C+rPPX9yPUvcbn9Z2ssHBteBjevrr1mcrsaitbJbS05BAaNkCmyR/GCIj3U+jmvEpt676tkE2el7MdrRFaRpoB1L4mwEBBaJBgt2YM9w4rxMMweqWWC1Q2LwPG3Hdd0elPRfeGO33q5EtLHc/Jkl0fLmg/CeVty3PdRvd9yeCMMR626X3P5C5Q3XYLzk1+BdZhd6aift253iSlE/k1l3bMh/yv5+oXnnI+PwV1DtaDl83ON+lJqT13mQgdrrLVNOk7Zbzy6KxRvGrv0dV9I2V7aDhutBg7ZyB5Q9696Vf76bqBk614ejWl5RYndvs0/aU2v1URRSorfXwOoAW0E3mwZnub5HQq81Q2jSMMccwZkIxK2d6g1LRfkWYu2TzTX+8sQUblx54L6cVpn4k3WG6kq/vLdzq23xzpcL4/CnlV2IJ8rpp+JgoqTwSK2zYXSTn1NXDiKB1r4JHTt4xyVHQxXKHrzASfyJ7WZGmc7q1kS6+oHNR1yXGERQjUignm366n4fueLLneah8MJdHb1zs6fR7NBOcLKJnadQCqwt3U8u5uLUt7pWitrhUcqohaYuTZ5aIQGrCv2paJc3Gbb1HtFNC2urrzgJmqurkf45iyn7dAoAaUotq86i7lmgXL0Ru+yNNMnA5KRCfj5FrpCYO/gNl6PQcMXR2UxLS8/nbydZCp65Mfh+vwQobDvv96xSqrvm3mgZ1sxMZSHnjrxFJ+ZCUceAsu7Xkd9X29fI0HkhsHzHvdvmQSW1mh8uO15EZBpU9aBT4EePy8QVSZGwFWtC29m02kbKy1ZsN1qpHmak7" + "sZpZWtVTpeCyry8BDzG45kddETo/Zu6C0hH7+6POmzW84EAaU26PxvU1lGnQ79fisPpAmem2w8l6O35Attvvq7tsGt5ecb06Vg75hSZ29xLZZw4Euv9EN0tWJNy0i+rvivIImVZUFfA7eCf46cRlGvCNjCn651NPDjt/N88YF44AF8DPb7sBqHv7p3Iuro4/N3vNMzS/fCT3vUn2w/6iUTnpmro3OS2inG4HmRPLqNALJMkVrhlUW5ejZh3D4PwP1wF02464fkIb8qDA5LKSoTqerQVYembqIn0heXaY4I56d6n06tZ+KBxKh6HijKii1VlP0IoC2kqcx1GGtz9KY5mBRg36RxQbgS58Rw+MFYGNkGffVF/C7ar5wKpy7oZlWtx2AXSpUgMHzOI2k8rD10JNZ81F84rJus/cvFtb69f7oN38hsDPcNcw/px2SCNaFlNzOsmZ26tY6G05dfFhIxQXwipeAnK8iimZyyNHVW0ieVZwIUztGxAIUIOLCSCmu77xE7+pdQ3CObUyAcc5B3LP4Vtgsdbl6qjBUqXktr0rUmYmF79y6tsKIcw7x4JCwPoez5HTps0cvHMsh91S8Rc4Dp/Rl0+4/mmXslvlS93bvG1Jx1jNz6RltYQh2i1l+HStF98PZFMwXsUiq1O8jOpwa/hlFBAqy25ppLhBgJy8h/ZMUngjdJ7jov4HRVQCSCB7ioASD9BYjyjsBI02/tsupz/gQtQp5t3k8oBwZCpWafmrTfrRz1gO68islhCmdRTWbxSIX2Hm8x1w0RSnGbKk+ZxSfQj3ZK7JkOswTfcf37EXTKYrsj1vU949qFbPK5zmJ+eO+YarGJB5XeoMPMFbL9E0Tvd59reeil8he68dRRP3Y7/hMtqKA1OmVIsybEkniNVRVvD49D3JewnTmIj0mMVjtzifBWFYZOA9zebsTUfzVN0UJN9jNIyhaBXWxBtQNX2EgXa7pInvfPi1/ExT0BxlS6s8Pjsv6JebsC9uRFog48N5RxExqzaXd6GnHLoBlfS5IGjVbg2c2Fdvv6cDV9KHWccMujR+OubN+h2bOG+UUBI+D2dwDxjzmx2WstRhlLvTqwuCdrTA/okr5p25IajG8kSU/GExxVJcF9frDz3l7JVyl0Z7TkZmKXoe1F5SztERV0sLp3W4eGJ0BvXPY5Ux66agWFsIbrPj7Ks6G+Yo0wOuQuAUruD/KuP6sMMyjV4uoH7crGkXLCf9ZMYK/Gq1sVWkQK9V+KW8/SQ/RmLnSt2to2Xs8PyYu3+aLRJnY6Y3Q/c8VyEl3j/hW7wibm72vjTbBeDmz0ZpdbdtO5/NnKrV4sacND/MOW0U4jqtnmRLPWay7YjUdcDl3ysVOAh5kDp6j7B8697ErNGzs2g0EwphpVnX1J3PRev8J+1INBqzVRuR+WUzdX6KnY5RHHyuKZZVAHyZHwPO5SQKtbR3z2+UL5OSWxTJnhBdpp0tiYhutmlrAFFPtJbdDAnk+jI9ZBOc3WYDZeod+D/qvM4Vvs0gP0wkrn56fwYBeCXaC/jiGyj3ABPFL3tTrDOeVtVkla41Ex8VfQbZLCgfy3u25E55Sv8P8HpQ3mN7QW/eUlvD6M7FwrEmDIjPEUHwfAZtHqYrLSqYXk6sVOcYUpybCtuzct/ed/qmGx90UTnwAC/s6ELRnf6HtqBW+E5xRp3rJHhWmNriUmz6pPLCQY1GoggctFhYsxRxy0qZZZxJxZ3wAnxZ+GWVfRNTXoJ85hvAVKM2AGeCfaiUBeMSDO8AgyjWZWICG7WluFHvuLRvsmxU5peee35vwYJZj9WbyWHd1qUY0cM4J8UbNIr8FtMlwDadqvZiEUR3e9bB80gB8yiPGgUGY3bqdoZa7a/xQM2U9tqN9EWPORRkbVjEln3quMUzKw156vh+SK/QMQOs+C4/ezU5uqvKUwcrj3afkK7Juq76VGld181beyETnEYk50devTqQWw/zCKl6+YFehwuOcW0i5/D2Q5mKTmNp/yIgEEpY5qXXf09UnZbvMO48rOTyuia5FrJyHHmEwGl0UzmpqabLBr7+t0IhSqhaQuS3zXl/kryBi1bUKGztXjQ0H5uuGIzoG26g+kIa0N9113WrURoB1vrAcvtg7vjHNs2HxWsf4TanUAvE8tR6iqwk7+Li87t/sBeu5XKPbSV1tj/GGb3fPARQg+UwusPQra9bscFkjfaXjTlP6lUB/CPXJy1qD8Wb+k2h/zwi5E6WtTIkGNJRjAVJVEcN7gAuFu/OFMSr8DeHfSxYdOECU03bHGAvvpo2YeDAElGDx5meyMjb6z5JXjISz6NfAr5V9VxtETQfzqWYdX1R7nMLOKd2t1CuZDcXxpmSz6EJ0GqxQTtH08fPwdE7IkNQDsdZRudPdHt1SrYX4Hn6Sh052uzAKRN0k3kHHMlRV+BJq+/ZhtFP1YnumMs3fTo1rYrzhSLi1SUUGBXnU/JjKGHgn2okLVYm9QlbiR9axVAVO0bKN/8iOYF1VRxsq34xhFhw93ReOpPeRMVULTcml5/97LcldOXIKTK97NAtf5SfFdFY2j48hYTkHFnVisxrwUfPr0cYeNERHWM9+4Glpmk96iK1wS9HFLzDi1FCB2stnSIeOf8KtYS0GMDcbQiYGsmdVVVrO/4VaKSHDorhHV0F45vNriuoTEb2obOLXB7uovi4u99GDb0EiYL7N2GmajtDzY6EE6O8C/OS8oqY52DdtnBlysXxmN+qgn+lK/JOLiT682lV8nIlGW3wc8SHh1aHUB3OwJzIRZ53s5SrupzR6qKiTPh5/IG8rV2AbmQg1iR1ZHGcLJGDwyN6CMot0av75qexn74k71Qz8cC4rK1LO20IPaXgqab5uQ3SJIrKxeVI/HfNMN0DTheDwGfPq6dMiC4Lt6f8GWhJWCjXGfiharL5d/qI4Uppcoxm/j0NMkMFlWBA65PDffGwqB85XhfuNKXqtxxxbd5N/Q0xHjfhgn91jyHtfQfUSDCG9XXLEpLaeFwnxL/cUE0EyoKgf86tFW1E+VPP8cp88qs70zuqzTWPdm2BwOtqi1BGOP1HyIJV1mr829FWPm08fzsrB/hzLBg/VC5/b628TaaTzF0lJpc1F8aHLmqB4CDNJCzdJWIbOenv3ZhztxXOUtJG/MhJMPj207cfyII8/4bqYV3YNaC0WMBaU5K2dn1WQXHhFhgR3IIye9np3Vb7vY9mkLSiV8Q260cbu9w9C4n65X64/2OqqN6MV29zBGxdirojCK6dCE4TKTpXdyWQTNb2R4WvoAqcyBbDTjq1cUkVHzCsVWOLqtf5xd8rH8qCS7DqXtnjwRFHGhVb1HmAlf7o16syh506S9JDnrmEK/2sCyhuJ6bzl4h5JuX5+jTHatWaou1q087Hbj5xs7YtWYnjH/VngIewoXaTioEBlLesaauzS3xtBrnN1fMDdr5Ic5QRM/gDyrMQJI3MozY1h7SSs4nL7cH/WY74D6Wn6AnHlq6/w4WE/e9ID/UBYSIY9opOmPaJrbeBy08QB+NqLm/hxq2knq5Dp5WlnTwc6w4WrFnd+OuG4mBuOJv1Vx0jfFuWjC+fhY+UVxY59bfq54ev9ieiFjWBs/nJRptKCY6qxVWSrgptmt4PuBg9YyCHcLvnNRQZsiB5VdRSIjU4woRJ5SJi5uf4QZRf4LblB5JsEoAucoanlB9YLJ+d3U4vT0LH6tTdRZR1eE9rvhp0ZC7bCZ16Fadmu/ArWFeit2+fydhe0xU6cEsxYvVNfiYAWqN1E2v2ibsqd67XY8/36XL7gaoqSRo/AhxItPKz6lvcpraH1bdrqvWqizP/1Pr2oAXqIM1DTkPzEEvx5PSlglgKzGX4jU1KzhejOpKfK6kUtIBmJCQLbjNuhZsRCKpy5G6D877u179b8ojxsef1KuIpw8UdzM654PAD76T572WFg8xUu8+MV41pQTT0Sx9EPMe8ClN+OfrNFdiKhQhrUcGz/hvVWMEQI28jJJyODysQNBTNdCqjvVHYOJyPIgGqyG7gSWvb/5eb3IiPbFCsgWk9Uk/l9Lz/6VDYq6ZbIuVx3NtnedDcjfFZgSKK3y" + "Z+I9T93PqMMEPcA4tWGLmo9Z3sYaLZx3M+QO3RpEzNtWYH1pGAq4Etzg9MZ/RpT7A7E8q2GdcyFbKsliI+LmrBHu4GCITVqKpMjhT6CVOLq2J3WTn/1z3w7f/+Zw9ydUTsWv7xdWLeCOMGYCA1R6EhwRRBf1mXhvxAXSbXa+WVH/IV5uYoannTrDyUEP6plbNjfgNl/iHfB++NU7cibSCmvccTzA8zqv9Tn08MvBy4uRvy5F3UIRNDSRGoCFcPeSP8Ddx8wurU3WphqBnDrt+cBS4fy5OzgB3z9AUtfx0G4C8z/cV3mK3rziIeXqCHNo1CqT0lzuIutD7KKD79hjViSSHc+ghkTmONNgLPVGB1EmYpv2Y56LVXa0YD1tTmMofGdnDPou3GrNCcxSVKXpBWX+342tit3+piu2CHIaHfwwZY5utCyYq2ozRoxQZz7gNMKHf+AW1A16/th61Jz9c1+DGe+TGV9+xXjjvcuyV3w6z90GCl8RYG4MbYeJysJ8LzvYj7bRQXIK+2mepczfpFDt+hSHwyX1n0QsCzhe7djoYbrKaGyIxl1u0oaysvAizvgI23Yd856sF7PDD0mXrxtDYoGpndgoF6d9VauQYa3UGgkaBAf8uNXJ/3icFzLuf0prymvztZYE/niz/kXmo+3Q1kDPVFtgAGP70OBeo4O94/rX02D5KGlkLSV8KG5g+iPDyCK1iHUk+hsgNtZr8zt0SOVCklaRmGQaBUF+DmAo/KdOtTnbLWam84mbhyA9izsXYf0Vqn5SLGzoh5dVNu6AZr4tCzT4CEnnh+xHmqAGLK76YdSlALaD9VDj8sLilzCInd7S73swaaSq0BSszenT+IBD77Vut/G6qgOfHLL72RLcbvg8Pyl1tCwwwMVa3aFBBxX7moWvnDucTz6q2/NuVnrASsZHrARNykzab0XFWVcCXlcs61j5rNUHjGV5s8BlYNSO7d+4hl3dxjX80W765Ii7Knm8nGX6owpZC39JGmJFsf840Yy49CXnXqj0VPdmMTHCBxZ+XuAoeVINtGUfvkmcPrSJm8BEBjPFbroYOBa5T6o2K6Tk94NNrv/OdDahLkjoEQHXThnv64mpHLQg/MbbY56RF2EqrT6wfO82UtIpdzFvFBcBtsr12Z+PU+om0yF5nXCFEecKzwYOplbm418ZW9tRLncDRszNPTlqCM7O0mT3V6x7IwFmXbpB0/Qq0z8IlvM4pfZukSl5+Kq+QGBC70vFCr5Wl77n3K/1egyQCCqV5XOFKazSnFt49j0si6IYmQYk90y83d2yPXppLEGW620rQftdfHLdwSBkxUpHbtNRAFz2b/nEOzWCX/HtdV6H98NJwdJ+IWza76cFv3UkyrO77DbNCc2P6QFaYT6uwSg1U27uLj73NmJw07GliEaNVMX++8iB/MGdCst0GBSgAqqqjG5qvNRDjtvIDjkbqOFWhaR7A8vPxcjKeVA0nmnlZchNKg95qCmb4Ge7E2Ru+vZVB+ZhFU7ShuTXFE3uAgqzxlJOfelFai5lxe5Ry/vUCeySFX+LXt9PKzwVBeAfYKCbpzmOHfueDho7WAyW+kOXbh/nu8n1fQ5loJ3qb0okt6bLfovX0zauHX4cB/A/7VbpqBHdud1xMxS/mltuEuqr7YvKmarbtjSGUpT6kjBG4od282Mj/Jid7zEvd4NOuczZc0OgXbnjCpddc9bDv/+78FoGj8VtuJzvuEhbsxB8z9tBfNr8cV/9RhctSO9Hi55JkgPsJaICfkZiLHos6er5BzXwzWIKES3Nxsjl4l8QwEgvo8sB37njrsH35ffAEFtpUG+Tn6Dp97cVwFFjEHDVZ5iA2TEDkUPB2BsLhNs4RIH0HYCVJ/kbeTQqH6EzMj09YjSz6rvukZo0Jbxhjy6gn435858KaCl0uRNXUVX/Wcnhn5SVrI9WTN8VdYyZX6zK9MiT8wfbpWsgLgfiWW06sN5dyrzit7s5Eeed15oPiZHpfrh/lfuYID9CY9EBzgsVpl1ldfx039TxZWhnK8HYokKNuy2UYo3jHUFDQG64rPIw0JglDtuP5bq3i/hOowZ77Nbe2PR1VabJqh5q1iAhCkKmEbW6NSvtrhy0VK9VJTldhRWnW6vmvTgGrz1gTBtVFb1q0mDwY/wDnaxwA7/Z07z3+s/NCP/dG9/kOzVLiz08HJnD5iVk096VryIM6MbDwAZv54TPlPMyGBXdImlhMkauHhEL3qCYmagcXvny0kTh4Z9/nXA+QgSuU6a6hrO5qry7KQ9U63KdFXgF66BzfXU/FXxwhpSnuIPBGAVCg9EAkMy3FpDzs/YeQd+OXJ6oQ/aQI/a/1i/YFScueTPH+QSK/+4JtLS8ZkpS1GQfZvBDGjHQYpfnbuGuvTgvJZYVxCukXqoAwGhxVeGNelLNn6O41AFVJ8JZuvdM+w5mjY6mfIGxL3l5qKv17DcSeh4kE0bu7e89bkIRCaOvp8E7xzLXrmUZujXCd+WyHIAVKqdJ81GjkMg9v44XBz1J2g9+tga6IQpAcisCLjF6mMK+/kPx0P8wl9E4tGVeYkFtEUI+Oxzonii5bbDbVvrXyR8bhKSuQbrvNH8MI13AzK8QygSvu1uA8ss45YCcrW58zpvU+L8hCYd15vwDGEo1UOl7a4bDtfbWumiFIne0nJTdf0aqsYL75ZEBjzU5wF4iget/7J5ZOtcKv0JYKWFK1LTx5ECxpDftK6Zd+LdZ2f+pAe7/K376JvB3YHYoPqnHr6tNDsZvSui4KyYzWKAHzN9PLzm6Qx/7DuAPwSlkl8UF9ZNl+q47ekvbU2n/4GstEvaKGuatQ3Pw/bhEXe5cfgULWwgXOg0D4OnquOyNpTp+hyua2hc71tfu1+ArkXJgu62MlKIO3O3y94Jyvhr5AdyuOmGKMwC/aEdXr87n6IasFh9z5CtHPd3kupUZ31jRnIfIfV6+JsbuejEwW4ct4Kmk926uN5ZiBHtO/hfnww8q0i7N91S32l+z1bGbieOgOZoKYMl+K52oCxen3vxRnoBWjLB9ZvGe5YrHnM3HTnxFeF5AtlyvOVDvCT3Uc0be890MthClUjmtCwwTx3EJ+RTXiDnPhnthACM/OgqAqHRXGF/CB+i1tIeBlpummSWv8a9gZyEAEIHNQ8KHnMLXmV/RVZV6Q5JBSGmIxvuBTgQj5FL9AS6ZEL7PGYBpXyg3JKgb4pYIKpdgMMwVTbTcNtjFfJOTAJwcLYIlx+N0HzH2JsWNDV/QY6soaUoIuCX0Q0XKaUyMrNL6UxJ12eSbLt/vyx/qQRuLcbqFxaNiw865IF0vbU9fleuEww8DfFk9CgHBoPZ7fc40syzy2Gn+ICrpGYFkuo3ALejuVnfpUmEjtr/lutw+VB86EQ59gdpQco1PokFMpvYi0bd+FR0qSIXVlWraHlDOx0O+jSamKu+w1THVH4HV6YsOvltydPiyBTsxb3k86TVf76P6pKo3y+4Y1ETFc9iGn5nKGzuRcfE2Xx4cmHZuwEp16oj8ctykWuoGQGoJTmXzgiHu6CyPxlN0qGcra3oUyboZLTOHhUvVrirTTDjX1ZboYklzN3UCVA0RcwiOx0WSx9wzh99ZDlPrzN9xWHHWfMZ+yVMVhT0jGfSTYq+ZjpO8xYyg3k7trqKiTglAC9kCwM/v/tC3e0iBii1gAh+PzIosvgmiNfDd8ORlbTdZeP11IeJrBCsq46QdpOUTJxnaSmHLxav1+vOpILHHExdXt0Kr9z/ybecay99wNYEZR5TgFEZPfz4pdeDNHyTNPm4E/ZDLrnVjOlPp+9FVS+Lv7i1DAEnYfZNkkkkEOtyDPaalMcd7caN2kzEXU8+ztz25xOe3ueT51Gt755qSQB+mo6f+PHrAXzN/7nXQDc0NC73uWwV5bVfKh8idx0W6cc3M3Xp6gkgOBexRIXc229pxoXl63WxwCPcGpSkSIMISmY1JZpfgs8wPvMAOteW5ajvb13FU0zYXdXT2t8Skzf8hZULflZlfL31l6+DqJeyWzxdtwE1p/dV6AwSFj0+X4mIU1uXlUNFtWar0EQQesUzNcwWBwzsEMDImdRJzJg" + "s0lh38p+DK7zylOFQh6Q1WHVx0Y7FFGOth6Q2Pj0fsILtxV/FOONIJmt1W5YeiQn5GjNpIbVq5qsIEkbke+RFvTZ9IhsCP8Jml/CEKTIU02llfeSLM5xqcP/AQR/Ng1P1S1KXuHBhmHGeFZLBM5F3TuBpoL2FbQnbQ63wpbhSfeHkBYg47Ya821OpJ0sN7SnNohGgsVOH4UCJQ6fGjUCDS331gqknZurWevFpxVUnuXnn58p8PLSXQ1pqt1zYdbl7d7w5jfKSUrPf8Ad+Q83RJF2hUYwIO4/BQVo639OQiFumaKARgrk9OPPDYGcjxhsi4tfIBeGyDXwExO4bzoWrSmYxWP0N6bN5dPu1Pp9PiltTT5vTebxhNtWgQnmdPzhIjio3RXWQuhUXr7jNtWXt1hegDVGhATukOm3ABW1RT4D2H7oMiunoGHtT3qXgrj3JkgRESkOgm/P4FlB/pi6ZlP8XiUb/SHu4vuC3yFZAMJeK5prLg5ywNdIa7wEbljIRbCQcfY8/Q0SNN9LpYCrRg/ilh+SbKcyWulUS4m7ZLRJIdKFi9z2wRxbv9vDATOqzFL5H08yYpFjAay12oQOTXRKPTpwdqZYYGHprTqmPqknsebhyAR7USh7GaRn9/daQPXa+g0Lp9jYV0ZyQ5AqMLzsJnFiMV2t4WmpYl52HkR7onCtQuW17fG94iQ79XLrAoZ2shGE+Odd9RXVGrjUSOqGP0IyGDPC63G57JCbWQwoqPlbMM/fmW05Yrik0WMoVe/lW820GapLM+jqd+eXbXTA15GnTYSVn5tWuckQNfto4HHJ3w4WtBT50GwWkubHWXDfh08xvp3zhZIuYlwfpE4qsiS0b3dTEIn7d6LMxmYV/+xguD5NfVq3Y2caIb3EW6OS76/R2JF89PlAsF59NProHppmgvDpNe+6DpFc9Sr8LLlDGT1oD6MAubqo2Q4mn9LfJ4LqYnhcp2Dh77mO57nIfOBZo8V5RBaukABxwae80dMr4qS1XPXr5itCXHSN23fLDdtHzE4wTU+dgwSpVR+3RkMTaVBo0n9DumZQ3ZIcB3+MPC3opa07VmOJupnU/lxXaf/N7KB4L5oGdYXjoKOS2Ts0Cu8mZivIX5wngHmPvQu2GhvXy1fKfoj6tn39Plr5TEKsKeCuhWuyYay6MIT1Kwflz4CfxepIz+agNPflq5GoDjWkzlHpDoDxdgUFD//Bs/VwKzhteaIQBGz5VsSqXslfchpfOax5qohHLY3oJOLqwlWXRdocrtmMEFaGj/yYNJv+LnbltDX2XWS3pUewxd64Vc+nJc9c+llMv8qr8BHJo0t4Fc+jCwNv0cxo7Hcy+Vw+O7aQg252d1ttpRX/0haR0s4yopEQXyg7m6murKdSFIqLoaBbHI20YvnBXBRIQDPVL2Vrdg+vVcmyS1FRvzusntOWNYqk3nsceVeHi5Y478FstN4eHXGaWU1r3DV3bbqhOJvB00WADVwSOs1Ajxz9t0JCt8uY78qby8qX+hW7zOQj2wROUvoagTi+tQfHX9S4sJyljR+CPB6NFQjrVaLHKyqsK9lvVSEszYuL1IHgA32WGpKeWJAszn+uBu++cDrZ3jVa8LuoCfat1sBT3KcdN96kG775PwPN8JtieYezz9NdaoU21pQLcU025O+Xbtm/zj11q8359hLA4DZtrLh3yC45jS5IIa6DgFr7PVx9ngiiBNtjVeSCjgS0Qym55Ow9yePbuxbflsOySU+sHteHvWuKPJJt7Yus6iT6thc19ci5inHo3VikUSLnFX8JzsijOQv8IJLVqhypFQRJsmw4wtMjCihY0DwvNeHjn694je+FbsFvEojHp1CLUOe1lWtLXtaEl/W7790m+alcoMFG8b2twzq85DLoblvstlbIR6jC+QIgQ6kJpYwQRcktSUjLQ/VIvb2uNVRC4xrEqLoHr6MCb5660coc7gEXFXQ6zx0/r868PLTkmDoC4k9TDhOMN1KkDe/LNM9Xh0CYRUfScFSX0WyQQOfTy6hl6tFlRNvr+G7FcN+Ox+qaEQpzDdQQnV4DNaXe3g1E75bDoEUPktFUC97ycsJzuZfAXbjKXvId8uXtOiXgfYqxiJenuBhgy32KCwYFM7h+uKUb0ZGF08Lc9j/G01mTrVyPZ3iDe5+VOOqWvHzfhgmhneDypbIfHbSrufkrqXAf1ujddzXsQyLZHXqcawFc+fLMKx/lmvw97LhcHxTc+d2tvWVoS9WN2s5FhQlFBJzkW6e7iI20QRUQ9j/zPv4mmovp1gRdPxKXETTl3m5da71Jn/0JUuTIx1xTDVHhINGZKvEH3WTBTddzPB2vWnjhfXQnDjqQjXK1l1u6mB6fEz8AOU8/V86wmcvKHXvA02Bh2JzoneDAGmktWWJ2AsThHQ8SQJnz2clzCWZyQgQihl3poFfdXfAL5/cYhp454s5BwEqv4DIjTV4fInRNl/2Ma/VVcxPf53W93hOo9EYg8p7L6quksyKkvClWEGk72eo1jveLP41qOm7t8JM5FWTDDu016FCH3d0WNYeuk25e48lGD3QyICqp/h/5DB4oJKqHYfR7es1An6FNNO6wHmwH0EmoKC2jCrqe1vWAuTRIobgMIm0Z+nRmgnMCN1A0058lYNpk39e3X4dNJpFRRoaq9AbalthKj+3zlZFPlxl4T7vCX3TkSMjLp5brPGBMWiEOFC4NZTWV/CQ/LB2x4wy+sX0usvBTee3kX9lx1J6jCTZcE/kP1CftjVlqFpt1Vl8jFfJPGejY6dVczdlaCXjIXJ0D7KY1MUXLpZzLzOOyJ7Pz02npu3JQT4DFE6hsuMw03qUbFLz3xgGmfxQrHNTad+FEiskSMH2MaVmn5wUz5MAzxKgLN/Cjekb89Su2p+wFZePoLorlj+19EJ+8lme5jzo+161ATI77TsVybc7bj5tproDkVyx76Csya80t8lu0ZW3T45KqJxWKOtzmuKwicpnF/XzZGXXDx7tLauRK9WDmT20/W/tDwQB6ujZJDvvO9wcFiryOxK1AXYmY2m9YpkEO/A9FrsLFCFnth8bjFDKiii/cwSxSb4XJtZdROjSf+QD2oZ911GSnoCp0KRZ22YQO2KqVm51EsNqyhWvt6gJHwtk5ZlzjQfJq69NhVLVVzjMMJeQXxuFOZWWQyaUmSdvMjdd8KT0oK7LLv5Qh8rKuHFlXYkk0btJEMS/zZ2olbtLksOGLu+v4Fve1lcFJQg6gWIGTjLu7nt7igy/ROt8eHRYcC/8UrxnxeddeCSAiv0vQ9PDHcYlifIeU0GHGzW3KumrACvWrcbOjVei2c8BZG56KYxXzng8JtEML/3jLyPNDqyxcc35Mj2jr0hMKS3xy08tC6e60HSLIKmYYf8pkDP3I9BlZ1W9qDKhclMz6ToIQ9xDZlsCUaMGT3gkjSKED2HNyKbgZ7r31Pt0Di0jdThCByyAn6OLuzmkM5UzvM9iuAx/bRJoFALQbQF3dnZdgyJPZ8D7kZ++5Ux3qw6fYaPeLKOypuxWJsu72qkvErEB8999/yRx4uKhfcBPCYawJ9RQN/CiKR6ShynhFOG2UKGUIXVGL/Ai9e2u2iGL7nffubNngyqxE7vvQsJyqjVGD87a+lyRsRPPGNthwZpkHZtDl5jvYB/YkBf5pLg/mDAqhgh1McJLw4YXwITHr12K5G5qD05tdXcndhgFEoKDgN8AlIjo03aMW3UcJFfsVSI6HFyseQkjOCgMdLstOM6M7f+SC/yjf4pG/rGrfASVvucjqG1aPhZa+k3Nn25g2QtcVziQlo5Hap3ayfJ+THYcoCGmi+olUCjgOri++5BRiiqP/XKb7PwKqfMmvc1jf8aVmQSUi32DDCrnGom8gx8mXx3zgtPWMUrtLpZARSGtm7CpDsbZFKn4a0pyU5ux0+Fx3e8x52D5mnSTzfjjz62sLA+5oBEh1KjNHDSXsm+ld9+R8bKpneM/nbn0lunVg5KUP1EpOUnBEVhMvwKt6wK3RH8UdH9a9SA/F53ZtL5IB1//U7MhKniIrfKPmeFf7ouD2pc0/LgpcmaO/JQymUtadf57COh7C0cn34o" + "/qM0J7gZKspdewGl0Zt8BIkfLLc8hYsMhSetVmP5Sbytvm+lvQxe+M41IWMZS5NkStTcv9zU/p2/zCSnFY/NcqD5wVnkRVj9pAgYvK7eQT2ZLqGXIqwa675hauF/AoUKQQzPD93Hz7MVakNec3YNo5l7Ldt81fJsVrkFueXa9V8RscjW9YNNTnCNxaD3rBtNxidtwEG6BKezCoQthOKRF+JFtzgB6zM3syR9FZy+qdAtPX+2frQnXakNrP+I9xlLtsqhIvYc0ITHxQ77QVrF3raE4XXBVsPK6MkS8fMokBfgWLY6Y/VzI8cwcfAHCsdXef+62VanvCLqEsazzVe8NkYfjOc21GhBe+ouLINRhn9uwc3FqcNefRv8VZl4eakJCdXjhswbNeXknapDx+G9ur2DBH/EcqqbA6ibI+G/JS0vy3xteW7Qr381uBRDO/7Hl6ufh1K5pjCkfg+BvSBTp9q08FT/yvunzVEv6ZEuJFK7eIMsCNcWQn56N42bFYFVMHTpPz8Bbik1jhXvyRlvzUjBlq0/Z0pFw2tzA2Yf8XtS+/jMGgwMW9n3bA2hKKxmjwAy5P8rQPhyhwEaCwjHlklx9w7jgG8ik2JsrF9qCzuUR1oe3aaA66a1z+N+45i2wRO7xRSH3pUSeBZjkaV8Nw03SPC/JTDwQlyNeTPB4uitoHvx75dZXx34Afv/Mk8s0+fuFTgieYc+VhVMtF/zKZbmhqs12A3vn82i9bQ1XNTXOyFznnBp9ccfAP3K/zYbVC6yDKfv5L2PBAjVcZLZRpQ7J2MaA51g7l2m5o3IL6x3gQlAtHtP7YWpg+NP0mRqz6/D/3oplh7wIGXFlBcPnW8kbbjepiIfRKRiviAU2Xu+sDcpPGI+Q4ciVbaenn8kLZ9Fmen7iLmx2JUEnvSV/DsxiU1bHy++an/uCD2h9JHoI96o7XJ5KU5JXW1+BTDGK33iwK/sT0K+Va6oPdvJH2WsKUEVl3+IJ3MhQdi/L/Q2Z/LGvYVd3voF86ZS9glL8TH9Y3rAJpLDeurnqsoX5ra/4VHkLn1qnzVYKuUezpKG2NOtIRTSU0mJWSW78dQ7Chf92tKGyh89YIEI4GNQLkV3QpZqVrOha2n+rZhfLQ5kkJBqJa5PxQRy6QI7q0mpVKfnR5rVtmnhyeY45SLAnmjJP4cBY5JWT5v2tR1WRtcth8v5WNlY6cLjg6XCU4MAVKvpHP8Ju8FqiB5czzEsGE1vrzCvFvZbs8SaZG2fL0OyheRyDhzShrtSGfmSiiJpZ2JXpYd/TrdSsGtDxUj0uOu6crS+wsgxgAFDzO0UsSowBJSsAKATn4FcjwoznpckN2AvAzA+JvfVoBqYz5mrV/DbliJ+KOgjEf8R8g7uvd4lgFuZqvYTNNwYk7Frf81bThKlVrVlf1wwQuLivkfKaluIfgbMNScU/ojbovkXKXik/YXJpqRPG9yj/ps7mNZkT3FxndShiWir7dd3JfoI9rlNXV6Gac4ydr2QdnF1GTWgFu+XLmAOYN1Gsl+7/VVx0jkLnLZ95TDWpivkQ7ybgCspoAxDKz+cdJoyxHTy5JV2QhvcfxuXwLd8qBCBKC8RUtqJNlrn0CXPz7I8IygwRaIw4qDq/aAkFbe1zIKuWgfu/A3puTn+lXD+fTN6qtHminUGV6sG1NRFGlB29q4ZagB1zIjDL3yy5o5Nx+VxNS/AVZb5ydNe+5Cgo2SaezO0EgJmpPT36skkTFRjZ+rOnD42LjNBGGn7tbIcOZboWQulNOVrJ+yyRybuH7UnPzBBylqA+yxXfrAAoUkno3wJSmNuxwsNgTXeNrgEULR/PkBSc6Xmsxv6+V7EaF+l3yw5npinr2tuJDESRraRfl8s7Rfl5pQKvnqw/ImLw4Ncp5xdE82etlU9SLBYSffSoRGfH6jYtERrwdPMiXiHFEKDJpNceRghWqp1N9gUauIL6CRULE+Ee0q361fOC2V2DE71Lub9Pb+LKu9K75gQUweFe6kU/TBBOpm5AP5/Xez3sPMIOnYw0blX0Pf8reDHU21DUbIdRld/XhfG9KMe5WZ+X9ynWk8t4FdTTHrJaJAezw2hhdCDH/Cpc7TC0GHCCVe1lskxz5YIKuAMaDziiFjwsQKu5PUeE/8cVMEeO8eviiqiHH/NrQenNkywAIKmpJa7sOAr6HeyS0AHgp5Ra0Q902n78vNtd+pqEvN+MNinz307YTdVu/jvGFyyLz8J7pYiVHZp4CjLX7mlMEVuo2PE6UZLDTtncrVl0dqt9aduK1mxq6MkXiH4zKIwMwv3PmotVudoLTYQ6XM4XdlpOrKWu+E676M2t5tGb8+CKmWrLEZ8n67i8+DrPp2cW4QLYFV+NCwaf4jlbDH3SsytmG0shOlsp0YpeTVcPXo72w5UxA2ktEM8cF+I/mm693gw04rR3CsU0Le+b9A5ZAX5BTtoHd6nxJ5HgP6oJREAqt5KJQ5JgYiAXLEYzTGjaW2hYAWaVgGoK+h94rgh+B1l/qG5DnnZ4nhp+Van1M54HZgbqHcz+7USAp1ZUK1WiDX0CElacl2wPuar8G/GKqP0y2VNWqsI7hgndEmThcLphqvzomUB9SvLvRqQ5Cxx/9AxhOdlEpGb4+eeKgQh2lW6Qb1OvrfYEBwv0q6ptO8231CBmwyrGYVmjzQcZB+wxoOhhrzeDQ4kOo35iX4a7ecUcHViKK6e26fsjbW8CUqrdOqWFGGiFz9sKkrShz3uTq4pRt19WZU4qSNZJngKimfFlU6m09EVxxNVt5ph7uJvsTUPOh2WavwXRg8rP5q+f4CaUlRKzNZwLPl22RyiNw7hxZV81vzBUUWIu8RATIHdsKjePTMtf1lHFTKeYHn0cLR0Q2472zXkf1b/Ev+4njx8elnYi7JieXo5lFrzYC4iXheVHPKEZ61SAi9gPGH44B0yrkEiMMyu+1yHfSrYhpWsauSEdWx9RGTraEGkiEZtOxYM5OqPOB6wTeJ/EEHKX2CGLrZvs9j+uCuFdsD8i2st/iWVQWvk8Dbez7BxUh8E4vyD+LJa5IXC6m0qSdfk/ZB324dkc6bjxU49nFb4L3CE5TfojaXb4vsxa56hPQ8bInZS9qwg0a5KweWocvl/B0TtKlSW/A0zgniU7KqHrQfvkrB1tZy6OWMIth2OsitZ/dxbU4o2gxip0r1m7dAttlsj7TmpE5bPnNikhF8PoGlzQ6FB8FruO7WbLvH+TT4S6qtfdwxXdfL9X3/Zf0M2+3BcBdNz6Sb5/dac7ugqT4rZiC+EGQtBHA9jlB9N6j0Wg5G8OoMH7xNAqQbCd6qlbS0Y2UndHJ7up0VFNvXi/QBDSDO5ZPhxFaTDqNFOLUqXhtrtjpSyo16PL4vFo250KEGHwy3ESP2j0sQUr98e1kZtNuHs9yNjEZ6iTi/2LmEJWQbxl/5FER/TCTJ9PLA4ErOVF4aOQS2VDxbbcfXju/VBYfebIjuWsdlra4Z+/Q3/hTBAfE6A//Z5VpnUP95F3l+QD54SUKGsyycn2jJRu/NyUwpiIBiN4BfR0hgqVswdm5IxHhMmS1DZKYU9NL6kC1e6pT7gOy8i5mgHDvWQdCwwRSq3BybNep+efSLFbs/ow8/2Sn84t3o8FzG0LSzNjM6LiBGxWTNqmKXTSa9JrfG2ISpwM4SME2Mn9y7Vb908Gczo3FJa6VlgoBL5nQFiWj7uGfO3syNmT74ZrJSjKrWtsc1FDiZG1UiGbX8oNUZ7BAGG21kH5ZOuXIYwT/Zgm3Acl7VzUxpmDwQcFEoSd6kcsYYhmek5qGYGou99Bozi+iI6a+3KBTThNHYrtbAe4nZr1kg3xzXQaWMcbe+616Ojj+/mTgpzOPx5nDlRd3vmdLu6zS9UpR7UZPLDb8m1QHrV5CVsiXdNxdNME3zX+hphJVXqxPaH93sF63+d4DmBxFeXZ4iNeNxaDLG+bvudojU3dz08YyXhDFrC1anpZeWriZg9Wi6ts0uK4tL9OW/+NC5V/wm2TuXvG9dMMRl61LbX5bdsz71SW9dEEp2wwSYcQnl8dzqvm5nD78TAnxN1c0myUEXKQAv7GmZhV1S+ay" + "YOjVjnBugQegqOja3sCRXnRoywVGs/F3RwE/KHoxqWyr1Akf5FPAJgSc1oU7p+vT647Wo7M9JAMGbXSD/jNY4wx+hXRsx49RMRXtPpG5RQUmWkYv/EK3+jw6kDD1++AM+1fQJgLEkxJI2Etv7q/mZvz85wuDYjjZuCZyLOsDW02G/CP7vboI9IlKcIyja83BY5P4cnaB71pF8r/ec1At4mUND/hayb2s2nRsMmiSaeGWR//u7wTPalVhn1iX2uVHw0ATtQ18y3mZWvpjaa0jkpGMQXA+pt5ai6a0FQdlEgD4tFth7e+KzwiVb+A1f95APifL0/VLKjlcv6D5jDfuyW7Af6jksAy4WZPOyP4IJUVOycgqq+Je05NBurazIyRPQM/tzktly34QIeQJhkvY7AzUt3Dnz2SEUy+oLj0iiK6iJG7kVmkO5fmtc3slK686IKpBa3pZHOHaWd76BgDFkPcSNsgaDN4zUdDOFbd2vS8l3OOO/qLonSe6QJ5SIgqrLjSDcrRjMvqqLjABIX31ErJCnAKjS75GsbhPFV2AfR98/SDSRIGeKN1GVIDZiL5vSEqzR6DxjF/5Ll/HcDZgpUZZSfrPtm9xxWnbrONU54JfsnockUFOapjFXvJdxVrYDNlkt4ZC31/58HRaloaK1eumaTzLW6zWSNa1ICsbP5Re+tUujbRdK9Uf79J6W3qXNnTNqmbUecHVghVdiFCvcK8qw/YOhlR9igXM15I9V6kq8KO3Nz1gNgzfxKE5fb6UmufKKOUdgSL2pLyUkl3Tvp6jhZpCqBR8OthEjSLwVO6ZdYwJFH0AfYFzv70TA9hipgNmltmzldLvBg5v+/CPFP8ejpZ8ykU03bKJ4TdP+rRN5YnUmQ52d33zpXjiotI26AvTw/xMWrTBvZX0ZUSjRpD5wuVoCZS3GWIaOS56shM1He9BIa11Hj9RLVDjZauZ+yY5ULLV6Htpy0U1fi9/4a7KJGzSydNa5HCmwonpXpsuNQB4jeeER9jJ6z5AZsEMuKV8KoxUA1Uk9WtzRozMzSnsXIYEIzf+0CGnVu526/Se3dt/czUWhaZnU6gQZvjcO2no+ywRdJaS5e+o4A3aRTdRb8kSFEXJlur/83VeV7LsOhJ15Tgws6iFQeO/C4MgAWZB9P17676juiqThIjYUQONC3he2RViyNAtHryP3kU0qBB9RBpUeoxrKIKsZ+D45u9ztBQbNOeI0aMdTOv8Jws/sU4j6afqxR/np4I5ZrYrgkM2NPuFm4FkPdgXqFU5mG6Y/e7HapwvGQrLwRnuGZvmNrzgDvzsv8Oql4HnZ6tmRFXxIIi01bgBuZ5ZuteTtqe4Z+6eARP1g5c7dP3Zy6a6jRQN0WeZZiss1l3qkkYN3lYsAlewsqETI0zPptd+9Ddd79X+Ih7sIJpSZVgLv7rnGg3K0thQcLhJGWxFydp4hUGebEqzwFe76eI4uoE++Jyrl9cWBG+G/XoPTUVUMOiOg327DTvj4X2OKJIfz7o4mdY77OfY0z+k9DrhtxsLEh46rU9goEAcBtJKCr/O0yS/4B4DfS0v2/ysqFgHSR3sCoQHcGW/9Iyug2E+2ZCP6/huLhA8nYOupm5+oHO+9r16cZv8tauq5WRevJMSS9xN/tA7Wn7hEPB0cX/0Ly3rCokruh+/mkfacH/1CH357dUgre9QjLrsjITXUVnzvaWvoa9+cf8KBWHxzAZ6o1RojJBSsRkNgsQzcJfR5r1iViL+ECCVvBC5IkP4IzPoG05uTjqCS6AdwgzCKpLvlWqyH376V/i7uvGy3FJYrdAlB8fT3thsm0yYiIiR+TDdA5Hfeqrx5YeW1oLjCuGkoz7cYOuRXZEqFgOUvFsblIFe3Yv1kKgWFpVwLRL7TVBMl9choNyw8Z1yI+ymw8c0trGi/rU6vZL1FJ01ADACCQln1GIO8jvbxfyaC8SmUg4/DfdB/LTgztk6MT29EUAz9Pv1MshqDxX6m6pXKeoxHZLUVVjLSxQXVSHQj0w3AOf14Xe3wIBFwFfsLlZUUrZuoedS/lYVNfNqEE0u/pn5UGmq/q9pZ7JUkXa+Dko3ESfMae5Dhn1pvSqzaeAZa/GP1eZ9FdTzpND40nJ/dwRyyUbk/hxlmnKTyzu6eGyYA98q0Gw+RMu2OfdPz1AxAbIt6Vr9yZy1f09Ug9RG3Za0JINqEdlFikxhgAQ2PwmtQ7teWNAA578W9zD9pyvw0dthwXYiJxB9Lq8Qh3lwvMt62WVk4fDvlYNC6qy8m2NkFqh7a6BlAJWHa3XqhnLAW0fy5ujuHAPucpjjOTMzbgbkqAZ8X9ScUcVSRJGKy4Nvkpa1bbo+AuHammZ+66qC+UfyA3Rwr6dIZdCahITukaHhC+uVDoLy0p22RBEXlSouOsOq74OrUZ1I0LosE1QB2ykhgAzWCc9Xan+wAE5cOBUwKY3XELaUtRtaxii1BrJV+rNLbV6YRU1ECd00EElw9T8rPDoymYU8SYSEDS4/L8sC9WIFDqo6Hdf1Dv7s/JxVFck6Kud9wtcS2T1U0Z0NVxDaN5mXVb0ceFXO6jqxgCcKa750Ujih+VnDEzuDwX6GKzowVeKuqDJSM5EDP+YN/OOmhaDlNmsZti4uM6sjkk1ZCD2ZbrKb+5haqnGVou3N/HfXQ8r6sUe6kSXdRnMAPtK8ESef3yxss5+kN9jRIj10HfaFvFPcXYqmBvJpiMjxiLkNr8PoTqp/YoCDzNFusj/F3YGtt2j/Kh1Y3Q8DTyq7KHkOUlqMfcjc1WGyt5yuo2nrzXnmTjT6CNA62eS8MLXVpCC943N2LUR8So+bU8Iy1WWAtSI2qAtMgWfzzEx6onvULPpZa9qG8Qh+smxAz5lrTf/LIDE5AKROWRa7NqHLT8mLB/rMur52Du9prKxfEnlSN4bNSux80axDb1ZFe1iR7ZyC4hSLgmhpTP8xj6Clgy1sBWxW5HyX7AsoqAqqBjNdLRd4j/epBVkodXdO0g8C30JhWXg19jAeviFe3KOtIUTSNnwG7wyzy74YiQUOAj+nqRpX4H1Oj8I2WoINuwuWdGfD1PxIr9uw4y6QAkvP4T3LrRrBihy+u4N1dE9ZODSFUwZk9c5/dkbo8JI7YKmypdJbcKH0LN4dGUZF1e7I6EVTckcWNq5pHOLX1EN/BisaMNpfvooEtGnM4NGkM26OoIxEFPkOxNWVnoTmF6qgV+tSkB/YjCjue86CzDGDCRHGOrV56wC+xKaLQRkR7/Uw7bW15icY+PACSnsGrW26J5nqj1Ox3k9wlSLCyHJCTlkYiQ3jDPrqsUGjdg8hXC9TpshHGBk5MseYKt33afrhj+jCS4FGIkfovG0ScFh4g4hBo8peGdpp75pPStfLPR79gwxo5+waqBKpw0L0cNpn/6TWtIYLj4awXod03VyUaWhzt/MZtu+6j+zYdWihI0dvYrP4XJ11R3t/Kldriw5WZOTpUfbm+7qNqFE6XAO3vYBy2ZDL7lPayzZF6l3qUjMeUXmwmJDJ8zxDfKXrvJVB0aspbqEGElGn65LP0Eu6JgN5FnJP7Vnn1koTRK1XQFWmoz/nYMZQkXQVQNtL+22zUe+1nIeVmFCnBx7yuZuAo3aZFdgQ7W7nS1j4lSgH1uDq381O79eYjrULrtLaHrYLrUAe/phEt9ojRmlb4gSl4qvJbqOWnHbzilE6G6pIwc7aO0A3c6Imh1D0ojs17rbppubFBC5mpVTjSWGB4MozGfeEvqPKpGSt5CUn9HsFxo1hRWBdOgvhN3DBiu/nqX/NM5WNq/nnBn6s3UPpMD2WCv3FaiQwgSUrxgpN2rladYwsM7mp2CxeOzjoO7sa4gqWSrZLa/r6VRa3jCQLnTTat36Pgjpr40UmHUxq5MNQLnr1uyaKlkscpit5ehUHHJnbcw7hO1C66in50WCQipDf/d563dPTzor77cTaXq78R26vlq+eb50+laaHKo31EPNxuumDU6FpP8fApuL790u6ogM6ikZKDsB2wm0jQEgDsKlzNN1QkSS8hpkY2gQzDMQ9vf1kXxGcFdTyHIyQRyqm4eDX+SSm+N12wfhVLB2pat" + "4v2/y7HX7yd7+bNnLyHA2Z27JhAfaRnYur26Sxe3RWTFqY09ZN4rwAfCHpXu7rhIxQEsJOlPAeObCAYSuw1ccymVcNnJQHesySkzYG8ZCZ6pXbvhUwve4r2loxQS0s+TdRV+zlx9g8UnbiSg/qSoQz7RGyI5f+e9MUMeceY0bigEyHyXoDwpLNGlILAgr1Zbw7GWCzOQhkA8vUNbbYIGr1puQMWMXF4iupzCe6rfldeF35Gp/+NnC/8fxqW3qDcLl7/pyW+7OhLxNZMGVBCY2lFPuwZi0xqNP9ouAJ7w40ltk3VhnqY3tfHN10xvNX2NZDregIWFkACpUcYNJWW+XJSXq3rjrJD6Z/nXr0uX+t3UpthLU0Wo0Ya6fwDBEueBZGjqB4wKW3YFB4DM3y3naNGLNBtz1pMZ9QFaE9ck9aLXrTK+8dlcCvPlqKavHDcMeqj8e/I5v7WPZwS+FDxqftyrrlk3jwVZqsezDums0Xs/Sm1REFfFPHZNPgSwWTux5VLApVjkRtehYhyx6sXZg619uI6XJ55Vn9K4W09Bat/JeRaI1HF3OBeo9OY3hOEuU+1vZqK1jDxgpeKEQSrKAx6XS5rsBjT4Xtqq4EwdKpvDXd1E/0Q0EGv/mma67Te98NKL2t1c9zEsqEMr3IEepT8/58xSS9J0u13OVu1ld1BUdaq5nYHk4ya4bucjdfXZFbGfug/wReD9LlpOORWE/QV+t2N1g36CJKEZU4nbfyZBx+udo80aFO+tvlRaNqr/i5OGQrY6mxX2YphxtoJ85c1vwDmde0HgWGQELZo9N8ZZ3E3rmLAdJlepkJtSXKbsfkkQwmmFUx8w4GKHjjX726oNFyMPduc9iA3Kt7KVT5covTr0/dHiCDar6A+k0f4NCj09sLQ8yr/9HabAelgU+pwautcbq3qKOP5Tx/9AT0osYrk5XYrQUm1lGq0Z6Irk87Ad8YG8L0yJKTR41wIljs5YAngurAmWElpM7Mc/kq2FXp0IW3B3da8sdaw6R1O9kfnB7mV3dG42U+4KjMM/W3QGwcrj9LqNO75bfhOjyU6lyrRFLhqSOD0osHT3THy/QFLv4S1OlIlmotcOrj45UBIebs3EcXSfTo9hTmil4Kbiow3pNTes1eqAM6bo1MWwc/EXGM1ljh9z0xG+Hqe/nMFV7mZ8dn5w/caIvL40jRx1o9wRKTmBYj+GFU0ezaW5rTE8/De9z7PB6ll7ffGrzCc6Fm13fPhOqfE6Agnl/2nKdvdNRqz3nIAHH6Job8Vl3PvbfzzDzvzAQJBmrJynUXWpOg7qLCPxXfyUL0mmVmfxDaO5h50oH1u1sYMo6n//q4pQbw/4JGjAFFdp0Fzq0arZCMQOEmsmcM59X7ck551P9ytCOWoLnavGCWzM8NiA+avVDvVzl28qrEju9JrQD5HR0PYoYEzeaTIMrxDvg3t6KarEHN0o08Qsb86UTeJHeLFFwu6+++kn5fZTv9sOG3LDUtVVfnEgplkli4sVTLwbsn5cweo5neYrpcKbpg8MCYv1iU4y2N0JnfVWbXT9rESJYPxjOYE2XiixHYbiIJMvRXJTp+YGHZ0VDAtMFpSa/YTtvAtsyx046axYyQ5fraPTUp/epbuITKo/VQ1T/6o23fGHgxHWhyu4sLo9d+smUfTDBx7dU++dTvhrEnzunzr2TDCH0UD5tal1ZryFFPV+zIIRx1aCPNR2VCOmOKAHZ4PnPIUG6aGCYioYShftciA/7ai50R8deeav5o2jNHXCaQUswgiQMRgfb60NqYQ33f++yGKv2qBCWbeNqK07MYo42ozcrYAcgLMxprMvgZw3WVBMLKn3wupnrnxjrUnUdvRtjz9LtasEaH0+Am3Qx251H40Ik17MOENbfOXjybGCq4uoZrSN7s97hVejs/5WMaUegtgIDmLrwDxGHsP6KbH7U/2VlCcmjQT9edi5jAQfrLwTPUkg5tKk8vbBD6r4leeuJWuNiaKjmIZ7xIRsolcGnCVO0WOVRo5W47HtH70KFrtpkiQ6sWFMB6n5xWFKZV2rJitcSlA8TB97GdeJ2yE9zuWps2qfJ6kP5tWjWob7OabCL1aaSSzrTr4qAq2izRJEBg1i/LUDdyDJApJdumRbqf9AeQQDtSz/nVWaO3PwzEnGHPAzXuCgFAsDau7SWPMLWXCBq/dKiNyHpQMk69vRRbe1stKtdOdFEK9hAYc7Xe3k23bVonP1BtrxIdZZjgZn0yyMBm2cpRAGMLow3zMJzn2MJowAdo09cz8JNVbxnWUoQHJaggd3p59lk7y8x8jlyibN5JzcBPYTJDHgiqxQgS3hqIEX6uAlGBfiBfTFKODMdaJ/vzrZb1on4QiDhrhBbCzDPqtehf1yOtINjV+vC7R8fqugPpT1I11qdfQTz030VL2TpKjDsxiK/5qz2b2ggEQ4esoN97zzkKAWn7W3akpjMlvsKzWUDI8y+6/AQhS5bcfxdgz/xmFLESqI3YmmEK/0d22THABRLr8V4RJN7XHtPbIcbT0n0WmtONulq1Lws9FE3so0PZMHmPVE5UpaPo7V5WkFFcazJ/BleJbbbhrcMFJgXW6nR6O3+vZAHNQo6szzJWFaC3D5Z6cymxgSzfc0u1f4ZiMSDMqhsNoeJVSKP9zUlFcA04LY1KpbT9YOKWX74lpFeidLVwvxmUoxUTNX7lBBqn8rNMz8DMVYvvoEu5T280T0D2atCKdAXNp2VheTxYR4ugKA1uvAJrDCDtgYp6vDiu/0QaS/d5DDAnp0D0hfM2mCwB5GZGley9y6ZkZ75X7mFecIGRSu5d+mxLGz6sAZzdENLUU4+WKHn1/LDZGFVuP9Su5zl0Fy18G3o7f20HaFA8tLhTzZdPyymixA2te7CJ7K2Yj7Fel6sbiQz2olJ/yN6ZaVdCt0WlR0ENKOVwX2OqjX/+VX6NshY3JP2siP5dszEVbbm6+F4kGO3A9o7mq9qnEPGkGrB/ND3dLIT+8eSmjUAV287pysDP03QLg92wBx43ju5BPnFAaZjTD58hqnqdQdMwjyVMkFxfxikVLeblv0/GBP/Ks1zmVPkWkt1HZ2jT9Ngz7aTOJPUvSXfOYDqNYC49s+MHgT41k1HLNJyWs6KHcB8AZKqOceNM02X41EYWUZLFjtAPBONYchhhQMeqqLtqE956gRHhylGLKY1PQ7p1GXeVQgPLxuXxUzgAa3sXW08juNioqjKE4swwrDAMLDfLgb1WFUyVn36CPtce9QcdN3HzBSNyC/S6/pKI6LvJ1bn40BiY1DEJ/UzROCTnAeAvE4eyxX3ec4pK8eKJlgNFZ3OXKzWKSrIieLTclwnjuA8sHUrbnERTZjwROB1U3V7eUwoIhS+poFbT8r7GPUVSeP761KzZmD6/XQKd9MOHCVD1vXykoN078Gi2Qx7mJT8Lp5GbzKKTadK9pLQCzF7ef2kSSp9dYXJf4nP7sKh1RPaVDGzTa2u03/7DdgC8yg9sbqNJOYysSYMtqDypNBGL93mkA05xlATBRpdJ+kIomgZM/Mxk94pwHOngE1IE0q5pjki0Aye7kAl20YtMlulk/H2C1iwwey5vlMJ2FMqcIuDtETq26UMraQayWGE1rtkY4AHU9PT1HN2oguQreshdBZuZZg27H7pMQxsIdNU5kNCVOi3tR4RH2vI33imTUpjpC/DwJ5MyWdPSZNInWMf7OF1tzZ+shSz+SEGoVDDV1y1P2u9Ms/HNQ5f2sMZcMAQ0Ie0oe+nAHrxD3UlZlPlFpUI0LwfGqif1g1/No2wJFKsD9sZo57eVaPft/OjB0vNPHrxTV0wd3tOAZIW6+C6foQczPK0AKc0IVa/jbPTqla9lLC10k8npUhl2D4KHhW9/+NxDzx/H7pxm11LhC3bPWpMlaB76upLn27ValbuOCWtweg+N1qjhH86zVG1mSvWDmPQWjEyBC6sBFoy6tbFeKF7S9hS5a1wYjBaqddCJWSCNqb59SHPvmW+QXldJnheGCPShJJqLJ40mRollGqgAGGMDAmqAejrGdJZPL+32e8I/qgZMrbRlQhYyw3ZL7XHC8oFpM6YealN5dOii" + "YLM3Bsp1uNUdglpGkJWJsJcViDxK0vbN9ek9t0JKj/ds1Kor5KtogzpH5NdlmfqRi2sqlufTepaz2Ps9z2XuqsYLSUbubaZsSMxy/HY17La6z5RMZKDoQvq0E94mIpMgBAtT0hnSfOmrWKF0qCBRVPggPlhR8L16lpqEBnjcF9p8zyLRpKq83zXvLjLMpgJaXUvrS0uuOqD0W+vpYiE904z/s14wY/2Nx6BfuJwhH3r97CJTqJAba7h5dt9ajX4Nd70BOft7gMPqJBEnaOOz4CjNNyfiQM0EeXv0Q+Xx02eq3nILps94gKPcMJgklwcaoepRS0F+Gc/GogSrKri2BHdPbc6TSY2uy8Yf9P3IO7AzLAteknqLvnkduKJflTWVv45nacjv68Wy0yAy15a6OzVEjqIXUlSsR4LTtlmjPY/KZtKFwIs36D0WUQDwYCDY7FZrpnF6iKRt60JBLcbUbJAlOu9LEb/x609g2WdpZQQqPLQJSzYVVDEb//sLM0nJzDe3oOtexkXZI+Jf+d8rGRdDEnPyKvCQSkgOFRsvQsmQxnjjWY2WqLwBfenZKG64GvWbMWYEwOLT4nkZ/ETVHhrj5Mm5Ackayi7KBzbE9FNpcL9oZVSatyg1CWqT1cfQrcsQpIwxArtIri4pmaWhaX9c0JLFItUXnR5SHbYzsXBNwyj6EBYUMrXARpMtY/xhZvSJJ3889gK1YRTvHEDQWy1BCwidX1Dk0TdlI9E5PXSbMpf1iKv0Uv02FAVhnj/yryEW2lVWiQDdjBeAaP+eO6OPOr1Hlr4zr+GgLsDwTC6zJaXtbEQZLh8nWyxYYl3TNu6rGpxKGHrP4h+Q3TWq4Rsu5JkjiuzAYELTiLjA7mYKz8GEGI1MZ8aDq7lIuBsus8E3GN3DSrXMYO4yWh/B8rRTKZmCAT6WttqOLFaiOVQMOc/qM+YefhCB92fwThUlnNZw3CyOggArfloGLDmBVvD8okdWWXu1v/sGaCEa+xxayebV52p6mAxUvjBwNDKSxBbxDOHWJ7h4gzCueEdJOdbL50xq4aVFR3KOxBUA49jcNgZ0Lw39X09pYRbpj/SDKMEWgNwxWTMZg7xVzIo0/DPoWDou4/HbqYC1SBIZdNQmnv4MGVIXSiCGJkE70uBGSH5cmkzzePoRDmjSrPkvQ1Xv2j5+YHXXnS6CWpn2kr2TWQuBFV1Eq54nAbv4DvY6Bekjye30C2q2AKdHp2H1iPE6+jLTkCTHbFrD04wPXy3t6GqjI+SnhFpRCUXV33j5gHPZpTdPJ3V0wquxEVdnauYsyoBWoucPpXfY3pSTWSLcqdFbqKcPGWjndGzCO6Zbvv6q14Y4kU/SghxyvfQ6A8IlbtqolcZpocU1TD+GeykHlkrcy/XToNQd8qqAVg/h3TW3WEBBP+magXsC08KnqzhR2e1Pyk8pxzhy3QHghLtzki4TYZ52vWoStVlaSas+hZs5RzHv8ou/MWjP/rltxvgYaCskPGJn2p7plhq7OqLueRfT9RfRdeUZTWuP3sYMyzlGZ7n/gxcPOkTzDdAg6DO6rFcgWdeQ6F9SS8ojYgNJ4X+03XWBe7W7yokONgYzwaJqok5O8TfNM3W+YMhHf6eHF0WAmkFH3m0RMLGHLw8tW+G9TD6CAdlGl7WmvxpzlWxw+ncWWUXDbbKUS4MeUXHu7WpXyrcOoItm+LtslqEaz/F0rXuVoMWHb8joEidTbpbW/N3TA+ru4WHGqCz7J7vRsqLLCYOxf/rhQEkKKvo22YEWT0wcNRv+PquAstKsiB4HN7gdr7EZ4zBNVgDWxZahKvgGz3zoqNYLxEtPHpM1rPSumW1O5/6uVIukpmOyJy+9ASlHyYpuP5eNgkBonq31oIWrM9s4Jnav7VjQSsVUyFOEST8yIcPzJzwvoJRLoGHNBoHwMBrIxBZqErWL3cv0R7Mee2ZnVNC9zeP34J3UewawL/9nccY39Z4v1xuwp2dDp087uwdsYHZWg/ktdv3NW4OoBBH2Rgaszpt+BEWWZ0BApB+0DY8xL6DnPnThMKuHfP82zK/ExYdp95O39m0CUx5NM1sbX5H4hh1cKnQjmTEWz3pwMxkvO09nqc+f0rsHv+xWC/T9aeHf/ejBU9W0SeEndPrCy5+XPUSHGjB1swTmLsMVvHSJBGlYuDm08F9iOkZQ1yJmu0ZEbeDvbAHAZlRwd4ffGMKUYwd/Teq3J1gGn+uJ1ZHvJAl5VX+OW2zg1D2XV6kuhF/qYQ1H3CgXWGPRSQMdyVtxD8/OU3HmRGkjjTVy7avf8SNqKEdrGsASDKDvfktltTdXTtMsKOaXlW1dz1xcupTy8ULWT2Lt07zXXULAqZQnpWQndAKqUAcVi0si8zKfintVQQ32ntJX16rb8ePrkYjc3XcQkQsxgwmuybICSDOIwgafObJ60a9/TxL9pVUCVfHi6W37e8KKaJowTKg1cHpTv6npiwIDWWUEjdDZr8nd0XKSCraAwRS4+dqlq3HvszQJWbAxdPdri857JgfmBMM/k2AO16gPAtb2tj7p4IRH0Pv4v00i3rWU8Xsip1EjPxYb5rqS0ZyhLCxRmkDfFjN51cNt65ZDYgTpZZ0ya0JeczNzSnAhi7NpnAUtx4hCQbRDq2mpgTcjY4/IT6vOJDrCpUcSMjmpL8lKh8N+QTYwfTyfojE6fCGidOA9NPTJ/QgYGBm7+hU8p703Datmb07TIMmHhgQy6llNZ562fn3rz2fE2EmWyziyynyriDxUoowNIds5dfclIZ9RD3gak9BKdtLw494p4rxYcs7A6zjM2lbUaKmlON5jgef8Yj1rjr0X+csygHkw3A0PwOo0L6RIxsADc5aR31cBclb+/fHe7K5ovNTnk4KMZweAqXTc8lp78PJfc9wQJx1KfnRH/A8b+q9/0l1IKF6Tk7PLcJccimH+xpdioLCkRlkGe3lyesUMcHGX0M9ivNedyTbKtnLb5gL8jH3T0e3c3dMw7JVb7VBnqyruV9FQAzojOlneeUXgg2oGUvXToJQVbBNaX8alKNnubbUgagxCkxKoGXOfRadj8p2EGLDm+5mFhoGrHup854v2HFpw9Qx5k/6GHOzVByh82SPr9rJGJ86X3JPeKcZqG5D6/vDv7fEP5tkzZDGHtTQCcgEWX41vCLRqbcw/t1qDPqjJpJuuZWes8qb7RkuxTkMMaafH4FVtiZKqemRtGBN3n3n38keHXCN4zLB9GRHZZtfZIiQkvYLD4Ai4Zq+WIMsk4bya34lCULCmKOP6IebdZyV9EfIQc+bi8Y8HACV2c8iLzfiNi5+5bYvLVgnjtLlLKXqn8zNxljzijB2QcdYvJHJnJUMr98Q54jVXCZ+EBg5po7dJ2307qxeVrWew/h9zLX4chsGP8fJgjbGiUrjVHJTCGd6+4aZ1CztJHZAoDga0UZzkPkPXei+if8pouqZoM5smIbEvYCWQZ7KwwzUsiYuTAte1nEsTUcTJ9F9Pq1N0i/zSKHbvkVmp1GUk2zzth9rvieVW43OEarsxq1PtrlF77s5X0iF5V8ACgMsE20cvg1ZXtaumamkrivN9EKmkGdFz2BDqpEBqfDRtusq6x8XxqKNYUdtkHo7J/uZRCsasIqM/yRuRabylVUJN/Vqm2L7f9nHyJF9YIvqxhdDSmWykLV8ZWMa1QC8LDkfJxWP8juAzRZoa/0fdk2aNXHRvKgXL840dVWsXiQRYf+2J4Uv/g2YCg+puOlTpamGqsbnexBEYaZwoq2PSyQjVNfXI8JpyZpt+/7gMo2XcEf/eSQc1nBE/LE8eaY/pZo1WjH32KI8aorKXkkQdRJWMVHoi81hemLWMOGIIajUZ3BybZpFYog+AK9cGS9Q31ecQj3qVTH0nX0RUkBoBOFPsj23HlilVJ77ftRE3ySfYSXXhj6CiRzXycHW6AqP4vIGTP7jqUG/WJ6kt1P4GYFB6RJqUM/B/4SaS4ndr76BekaPzZxEthGTFe3ywZW++fj47uuE97cXB1ZZg9YW4NOua4dIQ4SuRyAY97f44PMUSOvlx66Z6lugOfKdmjcqn0glkTW7ul85PkCJqwdDbji" + "+SdyZNJHhmnwpj3PItFlWm2RgX78HcLEaritNNt6lv9EcXm+n7jGy6a9kIHsULL6872/KVnsNsmkVBx9qwRpYnJ71geRymWWZIHsA+43dI9nQEu9OzqFD8nOtXptavF9mM1hwoNDEdYgl9r1btzA38Wubrlc946uXSO+uplU+h8YnejplziHCtA7pC7dthCQqkks2b1zHCYiAEaIzZ48qoLGkm/a7xUrH3iOMBpJyMGvJuswdoB/oTV3A557LePLuVpCkq/FGOQwXzpxld0mYdx9088seWB6iUsjWu+qcKH20MR8IFsblqz7C4s7UiT6I36CbS+LvJh+Uenh1Zhza6zQeNNox0wZO3k1tZZbTXwwFeM6orWWo0jOIjZfNC6jXP8vLuLbgE0945yHKh09bojWSSR7emFnuzcXGPXL1clSpUDdf8TIxFV6NvmNynhZPygsEw5sR7AHPFh5jb2RScopHpzbyyt7MDqeXjKWvKi0O1rKp/dr75VtZr6S72kWLUgZ0zTc2jumS6+HysqcZIwY5kPcVFFwujcba8/N9mEG3jeUrQxE+PGCnH1xOAeMozU+Mny9+VpsNMn9DqbCFCtcyu2ib+vqTc7EBcGHBN9xF2b8mKJt5e1xaJPFM29QZPwvewxD7h3tUsy8iS7S5C3tXa6jdTb88njGGq9Q4UkYfvSNMGHY68GyhxFCfz+WwwstuBRB8lDhI3RUREH5eF3lOxMuUT2uogEZxYTaY0ko9omN2oNIGAxc4AKIeMqiZAOYwNVgQUocPwPURtTWOQfcoqa1zWc3260IoDmi+j0LwDlMvNspUJ9XBUkzG6r+XV7Kk96Vb9XV68RTR9iHM3X4fiZAtA0RmrzIfSoHb7cZ+R3/CwZ3Db6Q1zY4LI6o9bv3sNJho2gqKxcxSZt8NJDOgun6u7wnJQqZsV2ImRe7MbHEFluURZOSiF6EgMx6u96dJF7H50iGe9+2THc+tFqiV6YNooofyIyppsdKBcLAH0o32l95a3WUoHDEUndt9urTzprZ1K1r+ueyBvLlfnmEaufB8S4OojsQLwDO1tmAHCzpyVttQkS1ykxgD4TfA3itvAuIzQANkq75K3J2Xg4FMnonQvC8GVfN9XapEhl70rD7OGliqZirvqhW8dTr0ZzNF0Dul3wdMfJN0vbI0SH9yX5jkWoU/pxpLVsGAzzncowiksoteTlCxk+tKXfsh/Urio8nFDW0ztgqv/EK1uWgKymTQBijNAcpd9L3wz+ljaHO7aguxz5HXn0Czg2w+RZ7f19rhBso0Aboec0xWOQtkYYtFdg5sJ4xxRW+NtpD/3wYGT2wOs81Fsk+YuvSwdW2UH68Lmbh7Rzxo2Lh87/m+oj267Igg9DGyWTn8OwbqX3gvzpITK+rdbpr9K5R58m4BeUliVgOKdlUGjsZh61WFUMNx1zJRzYKIsKpXwHUj0zxvOW0nPrTrRG6Nni6L7zUen0wzVZ1CmI9BSqO/JnUpOoR2yYL4iGSxUoj7JbdmLHUfYkqvpShdNSkomYJGPjzmhH74Y2K3Jz3wn0bHZ9JtzT49dVul+kXxwHtU9G2tPpYrqMrpFSTL0fo7fGjpOq7upCoa7r2IdSOlhtxJ9JMWsnSEfXM99nleQvgLieI3KseLm1CJEmBYgIuKBtP+QhExdMXzEcWiaUih8zd2QXN+YjDrMrh/5e/AeP0RQANKR+ggpa2qNwTtjqGYyzrkHae275o+JU0oP2smzm5ZBPv8WccTapuIzWnzDMTz1llcvTJ221+xRtzL1IZReMlWmJ1ZxWn488y3ZKu1EVq6kMV13QTpLH063MnV2+JkKcXAgds3V9py9tLydcAXgFc3UvmL9Rl1VdE2hWxQ4da1qyPAhgvVCXgYU4GoXNZLkqmbAVu2qGpwgkewol1OwMFhpFMORZeA3zCtOl1uQVirEjA6DjZveA/iY/KUFvoYmi94ziQ74nj0Rfdddo3E+4v5mZGejI6y3QM1PF5aRUl3FL3WMUdIhvvae3d1VSi26+Of4b6RC3xqJTkUVefxTIzUUCh9kldrJpWvvUxBlJLzczmvWXpa/xQzcezFKE7pE91QurXQWMgsdxWW8BRNop3y01TnkMKtNfQRPFgOEQNaP62TfWWv9kW4z0sPVBOWWzwh40J3a7a7TtGnK9/ZBMrzfYEIyZ8rhdPO0Zlpv3byNDfkcaNBUzun3khNRGsFecndteGQtP87tVN3MDK6BoWcQ+3qxs/56bg4IHTE9QFMUFFjDD77hh27KOMyZ86nvFbd4UNyOytBkaqCyk21t/U/gQVyBHb65ypy6FgNPOT81bD9DX653DNSyvhLrs1RCm6+9lpXheSZTg+cDo4ewZVCEazTG3Vkrmeub4QFpVgKBJh6Kkty0F4pcQXUeybqBNEgWSHqMCjCZRIWF2BupzjYQEsUJr0Dt6sMtpegJG2bJeSufE7EajHTBhRQ4fzPya1HwZFuf3LINl7phBSTGFaUcWSLQdmpSlpRwe85IX0F9WZ8trPqxL2krIAxBqtT4LExZAxxYafbCSFqvlhXA1HJ8Zc+vm4acdV3DDb8vsmTJ/KS/vtfyAgur8dWycooqCOmcMfMrYsmnS71/o1gz1bV+UYgQM0e57WpcKBJt35xPuiCzK6A+drMHlPwCQxJ8L2PS0KhX6mqh6i92ychePyhQGeDHfrl/rdcX3eomcFx9UI0i4seKUsBvSmAmzsG8vOkkn6dkgVnTYOW4P0F25wwGKT3b1l/wTTV/ZhCsPuQtQwNutdeslkFO9wrKX/pomsaMfLM4hPU54CB1g0Vv0c+RjQiL5dQrWNoWp7nFsS+LN+oOZ+CTLxZAtxkYml+yynAPgozhDLlUjuU1I8o2ppVLIu+RXlW9UqWZuJuXgtAhvQ22A3bRIM9VMxx+gcSMkiNc6AL2Q/93fmZWUnmU/UX/jdIjKtwsuT9S7bTxpALDSsN7ijJGFDuAv3VdndSXAWizF16axjbEKPELlipgITrz6YB35I/tHdGZqqZZBPyxG4v7ewqRsscgEJ0zE0XTz2v8zpmM3Cn+lu9H4L7lmlNo56HGpT0T+jKLuxeXQJ/eWwd5j4wsgNIfKWv06Rd7ZM/ZcZmcI7votNLG6Zuzcynf0Wn34PoCUmpJQnEkPsa/9W2yR39rM4AndvB+IVBWLwo4TnGMGeVl5dHNI3yHUPQqlBVsuFvaT/NhfCtyJE/nD+GhQm8tBu22UlI8U9hvSU2P33rtGQ6Cj9ZWx88xilY6aZfYEfYhDeibG9K/YwyHUKYmsXkfAvxiy52Z1Jcs3nRi+WBmgvcYoHNjtme01Cv9T4C1flKBkD78RfJO2TuXs/nnr2ZV9c7LYKjXak4CDkCHrpW1JdQ7BNEBp2H5ra7bT1ydkRnVN9xdRhbFBYORy38cjmGnafy9wn/5cMhztB6R+rD5a850T/+9Ny0+E1IfVfJ/VJv0CHfj5Hk7rzo0NL1dburW7HpmUNXcHWoRtIniY1HB3+Cd1y6KDf4Wo1Tr19WCvcXQmSofZzkXk40utkr6y14bXqsiFj5T7gGrq+ECv/f07bfgvc92oi5kvl4jzySSH8xA6R5zIPZ+2vDRo+vz1CPG7VR/f7cQgkwgMLsX6ONlGSd9RHW+VMTVi5q0yuneWmp6d/WNF+dWIY2LFS1LMeHSvQVW7VnTIdu18Jq5973+66h6ijPurE7LP253PbBeey31ymaBcg0I9CPMMvwp1FsxyePCfl7ZaGV5wLOsdyALEWP14nULs3Xl1JRRTxrDZRexVlbNRHFSsZxulSK3y3CbcI4YoMf2RcTunHLwlM2qw+l4uVp7sy7wG5e3qg6vvTPJovTYeKYKD3jS8m2C/zvviQiDccQnXzqHeAtOEhlGNfDp5tO4+E68wtkrfeZRJ/jzEEaWNH4nka0XNS4qZ6VTlvYhMVQCqVwyEz8Jc1oieeh/2BlPR7NJtTRpxBGc0p9crxhd6xcHnXd7foduHDii0DMYICkdYbb5PTlkgIPzvvirka7D9a5GQK5XYKIb1D3V5aV4DWGx1fluGzIkeKoNK6vm43JH6f9MflZG6i2og6gCsfEQ" + "ErexozUsNkole7QV5h3aZSclFH01VqOOoUyypHsQi6uThQC0MYO0YFA3k4OLRLJtFvNpgsqzXFFXZotdYfDh/pTR6HrCvppbOCwsAzms/BR1h68XFlvbpobhxT9iQXVKCi+1sG+azU+759B5pDLtrqOVElm+qRAehlfPn2QzLhAWio5t9sPi/i5rPuH1QaKw7tBLxkTP3nrEQaIzpaS4wxymnn+C0Dn7f8y6jv+wOysfpMjZP1nUjN6Ki7qKlYrXEp8QZqclpqd3mJEiO+NcDIWoRCcgu4Gf8yhl+fkBdC94MtZA/vGtoLImV0l53nKWCIMCr17zknA6u3fcULUpc62Ca/hzOQD+H3ivGp6LEu3N0soxyQTKDWHL02/vancj3/gZ/juC2qyNQdettOm+wpH1HvMeDtS0jQjvsJNubOt3NpiH6vFUWnw2NI1kf3UPnXYtnGmeheg9A0a38ilulzPdkE3e+1LbiiItZulPFza7yZKVQSe9PjoHieuevHMP6p4E07ZU0fSXmqb9PRDKpfe8F00/tw9v7P8kif1dL+mXrkUQSTh0/AuvgXp9qH+rFc/OVprDoadDWdAHrxALOHIiQwcSiL3pjDJR6DycpNLjSTD0cu9HXksVWm0fPhMgpuDIpi+s7RDokLejM8hL9SKkMPr4diGpTNv0fq0F2O3F2ZwH9a1OmYtJUlt8IFKXzINdPCjFOhSp9VqKZH3XxjVry9C3oUP+R85OpgzmZuEPmFq53osr1kCI0EOim9QJ4Fl1ZRuE7U2WxfS7tB9NxlRLT0vzC8ClGm741VwDSlj3pcwnLIbPyEy43pOHSNVTwHg6IeAYv9d6fcsFwE5kSTRwoDvBPtVgPatloiz1emrBi3j/SKkDWxnBEAUNcyDqBJNB3s+5quFDJwGA7hUIHahpKTm4w7eOS35inIzK7WeaMhCB01XzJ3LV5iHAvY+i58VMvLDLHZ5c6Tn97ZHpP4+kEUzzpIa2qvujxXmoeboqYGo6FQxdt5VduL7VcKbKrZsC1gMi42ySM4dg1R2tP7BC7MHznWDt/m0UZYNGdYWh5fI0fH3qnWRCWV9B0ajancFRhtSOrO0tvJCBYMTNByHRbR5Xjn9xy05fiFWmphlUHprAEKBqkjNeQ2qHImCKFN4Pge5cdNhUPAlc02iZ/c7kg16SxMm6ay6uBQKRR/IWWq/KGl6eqzfpmvJnpohceL70oFZ1q2yqCWvZTq0I3JXvmzKiaOd92GfDasTNpPdqWh+yzlZwGpHTOd8B11QarnylJy2rLuy5U6jiDlIcEExiNPa3uqOfvXotZM+99OHIoHQi9tqcIh/2qZK9bJKevMavCP5y4fOjC21SYNHHOh86J68UbPzozWomGmRckNUy4Jx77GPCoFcIZ5qB6Vdxew2IOnqQXLm6Qt52Hh9ht5+DpJGh93tJcgSp7MvV75jLpHvkhT7hVB3R4Jx+75CzO6Ok1RoPXrkDIvrVbozxx+JJXixd99SfKgaAymUnSQh6GFy6ZAAOuYHLRss1b7GsQiHqN+eEvUm12/yEHmilrwJBrAxnSkjsi8Dsa+mguo+QrWEB3wDgSEXdYdyx1O++y6e/t7QA8FQ3LnJvoqaPYUbHNTw3fBSDpqKTYG6QyaSqU/i0CZs+/4TB7FhloATB2CM3rfJud3qYR/vbyonkVnZvFo3BaXyT92RQNtJz5RT52PO33exrtJBDUA0m5Q1wdJTDL0y/2QUvd28wxknlmEcNMfmjWXJneautmUYAzadX4MHO+8olFF5Ttb7L20XQczf7y/dB1mHtfzgijvDIAaKRJuEA0fS0Tbe/QoE3OAAZTfd8zZRZg/8TAb8evJcnpOq9edRnhkFgfqDYsaLmq4H7WT0bbWtZV3orAp3X89Ifj9tyBAACMHijRRRs4TUwSlAhMPOYjjB+ho1vzUmNVI2QBXTFl4/1CvYjD1grFeh/Y8wQP2IwD7Jdq92XxSedM2qUp1slT4EqxgPUZDzwn8AL24noVWnNNqKstVl5h7aE3urHMXy5hgdD+A2ZlvUOyOvQdHeyPzjY+MnIE62c5mLehx8IMs22ZWZ/9ylr2LFo+6Vk3WY+mCZ9xCuYHva9hmioqcWcASqdChxuDzK0eRGjMlcbOysnWk8zPNHoTe0pkESBTzBnoGWFrSEHdxU4XSMA+o/Vxg52cshJZwctyBS6r79VFABL+ljkid2RG/spVe50SL5Itqn/TJlYQcG6osEU6NDhABsWkXhOXTSl+YELlm5U0kPSrY1oV5XMmJexpfHUmiqL5ZIiwI+vPmQLLbheu13mGahersKfM7c7y+6TfsGyz+JC8qiczbAcmKiI9gdZjjHMZS5/pR5q85Z1b0dir1BMwDHY7jjIoE6INBrfTDS5hKaGs2NwMGwenGDfsPnUpTO66Ja+3rT0Cu2KSEs0C/2HH6OJVFskQzDWFFXfXdNHGSsHs5CBwcnyGJppWKcvkrdQFTW5iK7m7rXONeAGdW3HsdxJ6SoEglGH8HMnuBcBaGHv1MNd2VuC0c3cQ8PrL9gppzhPd+2qQqmES0APcB/BTp+eYKPleOTcPlTb8cxrqetF9yfWm2nZlAg+Bukhmz3onujb2gaO8f0llo8rEY7DXIm8DE0zv/iYM+7/G5AM79nSvMLrulFk2ithpx63K7UCz7pRP3hJbkYdpf4zN8QrtQBGimCpFGH827JGURlQpRmhi+jTqi1offrxMThVZsXOqvprAw6LIsJacAu1f4/1PzWlSA/Y+zTTtvtlzrQseFpA765TodeKxZnUnM1VPWItg5oXGEWpiDAVPBdXmi/0OUi9n1ki5ZqNDeDVVDqkjxK0sBk3I5/dMPO+rUbOz1p12pAHmGnFWHqKBFDrHvZZQ/FuWZb024kkG1rAL7ElubzdR6rDCjn41Tmsuj/oUj0tJQ66uioYHnVSVr1AL5SWnRmJASi6Ie7I9ZYDN6S6FTbHsZiYsfulYCwzpmdO0CkvzAnkADS/75iQzCWno9ooI0QiRV+ZsWbyk9tzpAOA4KH4DAw6kWfdfkKQJwjQD/a+dwQHo2t4CJl3QOljXiQ+8/apA/9e6oGSMwKvDlxYkunXjA268UwJKTHBUYfyQIQb5RXJDd86P/Jjglj6OaP7aztGfZ54fN1G/M3jMWoCNN3oKRWoDrC0qq3Ta26LBkXNXG7cAT1t8US5gRTW35/z1skQxHn9gg64lQ9lmkwjTnhZqJOCxUVHQJPEHGC4MKtvTWqyyY2ZHdDb/Mjs4aALK8oDh+najHynzAyH5In1pIdfXDBCNS71Yss7GI9RRdI7z1PK0mb+xWVkw2jNdRa4SneRaF9gJt36jS79koPlBH1frUYvzdrWXsGqvta16/nz8fQxmzvb6LIbJvvoHG7UQyafNLdL1dFQXbx1RgfFDE4jnBINDBUR+ckkkpk8iBBvTrlxcOqMaALX3cKelaI4epM38BySXzRVQEfoYr74XR6g88+glCj0AdUezN163aYV5IMAxqKXCIWxwAp4anNri9wb+gS0MJllZKtDkxC5kiRC5ZRb+cMdZENpeQGS0GT+HUyY4AMfHJ0KB69HXWRt939PydrFQCEYDLytrI379G5bACm2a43A9yd69DOM1xQp7eDQbpG6mJ7E8Z6TvH/O+AOA9XdkMQkXL06X7inL0fmGkCH2ehn36wvz3k7zIeXNbu+7BHpNJw42/gdmW18KOAPi7181efoFANA1qcdy/L2WbBT/fHtC6yX2zsWyqDbUYkvgJVR6zwgaDXhAe1rIbCT6Ai8te0TwQ/Aa16P40lnRw69lpWrWsALBTFudmaJ4ynD/ylc0drYCNd7M616+v2yK0lcwUjzm7xxjwsGwX/aAHnuoRKXbPJSkA3vZaIlTxVGr6L0zrI/DrgdbQ7W/Z1VLX9DizEU8BB/5rKos9MeKn8PcT+cL7R2Bm9LS1bnlZKZfPiINf4V/v/r5PE7SqK1H925kd4UTKLfitbAhpBynmytQa+va7cin84KmKpshPO+xwPw34UO8hp8Gm89GIuxQAgFrWVPkWUhdqO0xFubOPuYXUvHh32YqHOYMlqfAD0xXI9" + "fV7EXBkIs0AmbRymkE9fIBFicHrILu0OIdH1RhTH1VSl/Zd36Pyar5AxWnEQ6ca62iiCvdwFbeAWxGKB9PLLc3fU1QqbWIA9bm6P/BjaXjJU9WncPmLil31C3wNgsW1yKKQWpp+EjsKTV/JNJhXMcXLz9GFOmyZ67RsUmdeI5GaUgueuw46ouanjQJ6QuBJqLnQWaqmK1gRpdPsxXdV71WcJWuJ1D31FwoMwUZXbTpjCfwtdPt7HUM57pTnb6oxltbORrIUP/UjKSHPxc4UkWv40LX7ntZ6FhtEYsimZL02RSo9Nnr9Wh0HprHhMev+FxLeMKvNbpej95l4xqjez3qMIlj7YGIs2SYrToNBV4mOXT35xGsgaj7KY+qU5Jb6wh6sJlQVkku28uq7mWSkNQlI3PZAAjHvv1mBWe8L81W4Dw+GqLgL+ZzgtaSLbxdfOY9rKmy3S8/qHvKxpthCl+T+cpnJ/2zcvOAYh3Z+FlP6MkwRKsptng+Jwoe2ZebauZb/VORI7zwVb5r2gWrLL7Lo9TiqOnRTB2jk5qCLfgAxOzZ2Y9G4TbgJtLog0SfaDru7HLqIR6yzFnCahdep59yaDQ70b/Yv5Z/QYtaa3wN01iktOpVHdugNl8GhcmveYyWVI3IURQ9Q/8G8Uwj/6NF/h6IWcLF6mlZxN5gMxVE20+FIeP36NE3vBk5pVNNAVKi0iEdwYVnUgqz9CEldlUUn0eZyeXZ4qkYXLqSli+wOywnG+ZKqV+03xeas5begjywwcyHlOLBUW+MvkcLKhkMYAIhLywsZg3RRTszpHgZ+WU9uvhcOVbncbYEx2ovI8dQxt2dxIFfzZokau1kuWoOl6iBdgwYr9kmmXOTWelaem+aCjn4KXEwZNh/sE6BaK7MycUA4Q6E4LzJy5qIQV1cnop/rEbNDhpPULjGHx6aIXw6076sufZZmmv+J3Li9IuXGMjHzQq/ozXr2ECxrdNLVnl+hNK/HP2nqD3b6klex0UVVwsOSwzRSuAqhguAJ4hQe5Y3DdpphWFXm3oPbVjl2MRWrQvrAMtU7uUndh5V6cWGbKgRrCLSzhaTMVfLNZIsYAsyg44lQ47JfLiNt4XNve4HZP96xijLzygrdSz6dP7J2Nt5ZmcARmk9bAuMbfGSmBpgRwwiXqbbJ5T2fL07TS3mPZj4evLif27YfXXROeJj4rKpwagaJt0ekVdHrjMydWE5Y/actyucbe4RGFCos32OoZKbgaDwdUU/bPGzbcgLnyp5ZmPZZe8f3egiqKHrPZvgq3E9CzM398DS0zX0m3arfPBOth+G47tSmUYCm6MXYlav2qf7i/72a0bxfyRDxekyaIF7cNVhoI78IMOMxc4UujapiRLbCbUl4y3c8YAJq75uAzEQ9HhRzoT++yzTka48G0eT2/Mcbo0DnGQXIxXULm58OlClqXf1glOosvA5Nh2AF6NqZexhO5QDd7MB2JuV2+E+7/vEcKu5D/Otu87PeXStFqBhkQw5vboea3MVqsLqsWZFJFKOdl1fSPFTcrG4hX6ZrkU74c9jvFYvv+NNNlUBbVkCQWarQLo7OMNoU2EiZTjUtcFmMqyans4RzYZglwh60NU1zKDLDGh1sy9koBh9p1nsILkbRudPLiR9aSN5OsyhVksWJH2DPQBg7qpHbh9OY48SCpMRPjFnoLCh3qxLL5cn4narGJDNwu/uLqjXGaM+3dxMhvL+7bioeB3dmhczlQ2lcpA79cXezX3ZgKcoAN1WHRlXKQKvkeOf7LZS14uL+5rV1pRTozAKpZ/losPe0uO4clBUNqOlYv0mnZ9Z07FvJMnGy+1ePvpD2ghePpwS1eggGX+zx9Tn/H39zHr1QQOWDlpiTTSw1i8SBga2x8jFei55V2Odba3qic2tGmX1tbcg6mW7wTtMzVrQfWqg0qgKlz6lZzdvuV3aXjsk9yS7Cn+5ww7Yds4veiqmSK/nzkr/+9R7RStUpPWhCy+1FLhh6Ml0MUDUI2fWau+k/dlTOAXLTJ+F8ieuxYyY4XsMIBFEZ4ise3hljRvfl7ynlDzCK6BTtPXprYoAcfDtUZGmkP3tcfLCvfqzA9yva64T9QPJmfji4eFZQe/cO32ew9sUAesZkT+X2sT5GFI207KI9U11T4/6g3/RCthS/bgG3M1Crb9iavDNkqH3kYhzZGtVPysBj02Kn1Z0+/RU7f2xe6iZqi/vAI5en8xDn0ddyY3F8smkcTcOvWX0OLqHdJSiZs2/kPGDrNUn81039jVUu31b81aKVsdJJnapHiBLp/rsnvJTSterNhYlY2v1eKBFj5xlWEZt9IriQzv6Nn04ZslL3e+kHFpC2oShsDRghgvrQg2wXk7xbnH0YspXvqFrCeAI+SjI7rePm9RkCvA+jb46tR7jpZMxwarExakU7NfpM8D4cECAiibC8QsrdF3FGqPL+bHtVwlofzMpBt+GaNdoM7yh7PLmHjplIFUXQ37ty1uRQWnRdT0L1/oT77Q5anU6DUCmc3UEwo1uvwZXy8qrBw55OJiL/5qo6J7a5SK7QW0xfDuHjfhTa4obWodR2PhYVs/OjFV1XsUTbdDb1qOCsejpyBdbUs0k+vFQzA7nCX3QZ337rBImjJ8NYgrhKLk4pNKXIRJZvrCZzkEkYjYv7XqjtmKxQVzG5j7eqC2NmmM9d0kWSP28dvYFUN/fagP1k7SHu/i9/tYpVv8ktrro8urO02rLPO8eGNuJvBSO++EbP6h8hP5Zap+hIgPZYnp8yxq7sqPQyWw8KQ85g+jyGrC1IVd/GLQ934WKJ1sm1si+KH4uBmKHKKfoHat8RiImeDf3HgIyVYK8Awwb6/q6rBEqo05mhklH47gXBYq4ZyTGZTpmER/CBMzfD6hBPuCmfppAAZZJjbnUqunOr6iULWs9vDGqoBkMQ5EiGcGw8WTxLBMM4fkp21aOlG1UoBm5Dwsf6wfVLEZ4JUIZ6hI40qnSv1qH5pwvBxeWntBRVfPeInBT1vIuqmmQy0Pq60V/1k8OBaaUfUaFCf1zhzIh3t3SWbn7woRe/yA6GIEOOtz+fiWjTYWZeumB9DI+K8QcUnWASpi3b8mQ+RCUqBnnyrO1HcPW/RLouhkm91GW9kbJd68nqgraDKwoe5tsiy/WA0G0zalMt0m/qlwudOOxb4ywjXqWanxcQqKgH+r34GbTqR+8njgaOnR5wgtyNn8do9LtsvzdRFXUiuVqfebIuY/u8014pzY0VJnw5lkHM/0K1NsjcDnNptQFb5s+u3UT36OJjtwSuJwQVbaVD0gQ2fllgjQDNntriK6m5WIYpy9YxTaJrhmCrOxebzpYESgl6aLut7Ybo1fajtprXe29tAI6U7MOl+AhLVjayy8csI7p9W96QB8l58D9vIpp+0UVpR0sIsZIOhn3pybK+0kucKLvuMSpaYTJFXQFlZdVQaVbMywGQcEPS5hvIv9Jv3fTZ7gZzxIL7Kc+6gTchgmUp4nih832hxWZctdyIwnsO2adEi2K4MpKaojYf2UAOZninnGmv7WEhO8NldopXxmU2t5SBSu1eo3veXIamM7xQSNpsvAJxMTyqlqcDcphs8/jdhOhlytIqADM5em1+uOrlySiSFwdu3gZe4ZNlEut1VW/IXIuaAjLCkTLmOI+DWVTpp0HM0Dl3JIpePNbApUWIMmO1N8P76hzatpafGm0VC+17B4e5A7MN+Kg4uFxQS7qjyMmxxYxQcUrL6cCdftz/j44dBEtOwum42gVBxPuiCJZ7iLCeH66i6g3HTJ+h2cFADzn9qIvcyjJJVfgWWtbvtn7LDoAWFRbrb6kT7OYFrQXvePqv0vY8IBV1x8rVDaPMj6VVltPStJMtX+3KX1uvWpCUhvXeXQ+qeUJu6fHbro0u3cCPbM5IFLnmaxQtgsgUTR7gHKJfnYbbQSf9mBkLh11pvWbFTgMh3lF3ib7xKqRYYrTcpnE1P6Wv7b249nS1IPxB+scdIZLU4RKrQdtJ3JGpZwbQGLJtr1a1OuXV7XmNDXP+dE65Nj/nsG+eN4NjM0j+sk0Weo+a09qv3bORlj6afi2t7ZQ1z3eJGO2" + "KXoU+A3Wf9BJqEDY/sc6grUU+GeP2YpvnJljCCs9mjWaF4NWMFv1QhwIoMIwHyynDK5ZfOQtPecPApbs5b5EDjV6CWRyyZqqHqY7+C1bJgo6w/kDfn4RFHkAoPDz1PRUjer4HpS11+r2CXnP5UFKwHzlaQU/4ICXezrmPnt2FMRjGl9WjwcbZWVhDybXejTAlyqdNzMCS+xUdiSINkFS+y2moei91+3oSR0o8yWHFS2vfME/vQZQtwyCq4h5MoKS5+uG4f/6cRL0ZWq5u6taeQbfe4f4pHm1TkHuXrSd6tNO3G5I9qo2Uu+sTqHX9LaDDGiqr7UR2DbLbxeNu1J9FjLe33Sd3FA4ZElXTxoARD77srno0JNvfE+v25pvYti2sSLcuoh6xRxICOApk++pgxLMPhC6qYYPi4X9pJbg5aQXKE9/VaHXmt1NlyoyRAOwR0bXZg47sOjq/eRAU/otwzqTg3LW8P7OK4ReH8Y+bY+xz5jpiQ8r7xbCxhcEf1np667RgfqLl/yiWWxfBXL8FRE/6LxB0Yw2j/VETfQrRnUVK+7lLE3OoOqtBEctZpiBypVu+vLpkVs9Ts5fgRGH+7Qakn6g8I+st8WqTUQdR3f5Z7Zc0yTy8pqo5vJTpIJVWoYVvJmdLWccgEXV75uEMKPsQVFzq/gM9nTR8zL1dcHpUNm8Obn+QfF6Jr0+o6mHwdm82TzVDi949xDDitesFXqWJ5ehuSJkRhQDVPG24DsdS/XJMuXC51i3x6ZVTFL0m3opWfQMT75QB3aTLcBL0GNrJv+VDejF7PHuuCxBxKaeDJ63F0MREoEZpG08lqQ3p3nCIRualnbIig9rtZQjkAfc7PUxglEsvFc3/+B26nzVza7agioaHvqvW1/sRXSN7dtvr9QCod8RmWs1p1gwjuSHmXHOrMWbSryUww1/MmqGZs5MxOAVWx+CI9tcwFHGaxnQbppVrgvtoE2/zKprmmE9Vx/Upj3lZ6evR+bpyJwWgN2k+qZE4OQ6w/kNLpVUvJ0YPlIZ4m3oOlNwtpU5+5deVc1CTABWxs3x+crrpyagR9AQFIVVgYmCAMp6V0XEMK0XHXfZ9ycnVlHEj6NxkNkCqCUATNElscLbp67cIs9goRLscemw+v956p2ZidX80+EieQPd23ehYLDenPT6mJlLdGxAVm0ruyk8x2dMbAiYep+uX29+Yjf6JJqbjIGDpfUd9wLfZbuqgRqJ590uJl8g89qQOgqeWcyiuERdeIP08XY/3ur0kvN4q+0zBD5Ce55vGz/GuLfBuSJkJlHTwZcyFaq9i7zReTa6v68B/K3B492QDeL3r3RqwQl3dZVItM9e5YLs7FgUAfJDXd7Jl7SAsbErRUc6PLw8aLXcl2+ts5XS+Ah3Fidem+nIZv2KSZuT2BhqBlf97vRiKB9yIYyXakXlQxhYvrrlMokXt80WDqwblmr+iDsqwPh90yKD1N41ozv/VB8+tX4vIt1wrS9fpdMTuFswoobzaYXnXV815GjUmuI02wwfRApOxZxy6A7FTglOxq8CnDoQXhZmLdXsPKFoa2qWp6dOgWLX0ftjreo9wJZzsyzrb3wh25aN/FyFxgb14gWGXox+6OP0ZYMCIW+IbZmtS8nKuPnxaKNH8+hzjWlQm/gNncFJzuYB4PFXY5QULZLQnqvAUBmyUbk2nxcNVJ9fYyKOs82xKIdY5SZTa2hUMWfFjzU1v5/DDeYOSg8YMlLAUaTHZUY1H3iCuQQi4qXzjFJ9+4dsKUpi/nUReONl40XeXzqzUw1qe5hzVSrbeugUuB1uF06vj2HdMyiiyIgMmLXxttmI2/rcv8NGJkmukHEdy+yM/yyRm9M1JCV9y3kG3V4vSsL+MnToyWmv7KllmbXsT5xOWVrdeJ+bVoZDBVOprUUg7G466ey+/i9oAQv7QKiAuBc5lTRLY2+f9wO5yKogviM2Oo9aIOTtwCNqzD1npSwzAbyiXgy7ByvR8W8s/ioZNhFdFl2F6gzRDs2u5c+srxzQufpDo2GOHIxl0WN8rOCVTM94W0zw63XTcy1jfRld/A1thaJExraHMr/cxhTCJz13um6RrtVoXLMsKiGHgrNewx66keGmSwdoXoLbqe++grISAwkdHXlhI1U06L2MqnOwGjP0lwq+/jVlUxufXYr1WGvUaQ16QB10JczgqKOdpLzZPei64JpirlzGVCgY/yaYbzSZnpvdmnOEtkb9m0OokBbLvbDFfNBZrCPdS0YU+MfnILLzEGAjJQ4sSMIK6rMZAcudRQx6aJoHymC2adc5nLuAyLVbxQKg9uYJaUlgQq1j1sg/fdaXS4tu7omEw9DuRemZ39qqyZENdot0w+Sb+jmudYbOpdadXgoNzx1LQtylefdnb3yTiuyhBLRYlYOozm6zjG6Guk4Xknut0d8ZPQJ0WNbpnZiIdDZT/1vWULVWut+s9zKNse+Ch7C5LZLrUnSgPB8suMXYD4XUQA2b+9YFdYxqIMPnNYNSSAe68CpEBTR8ZvzDD6mcu555K3BmzSqZkZ8v+jvlnkMw9yp/s6Sz3ZFJ91NSlCKARNrkhKqRTORpZ/QY7Gv907GvMTOjPHACIhPGV4y0WoIbBEvnt8xbRc+B+rfM09C5D96Wu63fhPAHme2LbyhjphBKVNS+8cekD92LhYA2HVzLGCK6WKUpoONV0hiGeUmFgnH2koIRmSiiH5FAZ+h+BIraR3vUpW10nOUNKY218PG0DcPg8bTpkp7hUpR+CISWB3TEY3WM8C1pTYtB/lace5VpNvGXudtG8cIvqv5boCKCcotnU91QUFk6NEYZ1YvlD4PdfxGjVmP05eFiG+OBn/Lsgd08iKq8+8xBJd7yXj9slZaOQyrCIGiBpQ+1Sn0q7CxCBEjPbGoJ23J20fXNPc3o9wIW+Y6wkpLeBMlZ1S04rEmw0S7d990gukqDhi2s+bb4z6QOqv/lg3XOSrZwhWNgNNhx0DPoP30Ggh2qAosZmvCAM5mUONEXLDsHl2OkAqIui6W2e936nJYxbPmdKpSuJG+37cAUwygtr8oj90DoWLO2hHAI3JGKcKTn0NmjV3qLBKblQuAqqtrudv1wtPCniRwPPbDPTFjaLcK/0lHYWoT7LVB7+lNsQXhUfWuxYNybrkvtePR4QoWIUA00uZf7mt1EjDBAQ0X4PJEcJjBLSzHvawKV4c9rQs821tS36odkuwZV/5rNrvc5Fm3pw0nKevqPZs7DPA6Q33JwrZ9/SNNfpaz16Wo1asf7ncyh1m2crI6Yrem9C1g88He/cq1Sb2Ow9eptxNYHnpEGYk4QU9yrJRBwkmoyww6GVNB/nfo92cy1AQSH54jJXDo8TKirKrWezJs2sHyeq4Jh7vibYE49/GCuIGCbzafZd61G5bK7QWE45PxKUUDx+YYZNwgzzxctDnFgsAJuJuPyJ7ujth32V+Uj6a6xdwhvpC9svtyGsk2kp0wHx2zBzKgnmwMvQJPx/JV02dR3VdWzHtsCWm9ayMs6jq7TCN78aDRk0vGUCNxkiXQBdI1fQD9TF916snAlPqOpOzI8bAlao69hjKDjFp838iySbbBxxRk+mQg09kcIHGZ1PCRHO43AX4s/M3iAQFhJTvIMaoEZdEp/jkMrCpJIO9UdqgtamT0s7qlor1FVivjQsb1JAjJIC7yUv9wU8a9GXVrDl16JWhxzmw8IDFylsV9JpYS+5IqSx4qGiqi7TDKQ1PxZbZlqan7Dh3ABM2s4dxTs5w4JTI9W6cFBjRfQVJD8qmwbfsJR23Qkvk6MDvlpvkQRXJYRSUEWlS1RfnbuuWnn9gdehw5ulgAFCUV18pqOsyzt4SLbRzTxAgDGp9yi/c2yrO4XroTo1y9nOk11jt1CCwsVO+rhL17fZpJMgbSFFNlvSwrzKcHuiEm7df70cwpR8xvblvYIG71GV9TrmOnZn+0VqGOtkLiMW7ynZ4r1ebECv9fEhR8FLPQxNah8S7K7AW4Cuw7B2/MpY90fJWRCaie/pLZtgbACRLEdrFEv4Gl1MhNqBWd2042WFYaaIxLBt+ie14QJY5C1AUn/DHiVVcflPvcAws" + "PNMFzsA+mTALXWwnMWmu0R7X/r+MNh7beiom9fxm/FDxQO2d+HgNtQ2AyNJIYLVr2OFUkMZGhVpAEA80jcDBWFOqeHF0jUW+XxpJvZaBFF7lfp+eAtEf8GuX+65ZVKHG8tAf4Fa8VmAoPa42DntP2+ERXaCNfFeZTRWzjVwDDQWG6ucE7HDIyX6NZM6BwLo/OULTLK8XlHqKN0W67vM/m5PIYbKDKHBmjfpw22ouoXixlrMo7bhreu5AB/1zEMlhUOjuf7laNF+4iKvQ+7h7w7w97M+IUtizj9lz9gqJbbv9sCntV1BK1Vh90o2KwN3wX4P72KSXSYIprNtthYqVqDx/pYM0QNHazceqN/RraARwxzRhUE/3Rnb5pdhecOTgsYVSt37sB6Jo+6wlnUTd12P9vejUpW2oz5ikG6Rdqvc+aFB6Rpqu/M73eZM7JIIh8hBRYnqvun1mPyEicDxM5L6jo1p0w0p3mm4OwZcGgHWoRMt+DMvoIcu9TqhSp55GLGPfdIopdkBMEDJxe4f1kwbRmdBZvmc4dPjg/3mlf/MVk26VAygJCvKTGenGemLatZixRw0gazcyK4Jr20mph/phdIinKxIDAIGJvs4sL5hf8AZRxLUgA7aBERbdYnQsnNidh5rLxldYePs+VAbdmHLmDFdQVjWIuwukmZ337rmjV7yJfPXVfS8jrnMitjd/BI9piESr9m6Y61MEh6ZMd0QdNs1p5NRGA5Kh+b3rE/cQnCg98eZXVrv5ZEnEJlvh6aZMlR1tCF55QptYUQ+P6xJcq2YiNJ3dQhAt8ugFqNz3Xcxh8ZOt2kiwmYDbDKHS5emom3Lr/lftOaaw4I1DzW/fHJ0Wc3J0KurWQRbDW8D5x4ZEozeU9wXZqv4jXNbYTc92ZDTGXbiUXfm8dQ5S5f6l4a0tTlS6VjSrWK397M+kzevd1rYCClL2KMGXzBEFmvHZ2FY+ofT0q4bQK2nsI55xwtzHHmDCnOFpbj3bOVsEQziVxN1MDVzPNMhi6kmcEaiZ6i7qczGVfm9udldeJD1gbvvsKdRLYZ8PKw1PyTuzJShCvPIAKLherPwct4GSK57xr2AGBrylk76zDhkPJuYluT/blw3M6R95UqoZeeWMpcYd9Itc7QLNtv8aoUjV/yQO9hsGuA3ue71f8dMlGYxXpSt8zephZS8HNHH1RTjqK3zAIIIKCsHFJ+oP2Wls6eilwcD6uCn9K+5xczc9JkveDzyLBeNkh9Ux2f2CCMrekSzXgcPIxGrLxPZ4ShEDnPZ7uBFS9suHIatuF6CbGjTGX/kbVw1//03+0GOCxZBWvLdmOMvrrCOvdrVy3dJ6L3ubuztnZ6q5qztsKSOauHY5ZWU4QVpw/erOAy759nXX79C0zAKsGVjcao+TII8ebasHQ1mUhiEgHT3jpYWwrYw0zx33CZlkh0oZbHxvAoD73KyMb/Ofe7Br3QEJC5Z+gGsvn1w6eofvkQtsBjpks2zh2e8ee8gpdp5h2fyau/lGU69OTktZfxj90cgYtvBm4VtvNbr3zhlvTJ1LC8TUtL1r4cl+PC9R5KOqy0fPqh7baZ4Lyai+pmm+TB76kbKcrdC70lH3UVicRPZH28wjmasWZrEIKabVTXeCyQgZXEqV3q59AasRe/OcIvTT/rUvRiYPoFcOWiA1xFRP3joVvFmhWk5kr9j2hJHTn7UISAX0/+kqD86tvvt3YaxtF+cRyzqsy28gUiLWNdktko2PkjWEZg8RheZRnJYZz4AKF7f99cKxbyKJh85KCYselYujvnr3Sl30L6nrB5a+6VXF50RPRII98MVoxfRHCm9Dbn9ZX0IT/yJD79UGhGp3xcVeOoD6XxdKA1Y11g2i49ostPHTp4sXLaYhDlNtbUI5inm4tf8NKjGkYH3p+xUhNV1+PooPuMFKVjGYaAfNEpmRHslxODme12Fij6Tpb3+IG6af5mvuBsxitHb+6qfzWjDnbJ7gJGRo5+wL60A8hTvOK9LaXme3URPb79Sa/6nD14OBqsaIEaJa8cmqDpvjGIf9a897bKeglcVI/XErTUGBVGIAPQGtaL5urmrzgP1qSnTGdjFemGelScQWqxeEw+QF/YDm8LUZ45ntmkD1Ln5TZRUaWd70y6pbPx3Q8Vg7nIS7psqpOgN/UraeOgEOW4g4duUs3No5CR+o42bPQlG6/9lDvM2EzXH9uALefud8zQDWFkeJLGtttbq+TVoh0clT5rtRl85dTEtkABce61lzVvMjGHdEsDMXU6KT6LbbZoA5rBCCetNSwv/HkG/UeptU7REhTznK0rt9KT1ZcOT0WwRmW9LWaaodmsTT3zaV9KocvckgoJMrQg6Q6zA+ty5PUmYixGX8F7lIcouNBSjSkrptLQOfOJO7dJPBbTRir9vQ+QEc5AF5LAAO7ZjaKK9Oc54CIB7s9fRm/mGJ1/9HMsu116Y5EkbjBDkSTDgwx62atYD/BS+u4l995Jtx0zgCbTkdw+6XQWrOQh9JXqlFg1zVq1xqr+8eurvAHNPBUincS2bP09xhlT6wruzr6eIsjtd2dSGDy2ZKFjl8efKjQD6losOSgjmr1uRMkKaYMe0tcH7CyFJELioiMDqp0+g/ZulFT9bmPnrraNXYA4GEyJb6Vr+uZjOixkZASNweGaVJmsZtO6VBnf0zcefWm9DJOZzjVog3DrxTNh2J6C96RCjvg3QQyI0+5elALXXPey152bh0XmPrQWR4SNW4OleMnh+ECsKuw2/pyPvprV9Ps5HqaxMcpIpuHpCgYA6I9rdPKtjJtbFajiAKiHM1yYCWOS3wVGN80+iLdekAMGpohZhzG8y+MDGFT1mBYEXZioaRnNoa/kWUFvszwSoJ4oPpRCz9ZEXEXRqe+RN5ejGikNndAiGaut6zmiPG4Zxr1wCHEEGOYjZCpdGbKsKYZsIxJKIwKZF9yw5rLFrXSlRqsl4yH490o0OpjFIuV4OUodWpnBtTjUB/Az4MNr+Ca0hqPxJrTIyPpFLUqAbwWF07skD7hqBptxnIHdTgryDCYFKKR3JIlcQztP25vwJBNIL1P3+vC9W7u5OSLw4IFWiPIFkc3Md8TwYuVxcl1SU1HetmyZjMGX+enwjuLb6WHZfOZUKSZY7KHvocH0kL0aZ9LVTTXRA+gaM/qZQWDYtPSZmFkqUud06Z1YrujsFD7+kAOX3fGHxCPjaOfN8rT6P5EBVCt/2vzfq3DhcJm3oLaumnLxYZUdbYZlR2OtIKcay53ycs6RNjBdo0U9bzOYqJMo0jWpqgpBGxJUUZy7P/H2+Dtp9s14yVVmgCns1JnXDkY+Rz8ne4lxZMnhUCCbI5a7tEVn+/iTs12dCaDeKNGpfxMnsmW9wLzIZqpdWnYGK8jNm9Om1KFjbqc4S+fcXrXUIX9KEaZ5Gj660PmpZn/+uFFN/cUrRXrHZnG+K1gt9aEugrdsDi8WnfRpN6T9/ih1es0JPSP50z7BhM38SSR9CZqXnsHs+/sCK37wfNGptdbD8eYIfoY9do3gRnmZYeHPNp1e8L44oy+fIGlGZJlbSpLba7A4bd1kGQtVkv4fNtolvbNnoFGjp71GEMRDMx1+Coyj9CmgUyrhENiLFuXsn+sRRens2JFAEolVI1iU0r/GVDtyPGWrEGWJ5Ikv9gVbNfeg9LJrNFXdtifO3S5rlpu9XmGHvBc3Wq7hne2ItUYlV//4o0ShUVYLeVml9XCfD4fmCK0XxQ1oucqjGkUlMD2CDz2CZgElRR6w2X9jpCs8oPeBpd7LzFwam6tH8aTcro7eylXeTLqrOgcYuDfF0ueotE46P4YPqm417pJwtkYNHsiOUFZdvTBzqubmYyGhxiwviRVCVlURsXxq1x6xkGvrLXAAww73mD30EVRzt93FAwQbft49lwLcp2fXOZqiz65jlyHjD1sMX4z0YubIKFBBo+teLESnWzNPBj0ObTKvadWiu0ZGuCeDLj/lFIJMipxerTQ3O4PEUJMiLiRj6ogEgcnXsnXSFy+bRy0PlzxmdLmNrZesbwABS2QAcKEHJj/33k4tuAvpZ8N0meMXpw5WGW+UqQT/z2eZ" + "qa7Yrs2k/wy8IV9uHVAMiblZUdZQObBCL+ZA9yO2ymJwlOXrK7ddeTFREKrz50uGJtq707EdWsG+LCN/qXuGPVUiJqRNr9Qy2lxhBmWjMmZwZy0lGHdvrdXcMu7uzhXAkrT5AHGYwod1N7Tz4bgVG82Zg6EDsD1D0+z4YKltPRP6ISHLFHY2nbnzomzgWJNOdBdtvXvXGJ0EWcWLP3gcVaVzzEhdqAC+P0Os4M8SZ4mLx3orVtugCfiRHh4ZdWFtuXb/k68xcDwuawLca2l14NUdtqUNSEwgm1Mvkxbno/WwENoVgxy1R2XdQKotGkvlUs04LI8/CGw8uaw6uEioz5ivJFfvIJSuiGB0Ve3ybnKnrCaHwvmHKgrdW3hOrSp7LzCg3Ps/XjyUbkwtLZPdW3kM8VBQxZ9HJL9C7S2vlJknDB4nDM1xf4uRIxN4SIhknGLf1poesm9RbZxw69NG9xcjcxYFPB7cSREwn+u2jlWjnRNkJsFAEEmsaQekvr6dNY9fs9rsUONtFkpc/M22I2JwPolpkeumzVlyjGej5qQuOwU5VgzDzmFBL13SuTxvrf6nVzbPrFmmW3vlqqLURK6Jvfj49oYDjg5BSDharGwHtl5l8tyJLhlDCJWXL9XI7QetbGesS6/Utajt4Pme+9BRLc9oXdJ8AJxh4grm6x2w1Q58N3SlFJ1u+kKlHGq0ClgYSXrKAsM/m0fqsjW5YDH6lW/dRMQ+jeVaf1FjZrfSQX44snSqdB7YcpHlfD2Sk/VcgjBVauJ3cwJCaJ5Gsf7c3qhRi6SbeIijUyGPbVBdMr6oBspUPvxwC04CalwMPUJa0F1HhGit9DG0N3nI1b/8IyN91xit3lDTkN/ermidUFpXiOVF747UVYggXH9zqKm0Hi9adRhFw1V5UP3dnX0zg3Qpun0dj4dndTGeOOVo9aMSXH9WP9s4Qt8Xalm5LAlNOwfuOpjC32lO17ZZs7Hees3cHjchP9NuG8UEGPFX2JeF2glLNg19rXIPh0VkQOKlM8R8Z29TWHIsvHZ/A9fqc30vf93JirCnoO3lViiQS+7gpqezsnz+y17iCTrGOaFFJ8sSflpAQGW0VMvuATqmpR6LE+1mYMkGMKVIb5K0v/js6vu//b/mX9P+73/OgldU1jaLTvY8udnG/WlaqdL5Yo7bdj8ul/Q1W7YCf0twr5h/qYizty6WsKuvzzKwV5QIKIqfkoy04dFA1lP8DDOW6cIf3qH5CYMD8ZlpLsjDN6GcXNGUBUzbFkkDqTgccfZJ/b4XSFbHft60XJ8TAtMFboEykhzezs3Qgde7dKkd6lGhBbJ++KpVMMZa4HGAR0m+w6VNVN89W08HFeHr1k+Zhaw2naolW7YUKFiaBlJLT4vZTguoXcdaYUoQLrWzU3jKuVMVFrl8Cs+WIh7oqc1NlXM7Vjo7crQ5WtsysosozhyERJw7U7Nv3neX6rJMZtnFrDlDewM3LHSuswO8gmHmWZ7dPEkXHANwcwvamGWGjHzp5U7PHb9GveyIMw6RWSjv6po7Kq0KzFjGtM3mr74CgBoEMF3utqGRorK0Ow7YSGkLpEhIIdwAnapyNP0BLqwPMmnHR/XPP+tp/nu41R06q/kL/EpWjCF6hbLAwRQYbGt/rF3mHvcF7DkbTgFDX2Hquk8HPcTLPR39BDr8Hs6ThczlNrkYgGoU7JHj0oO2kidKoz2ZYa2zXoZE0rOP3+6mV/MGZHasl6zyEEWnlo8p0z9ZdYPV6krijBKouzvzbKNk7N319Slm8Uo3SvXj8AoYtGeeoxIszVVb+fRLXEjXNbRy+QcPS0fE8MJ//u2chdF73QGSoFJ3zv01KudVvG25AATMh/7cmm3wlimoZFdxtPR8uI9PywsqKqPn0Cyvv7WnqA+Gk+TRI6RKuiQUHTqjh+ekR24WOc10MdafL91eS49eVRwbX64m9whL9VOcrzkxeGCXwBNZyjQphHyf6NH/43NC1FPD0cpIKfbqJL0ROt9TkhRpo034QElLe3FFYlJ2avFwZc6iuA93uAKFWXV+EKi2iqdX9TmLF+MhX2fd+HcqiuifcM+fSWXDpQzQAbfGtF8sfeC1e90/VQLNyE+q1GEtcGmVYUsh8f94KBPjIC35iKmsvSsqubRvDajZ7objhS6+LI/DpAdxyrUGpbW/1vY68toLswblWsJ6oQT8PTgqNSspgLK2YRwQfBKUHt4/+FQaa0FAKM/7veWweZhhdkvg9tR7WWTNKm9nONBzW7aBQuZB9iI5OBqanWtjc6hVlXftDx9uYNLDPdwDbE2hw1H2X4e0EQC1cj5H9Im2psNxeoU5uGFbakMYw6dfh0IAOEUqidhwTWe5b/VAYknEL1rFCGbYd7ER83wDAbASGn45Tm8pFVXW1H5Eqd5AiccqKM09bLpzuImZEz8ySeNVJ/5nCzrftSwXW9Ykw3bEmWkp9IX3FUDRqOroe3vbLdB4LSo8gO+yDs0unoYdKSvpDZ9SeLSznwt8CWvpVvDJ/zpVYiPAlNBnM96gje6FGjUUCIN8uUgbl2uZb5xsOFxLkipHFNiHLJb2JLlJG7nOIyg5TjP9Pmz1w6zZmF2xy+uP7RsOTKOdeLwab2SpjKJEsOsjbWGU3L4CeBuC8PMr7njOgEtYe2okRLzSfT5/f4dxxdDJ7fOZqJKdZQWs+1mqaXI66ygM6YiX0AfMPxlEZMxdN9MTScz3jYD8pEU4uF1wLsqtRb++fcOKlkNvsbHjARQv86me3uaIbjpLty5CylUQOXmOC5XWT7NEN0MIDZjFpoGwmJx6XFOvX4NFmlkDvtmLs3NfslNoFWU6q5H6Ns0MX3RpGBC7+HLoOe/d33T5CJDk4doGpviStjueTyl1IRrXFBwzk176qLznLdU5xu7eOJajOOdzhlNoeLhgoYNUuD+mNR8P+vm8awPmbbb30BUAzcbLV6w5LHFLtrYUAQSWFJkRMt38KbunBDHJehReOPNsdGmoNgRv7giEyqzyaKzUOWoU2Tx3jPoNDNNMktZMhl+SlpW/3p+q5CBXG7NoE2XQJC2jSU9EjXv5y1DQS2+mWLjtAxiIHIRChapoJOlEYU57AennbCR3hlRNXLEn3kilDklqLPwcn4a97viIcPMdwb9Qfaqawts+09lrLpsjUEAFFATLgskRZUVgnzO8xwCFcg1maR3nrUeHoh//fX44shOnbfVoP/+H35RvcJ+XF5WBX9+f6HXUFYxL60ISvXp2shiec9xFLST8uBX1Sdp2yXOYLKTtGuNJ72FzYiC6BGZgsh4b3FFriKUyUsW13GuoYd3vFIrQ72qrzSnQ6ok5VTVV5ht9reZh4xkRm+J3mnpNxyJGXGr6yMvcD9Dv4FOoIQcHz6hcRlRBmzuapzj0j+OnE9i+GlxRQweGSWJYomMpG0fdZPBGad09tYjanGJwpCJ/VbcMp/N9mij5sxu9vRO1gqqvFntdncZayxND3AD3waRyqZiUVL7SMyQPDpMGOZyRF4mizay4m2zENbKQr78xdtPeDwO/ByLuXnmdipBl7VHFXfZX+X8Ck36/kOsxplOk+BWP6d6+JSz0+zma9zSzFnzwwZpa+gOalVeovKFbIEeIiNIcUo4f0/L57+gpFuAtfcnWizckgKo+OzLGr6KGNO4aEWefpjtS3kwHBKsSgjSepK3n3GNJm3qMfkZIA1qbHO0wuoVAPFvnNuXkT2wqXQdq7VRE08++krmSGVgx77YPU4jLOLBqivungTTBYUs2HX2HUZz042eFKxDGPR3CrYZgU2223f2L3Fw5IsdgdGlz6O5TYxD37wmi4ieC8lEjoKC24s2G+CRHUD6sqEoQpQBnsNFecoG1dY+dxsdQqzVsCoHO+iJaAV15e+HVkhlLmL5s6NA8Fur0soUEgWC3h9wbKVrGI4Vcf+qCLq0jwjuhF04hrpRqt1c+z7y+HZYp94qIyWv7nGc7bIcg/a0hm6n4lGJWN5g9qzVmUYE9HTQYVfr2CuJae/eit4M/mX6Kk10HwI48DMPk8J10u79zdbf53gotYf66zA5Jn7glm/WaC2igrR7rkuz48mUGg44ZiF" + "QAwDRHHTsu8pKHmV4X3LEcc0p37DOeVE0Zeo4CYJbXiPCjRlZorkr6MvMSlUnXLQdv7Yx4KXURf9tdBH93PZnWaMmtKHCTVFJInC+F3tUgdbgkZT34ZBIj99geNX3KuCjTQeZ0TwEd1a2/yA9wBSKeb2nKXPg9HXSv54ghPopKdPpWvtWFA0joRLK+m/pSgVW667tGlw732fLcrJzNMEpyXPtTW9CPWWZIQNz6zWzyOAGpE86+ABzSXU+TjTQivv4WQfcxdL4WA2F2CWIeqawMNjj42Pp+6Wp2aigKmRKrNxLUOfu1qniuLSXhqZdW6Eyoxqfx5I8Itd97+Yu11hV2DYj9zNETdswLQ+LjLOpH1F0HURUpDIYVOYuQwP8WbiF7p/9DvvXigljkBp10aNS/WRnY1dxhZs1TYiWxoJ9eDkkt4eMlFR159gMVnT2EqaGi70Fps7BLmCFE2o4B+blr4Vgcy2NTVPEFAC1msASnu2cZ2ZHUI72/CoTuGzNU16gReBxdsjfyDXV7z/qGVYabCrdSDSB4cA5cekILRCivC5Kr2lN5HnxIcnUg0V2R0D9jaH/vfaMats7KeXJDf3CIydqzgiYcHOnUE9QenOhgsujpyT3QW9/PCAvZeY/weD1HWuPW+grdrjP14eP5TgWzXKdEx7Ka6s6XzkdP+QgkdZ1+hzHN3skC2LLeOlTo7w0ci+Ap6IX/3abcqtm/6WdHNpwuCFoGE9Q8hLiUIuca5/1KatVqQsKm4z/VFFkam6HUtNtQlT6UqJhzNkcro/35QkA6yF41uleoznyDyiI+CmgDBYZetM9uyoAaKSWiqPBqP8FprjLnV0sbCwfX1dPBOX6sKxGzmM7V1EekytOokR9oTaDa/b4ley7nB1YdRr2HfA+9z7ryNnp4W3DT0vPyj4Ptu4LXNdkENGPOWTJy7ao/4zNEZ749MCKY2K+cGyNUvUJI0k2dNzmTea4W7ApaySv4UvOm12lFt0FfEdI2Y2gv1sC2jMlLZsndpAHfL5QO1aUxEvfrhFZBU5VFIJt2vNWsHp/7bGBfZ4u9XQ8kNQXUiBwsJY1wTV41cfYzu2ZunTUtPrLD3/Aj99xsgXbXGcce9OdrXfBWFNtnV3iW/D23ey1aL3jdiF1LFm5e/LQyjMP4rHPp7PMD2TZ6rPvk0uNStSKJqZ8ArLAYlXrxHEh+UBgFecuTHsGSPeyBmliTKnqn0mPlnb1KpDmzA6/DNvK7C39Jc1ZPDKnnjPWqMPhqguqzUIUwa8SUpdaXJUH00bUlskKgfNwJN8GFna4hboir1/+Z0UF5rIDk3RSb7t1LLaeyA1DXlWGqp/9ucrv29PDJWcDu7n7njwzMFAyoCxRuViVN9VLzRRue/ylZyDoUaUtk1g6YXYcdYTqaJSxJmyKz36A5haNpuj7rGwfST9pfbzM0wkDi1/C19vJcW+0L9a6YfPEQuVQD7HhhK5qm8sx8GDuk9u5EujNSDYx6/MuqoLjtTS2G6FVa5OEcwNpFPj0Aaz7JISDDf27SM1ZF2dH+Nmg8bjWGiPK7YJjLRBbwFTcdQ0JEOwjR0IOJK1pNKlHqff7ggbQAjnGIldHOM1Pr/pSZs53tk5+edz0htmxc7L01j6Fydpge+TEPopstq0Bt8giGfmhsQ5blrDVOKKQncI1npsFpYez6/Krv2krkX6OD51307ZVusHPYBlvIBLmHRR10tlWv5esD+MzQd5wMdv/VbogW03ruZ4FJ+w9zaYdu3W91sbjy2lgsF7uQ2FrAxcJa2V+loIwzixTgZi8ioue3eIEk9rw1qB/KbHllbzGlN2fIJmPqBi2JcJJeagOEzJJ8qcbcH0t2pxZKR/BgiVGqd7Pl44OOKlR2KjfgdppxNoqAiN5rdb8Nfjj2OadVHXjEA1CQTFftI6FV9/YMooEL+FWKTmjImoGdTYnKGtv/7+tLsCRJcSivUheoeoBY73+x1gcJcwlFzz5ZmRHuZqD1L6BOK699docN0AnyIpNmyvXIGE6F4R67sv21zSMTMTNrCCZKwmOsiIjFFcsQNh3K+f4i2LhnLkaa6kSMkbPRLjrr2s1KOpmQk2y323DBYrdEkRFKmm4N3ZQ9xNG86SHbK1k9WWiqQymK7XYbiHJxUdj77SqNf8udQEBNqVAPukpciSgy1eFNwgUysCFfz3qiAyRQ3JkUDNOmVeWnIEvc/RgCzDfP6iXe3fLvduvGAwIggD8U2T1gJv+B/CsGfx6eVMD4flZKZHGxikMp8Lk952PVaVGXB81fjMNmFTR/30OB06Jxt2nbEbWSrCqPgKWTAxpLbMrLAcJlODWxppNTAHtY0gw/MBEKZr4r+/2KIBiHlfdVUXaiaRVjzrvm5rRZxM/3rtEld/X0eP+9QNe4KL1CuejXA0U0TlpmUa9tKSJEorfOKNyg92CgnGGp8TdBOnOIbsrasTev6hA0u9wkfC+7k1SuZ04lskPj3DwV5QGdYC046oQc4sXAdufTd712XBF19+9OSL4oeWeOErgyAPU1gtKPqhmdfd7ZnDmb9QRTQ/paSnSUuOOgW5PvoGMmmcr8sevo9Slz0+qh2gqgEuHEgvIMix60EP03/Vw8LH8op29z8bAWGzT9UZndzdnEErgOFbWqQx1CRnJiJ7LKhFLOFP31MV/UBqGnTS/aLC1b/38pBrijEAnpLvsvtbsotbtlK2z9uSe25CoC5Xk5JwLFvuIVkV0YKwEsfS0D7QZ/6iI5RWZr0P2jiELCqfEeiBe7qwazTuHnDqCx2f100Hq+G8hevOK9HSUteMMfJUUE8SLuxJT745zJl8WQmKW+xWCzBTLsWJooWOdRypSqtsAb61oCrdZCvBcf3BpqPY9XCFRPR/L/Yl24dBBT+FeM1QL/RK4cvYyw+BXww1A6GD+4cdViZ72NPheyZqwtiEUYAZWrktXgKpuj3Xb9tmPdFdvjo3BQisU4qY6gmgDPPVMaD00UbAyLIbqRw40rnJ7L3PxE3+NCM/A3topr2BrT6g0fOy1kDY+MQHCt0x8rLhRtu3kq10ZuB6XnC+A9OV/k5CU1+IwyaxR7oFs1oup2YLt8sK7QPRxvo8R1WbtDRXBKX0LhFtpNAdeUA+Sy8o9ymMowpHLdqELjmOwhm0KSMSZfl9sGT2bRFEF8lEH7tqVQ3hr/fssHPYcKDp5SwSzYQfQXsQqelJwokFZIKhXA7Vs/o3Su5UqZwQ58sxGNSEATR+xi5X7OihwyokR+qFT2utf36BCT/QV9NcXm19o81GzNPm2rjecGook7PTJYamPegnfWq/E0p7P9O6eHU6qatvBJqpqr8oR+wBNn4OTu9GBPHwBPPrX2BbHkxVplvGhSnPO2WvfJaIKS2F0u0lyDRXsOUk0hC0DRE5HHrgKlZ1l2rHbnZWuNSOoHIcYSN7+uGVmherBpQR596xWE3xaoV9ulhJa53emKHFYzpy0jUHvmylxvwV1mK8EuztXTFzdYa9xYg8xEUS7r4Itf1SggCc6xAA96vtquNLlram+6ypP74he3DDOyotu4zn1MVPfyuXBISh3kAVEnWzpXZ+yqV+Z3HS0N/dENtzatOAFBvE/Kmj5zNN3jSD81b3F3TDMQx2+o2ewCXHIvavXfiPFN+fhDZnoODiggUzpi7tWmPxWcn2i0p8qBqJcwuSAom9/ilpM6hUqec1dtpkohFZ1sN1z0Gmyz9mb6Ilc5E5MMQ8BBtPtLEXt2FZFC6+Bl4zTGZVrMSfZXGkZBUIR8E1C2CqSmXpZphr9l0fRxdjfS6vJZmoH6LsB+8ZysodjOD+mKm2nZdG5qnO4Q5gqs0Ean3pJ/icT3o0+LMRezQoJP6F37DFdj5KPHyO1sDsYcIJkF9QMWu+PtawvYVxTIOG/cpqJsN0YuKDv5O40IYW5mqd9xaHmOFnSyhMWWPSbimlFovbbeBWZmUjNMCNnOp17lOFVrVdmT7H2IpZDPVltKDw8XWlPlrjiC5BqKQJfY9Xv17rhvYppKZb4OGtgyUwm4M9woOQN6EeHhiDbDzARO1VRDnGJXd0oOHI4oIM9hkMMunHxErdLTV/PvLL/zjvad2gai" + "dkAmhKLsZXJhDBOJUGKUdYIMl2bDQlZ0XGuDya1dIe5GDh0uDfTwrgE6im29RCMVrin7uyPiOtJYekrBUqx1g549ruJmercAWxmbPtX5Z4GUlIBc6EMCcTenOyRO0E6AV1sieILERth9U7/NFzqj9Radj+otrnUvSm9Ma3i0z1Sf70qd/TsSvZbIXpVTrClqrrIT99YREJQzMuWATL6GbcqqisRzhdWf10uQvFDeHQajuuWZq45i5bTTsUBZlph65q6ogVRS6fwYiRWZzGsQ5zqol1AA1C7wC6jxbqZbHuQ11E1J8XPJUoFVh9gpglybxzZWpCk5uyGfXJBdXxa1cEkZGLxd9J3FKXz1ICROW41ELLrdh9+5VQfSWD1pSWF1HImbIq/4XfwQzvr6fGK9QbOimwsk1b09bOmPDdLhSq1s7cZ0EmgnGl1NiYdnb+lgrucoROVh/8FVQOjWr/dWSBFeQga61unnWzFDyvb/kEUg4dNk+cIXZ6p8wHzF4UHJH/OR1uFP2s4aBttiI1tzeo4O+kgAXIHK3LyYQe9fI5jiZSl3Wre0ZK6mSg1gyW2JCdKiYNBgKKMneUDbW48nRw1nMiZF7LDONzpQS9kh3rlz0UwCjyRtU9BQjJeYDg+hKcBCmOj9HjTRo8Cy0eKNBUMzsF5owUY5eaEP0cSdXtFI3L+smVNSDjDBATQip2e+v/klp8ObcRgpahmolKYDFb40kJRpf47ocACoPiM6Lnj6kHkvl7YHAA8ZmqFGfN3xzVRxEqQskVDf9h0qX4EGv78zEgzhIjtvuKGEtjnodEbUDTXyrlFXPEdLZy7kusVOyhwOcHfVD0zYoashq50u35H/QLzP7yCOc79PmUfyqyeKeCadT//v0PO2XlgXqGsK9OyT3aXLXqDkeQFeHFFKNbNbIcPl4g+h1HhrXBnZ4ohpF+7wBmhBBVcwT54Z32axGIztXTYsuzZcTrgHNiJkKtl9DrlmScMjqqGWPcjT6PjJt179YhKDlzIfhM3o3W5gTshc3dpwZNmyz6bKK9C+DCrmuud7L7s8L7++EyQVZ7hmCjaBT7dGka8D9F3pJdNABG2owAoWvu9WCa/2cn4nfFzsSTosyWk1VUSgoEKnaD5SK7lbM1ctl+fGWpi8fdby06DG7uJxwir6kdtpzoDmcByqg7aeBgwn4emVyuiJ5gv+XKU7PSDZUDv1L9lHuvX5laMr3Gxe0486PUVeaw8q/Tb7ufbgbGBnloL6mj9QKq+SLvW+DVROZHJbHzWAgLt3DQa+AMjMQEp3Ycy8zIZACCkdfuBq2zQ8CkmqwOYXrRJz7Bjg7ii5WCqR6Tr3Ah+xfGzhLJPVpLgkbx4vxSUaqDH/1AQDR4XOWA/GmfXZC0DAk2yvsANKtkSc8o/UOii8jjtcTv2x7UGNmp8dQYM6ZTYbIyn5SlNUQ7Oz43sg+JaUHCjdIha1S5/Jyds9HMR5hcHxiRDbR1pg5nN5S8sTAvtwHNIzMIH86MXV5VGDKQnf0TS8miSaBi+eRcC6vZDfxTe/P+zoyjcpPSN3TkB2SiW6N7QNY91dxkp/lWA/Q1ZT9Y4/tg1rIBkPA74AkATRtt/MMy4caZKDF4nRtKmWL+EDYGL1q+WScujDp2TXfvoeKNsCXxEC+cGSDEEQtRbwyviINL1LhEl/+T+2Ctv1NmjZIBb5Up9K4bitbLJyG90y+1V0zNv1Tnb2VJ1Plzx4/oglyKLYYxjBl6+1Nf5Yl2QGLbBo5snP8WGMSfNM7XML49ekCnRtlToDPDzG+V4XoDgZc1KdMH00zQ74r8AJdEcDlYZAoEMfZl4hpxfTxvqZXc/Qih5SmSWoSfg4ZJUf4SDcPXF7qqp3GjVA0pKTSrnMeLhIUw2eIcGqWTlXY7lFzO/2z72Dog4fr9IINEKywmQrKVyJ4wi52YpaFzg503aNP2ycTarFgFnhDxHeGnFdM9BS2mUwQEU0BDAljLyVTpLT5VEC9vA5Yz9yQyrOU/pVU8heT1JeY7IJb7c20i49PpEfq3KkWLbaTZGvgCPGPmOFoKQ0HUir6ywfdFF7g7jTKA4vtZW4xrQyDlueeAD38vtjd2hdtfEjEZahBU/rrJTb/ofIxu/UurGfkdyxwXuZbHxaKYKaQCnDjmLKP8LDrxs4+eEgk1zZjCG3KjnCPaW8QtWQ9JrXM6wo0WVzSPpzMjKBwW/++GhJ4kOrXuPI/Q2PcD+LjBgglzECEkeblgmt0zJU1Nq7FstVu6xrymAjX8WraZ2lRaqjdDD0z1EaE0B3E7nH6RhGtquoXZx1y+HXgE67MjU75EPA54xcI9QtfxZZV/LZ6sPy32SlDWu98be6zwS2y9dGDc6TL6GNk2QNohEiXQ56l1Sdd8gVEcUsOHB6aESxp11b1pVHUzI2GSviCG1AWFCscg2egy3k1vN7jxxssqx3rsjGckCbkWbapDIj/CwiZopEJYbzX7sc4W5HIekqBi0I3tJvr+Stj6pTczylUSnOl13KNCf2r+JX3CtGg7Vka9iflR4QGf3TEDa9r1kEcFdFy+r+F3Govk6/ewEdzsC5LvQgevVnmtx/XUc/fv3Og6JoRvVZwm8DzMFRibA5rfX6xe2k75HlFgrEpeXkwucVEOxzXNvGtJw0mz7J5gQNPvi5lTz5HvGardshlPJTfFGibLl+gTVQwHLsPJWjARprziD1lnrtorIr3z5+HNnJ27UOiTww6LrIw7ZHX10t/kh9gn98itOzHYPtT3qYu3A/LYYsIxqUlqskMW9UQ6+S/hsggFmHn/MRocSN8BscLrq1YdjJmmtAs3bWGAkpltkipLG1Hk2qe1En+dFcUoyoU/A7gRBbprduo264NDq5IZQlQowjNF/06p3MZSVCx0VjGAllSb0Tbj9merozL7+vYZcMJAxru628YmqtOyfGKoyfakimF9QDqJ7jdw/Yq1nvpZ264eN5BnzVm7PukQC6guFZleSKhYPrKaeTdjMaPoduA3iQBR2W4Vk9c/hMWUzPwSOuFo78tjG4zZRN8HKUImW1WmePpDiwiM4vchhMzUpmhXK2F5Vfc53P+AEmnlWRw+A5lnfkUMu0LCQ5dFwRdjOgkZnRbE1JLtzXlSxpmajlwEYS9AIHLaXffypxfMuoNXU7L1G7gOrMrqplMwbNrfnOotqy3dG42zB49dXfrO/mGxZbokcSWxQh+m52j8vD8uGtaNQ1uwNOL+riy/iDjI35yOrB0dv7ZteVKhTA+TWsdrOYXQ7/EOXBwXbi0bog/1A7ZGHAH0UKYyzjnfpxpKza8VV4hDVCC0sIqF+5RTR9UwLPYqjaQXbfW2reTp4dJiUcVrIjnEZkgEgvVSpR9X5SrtbjDt3JNctkL8IYQxJiRLUeUKiRHkUv+b5Zyh6/p0rw3cKmbmlOwOJrzWfd+q4YQoXp3x8TMt0B5GmRSfpOKv0ID/ti+fb3rnS6ozN4aNTAvIGLHKs7M36QU2tmty47QG8UniJhNfLjvICh+LI8jSNDzvWu6LRtkf7LAslZR2kDerbi3w2jofEWe80tb0VYH4Tg2tq7NS4AeihUgeBT905mOAU1t45PFzO0AowBvBnkmY/W3ChLMvKEfNJTkVMbxpjuB73Ikcz8qCaelXBBOuhoDvj9HeCTpd9KYOT8O61gVVdmqFU5OLiWOhrd4o3j/hzFSdZ/cxUAS6/7Vy3z6v+sLMM0aAt1QxvJYt/CX7C87SuO7YxUDoe1DVUkfYOabaQRUrfL9jh2BUY6SNk2xLWwtUU66j5ldHprfS7Hs8PWHiAR2TXcLdtmirTCufikAJOSN0BXwMZWE0EhTZA3pkhZHhLyv3cVGmPFK2hsz0dJptuQI3k1KpiVNPXzRie1j0kFdrB43Cth5JJ93JzgEZseYHMS5qNEkA5YcM5rHwW2ULCi7c36yJdPHmPaXbsCTPrQQn8rHVEkgAnue6Ars/Glcma43NkqumIMV4YEAgBJSnGHQ+wHFkdAULZkBVtmkBw5jOReXrIgLEqFrQNHriurWfiil5/IwM83j/wEYnAKRRMF/vAC2IPM41u986PrNsSd6AWY0vB7Pj6u6zeuH5" + "oFPGVFbaDCkNyWSsfTYjgnHunuoCj16ljgwA9BRcOTRbk36B7s6k0AbHNdQh+lYT0KSlZLiwo8SQv0MrlYs63K8V7hiznqo1UBP8qW3xEZjK4kV4MEVyV+zJUNikUwm2iybX9JZzvF3/bFtPEPKPMVuURlSivY4NdsFWa2aJjiQio2TvPBSufcqKkNEwc9a7n1k40GPqHf84ARsapwPuDk+I+onhrY+1VEWnYh+Glpg7kuvUR2o0WdDxmO2a+1eCqhtyjqC93fNE70NdgZ0wDmICi9G8b+Rc0spmlHPoRuWuFeh7Od04ZXpNj4xL8gmREJKVVASoLAv60ZYrUk5Io2RWC3WF93sQyv1ZGXqqjV9/UgdwB07XRgFqgxzminbt7J6dud/JC8OsgYuhdxRjB5mTyoikmVGxTraKVvdHg7vHyGMMOpcgm+dSQD7blsLMj2XUWBWS2zZV5ChBXvwgx2r7C4+yt3U4c845LFkMjMZ0jw8xU88ZeaA3hve4boiyvU7PWSJIdAebxJn/7+VIG7jsfQWPq+bMSNLxQfu9Bw1deGFdO448ftrGSMDBUcxMF70AsOqo//6DU1Ttn8/S+V1e6i0gkrFZnggKxA/AqEUYY3IRL/lyWGt1uA1u2txOfGMDY/GiCX7sbXvXxc0duRACU1QiEM7iQi4YIdX9vn9OckMZUdliLTvwxKldLIocZVI4n94sCQFykNV6pJ0dYlrxmJFQCX8fm45XF19ceyM/Erqj5byQEWDFIkNQ5WexDu5V+vC+YKtPDnbCOQ1ytQywv4G5hhKKcGDpKvpTq8eebtWPhJpKixX653rtfNtvarPcFthwI0UnPolatgiFpPu3mIXKu5fStea0veT32IdIcwV7k0v4L2/IlyDTgPrdb215YAq53iLxsn1uLEs/6RZmCuWugpHbG1E/4DHsZ58IiW5dF94OxaI8WyVe2nlPEt2pMueQBAqdSetQ9GRE2MNzmmZCc0JDJ46EiLtKeA273MBg5uVphJFgBreWefKmPcWe9W1FOpzhCDe2atBDG5eAcIfTVjnSsT2g7YdUB1KOgl6C3/YMpaA7k8fqgm92uEb9OHSlpqfHZhw0Axku6aGpnty10fENRT56u9TBjSx4oRCxYbsmrnf/uonr0hsapKoQigzeokbM/ogK9bexa0tKozMV8ixzwDB7OM4xns28Fi+FSM07hYYWrXhbwlY8B9vVxhTR2pLtYwwmMC4i6CnLFVR2ROXHq3BLkjH0H8Y+jXtZzL+NTe6gCYtWJzRZfthWP171PBBdeKxBVpUy/eXgIy2zFlHCukfvQU13Yo8eeAb+n6zRknzfNxzlbqoYmIrHMUPB4FJTsK0BQNlSkSEIS/8aR+ftrWmFhGjkAC9YBOAKaVFp/gJM8AjYrKafzuKQUVBGL3czwgyTkDsQD+3KO9+kQNB7Q/inkZAkE6rnhsgQW6MapbJByCbu/Zypic4vP8RDoKLc03lxAL3SGmwuVFbXgW8PiBddO0PK9L1uUkXUoJq8MFsb7s5WZAh/hVCSBhS/WaHswZv9ZWn31khqD+Qe/U/bl8xKjIW+2tEfnP3d8W1RBLLriO6IXrpho0pxyRpgrLQF7UJigZ8CebFhTQ3BZFGHN+7m20d+FTuPntd9rJ99wRsU9lwVHoHoVUbWSTbNSdbLGGlFIdQECGWVyeKVMJk5Pa3iMBAK/yUPYOrAQUOYxXe3UjmSMHXPMUHO9WdhM6igVHK2uO7+MUUaHptG/2OdizUX8OoLPo3p/CieYIsL98MXOgoVjAKdRX31utwTSTejWicvQRUWZTBAtNm/VuA5FaKW/Zsi3HnUHE8SbqTWfkHLGTizEnpfgy8sy1IBPQn/hBoH2Vd9ANGVIdaW8p+pfGhgpnzreZnMmKAtP1UOUCv6r4wyBjV/TTaFRwFpofkmKW4xiKJEqE3udBGrYeAAGxNLbDGHmUZIylhKBSAY9/dNK2goofkxcwvfoLkynTEAJ0SQ2UZlEiOrT2LPNfiBQZ0w6ByQDO82JYMctqrRkq4el2oKE8Az1gmL5Y/I9MzjiUr3so/eRZPVof6PuJGA+g/gxZOkf7auT0BZE1CncfYmoNEHv6VTqa0G6ww9ONdsF063oCy0+Q+nkWagEjGEpbbu0nyhQEbHeg/slFFo3xxjvuNB3+cp9pTq3ZaiTVAwrm1kz0kop6z1HA+wDoUZfZsw5naCeDquSwNmLamZ38jOQ5bHBmALvBEiSIe1ZY6WeWZ5fMPyqgCNIp0ooG4csS6aV15iM6+hOQNu7dWVnKhKz16rRd8tEY8rVrUef6B2DADfcrjbDhgo/4JtZR0XAbS+YW2QCU/OPZ19Dm1ABSklteP1DIkUI5zfyw8gR5UPhf9HrFuqH0VN69KpYb9wVAiqrUEQwyuMdoIZEhj3LFGLDL94iQrK59NZTXxeYv3JMeEM4KGpZg6qWMFkDaRwmmUliemqbf8eQKPE6LTw0cw4yQvCCHUeO+zo0gEiaZnaNFPbdvgnVffF8Cu69iQu46eMFqdU7OKo3PUHlZ0QkWWLa+FUl4IJhVRwKzmWBkCdcgCyoUbzqjl35jPofTPF6CXYFiohIgt47aCzAHoCK/XnNYKHW3glMJzFbfMrVytUgvB49D6lDqAje+gIyI0ne20Npx/QPM/f1MdPgXjFd5FdKMVXaxWNFboYwTqjNIow5XycF7kgexcT9i2Tj/SKgHrfgsGgd3B2fn0kaxGj9HaYTcKT5tV87JypLuE8I1cpuveSHfn0Qavft6hFelau12iiXnA7IL9jwtYchG3gEbYRIoZ+7tvTKpm9kfJzUI4Cfg2jddsfXsGNaiHZCsSPCZu9Gg38TZ1HNwCw1WXVLRu07hr0ROdbvviR2RNZyiI1+3nCOd1AmQyAzqBERTOzM9qQj6naqfCE5IHiEei2vCNafvjgmDh+EB/LDNFEDAAPh5/a51YPLeT1sAwcuhYs8z1EeqOUxn1RpiX2LE4kiZDBBL1aStXNOdvsFZYEZi0ivbVd28xKySVlTUco9m0chXnLMlpyWlis5OV1NI/6Cf1Qd2hMa9KMM7o6t7SVt8KaEIecZTAK/nl06D9quGGRMOgg6/J30VauWLGsGvkFL1FdxWp+1VO5WgVoVz5Yz8ebjXrCn0NOBjXgKq1eBG9fdxe+9coD7Kq2BfzJTjmoc1x1oU+75hrbOPnD02LFagWukCeXa7DL3bulIi1ABU90L9cW755gwGvsfAUxEB/fHeFBVwO8e7JL28R3nvkQBSlQJ0AJi/NdT2AmDuNyT+TNHAJ8wvRZd7zSrdb3Ue0+ooAA1Q9XKrjukvyioglz9vCfexBzgPiA8FoaP/MNHTtELqd5RmiRE/5QrXt8WNKrSpBQUzBZhrTLVbuYO2YgFm9boQWK+BzyWVuzsHJlesSIO9Q8DbqjR8bztVuG3UFKCxAQHon5tqz17pUU0rLIZD+1yEgmmEx0mb3vdXqg9T9y4AEjyw9Mn9JYlniwn60IjY8F7xq5qsj/EPkg3z7d95x0lhZfTcu09hsPF6PeowArETdXyXDhSRaadOppjJeOwcpEDByxHpCoC2DqaNEK1N4t2FOP/zZmWPZBQDRFZ/dkygLtvuQXgqTrZFkxzEN/LLb4J6oxVFPQtQeAZfPbdBrt89jocgk19TsDLd8FGwcD05DVKZKS/Lb9eZ8p7Zmb8uGc4aY1TFTnpJvVOWcR1S3nKe311xvj176g+MxDC4Fjq6MnUFAhxcpDotjCOm1DkU5mcIWUo2aHHVTJ9HHexhJBMGOUpUgKBOEJMh97Oap1em1oPxY+VQ3AMd2te2Wi39ukohYJYbjxfGzXaQ4riyBtmJDlyWwhZ1UzhDTuQ0tpSKYjZoPyEuWZuD/V/Urq40K1VFlwlS/2r8lUOejqqF5dt8+KG+Wn9WAxj8FOtRd6y0livPD5Ux15cWArHJbCov0R2qVdwv+Dc4qQLdNnMzoWIEkKJ/LeWRNlOwRoJlXw2ortQM9f9H2hE2MC8AgkDGVf0b/v3VtlbKoMPfOau9XJ0owe5yFk1rgnUIaBwss4AeivdukuUBJICi/p3/cn/VgcGn" + "EiQ9ugLC+xJIYW+zvPTG7PhhFySJLbM2TqhH+6sXvZ2z0p9SjPAxXNY1astcrPrqRINNXB8rCyhirEOvAGFYl9Nc5DhRsLOzXY6iewKm84SW08TXOFhfQ2Uz/RZwql8PJk97NVkzdQfyzk2FtLJ6qIB8JS4YDT4MutfO0Fky9y3LQtNudxQPUauXj6aTlKpTxxDt0BkZewFEl6WN4ocwHFtyKt7X0uhENw0smZCzk1VUCN1gr8/gnxo5NeKdFIgLbboncc1Sg+5pcQXfg8qodg+IkkUWxsf/R/LpzPMEhLM851cmoskVpU0934NavACIEPAhR3/kcKo2qSPumDpejTAvlmE1a5NE1ZhWf3Ze5MSZ17V+G607i4GmDZAX0p/qQdVHIFaR+IINRyaVB5a87aj2yhmAoXcuA1Hm5gbwF/EIFYE/ZUZQjJTimYqzoTYT3czlTu+Q0qJKoucH68w1TwdZx7cO5PzRLrhp77l0i7BmjkSOwEdukV4ryqpooQA3yhmQVUFKLnaL3BQPdY0e+844SzjAk34Ll3tdR3cpUPqcaUmEiy4ugQugGcgfnuleE5mmqS00bk8P4M7lmCddlXz3Q51tNJE95+J6QUXVrTiAq7qVMya6cKVdcEkVV1OsOl7n8qD6K/fUTbt20cqdZgtvMFmzvc9FADSnoCKE5VG9oJPlRsRSReTYTgDr5PuusTWkFoliOG9R8FNlKjWxe3vBQlvu0mKEcjNCgdJCYowYDJtmc9FNJJ9Wq2/oHHDQModaNUxt2SqeiqgYRYcsO2ChrmuAHLXKfvmCn3soJtebnxxl9WugD5BWe9ehB0xNUn+n89tNOVTB5d7HCmiWqxWxPq5LCidb1IFQV5m+5JnlpJZ2j7KxEJmojGjMtbaFwFAvy/qiV6GcvK42ipNG/UUech6Glhm0vg5rtlJuDzxolTo05rYl1zJDoEbn2HDDsVMTgfysMlfwgjju1fuIubwYgXlhghCCBdQWFeDq1yQ5c/OsIXSm7IjkS2notSm5qC9Lh5UyJ8N28heay798PDY+uAhO5eagsR1o81SS3GekpwDuadkvdcDa4NNokwRCXm/PtoBbSEg3aslRUo00gbhVr9rPnsH7m8HAOLmPH1Il5dXm4FrsSi5BCHJFYJVsjUmyqrimmetbhoD49rt8vhtN2j6kxyodJg7lkc8araYS8DjeHynAu2lRF7oPQBJKEYxlJoseUf0OPhXTIrBs7YLxqOo3bolgEQo4CMvpVDvp7o9qD1QV2qiO36ZS87nnUGEBm+9QoLGmPoN9I/7DsNs8NWfqeUatMIBKFMmiQWb6uk8UTL/m55JeAyUoACxueTl8zUUKAKR23euHU6fT5Usu7h//eDB2Q8sSUOwqwx2qjW6FPv25q41PEYnZ4t6M+3okQzPseWMFUjun2KQOEt0LNqg5e5SkoA8NxO0CD1Bt9KCV6IJ55Mw2LXlWHAJqdm4y5cJIozl9hj/Q+16xu53ZTbDuRoYL7f7OKgmXUC4q19jUtIsAGjEHqQ1SP+uFxWJGZjlmwtGom193amz4PgjPBwR58MCFs5LcYdmXEvNMegYd4BBR7KUDNZLZPA+IoEJOj5pKX7Ynb4Kr7tXulA7UsbTXaZirv/H6dWKFWe8yuIxeP40v03yty+illCPl57xGboFaBFxPArklOI3SCiaYwwUUNWrl61rtau1MtfmoAH98fFr5Q9en8uFvbrGDEtLfn3j1EFOL4E7cdlU3ThBSN1ErLwoKMP8UYaA4aVg7FNfYkCv0TtivQDKdq7umu1Jd/GPm74Zck8BwjtHSyyKl1UAxc42mov652SL7utRvtb2P4l0jDWVIcudAQxnjpRvzK5qbsyvgikVBbn1YoR+1hM5j8/6GbmfHa8KXtvKFvUFJ4Ey5BYRw/ib9ZvORVEKGsOwJEjh00lsAeStAx0fo+mpUbLz7Ueme3rInncD7Ns/DgX68RcdLoVdee14AvUc0WuKG3+VrAZviVOWXJAintAhkz8HbIz7vJjiphAw/FKebVEQkI6dADGKCQaUW4d15WQmIbbbqqopTVfNB6oEWNz/dYtmTpGpQDw5SfUitKsy1lWncJ7ceyG/lMkP1rW2wdhUFzNX8+N2NX4eNTodmipn2hVNWhKr1zsLATyt/64hioWZB77TB15xKitcmKhvo/My+1vLV/zxvYaUnmcCUu9/ZSCu11BKwM/jYjKhVs4qsn9UA9/8UJJxap1X8ve1cg8TFc+jWNtN7h5m4O1aUVtBt/JfpRbclSsXGU5V07kZx5x6oCXXNYPSNcUxkibXTTEA8BvRqGZUkndPgr4/AbCZj/vN/lNvgyZXtST+uT8Dwq7JsLTrB9ihsES54kuVUuP50c66qCqpe/FZh6suGpnl7DAcHuqycCo3CoOagnHuo6JbKtdqkNFLkf9CdFuGdbcMmtuYLDWnJy7SoPln143QFkjkCP4BkisID8lzjCebU9zD07s2gdWzpBXlVr5bbg3zPDHBdvVzNCHAl0oOtBTTKKjn+ABw5FU2LNDsyE33V/Mj+wcKivAyeml2MlNEedXO1SQAiC8K2R91qjizosmbnJFKt9D35MWdGynfvwqGzv7wFokm9u0TqqHWujw0GJov4w9J1HKQIS1O9eTgnqLwtzNQs4ELpnOOtiInrZKJXPg0mhoEs+NGCesNTb8sPEs+AhzbFd8qg4JxWPivDkTWPPtIWNfer4M5tgFWG31thTGGXlaiVVZh1sxX4wG7I3nkzv/JpVeUEDj4tJuPqmmKFUN79UOHeeda3DqMyyQGUitCSV+RSO7YZzMumB7rZ4EQdT4FPdC9Fu7PmROYVc1VmJI+6FziR3ikW3CtS4wF07aOZDD15BZZu9E4u8WxGEABBgB+RDluyXgDfMUvWJvADTYLZ020To6JKnNguZo2PXYnIWZkgc3VXerlXLz8LoxYVyUsRLRB7M4q0SozHzO+qB5ElheygbUUidQtc5gONS6Qhq5KgT5sPijN50Nl9rfPqukKVs+Vgy5JrNbTNO37ik1/+GD9xbJkWzKOj9bLNzB+wEnA0/U3TjX915HqKeWuk1QXF0tZVVXn2q81NvfXxDmBQwdPbSkP0osyYbb5atyzLHXumlZdquuvLrSqgvo+yQfTjOFEk833PFI2M8orSiznH2sWYWpAkp/4og7Nkzd+1TBnDKt5OxQfV5pS7RcNmK9K+jTOw/ZY6VdTjdOX3shdQaV81g90r301+X5QdJlBcTlKWq859YSn5BY5x1m3zM1C0cCu6rtDlRf+VUlqJQB9A82mbXa0E/GUHpey9ksRTg7v+i/vYSftti8ryvW/VnrVxk/t72Lg7VwXdateFZ1HVZrFLC2FHeOrxGcclA0lWt0WOxmrD0K3tueIHuECaNdowQ3XLivmqYFJqJaJ6jlYpBIi4d4HTqS5Hc37w+jx1TrOaGf/eOgXkq7uRLFvcretDv4BqPnrwW5dpLvfm5fbXlLozz1Cx1V4ifautH3UL1WxxRB/0HsJq4+9mp749+tk4diuzUEWIZQWyZqjEimLrzXrue4/tW5y9ct1KBQekXITsuZG2Xg0Kh+fabCmuY2DBpim8VGdiK/OSVku/i38IU7msPQVq0uudsvPfoetjXq1s3I9E/TQWH7dNWcne0Hu9S+6+gRW/bXx6bU65k70vr8MUeIb8qkbWOrDd1+ks1vZcCbTN/Q75/znTY0S/VQAVQDCb6R1FpJ6vQ2tq2/xIfCrjH9ONC/Vwqrr94kizN8IVhV2jNP8xPqFjqLey0dJ8MLi8+J3iKBqESg4NclH+unJElqhWnuJqT6DJWqFM0QrA22CsuiLyXGDuq5yHZNUhIBF57I4VhZPryPeLHqkzUEhWD+j0iR5jbO3U58NS0bLTAhk+WA7VGjGOoK68XkcJrDVqSD7JEHG68RGzd68Kr26K/LbofqqLuc65xtMfr/+tmuYNuroBLQTSix4uoteNT1cj7zbMP+lBU3FUbc7hVGZjxTJCj1RTbZb4edDarVja8amKOL/05/bRsgKrKshRi86p8RFHYCcIwdISYnS4Br1ZcNSqolHAQ2nmgzVs6zf2Ah" + "KW3s1F791pe0hI5owWbThhAP+2VJzBLEdYZK65N5jj5SblLWiis8dsgfa6F0W1U3QvuuP6E8Zh4+CWY1KkTXdrZXVah10AXgBDtjoBVRt1yE+PoNUDg4fyq2OXYe0wXxQuLDfW3xuTbdEeCXCMbrdiTWeYZmh6gwoYGBf4leimbT7EMzxH/GNmJKIx3dzmNox1em6txI5hHtQPo82uLz8gLqEHzzEQYbXmiN17U97MVk6QIxncTxXV4cbsXNvKX5l82Qrrer9WOv0SRw+jV3KHF8BH13eDlEAT/3Ba/fZRLTlnWrmkWP0rh4LT/x1qbGn1ACI34Bt9nlQfDsCiQzSONkb9uIhhooFEN8UPFYBRnqBdIb6l1s+zkZ3iiSwkV+s9mOpzY+CIB1L1Zu+aLkmT2+9557ZrgBn1i3WsalFSu1/6LLu6F58KdHcylwKuIznu+W6DYTc5lJ0+3o3xAubCRLSl85kRlElwu03XHx5SzhY6nFUhxgEKpEziYJ0jtPQun7P2TcmtDPa5ASEnwB4V1NvB3nEUg8RI7RLvipuKX3eCzxoGDNH+rgH4EU+lh3J4mYqUhrmqpbFrOd2Gl4aWQOyFQOREzezGEHKiqnFYvUKjfPN7DnQRMEht2lE37obKCLik/EPH7/hpNOspUM44xikvyNMtTl+kqZW7ZfMoWiE575aTBy1G6yLvi9Z2UNa3YzSVOOgeWJ1V5CiVEOzWqVBwqoBOH+W2aBg/z6HRCS28j/aCEeYsoD1yr04ASnnGhPAULJPGWk4YXWrGbvUjVv/Okd0MKawFbUd6y3nO5pPGW7WnvTEw+DSpK0HPTcEkfR+S5XGLrXaZ48JfuknKadu/2dWEuWNIJVoC3TB0ZNuzZvYUPG2XW7dgKhFYGe26W4Jz2l9OOxo+O7W5TsPUg0MA3Gum64UzR3llILmRmdfMEmy7bKLLQStt8SRdEs9SayCfhZb8yvhlPF1SxLdfHgujA4/QiHUKxhFI8nrxBJAdKG/PMPoyz1e9T7g5/wvGhjvn1NRlEs2RztmBtGPRWJwahGi4liL9G3cn5dC/E8iKJZiLQSbZCrKoPMmqTkRB5XJSm+9Ae8I4xIIchTk2V397ZfA8S2QqQauNQFSL76gVUpDVGOgEikWsdUwVCIEEaOQ7UYfVufoh72MmS0Vtd32JSgredUMzqT2IvsGkd5ATnfVkzfTuEsqIv/5onfE9nBQBbvAfXCcsCxfyZLdrgejN80j7/hKrq1/rQivCuHSRBEpRsEhqtQXkY1wTW5mIXRcMJ0prwRoJIzsJ6IVCa0z48M7ogCKuepq5PtINRg36CEBaoj5iWHWs9S2hKkrJEmKm/VxVMI8gUQWqi5zKOHrRF1DAx/yTeTcIbB3/PoApd2Y4Z0ZXNU1MmCx53WAUdvTsdsDcs5SSLeTGtVamCO2WRiTIBbPefoFK02ntnnxRty+I7HxadVqSBx5Qe7OaYWpbMOpQRQgoEzwcvoze8I7a+wyJmfzT/Ypydzk43OXpcvjVNCvYpralvV9N4gYwVXlQk5w/q5X+PpBap5uq8Q4K2iMaCfMbnSssPsYSSAsQgVOHWnVPcl+gSifDEU460uIoCAszGSAAAkN/rgKgVOfkl3cmGMaRRHTg+OeahvKcQDh6LH//V2/GA1K9R3rr9aXjwl1yKNhxdKP+dDUd+6NcrcRNri9+1x2iw7kIo7lXyQGvsAYsFS7xzNCs/sJ+YFp2WA0cogc9aWWiBLXFgqB3Rn/UMtCUdCNnKRJyxSCPThPQN0v19yff2QPXFPTCfbgXcf6BWg5Ui04TrU4sNNyuU5ggxVmAyQKGvOz22bE2QpN3pn11ZRt/VKSlQc5jyN1O84VSLAy42yOqurjhcVz6fBQguV44FkXQqSkvsh01vTvhEtG2K56i3L34lkT8asWktLTEntCqTNSz/KWsrQG0w2skVtbxnu0t5GCVfzvNs9GfcGfOfiGHtfN4GG6EqWsLEImPqO2eLGMxWn1+KKCBjbe+7PAIWMGUuXMwVZUgNIpBbQTDK2X1tpJXfsukjffTPhLANovHPcMKhNKXEQr1VIuoKSpuPhSM0flSK00KvNxLAgYFtJuyWYgTlSK6N182E0eHMifOzzy1LGBh7Skc+FlvLP0xy67ATZKIQy7+w4toJSOxdpV9aBnY0OdtVcPtLz6OFWa1ciKZupUU3f0J+FftQW1xYWsUNE8imGUaGdOjRMM3heqz8S/gKj7pgQ+g0UGUAwgcYaAmQq2ZSeY9gMuo++0xmjgAWENsuuOy5FoQ8e3s5NRgpURZNlXrhgQHgdS2ZzTn5qNdYutvM8zhyvtqHL0PjtjVLHYPcoeS8xOVPUjJVgS0CAA0GS0EndUOPzGX7cga1tKFKP7px/txZm7PbsQsI0e8oF6mJ0er02L29oKirMtRU0sd8E/sBZIzjX+xXumcvduMNQYXHIO6p5QBhmBVA44W6ajlEXJLy61aT9PeOA/Z+kQ09acYeHD2zbbgPS+Hq7satO8wdKAVlN/pM5vETiZHPIFenL+NonMf9TRF55qRZlX02rGEE+nFMpx1sawrcrIMLhnvrOnMp7rIHcxAYQuz9Klso9GSc3cX+Aa8nulweVsLvDxAg8jvQo4j/fyYaBMi9A/4FQdmVS+Gstzcho4y2yQp5GC+Up6uuPKFsGWASIIaQT4Z4wGskkRFo2PFHqgxpE3bW8HeaHQ/CZbGjI+GJmG4BtUr0DVyDaSPuVIeUsn11Sw5UpWQaFgN4JNUG7cS9JTlNKwZgfZQkzi2GOcJYYYky2QSBivc/cjGSzVEgH9Kjma7qYRC7Jwqyrzqs9ZG6aMaYWjv+IhJfFv6fIFXGdbhFJCOstWk0x5scLlgMYZuKkNWyEOWkmmXWgrpnVddD/S+gLqevnePr0opIoZgkIZ1l6jo1Xa1jpzb37diRZ7MLeCDgPRxdUL5hI0WqXm+/0GxyE6P7zI7YBQsb4br1Tr+bljhgphJ1ng1jcf1gDjyWH1LhTX7rnv9MezRB9qzl4K5+lLz6kuNtNceWeGDqetECj5RLdiBcJ5wHm9C9oWZm2Ug6XTJ72wUHvPu/kUD1zz/HyfGNHu8rYB4z89OaySHXxKtSI67rjYWY0bCoG0+SGvo8okwLxcAA/tuIWYUenzaQUKiI1cD9ZMu+qYAxLXWAgBT3cJ45j9I/ug3DkJGcwZDqULXUYaz3yQ1auy1RDrc2JZahw2t/r6Sb/JvqoHiFAbiKpfipcolXHLLa4SIpReZpRu3JxkTgy4gPBT4e/cAboxGu0SDZMI7DDrdnV00ataHaCUjeaQPJZeAglTSy7SDrGAJGl/sy8sIgMitdLMq/RGEQUc6D8rRqaroQpXv6BSkKod9FYeGmWdLgXhZcn88hbPuiFo6oKSuZ211PoOWE0UXjhBx+zI0F0PozKaUi32j1SLU0QvngEL9BV1l7IBCWQlAWaRMy8jUevTA7A1iDdeA/QZybnerY1WpPhN807VwQ615HX6Td5ZRh9/nZ2nsn32EsZ/fcI+wVSUZWcebcfOmnrzHq85kcBpuxFJBo58PCAiWiEKV4XrRoR5lwVJHDoCVZVr3as0nzZGE641W3HZTe6PVZgq7PCNgvfRD/K2OsK/Gsvwq9HSs4TTDilx5G/ZJ3a04oF1CJ5+IWfvlMy08r48ePi9vk8ryyYhUUw4SBMGgja5j4yPZKLPXbaB217bcdw2zz+/X3YprsLt5dxj26Z2SahaNIO5V7fZaqWccqJq1bxCXhuZ1yVThrOQS7fkybLBmQL9GM5UoUALBZ3LmFBfetluxpkSFviJiLrc2Fz3LlYPVKbpjzWRpDj9mRRl8Pd1XTevV91sHcCJYNhCdDmHFZUCjpCGYsvVWED0W4EaleuXL4KYr4kBQcrka5rVd8Visbr1Eufg85FKDF5aBrBb52IpZnyKllhXJvTpN0LYEBUgQWxvF/bw6uB+ugAuC/WgOF1Q5OUU1uQt9zGjPMay+1zWX60Dilo9yOKyW0MVa1RlpORTvZq4XV36sXFAqPRyEc06ZwVgHatIzoDdUDILclSRYn74498mdlfY53elS1n9ur+F6" + "Gwm2da0o2OZa57x2g2TWdh+2Ep2r+3XCOgMkxCi7X81JB1zU62gNYq7OCvjrsR5GoPWq+XA4p3q9pvhzYwqh2Hbrr2cQsSi4LIbtwCKrU2Q8iFjgfQXUDjXDV+a9AsLxmm7wPR40y5M7S25uln4gpc1obujbrMXq4l71jGUBdp9b9qCaotatzUqxuOxM/ULeuSNpgZ4s16nDDJuV2Gor6qs3ulVaRccJ8ETVoXRuNcJJ31pwvXyqsx3zRLP6OU1PstAgvcY7H0QClVYv/fNaT1j2rAi1QHCB6pc+mLd6pUBp4b6g9TlmjGWGgKfFP4Ge/ND5+Y3HTxsD4/SI3WPSkIfsl3cvfQZ5EKT3B2dkWCv4czMmmI8fF9ALjJ8YYLVXta46Feb1teWaIgda0WRhP59IgdllX8NIJNMaBHyq5LYSKtdjIDxal2ND4sZzuzVGX/FibBfk7Yc7L9cpeaKGfYNQn3bQr3pPDdVMADYqsHCJdprgR7poj8aUAkVi1Jb/yFAbquVNpm5mwHXCCjdxSyLJbGnQy0+r2EP4xi3nfO0OtmD/6i9AP/NTLHfUXsl5YBxZ+sH9/S3+RvYsU4l9Fr2JckVFeYvzmFaWqV0B/ar4uFZIQg8kEoLQc1QXimpzlP4UE6iL5vVCyclAp+q1fBrFSmmdRShlK6h0F6HVD8tP359bu5Unx/IeFPrIFM66Vmv7BnNUXQNhdR6sNrFfB85K1aPJLU6cQn3ts78IwIb7KRMDSLerV+osV66n+FZVGpN+8bNWZEhKjzs3JBeJVbrHch0T/dCO77R2YE4SkexmcUlQKchzXqqrM7VUrTgUVp4dqGUkbB1aINDTnTjzlZcEeFpTCOKBWYz0S0HmbFLLn4oheBaDBIlIfstaleS3AkmLwjcxv4J/sLnq9I58On7PPNY51V1UVcbOFx9fuIz5nIK7LogxUvzEk2FelgMMIh5H9zN4GbDmfpu6UR4+skApx6dGjym2JRbp/mzdMQwfX4+oVRG2WxxCmOI8ev2Cq9x5R2uBTK6xh/nmHVj+3eCJSa4QxjJmRHItCpSxIskWAI6vROL29FANYk8TyPcc1/YOwGxy/xmqg4/oELUa3JzE1gWT1+vKCpUq75ckEjTQFrnT82zDiU946QPXvnqy6nvr9A+lXh3D9WxarsJMa6hcVb/+zSsaPeUNwMpKmTJtqr65RLNmSxbXk28VIX9kkBONiLq/WTor0ijD0PZmQbBmMcJNortqEZTnfXO8yyWouXO3fsC6uSrUi5KMIdVHn3aPlZT4GXYtsNRPIuQixFK6VC0TpzHYWYMvdtHtxU1b1NyO8C8DsezNrEntpTOAhqAHcGZrVapzmgoLRRXbzGZhiZ8j8Opls+Ut8FGg9hJwnmkAgfwnQhnCEinAzvPVruoDNpf3E1A5JytPd8PKliKMxPGc0dht+7ZGz8V9z2Ele9VMCpJMM8J9v9ige0SyV55Tv7BuxQZvluTblNcMcPxgJH92IH2Gs7Yj9KAJE2649p2o4TqRobt//X2Z3mnx+ocPKu3vFwka8nydd7mhscu9dvQx3Xc8MtBrurZ3Htxldd6CWbf1ZKWfL5jlq6SpeNWOU6qPRpZlq1EABtpF8ObVoa022ATdQX0vNFjVvaheDwDTwbK0zK7EIMia8me7m4YZj1UESIeG7sHxw2Xptyg98xRIj6riWePKZ727qZeSNs9W2GgV3cmX5Y98ro8VGPxuQP4n9QzPAlFTCLt11loGvnQzqGRWsx1Xvf5ImUa/urRGQUKbEWhR3rkHFDmzYeYp1c46DH6aLMX74CqQF7RonYKkEg47MqzjAmNr3Oz5f2RBsQJsbyREq02vawuAhJrT6yPBIE7vHEZl7UhWb0wddjpUxf62SVJESIo5RwvE80Ah5aQJO+wkFSGtfiktv6S3EVaqUJVdgTA5nwIoGur1g4B7UcnpNWpIF8vQvpFcKf9cXmZz9KB+vXgg+EaBzMfGp2hwnGgJ4r0GYdZZ/Fh0swVlr0xb61JUIQxYWhlR+VHiU+WaaukgB/aLodh+77PnbNU117Y+mW7ItAs5CGbTDCCxXIJbjpHixKp/ZbKOdjbVqgKyypwBFxCbkPUSNbjIgViKUqvAolSMQ8uhKQk/0KI2eZum/QTpxYeMI8cBPIwNj/4dSO0p1vE8z6NQKLFEOZKFBSNjBCiGCrUgE9qu8fgsVvyhClM+tYAHjo2pfZFVLGi4K3M6BFxDOr/ZfShmdlZ9ompVXqwhCp08n7qqLitOONTEsbU7E+2VQn202cy++NrXw9feTzAEEQFxHlX0KClVegcVsMrogQIk1699BK1bKcbC4+4457aiK2qFVvK34QLLQkmlebYAVYxRTaEIyDcwyPvbbgB3U9bGaArbO5d4FR4EiusZi10l8usjJQ6xl/ySpqgYiuyJDBVu6VW9nsm9bcn6y85QLmyUYPib9Vi1GlD4ODH2+c41J1xEbKLfAYkb6hzY7XF2LVXVFgvK86PSD5i/xojVfd13ygIih5MTA5I5nMHblL1pmfOBq4DoptqMKKXXeHBTC2HcOGXTwYRzi2r/mOJfpJrUXHyFOz3uE0OMe4XEp2kBVceqw+DkXfZRgweSZLXWq1MfEiJ6s4TL8WkGOQtcj6C0siztH5W1GF3Fet0QSJ07nd6Rrv8GlAi/gOSqmimsFDeMXYqS0plFgipML8EpRuSPMFYF7NNoAcgxeAbrHhSgbiGp8z3+SV9og+tHM+YhUkNBre46haaSwqrJDeWuthxWjiWFK0EUOoaToxhb7pVywJIDMcdoZOjasMIfLmAvEcyHg7FFBjfnSq+/v+7OfHuki4VrM6MlNldGfsWh0EIzpP31K+U7awkDHwpwcmtBfss4mgVs1Y1C2bB8GEI/pTeGJEP8f/hA0etxnDifC7i0IZrQC9YCQcm2w1nU26tTcLvTTgocggjddnpb3VEsaEZDJzbmzUJLT9/bHdNE+EEQYZajsjd/rwtxHsBYveU45Toj9YYJEIUNGqrInsxOSRhvI5cZ6OsAI9vfeMdR8MqaAoITLX/4DOSa/hy/AvfdH3/NzQjJr2ZfVi4bd5WTP3WXJWNJ45HKHjDxfjiUUH8iRS7U4rBOSlxD1/kOWwEhosBHBjKdurFG4aC5mB/acKJSJ9ZCC3C8qECoRUyl9iQvjk3KnJq3AiOvxKOEfhdMZH46YcEVGMwsQAWNNJf2fkRRVOJ2zVGJz2GjabU75oUPuspU4IMQHe9vA0AoV8PBKPwqpJvE4u+6tU+Tpu9+Gx4atWl6nXZO9wNXrludwut1Q5m7Vl0M9GLjhwoPptcTogCZZSrss9MlbGLOSrckJ9a1p3MQYX3tIWBt607doQRBn1jbxOo140TbYZHTRRU+f039NVkH4r1K3Q8x56JQeKglXdOGlbsaNUCSXes4LiSLtoOYTQWghuMKCuG2l95P3N7R2/XBRcPSAaUfqJx1VHs/U7toYq5i49lBR7lq2r7d4Q0igThwq9JFG7vTCvQWgeqkrC9zqjcZ9TFfjANfBrs2VrEv8IVf+Se+yu4Iq/DgrDlS/uLjTD1Y74CgVoKBAcaRNYhFkLxe5ZWI4sc7siWISSPG/fMd8bZybRkGOd68yELw6c16juCnE8j3Qr/IcuNPwKp7yhnxaCGVoT0mVvoBoBK4d2Usct52PhjSKuRhdO11scPXpkRSH1wJVt3rjGHVy5SiBqj/qq/ZR5tw9XhNPfiTjYgPDiPDdPVEuUCkv+edg2+5E3vcJ74Y60jRpgHR/BEobs3K/MrZ5vrdNP+ykkcvnd6uAL6b+WjrWZuxe5rbGt5w7fSbyxEyFf5FLfLT6k4/XGldLW202ssD2mL3r0YW6E86IofwVHSAU2vd6Xuo++Nw3gonQK6ZzZWlj7AxvbiKwGHxuWsAQ+0vODALsqi1j7vhf6y2tRRDVY9vZVTll+V3fZJ5OXEuy4usF+htHTklIgMdF2TktMlkf9tGInHmF2vcjcDFHbhx9V7etfxqdvzddcDLt0i28ng/EqY5mlGLFjXWIGNdPgg3osZQMn8CvLmGGo1UxkUZLevqlT7n9e5FyqTDHXPmSz" + "AaKc1g4T42sOOd3YH3delsQMXrESVbj9UbcG3BdxvaPvOkQMSHP3ZvugMqZfawXMQ+M4Kwc7VjrpBOB7FtdTsPUibHtRXLqHiiESJq9GLun24JJ+JAsJdY3XicfuZzlZwfgza9PZdxgbaAcpUfdC0/hTRfFiZUn+rDhBtwqOi+0yl8ZOjYYuc9xN7ndi60ur8nWzWFaPU5e4DB5rferaqIntYyVnhauaWrbogsexNyvFiZOrfWnMLcVeco1sVKxaYzhVZ4WIIkl+/P8W7WIr1eJO/yvLoutqomP+gx5reZnRSC9trQNJNRTLaodfo8VmlGpxiV26I3/qJVp4Dmy72idalQ62Z8bi8vqEp8Y5TIlgBV91cF81N6dJQzPYjuiWue/a6bWm2l+/UFNHBIKXXdUudU1pZMzr3CGVD5yYHQKZdlVL/6to0RVASoCOfF6jqi1Gf80mujiBFU4ZU2nkBZGwBEenqaZTnoFpxrf/UTgn3SuDq2Tvvhw1wuW5t9E+fi5C6ub2Z6xnpnzmmt1398ZbJTZ9GQxk+vrVBIpfP9s2vUo8gEpIfw65pNRkV0bZf9EKIHBPFti+y/S01M18abEWmjfpXrNeqIcLd1jPUjVzsiX24YiWA7na99jh1SnfcGeRc1WUbbVN+LvlHz9PQK3Bvxs/hUTEYPhqaO7vo5aufhyflyXDYrzRRTau5KO3sohx9Cuz/cDOguDv/eMjp5i3G73D3ORdmL/gWcf1EWS7VHtFj+6fXBJmZI7AZrbPgtOHb+KaGz42lfu9x2GR3Jz5Tk3XN0DaRvsNkvgZEYlnnjJfZzuzgsbeBoo9RO1vRLFTPgd9YjwWtPHpa9eF25BdrXWIDUQDYFsywfAYTWZ1Pat4uqeUVFO9S/erD95lKErMKetJWltxAhg6fBSbZ55XMwiXWFSsAXvAX3TNaQ9Fi5Q8uhNL9BBXOnP5Yp/PeoZyGBcMs5fNbAK7VukPtkgezo6hslYdtTo0vyVjyc8YgmwuRURx9cA/d0WUTAq3278OKMYWGaqpBU8pp5uvjEtsb8I3EcWNW5gO+SbdJ0k/xNCIKoU3oODFeYTmmMKP7hdFEukYdDzXWm0MOBFIJDwPZIbYshhL0fjqsxvC/guW6jWJFIBQHSi1Tcct8BwDQ3hzL/RxH26ao7QKGj5Rc1t/vSkAo+HZ1WKwyuYe7kq1Gvwaqc/7BGGPaKMZiyB7l2aOmRwdyaPSWi9wKT/62hR8z6rlYC52tcMGsw+ib1g5iC+zd/D8zHDqfhBHhkMLu62mdzBfxuXwZIg84EQeGm2E0fuaxB01zJIxGIOVIJ7DUGhb4GIGH2YF9XklcBzyoym+1uXDct1Kw/jyBipgeB6QCpVqvcIulmcuQKzgREMCL56so9oB1NHDGuWXMJoBRgAfZX3RhUtGH9VkWla2brnS0eStzgNAkYnHOd9Ka0K+/PFBOlZaZIt42pxecCbWPIwq6vtPnoXmJDJqB5m3pfcjD9rl61i4F1UY3WiIuAx/6hxHSnLKPyEPUR/tBoAembEfTCr9Pg9eOaDruqjKHZHtUu1fPKf7mldQ/9VHmMmtUA58Q+2HUChNnr3DtV/sMGWdkFuuDWbV516W1riPUJXrqVGxr5CZhcgPsEObkO/8+9G+/gSM8tNL16F3k7LNXAvsX8c6xdDxKY5vgME2YVa+4/zPxDB5wMOLIiUDVV4RmQvuuQ6AT1tUunDT0hWHEi4xdN+WUvXLn4RWO1zoet/3F3f9xr98+nA7OtwIB2dASl4//I+AAF3hmjouKF7tXW+oMrO1dZwMZwG7Z/5NwVA6cu6OSBjtaHknD4/8PhoK0JAl2F3S5u5cLXWpspujKWapyGOT5MMOEbNy7n+4MYDkgPl258lpPKYcCODws9vtwdlKTdN25XI+5mMFcHt5zvZoPuGdf63Gfn/b1RAHUIFQ/+Otz6/9P/A5F0Dji80eD3wR0ZLEcwmUeqA3G5bpkvLq5wzPg7gNyx/wz1FqbfdfOi5Pvy7+L/wF8BivT83/bD4Q8DeDJkyAjd41FDzxU5A2RFjKQ4ZW8ZsIydLgzqaTtbfP9zS2dylsUkkR9q7bja//G5yEBj8mcHwHGKQFhBTYtukLsSofV1jKe3wxGMMObKcprbNp8C+4gLg2OCyX+ApMwHPIu9Bvx2+VAhqWIa2+vudwm64QukAoAIOX79ByFIbpD51vBvau1+9AIJAcLirs05NzIg/9cJjwnfBnEiH0do2r+6Ad6au96uugMDweUZA5ue5SBXfhydDoyez3HHC+VsCCZRGfB3meffN4jMwuQEJDfInfNvR9ggELu5JeH2UOCBGdwKPqgDfthjyBcgnBP+yRDL4v87T/1eWK9xooVaO/8XrIfRTwIoh8dEoDAmOkq4qOsAkOULNPTN5v82drJDu7E3AEL3tAg+iQ3KvIBXpfxdsQzyyyBOyRiIk74aPoYLPp2gOfcD4dnTHDBMQNahvA8hHL7GpnpArFjOysBXaAtK5Ngn9ipOBFhkzQ1a2Udg/Idrza0exjxjwkAs77AMG/RyWsCD+yGcC36n/AO5vqfvw3PxDWGihTXCgL4EHgvHPO5aUCWDuZT1sfLlzVWIyxwNEYs4gHIXhZ/CLy1JOM4g5nMlUhGLx0yCJuGWsW0KdeKmb9yXVRA6+Z5wzIFZdjlio+D/QbJiK9+s/bYhY7r3+/0gL/45oQIY84a/vT+wPH14HoFNsjrc4o7ePPjsUERv4JjIaefyocFPGYpEINCdCA+V1wUdpVnLOSkQ4uaXAsOgAVvvfXWPHTioAVxJ9n32geNESscmYkLEZR7HNm6VuFaBgeY86WnTm7ib4x/c0Opw5NipATm4ALeylzr5yJ0QxBQ41C2IxO3n1mFpBnocIL8Z/ENEqmNfSzsWI7Pt4TBtIabBBx8idEv3PfChGQjkyIt5aTTjiM7hh/sZvlucj8Qtjo4PN2yktqPyPT+4UnhxfEv48VDRDAcNLH6zu0ks5yks4MLRVLVNylxFLnHfFxu5d6K3X8i7WK7jsHNkH/sjc3occCMYKBE5iuXv/vHT56/HZx/5nL9UxVEBD5izG+cajgSdn02BRivCDMyC+SXtU4bnBm8oCN7yw933EUKbhd8d3zZ+k02+D55R2bQzQAJ2Fq4LE5ytAPLFjj39gZw8h1rOSuUnT+AjFYih86uB9cEeZ2EXApU7gDKQEPff47qiIyA2HEH+NkjcdT9juLJy9QWlR4SADkeXAlDKPGK2g7Myh2++XluMsvzXNjU178nkifB45BxZcF8noFn8LXamb23LtEJadsx2Uj1/1gqnnbkneKKnzyGbUESVXVbVKt8vgXwGbMgEQ5F/IXF44peVMdsGgpNjL93IzXUNYGdUYTLRN+iOHy0hyXLywN8XIU+ODrARgGccBBr2p9q2PSin+GHcn8nflWuqjnKx4MuvJemICHY8nKX5DsK74uBWOGBPDDj5cd1w2PhO8yfHZe4NGVzfHRp2fDdktAnvXj39HByhu4IEyGm3n2Uq5F8G2jwuSiArh9MCUQY8GDixpfmTPbBhnRmsG37v8I9akoMwuAKEm+siro7u/SwbbcLhHNv4emNzxxaQgwenCEBXd4CqMJWeW7YKNLDz+nCAG2xu+ZvS9qPdxGYYUCN/8OdNu0zmZAYfFoiw8emfdGIWR+Athd7h1AlV4fOnDWU3f+cJDHTDkIg//oTZONRJMfHACQPfH7oM2/PmK1EBmUFi6oOvPxCk28IF2NAKNUJI1NdtAIT0s0XDKr84DBvwFRcIK5AdhlrGpMPu7HgF6Agaqv9TtQ5UD0AY459PrWu4yEQyQZ2lZU0Ht6psC1rMwPfhhPYFf06YP+4vxieYPxdmkQvBvm8wae8449hoAH9dx/69/DvgdjgBzpEaKaPU3n4MAz9zKzNwVQ0I9wRUOaMcRMBc2Kjys97l89g9F6pfjrQE2kPBrhxlLG7BQPPTNkBPVN75WHEk72W7T+wEiHoooyGAsGaWQgUtEsEPlIMef4Gd//L2sMrY2OesBxKBcwEBu21hwGcBXXS3kyhhWi6/hXHj68jPfKEj4wsz+pmGFgjs8/tG" + "YN6fgK9G26DqjoF4+gmYZbcShByCVm/XghWpKQOoCaTAFDArGgLOQmD1bW2LcdLWhJwDN8cQSAXqbeyKCRwpvmYD1htlbD+a/3aByRGBcI3kX9ctidcwI2lI3/vvoT1rKI34ZE6pFqC+ilofVgpZC8MMbVt+2vz7sZZoQ4wX8pZR34jBXZoVDBA4qnNwI4gx764JW2/AGgFzpbQERgfmNxcmfL9zExliZFIuKDixwDDrFDR8RPd+d6HU2Fe5ol6FcEKCUhPd7vC3h4H+Tt8ynU2+f+FIgozHN7PhHO0jNCr4M/xB+frxCWvyqiuCxm5qkPRIIhvOJ1oHvvDcQ1Pno1phTgcwB+e/PG6IRne6dQP5NYCl8eV2tD84yxx7QbAeuMll7eiwnUtpn2GEZli/oUyDecC58RPxl9NaRRrv/OFHRos7URYgfEhsh5MnYj3/be4DsQDDEo3/f3xx8vb8PPr3GcgF/mH8HSFDoZ+wY6mHoEcoEMc5kWML/8P8CD33aeH4ilXcII5raCU6LhCAvMgfMG7eG+YMQS3k/YTqf+wDgRvEJwsjNr5InJ3/+Zf/F6GA5HaCayn41PC1/5efxKhbJLgDQo2Z6r9T/xey1XECR1EFVdOFPwRplRM0f6eC3coEVhRnC6cNmw5oSoPNgBFJxlfAc0H5z+cSP7Zw/cXnHxcCjtDYGf+LgQRuzR7QwWWgLvkIkIRAb8U/GxV8PX+bnxSmHJiCFrT8+pG5HYSxLI7x3Nn++y6b7Y9kxPmCL8z+8jDf4QDcdnzjwqiab4+2e2zfDwRHrsz/bfAP64TOkRC15/6aaFAQSJDl4C3Hbdr3BDkjblNmjicdxE35c5ga4VgMvEu+ePsRcDXEjSE6nq3d8/NJuP5DdsGNhObO+SkdV5fPZ4NuCnT878vr/+HCIB9vyzSOXfLk+W7ihXOfAX/l8ywx5QCYsuwgO+DV1JBvoKTDtw8qDa3up1U2C587ZLSlXEF/HxCwfAzdEKQy2gl8Bnzcfn4s54y5Dw9hi5JhmYLGcOKb8NdoUL9r8MjBecn2DKJT79umle8AFvVlmwrhncFRFzX5zz84zwvq7mhXKr8aQPDOQ0RK5buMyQYQJj8fn4tyQKogI1+w6sBJou0dgep7f+Dz1lBoovWCICydCwQxX44wE4+K08Q5tXg+/NY3CR3DoH1HCBt4MJwhwV/l8fOhWYBjQCEK/Xo+f3PfOz5lkBvkTIjHD/Isx2P8HQBh9jOuOO5ACg84bMxzZrj1QVVdMrRV4bW1/z2sp5FJGsS2+Vb1c0UJlMW6KwKwGfDNgQQsaKz5f3Pw1zPL56Gj2Jh7AII55n2AkNRCfIXqAu0k+fs6oHhCuyFZANye14FpGWYoXINNVGRtfx6Q/CY6Rr6lWzuA9g/IMJJGL5MxlJj5u+8Y59cty8hh7LszKD4wLJ0TxUZO51XhXZG4BkEo/7xTVBhwzZoDiWq/e3BYoeiGCUWbNiwMqJBwe8u5mcPwlEeD8TvfLgR1PGS8m7HtCvYcBVXFzw/h/McRDkL5GWAfzm041ahyEUM6yppKRX8fPJ0L0GKwoIfjyb9jW2LDe3zDczl672eHcMIfeW7swZztBhvU/oBIdZBj+lySDhYSCOalFWzjMX30Q9mUMD3qMGPBR+QOrqIX7TurFPnh/DdQ3HdM5M5RrQVpD9cWqDh8PLnLKMVQPB/F2vNWYIDBiQnRluNSz+e3T9w6MI9xB8vPC9/kKUjop21C+q8mt4LwM7d9BMcsySqId4ivewmCMRb+kNMWRpXcycEXOeN9pN2roQ2vSLD9iSi4jm27rmNKQ+fmAg6GJnTSng/u84sWBP1XA7yFr5TmMT6o6M9x4Lcmjt6cCa1u5OWxD+dPVELDDAziRPbl/8e9TkCtNswvM/L2+C4hOBkYV6EbxsDj/PnCUrljr32UmfYrarjAgIKi12i/v3ZLHzdUcfu/kYuu9T+MOQCohGgmMrmeUw4iDW0pN21ACECGDQTuifYcg0kJOeilCnY3u/fM92uBwpzhysbpak8i92Pjrw7GwK7dN+9pRz1YMeCxYGg7zo9NWzMSqqBoNhBSJBVuL6n9DBegSPsv1+MJjRU0QN3tvCKuLoA7gZUnJz5YAZz4wCUD9qHcsfPHyJJKuXXerIyxuW14nwRLOBB0B/CmKBzkm/HP43+JagdHCMR+La/23ZkowOA2NXboSSgWOC7zT27AXPDvQltV9xyVaz/A0Pjv8X/mLhmzCMw8hzutczua8H8fe89v/ivcsvgnY7HO3xJFG34H9Pf42TesihY8q/bdTvAm53iMKe6g8v0QOKzhFXK6BAulE6ISNjzcPTV8ehzE8/wmABWcnvgjzX2cduGF2LmldvmvUvvJ93wTj886nsv4zTJQA+B7SNjMdZiH3i+0sOLZNuUVsa9KrMDoo6H2x2R3/lSJexa2VxRoqvWVoi2tcMbjyNXSPmnYPRFKIOgASSLlKh85mV9w2gPq/F2NlvaArpxlinleC/QviKVAEDRrcM+HAguGHjZNO6cTyAtcEPB/4+NW9K9CyRDyD4DdT0gb/LxU+g9fPm8ZUrT5p/xGlQG7EP6qEz/0xKGyR1ADuGdgjeztxih776BhUI9IfSpcfskdpQJWg9t8Vj4TlBQwM+G6EOGzt/3UOT5gqoyWBpNzezQbHNyQxgdqOFonMQO4TntFCyz8fgx8k1AK8F1YuI0uDOn3Fpk41HR83sd6ojbSK+wbuW7K2fxT1DMLK1Wc+p3+9tZsG94vbMcAej89CPY4aQ+6CBWQrW52b8bfEwUm4EbnjGCwBdvHzcKu++cAigwUFLpqFG56fsvWVQMkKZEURxvsMJE8MSjBtP3f4/PI3xE4L/TMafx8Cvi1cdrBZilDVCPjG3Ii4KyHXQ7/7yb5Gv0bJEEQ5kEv1SuBQiRjoN7gTox/jvgKTA8UZJrNhyiV+MNwMIJb7+zaAuKf74KXfuLN3Fbf/E1A8Rpp7QoIAbHvtQeH+jZ/r/mWG8F/n6fzOn8IDQCcP7QIY+3aDVzDXYjzN8bryucpoxbdOQhLqTJukd+wnQNYp+xD/vsJsU1DyoSCO1jJ50nxoyw712IKcd7M1uyu3MjtYSoWk3ztOYRj3IJEPja8b5eEDTIRfG4wSV/n2fMhLRtCxOGkLTRshJ0yF2ALDmpYNN5iu2JTjcE+V/fSPaHE4RqCjwQ8frFw5wcJBgNqwYLVNr86vMyFaV/f2xc8ck1EqJ2BYyEAo/s+EOcALlRjnMk4ZgNdKSeKu1C+NduNec9fXU1UNiyhF9i/czI83xocPgx3JyaBdNt4jv78mrfvJOgrG7aBjgTxpAFam4eURBWT/oV0Uzfxekrz1sYeUPG9AXf2plZcGn52GdVF3v3LlGgOA562hcs4J7TT8E84ss0dsDDwyE2DHqAVC0MjjkB1RzF+PJjIY1NKXXN5Bg91G0pVrEkkwOf/Np4cBxFbCiDf/z1TJ6wUAdDdI4oMiDJCBb8WlGr4awMwOOhkzD316E0bRUJlg+kPbdrod1TRI4ytiN5RuUn/gSsB9jf+Rz5F+DZ+bKgrsTA6VxTnZEMPF8YUmLDhoSREdA4LoKjWXLXIHCiJ+cHBiKHveDJBqt3DTHzin/4fky/alqJ7ZbxP4X4JCLAoa9Hh7/pvPy5YDmK3ygUpfqUUahirQNoKaq9zZ+VDMdlCeHnAnXtWOjUCOsdadtCFC49+kgFwPioKUJkQAro5sQCN9O1YNHFM7/lHdbZXRvjsY9bbOE0Ew03Owg2ncQM2QBQo9BDudrrFeq9i3wvqJxqLc2FBtVvbQBVQiPMXB1qugaqcY8p+rpjoYnYIQNCk2xtw7ObTOoDuQQjpeEhrb3Ax3amc1qShAUyceyF4zfNhP9OkhAUlgGkc1TpC8gmOEI3GYZtH/1LaUbSo21wub93j/f337/eyqbRVeo3E5n5LnL84Q3BG49YViCz0fPl/NTe/8g=="; return decodeModel(model); } svm_model* load36() { const std::string model = std::string("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") + "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"; return decodeModel(model); } svm_model* load57() { const std::string model = std::string("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") + "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"; return decodeModel(model); } }; // feature intensities are scaled by this array const double featureScale[] = { 1, 1, 1, 1, 1, 0.319228, 1, 1, 1, 0.239435, 0.791047, 0.065805, 1, 1, 1, 1, 0.598952, 1, 1, 0.8092, 0.844833, 1, 1, 0.551145, 1, 1, 0.457528, 0.596043, 0.951887, 1, 1, 0.271639, 0.596043, 1, 1, 1, 1, 0.08595, 0.623073, 0.622132, 0.864682, 1, 0.868717, 0.542905, 1 }; inline double featureTolerance(int index, int charge, int electronDelta) { return (index > 17 ? 0.5 : 1.0) * charge / (charge - electronDelta); } void etdPredictCharge(double precursorMZ, const set& activationTypes, const vector& mzIntensityPairs, vector& predictedChargeStates, double minProbability = 0.98) { static double averageNeutralLoss = Formula("H2O1 N1H3").monoisotopicMass() / 2; typedef map > FeatureToleranceAndIndexByMZ; FeatureToleranceAndIndexByMZ featureToleranceAndIndexByMZ; int featureIndex = -1; // first feature is intensity of precursor m/z featureToleranceAndIndexByMZ[precursorMZ] = make_pair(1, ++featureIndex); // add 18 charge-reduced precursor features for (int charge=2; charge <= 7; ++charge) { double neutralMass = Ion::neutralMass(precursorMZ, charge); for (int electronDelta=1; electronDelta < charge; ++electronDelta) { // rounded such that 2+* == 4++** double mz = round(Ion::mz(neutralMass, charge, electronDelta) * 1e6) / 1e6; double tolerance = featureTolerance(featureIndex, charge, electronDelta); if (featureToleranceAndIndexByMZ.count(mz) == 0) featureToleranceAndIndexByMZ[mz] = make_pair(tolerance, ++featureIndex); } } // add 27 neutral loss features for (int charge=2; charge <= 7; ++charge) { double neutralMass = Ion::neutralMass(precursorMZ, charge); for (int electronDelta=0; electronDelta < charge; ++electronDelta) { double mz = round(Ion::mz(neutralMass - averageNeutralLoss, charge, electronDelta) * 1e6) / 1e6; double tolerance = featureTolerance(featureIndex, charge, electronDelta); if (featureToleranceAndIndexByMZ.count(mz) == 0) featureToleranceAndIndexByMZ[mz] = make_pair(tolerance, ++featureIndex); } } // extract features vector featureIntensities(featureToleranceAndIndexByMZ.size(), 0); double basePeakIntensity = 0; FeatureToleranceAndIndexByMZ::const_iterator featureItr = featureToleranceAndIndexByMZ.begin(); // featureItr->first is featureMZ // featureItr->second.first is featureTolerance // featureItr->second.second is featureIndex BOOST_FOREACH(const MZIntensityPair& mzIntensityPair, mzIntensityPairs) { basePeakIntensity = max(mzIntensityPair.intensity, basePeakIntensity); // skip to the next data point if there are no more features or the current feature is not within tolerance if (featureItr == featureToleranceAndIndexByMZ.end() || mzIntensityPair.mz + featureItr->second.first < featureItr->first) continue; while (featureItr != featureToleranceAndIndexByMZ.end() && mzIntensityPair.mz - featureItr->second.first > featureItr->first) ++featureItr; if (featureItr == featureToleranceAndIndexByMZ.end() || mzIntensityPair.mz + featureItr->second.first < featureItr->first) continue; // set the feature intensity for this feature featureIntensities[featureItr->second.second] = max(mzIntensityPair.intensity, featureIntensities[featureItr->second.second]); } // assert that the featureScale array is the correct size BOOST_ASSERT(featureIntensities.size() == (sizeof(featureScale) / sizeof(double))); ETD_SVM::lease svm; // scale features first by the base peak and then by SVM scale while also creating svm_nodes vector nodes(featureIntensities.size() + 1); for (size_t i=0; i < featureIntensities.size(); ++i) { featureIntensities[i] = (featureIntensities[i] / basePeakIntensity) / featureScale[i]; nodes[i].index = i + 1; // svm_node index is 1-based nodes[i].value = featureIntensities[i]; } nodes.back().index = -1; int nr_class = svm->m2()->nr_class; BOOST_ASSERT(nr_class == 2 && nr_class == svm->m3()->nr_class && nr_class == svm->m4()->nr_class && nr_class == svm->m5()->nr_class && nr_class == svm->m6()->nr_class && nr_class == svm->m7()->nr_class && nr_class == svm->m24()->nr_class && nr_class == svm->m36()->nr_class && nr_class == svm->m57()->nr_class); // probabilityByLabel[0] is usually the null hypothesis, but it switches for +4 and +2/+4 vector probabilityByLabel(nr_class, 0); svm_predict_probability(svm->m2(), &nodes[0], &probabilityByLabel[0]); if (probabilityByLabel[1] > minProbability) predictedChargeStates.push_back(2); svm_predict_probability(svm->m3(), &nodes[0], &probabilityByLabel[0]); if (probabilityByLabel[1] > minProbability) predictedChargeStates.push_back(3); svm_predict_probability(svm->m4(), &nodes[0], &probabilityByLabel[0]); if (probabilityByLabel[0] > minProbability) predictedChargeStates.push_back(4); svm_predict_probability(svm->m5(), &nodes[0], &probabilityByLabel[0]); if (probabilityByLabel[1] > minProbability) predictedChargeStates.push_back(5); svm_predict_probability(svm->m6(), &nodes[0], &probabilityByLabel[0]); if (probabilityByLabel[1] > minProbability) predictedChargeStates.push_back(6); svm_predict_probability(svm->m7(), &nodes[0], &probabilityByLabel[0]); if (probabilityByLabel[1] > minProbability) predictedChargeStates.push_back(7); // return early if at least one single charge model passed if (!predictedChargeStates.empty()) return; svm_predict_probability(svm->m24(), &nodes[0], &probabilityByLabel[0]); if (probabilityByLabel[0] > minProbability) { predictedChargeStates.push_back(2); predictedChargeStates.push_back(4); } svm_predict_probability(svm->m36(), &nodes[0], &probabilityByLabel[0]); if (probabilityByLabel[1] > minProbability) { predictedChargeStates.push_back(3); predictedChargeStates.push_back(6); } svm_predict_probability(svm->m57(), &nodes[0], &probabilityByLabel[0]); if (probabilityByLabel[1] > minProbability) { predictedChargeStates.push_back(5); predictedChargeStates.push_back(7); } // return early if at least one ambiguous charge model passed if (!predictedChargeStates.empty()) return; predictedChargeStates.push_back(2); predictedChargeStates.push_back(3); predictedChargeStates.push_back(4); predictedChargeStates.push_back(6); if (probabilityByLabel[0] < minProbability) { predictedChargeStates.push_back(5); predictedChargeStates.push_back(7); } } pwiz/pwiz/analysis/spectrum_processing/SpectrumList_LockmassRefiner.hpp0000664000175100017510000000335012664775615031007 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_LockmassRefiner.hpp 9095 2015-11-01 01:14:24Z pcbrefugee $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_LOCKMASSREFINER_HPP_ #define _SPECTRUMLIST_LOCKMASSREFINER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/SpectrumListWrapper.hpp" namespace pwiz { namespace analysis { /// SpectrumList implementation to replace peak profiles with picked peaks class PWIZ_API_DECL SpectrumList_LockmassRefiner : public msdata::SpectrumListWrapper { public: SpectrumList_LockmassRefiner(const msdata::SpectrumListPtr& inner, double lockmassMzPosScans, double lockmassMzNegScans, double lockmassTolerance); static bool accept(const msdata::SpectrumListPtr& inner); virtual msdata::SpectrumPtr spectrum(size_t index, msdata::DetailLevel detailLevel) const; virtual msdata::SpectrumPtr spectrum(size_t index, bool getBinaryData = false) const; private: double mzPositiveScans_, mzNegativeScans_, tolerance_; }; } // namespace analysis } // namespace pwiz #endif // _SPECTRUMLIST_LOCKMASSREFINER_HPP_ pwiz/pwiz/analysis/spectrum_processing/MS2Deisotoper.hpp0000664000175100017510000000371212664775614025642 0ustar teamcityteamcity00000000000000// // $Id: MS2Deisotoper.hpp 6389 2014-06-13 19:46:19Z frenchwr $ // // // Original author: Chris Paulse systemsbiology.org> // // Copyright 2009 Institute for Systems Biology, Seattle, WA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _MS2DEISOTOPER_HPP_ #define _MS2DEISOTOPER_HPP_ #include "pwiz/analysis/common/DataFilter.hpp" #include "pwiz/utility/chemistry/MZTolerance.hpp" typedef struct { int charge; std::vector indexList; } isoChain; namespace pwiz { namespace analysis { using chemistry::MZTolerance; // Deisotope high resolution ms2 spectra struct PWIZ_API_DECL MS2Deisotoper : public SpectrumDataFilter { /// PrecursorMassFilter's parameters struct PWIZ_API_DECL Config { Config(MZTolerance tol = MZTolerance(0.5), bool hires_ = false, bool poisson_ = false, int maxCharge_ = 3, int minCharge_ = 1) : matchingTolerance(tol), hires(hires_), poisson(poisson_), maxCharge(maxCharge_), minCharge(minCharge_) {} MZTolerance matchingTolerance; bool hires; bool poisson; int maxCharge; int minCharge; }; MS2Deisotoper(const MS2Deisotoper::Config params_) : params(params_) {} virtual void operator () (const pwiz::msdata::SpectrumPtr) const; virtual void describe(pwiz::msdata::ProcessingMethod&) const; const MS2Deisotoper::Config params; }; } // namespace analysis } // namespace pwiz #endif // _MS2DEISOTOPER_HPP_ pwiz/pwiz/analysis/spectrum_processing/SpectrumList_ScanSummer.cpp0000664000175100017510000003647512664775615030006 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_ScanSummer.cpp 6567 2014-08-01 20:14:32Z pcbrefugee $ // // // Original author: William French // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_ScanSummer.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/data/vendor_readers/Waters/SpectrumList_Waters.hpp" bool sortFunc (parentIon i, parentIon j) { return (i.mz(param.value); } } return 0; } //void SpectrumList_ScanSummer::sumSubScansResample( vector & x, vector & y, size_t refIndex, DetailLevel detailLevel ) const //{ // // if (x.size() != y.size()) // throw runtime_error("[SpectrumList_ScanSummer::sumSubScans()] x and y arrays must be the same size"); // // int nPointsPerDalton = 800; // // // get the index for the precursorGroupList // SpectrumPtr s = inner_->spectrum(refIndex, detailLevel ); // get binary data // double precursorMZ = getPrecursorMz(*s); // get the precursor value // // vector::const_iterator pGroupIt = lower_bound(precursorList.begin(),precursorList.end(),precursorMZ,pGroupCompare); // returns iterator to first element in precursorList where mz >= precursorMZ // while ( pGroupIt->indexList[0] != (int)refIndex ) // { // pGroupIt++; // lower_bound returns the first element in a repeat sequence // if ( pGroupIt == precursorList.end() ) // throw runtime_error("[SpectrumList_ScanSummer::sumSubScans()] Cannot find the correct precursorList element..."); // } // // // setup the intensity bins for summing over multiple sub-scans // double MZspacing = 1.0 / double(nPointsPerDalton); // vector summedIntensity(int(TotalDaltons/MZspacing)+2,0.0); // // for( vector::const_iterator listIt = pGroupIt->indexList.begin(); listIt != pGroupIt->indexList.end(); ++listIt) // { // // SpectrumPtr s2 = inner_->spectrum( *listIt, detailLevel ); // vector& subMZ = s2->getMZArray()->data; // if (subMZ.size() < 2) continue; // vector& subIntensity = s2->getIntensityArray()->data; // // int binA, binB = (subMZ[0] - lowerMZlimit) / MZspacing; // initialize // for( size_t j=0, jend=subMZ.size()-1; j < jend ; ++j) // { // // binA = binB+1; // get bucket to the right of the first data point // binB = (subMZ[j+1] - lowerMZlimit) / MZspacing; // get the bucket to the left of the second data point // // if ( subIntensity[j] == 0 && subIntensity[j+1] == 0 ) continue; // no interpolation needed // // if ( binB < binA ) // { // this->warn_once("[SpectrumList_ScanSummer]: Warning, grid spacing is coarser than raw m/z spacing in at least one case" ); // } // // int k = binA; // while ( k <= binB ) // while loop ensures no interpolation when binB < binA // { // // get the m/z position of the current bin // double mzBin = double(k) * MZspacing + lowerMZlimit; // // // linear interpolation // summedIntensity[k] += subIntensity[j] + ( subIntensity[j+1] - subIntensity[j] ) * ( ( mzBin - subMZ[j] ) / ( subMZ[j+1] - subMZ[j] ) ); // // ++k; // } // // } // // } // // x.resize(summedIntensity.size()); // y.resize(summedIntensity.size()); // int cnt=0; // for (size_t i=1, iend=summedIntensity.size()-1; i < iend ; ++i) // { // // don't print zero-intensity points flanked by other zero-intensity points // if ( summedIntensity[i-1] != 0.0 || summedIntensity[i] != 0.0 || summedIntensity[i+1] != 0.0 ) // { // x[cnt] = lowerMZlimit + double(i) * MZspacing; // y[cnt] = summedIntensity[i]; // cnt++; // } // } // x.resize(cnt); // y.resize(cnt); // //} // // SpectrumList_ScanSummer // void SpectrumList_ScanSummer::sumSubScansNaive( vector & x, vector & y, size_t refIndex, DetailLevel detailLevel ) const { if (x.size() != y.size()) throw runtime_error("[SpectrumList_ScanSummer::sumSubScansNaive()] x and y arrays must be the same size"); // get the index for the precursorGroupList SpectrumPtr s = inner_->spectrum(refIndex, detailLevel ); // get binary data double precursorMZ = getPrecursorMz(*s); // get the precursor value vector::const_iterator pGroupIt = lower_bound(precursorList.begin(),precursorList.end(),precursorMZ,pGroupCompare); // returns iterator to first element in precursorList where mz >= precursorMZ while ( pGroupIt->indexList[0] != (int)refIndex ) { pGroupIt++; // lower_bound returns the first element in a repeat sequence if ( pGroupIt == precursorList.end() ) throw runtime_error("[SpectrumList_ScanSummer::sumSubScans()] Cannot find the correct precursorList element..."); } vector& summedMZ = s->getMZArray()->data; vector& summedIntensity = s->getIntensityArray()->data; vector::const_iterator InitialIt = pGroupIt->indexList.begin(); InitialIt++; if (InitialIt != pGroupIt->indexList.end()) { for( vector::const_iterator listIt = InitialIt; listIt != pGroupIt->indexList.end(); ++listIt) { SpectrumPtr s2 = inner_->spectrum( *listIt, detailLevel ); vector& subMz = s2->getMZArray()->data; vector& subIntensity = s2->getIntensityArray()->data; for( size_t j=0, jend=subMz.size(); j < jend ; ++j) { // check if this m/z point was recorded from a previous sub-scan vector::iterator pIonIt; pIonIt = lower_bound(summedMZ.begin(),summedMZ.end(),subMz[j]); // first element that is greater than or equal to subMz[j] int indexMZ = pIonIt - summedMZ.begin(); if (pIonIt == summedMZ.end()) // first check if mzs[j] is outside search range { if ( subMz[j] > summedMZ[indexMZ-1] ) // insert at back { summedMZ.push_back(subMz[j]); summedIntensity.push_back(subIntensity[j]); } else // insert at front { summedMZ.insert(summedMZ.begin(),subMz[j]); summedIntensity.insert(summedIntensity.begin(),subIntensity[j]); } } else if (*pIonIt != subMz[j]) // if the closest value is not equal to mzs[i], start a new m/z point { summedMZ.insert(pIonIt,subMz[j]); summedIntensity.insert(summedIntensity.begin()+indexMZ,subIntensity[j]); } else // m/z value recorded from previous sub-scan for this precursor; calculate the sum { summedIntensity[indexMZ] += subIntensity[j]; } } } } x.resize(summedIntensity.size()); y.resize(summedIntensity.size()); for (size_t i=0, iend=summedIntensity.size(); i < iend ; ++i) { x[i] = summedMZ[i]; y[i] = summedIntensity[i]; } } PWIZ_API_DECL SpectrumList_ScanSummer::SpectrumList_ScanSummer(const SpectrumListPtr& original, double precursorTol, double rTimeTol) : SpectrumListWrapper(original), precursorTol_(precursorTol), rTimeTol_(rTimeTol) { if (!inner_.get()) throw runtime_error("[SpectrumList_ScanSummer] Null pointer"); // Some parameters double precursorMZ = 0.0; ms2cnt=0; for (size_t i=0, end=inner_->size(); i < end; ++i ) { const SpectrumIdentity& spectrumIdentity = inner_->spectrumIdentity(i); SpectrumPtr s = inner_->spectrum(i, true); precursorMZ = getPrecursorMz(*s); if (precursorMZ == 0.0) // ms1 scans do not need summing { pushSpectrum(spectrumIdentity); continue; } double rTime = s->scanList.scans[0].cvParam(MS_scan_start_time).timeInSeconds(); ms2cnt++; if (ms2cnt==1) // set some parameters { lowerMZlimit = s->scanList.scans[0].scanWindows[0].cvParam(MS_scan_window_lower_limit).valueAs(); upperMZlimit = s->scanList.scans[0].scanWindows[0].cvParam(MS_scan_window_upper_limit).valueAs(); TotalDaltons = upperMZlimit - lowerMZlimit; } vector::iterator pGroupIt,prevIt; pGroupIt = lower_bound(precursorList.begin(),precursorList.end(),precursorMZ,pGroupCompare); // returns iterator to first element in precursorList where mz >= precursorMZ if ( precursorList.empty() ) { pushSpectrum(spectrumIdentity); precursorGroup newGroup; newGroup.precursorMZ = precursorMZ; newGroup.rTimeStart = rTime; newGroup.indexList.push_back(i); precursorList.push_back(newGroup); } else if ( pGroupIt == precursorList.end() ) { prevIt = pGroupIt - 1; double lowerDiff = precursorMZ - prevIt->precursorMZ; double lrTimeDiff = abs(rTime - prevIt->rTimeStart); if ( lowerDiff < precursorTol_ && lrTimeDiff < rTimeTol_ ) { prevIt->indexList.push_back(i); } else { pushSpectrum(spectrumIdentity); precursorGroup newGroup; newGroup.precursorMZ = precursorMZ; newGroup.rTimeStart = rTime; newGroup.indexList.push_back(i); precursorList.push_back(newGroup); } } else if ( pGroupIt == precursorList.begin() ) { double upperDiff = pGroupIt->precursorMZ - precursorMZ; double urTimeDiff = abs(rTime - pGroupIt->rTimeStart); if ( upperDiff < precursorTol_ && urTimeDiff < rTimeTol_ ) { pGroupIt->indexList.push_back(i); } else { pushSpectrum(spectrumIdentity); precursorGroup newGroup; newGroup.precursorMZ = precursorMZ; newGroup.rTimeStart = rTime; newGroup.indexList.push_back(i); precursorList.insert(pGroupIt,newGroup); } } else { prevIt = pGroupIt - 1; double upperDiff = pGroupIt->precursorMZ - precursorMZ; double lowerDiff = precursorMZ - prevIt->precursorMZ; double urTimeDiff = abs(rTime - pGroupIt->rTimeStart); double lrTimeDiff = abs(rTime - prevIt->rTimeStart); if ( upperDiff < precursorTol_ && upperDiff <= lowerDiff && urTimeDiff < rTimeTol_ ) { pGroupIt->indexList.push_back(i); } else if ( lowerDiff < precursorTol_ && lrTimeDiff < rTimeTol_ ) { prevIt->indexList.push_back(i); } else { pushSpectrum(spectrumIdentity); precursorGroup newGroup; newGroup.precursorMZ = precursorMZ; newGroup.rTimeStart = rTime; newGroup.indexList.push_back(i); precursorList.insert(pGroupIt,newGroup); } } } // end for loop over all spectra ms2RetentionTimes = precursorList; sort(ms2RetentionTimes.begin(),ms2RetentionTimes.end(),sortRtime); ms2cnt = 0; // reset } PWIZ_API_DECL size_t SpectrumList_ScanSummer::size() const { return indexMap.size(); } PWIZ_API_DECL const SpectrumIdentity& SpectrumList_ScanSummer::spectrumIdentity(size_t index) const { return spectrumIdentities.at(index); } PWIZ_API_DECL SpectrumPtr SpectrumList_ScanSummer::spectrum(size_t index, bool getBinaryData) const { return spectrum(index, getBinaryData ? DetailLevel_FullData : DetailLevel_FullMetadata); } PWIZ_API_DECL SpectrumPtr SpectrumList_ScanSummer::spectrum(size_t index, DetailLevel detailLevel) const { size_t summedScanIndex = indexMap.at(index); SpectrumPtr summedSpectrum = inner_->spectrum(summedScanIndex, detailLevel); if (summedSpectrum->cvParam(MS_ms_level).valueAs() > 1) // MS/MS scan { try { // output ms2 spectra by retention time, grab the appropriate spectrum int newIndex = ms2RetentionTimes[ms2cnt].indexList[0]; summedSpectrum = inner_->spectrum(newIndex, detailLevel); ms2cnt++; vector& mzs = summedSpectrum->getMZArray()->data; vector& intensities = summedSpectrum->getIntensityArray()->data; sumSubScansNaive( mzs, intensities, newIndex, detailLevel ); summedSpectrum->defaultArrayLength = mzs.size(); } catch( exception& e ) { throw runtime_error(std::string("[SpectrumList_ScanSummer::spectrum()] Error summing precursor sub-scans: ") + e.what()); } } summedSpectrum->index = index; // redefine the index return summedSpectrum; } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/SpectrumList_MZWindowTest.cpp0000664000175100017510000000703012664775615030270 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_MZWindowTest.cpp 4922 2013-09-05 22:33:08Z pcbrefugee $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "SpectrumList_MZWindow.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::msdata; using namespace pwiz::analysis; ostream* os_ = 0; void printSpectrumList(const SpectrumList& sl, ostream& os) { os << "size: " << sl.size() << endl; for (size_t i=0, end=sl.size(); i data; spectrum->getMZIntensityPairs(data); os << spectrum->index << " " << spectrum->id << ": "; copy(data.begin(), data.end(), ostream_iterator(os, " ")); os << endl; } } SpectrumListPtr createSpectrumList() { SpectrumListSimplePtr sl(new SpectrumListSimple); for (size_t i=0; i<10; i++) { SpectrumPtr spectrum(new Spectrum); spectrum->index = i; spectrum->id = "scan=" + lexical_cast(100+i); // data: (i,1000) (i+1,1001) (i+2,1002) (i+3,1003) (i+4,1004) vector data(5); for (size_t j=0; j<5; j++) data[j] = MZIntensityPair(i+j, 1000+j); spectrum->setMZIntensityPairs(data, MS_number_of_detector_counts); sl->spectra.push_back(spectrum); } if (os_) { *os_ << "original spectrum list:\n"; printSpectrumList(*sl, *os_); *os_ << endl; } return sl; } void verifySpectrumSize(const SpectrumList& sl, size_t index, size_t size) { SpectrumPtr spectrum = sl.spectrum(index, true); vector data; spectrum->getMZIntensityPairs(data); unit_assert(data.size() == size); } void test() { SpectrumListPtr sl = createSpectrumList(); for (size_t i=0; isize(); i++) verifySpectrumSize(*sl, i, 5); SpectrumList_MZWindow window(sl, 4.20, 6.66); if (os_) { *os_ << "filtered list:\n"; printSpectrumList(window, *os_); *os_ << endl; } unit_assert(window.size() == sl->size()); verifySpectrumSize(window, 0, 0); verifySpectrumSize(window, 1, 1); verifySpectrumSize(window, 2, 2); verifySpectrumSize(window, 3, 2); verifySpectrumSize(window, 4, 2); verifySpectrumSize(window, 5, 2); verifySpectrumSize(window, 6, 1); verifySpectrumSize(window, 7, 0); verifySpectrumSize(window, 8, 0); verifySpectrumSize(window, 9, 0); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/spectrum_processing/MS2NoiseFilter.hpp0000664000175100017510000000447312664775615025756 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_PeakFilter.hpp 1191 2009-08-14 19:33:05Z chambm $ // // // Original author: Chris Paulse systemsbiology.org> // // Copyright 2009 Institute for Systems Biology, Seattle, WA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _MS2_NOISE_FILTER_HPP_ #define _MS2_NOISE_FILTER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/MSData.hpp" #include "pwiz/analysis/common/DataFilter.hpp" namespace pwiz { namespace analysis { // Noise peak removal in ms2 spectra. We expect fragment masses to be relatively // equally spaced throughout the spectrum. Select the top n most intense ions within a // sliding window width of w. Optionally, allow more peaks at lower mass (below precursor). // // Reference: // "When less can yield more – Computational preprocessing of MS/MS spectra for peptide // identification", Bernhard Y. Renard, Marc Kirchner, Flavio Monigatti, Alexander R. Ivanov, // Juri Rappsilber, Dominic Winter, Judith A. J. Steen, Fred A. Hamprecht and Hanno Steen // Proteomics, 9, 4978-4984, 2009. struct PWIZ_API_DECL MS2NoiseFilter : public SpectrumDataFilter { /// MS2NoiseFilter's parameters struct PWIZ_API_DECL Config { Config( int numMassesInWindow_ = 5, double windowWidth_ = 120.0, bool relaxLowMass_ = false ); size_t numMassesInWindow; double windowWidth; bool relaxLowMass; }; MS2NoiseFilter(const MS2NoiseFilter::Config params_) : params(params_) {} virtual void operator () (const pwiz::msdata::SpectrumPtr) const; virtual void describe(pwiz::msdata::ProcessingMethod&) const; const MS2NoiseFilter::Config params; }; } // namespace analysis } // namespace pwiz #endif // _MS2_NOISE_FILTER_HPP_ pwiz/pwiz/analysis/spectrum_processing/SpectrumList_3D_Test.cpp0000664000175100017510000003216612664775615027167 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_3D_Test.cpp 6388 2014-06-13 17:13:45Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/almost_equal.hpp" #include "pwiz/data/msdata/MSDataFile.hpp" #include "pwiz/data/vendor_readers/ExtendedReaderList.hpp" #include "SpectrumList_3D.hpp" #include "boost/foreach_field.hpp" using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::msdata; using namespace pwiz::analysis; ostream* os_ = 0; template typename MapT::const_iterator find_nearest(MapT const& m, typename MapT::key_type const& query, typename MapT::key_type const& tolerance) { typename MapT::const_iterator cur, min, max, best; min = m.lower_bound(query - tolerance); max = m.lower_bound(query + tolerance); if (min == m.end() || fabs(query - min->first) > tolerance) return m.end(); else if (min == max) return min; else best = min; double minDiff = fabs(query - best->first); for (cur = min; cur != max; ++cur) { double curDiff = fabs(query - cur->first); if (curDiff < minDiff) { minDiff = curDiff; best = cur; } } return best; } // drift time // m/z 100 200 300 400 500 600 // 123.4 0 1 2 1 0 0 // 234.5 1 2 3 2 1 0 // 345.6 2 3 4 3 2 1 // 456.7 1 2 3 2 1 0 // 567.8 0 1 2 1 0 0 // translates to: // "100,123.4,0 200,123.4,1 300,123.4,2 400,123.4,1 500,123.4,0 600,123.4,0 100,234.5,1 200,123.4,2 300,123.4,3 400,123.4,2 500,123.4,1 600,123.4,0 etc." void test(const MSDataFile& msd, double scanStartTime, const char* driftTimeRanges, const char* expectedSpectrumTable) { boost::icl::interval_set driftTimeRangesSet; vector tokens, tokens2; bal::split(tokens, driftTimeRanges, bal::is_any_of(" ")); BOOST_FOREACH(const string& token, tokens) { bal::split(tokens2, token, bal::is_any_of("-")); driftTimeRangesSet.add(boost::icl::continuous_interval(lexical_cast(tokens2[0]), lexical_cast(tokens2[1]))); } Spectrum3D expectedSpectrum3d; bal::split(tokens, expectedSpectrumTable, bal::is_any_of(" ")); BOOST_FOREACH(const string& token, tokens) { bal::split(tokens2, token, bal::is_any_of(",")); expectedSpectrum3d[lexical_cast(tokens2[0])][lexical_cast(tokens2[1])] = lexical_cast(tokens2[2]); } SpectrumList_3D sl(msd.run.spectrumListPtr); Spectrum3DPtr resultSpectrum3d = sl.spectrum3d(scanStartTime, driftTimeRangesSet); unit_assert(!resultSpectrum3d->empty()); Spectrum3D inResultButNotExpected, inExpectedButNotResult; BOOST_FOREACH_FIELD((double actualDriftTime)(const Spectrum3D::value_type::second_type& resultSpectrum), *resultSpectrum3d) BOOST_FOREACH_FIELD((double expectedDriftTime)(const Spectrum3D::value_type::second_type& expectedSpectrum), expectedSpectrum3d) { if (find_nearest(*resultSpectrum3d, expectedDriftTime, 1e-5) == resultSpectrum3d->end()) inExpectedButNotResult[expectedDriftTime] = Spectrum3D::value_type::second_type(); if (find_nearest(expectedSpectrum3d, actualDriftTime, 1e-5) == expectedSpectrum3d.end()) inResultButNotExpected[actualDriftTime] = Spectrum3D::value_type::second_type(); if (fabs(actualDriftTime - expectedDriftTime) < 1e-5) BOOST_FOREACH_FIELD((double actualMz)(double actualIntensity), resultSpectrum) BOOST_FOREACH_FIELD((double expectedMz)(double expectedIntensity), expectedSpectrum) { if (find_nearest(resultSpectrum, expectedMz, 1e-4) == resultSpectrum.end()) inExpectedButNotResult[expectedDriftTime][expectedMz] = expectedIntensity; if (find_nearest(expectedSpectrum, actualMz, 1e-4) == expectedSpectrum.end()) inResultButNotExpected[actualDriftTime][actualMz] = actualIntensity; } } if (os_ && !inResultButNotExpected.empty()) { *os_ << "Extra points in the result were not expected:\n"; BOOST_FOREACH_FIELD((double driftTime)(const Spectrum3D::value_type::second_type& spectrum), inResultButNotExpected) { *os_ << driftTime << ":"; BOOST_FOREACH_FIELD((double mz)(double intensity), spectrum) *os_ << " " << mz << "," << intensity; *os_ << endl; } } if (os_ && !inExpectedButNotResult.empty()) { *os_ << "Missing points in the result that were expected:\n"; BOOST_FOREACH_FIELD((double driftTime)(const Spectrum3D::value_type::second_type& spectrum), inExpectedButNotResult) { *os_ << driftTime << ":"; BOOST_FOREACH_FIELD((double mz)(double intensity), spectrum) *os_ << " " << mz << "," << intensity; *os_ << endl; } } unit_assert(inResultButNotExpected.empty()); unit_assert(inExpectedButNotResult.empty()); } void parseArgs(const vector& args, vector& rawpaths) { for (size_t i = 1; i < args.size(); ++i) { if (args[i] == "-v") os_ = &cout; else if (bal::starts_with(args[i], "--")) continue; else rawpaths.push_back(args[i]); } } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { vector args(argv, argv+argc); vector rawpaths; parseArgs(args, rawpaths); ExtendedReaderList readerList; BOOST_FOREACH(const string& filepath, rawpaths) { if (bal::ends_with(filepath, "ImsSynthCCS.d")) { MSDataFile msd(filepath, &readerList); // scans 529, 554, 557, 615, 638 test(msd, 2, "29.6-29.7 33.8-33.9 34.4-34.41 34.57-34.58 44.23-44.24 48.13-48.14", "33.89830,99.9954,0 34.57627,99.9954,0 29.66101,99.9954,0 34.40678,99.9954,0 44.23729,99.9954,0 48.13559,99.9954,0 " // I don't know why these isolated points show up "33.89830,174.03522,0 33.89830,174.04278,1 33.89830,174.05034,1 33.89830,174.05790,1 33.89830,174.06546,1 33.89830,174.07302,0 33.89830,174.35288,0 33.89830,174.36044,1 " "33.89830,174.36801,1 33.89830,174.37558,1 33.89830,174.38314,1 33.89830,174.39071,1 33.89830,174.39828,1 33.89830,174.40585,1 33.89830,174.41342,1 34.57627,177.05704,0 " "34.57627,177.06466,1 34.57627,177.07229,1 34.57627,177.07991,1 34.57627,177.08754,2 34.40678,177.09517,0 34.57627,177.09517,3 34.40678,177.10279,1 34.57627,177.10279,3 " "34.40678,177.11042,1 34.57627,177.11042,4 34.40678,177.11804,1 34.57627,177.11804,4 34.40678,177.12567,1 34.57627,177.12567,5 34.40678,177.13330,1 34.57627,177.13330,5 " "34.40678,177.14092,1 34.57627,177.14092,5 34.40678,177.14855,1 34.57627,177.14855,4 34.40678,177.15618,1 34.57627,177.15618,4 34.40678,177.16381,0 34.57627,177.16381,3 " "34.57627,177.17143,2 34.57627,177.17906,1 34.57627,177.18669,1 34.57627,177.19432,1 34.57627,177.20195,0 34.57627,177.59120,0 34.57627,177.59884,1 34.57627,177.60648,1 " "34.57627,177.61411,1 34.57627,177.62175,1 34.57627,177.62939,1 34.57627,177.63703,1 34.57627,177.64466,1 34.57627,177.65230,1 34.57627,177.65994,1 34.57627,177.66758,1 " "34.57627,177.67522,0 29.66101,177.71341,0 29.66101,177.72105,1 29.66101,177.72869,1 29.66101,177.73633,1 29.66101,177.74397,2 29.66101,177.75161,2 29.66101,177.75925,3 " "29.66101,177.76689,4 29.66101,177.77453,4 29.66101,177.78217,4 29.66101,177.78981,4 29.66101,177.79745,4 29.66101,177.80509,4 29.66101,177.81274,3 29.66101,177.82038,3 " "29.66101,177.82802,2 29.66101,177.83566,1 29.66101,177.84330,1 29.66101,177.85094,1 29.66101,177.85859,0 29.66101,178.07264,0 29.66101,178.08029,1 29.66101,178.08793,1 " "29.66101,178.09558,1 29.66101,178.10323,1 29.66101,178.11088,1 34.57627,178.11088,0 29.66101,178.11852,2 34.57627,178.11852,1 29.66101,178.12617,1 34.57627,178.12617,1 " "29.66101,178.13382,1 34.57627,178.13382,1 29.66101,178.14147,1 34.57627,178.14147,1 29.66101,178.14912,1 34.57627,178.14912,0 29.66101,178.15677,1 29.66101,178.16442,1 " "29.66101,178.17206,0 29.66101,178.39396,0 29.66101,178.40161,1 29.66101,178.40927,1 29.66101,178.41692,1 29.66101,178.42458,1 29.66101,178.43223,2 29.66101,178.43989,2 " "29.66101,178.44754,2 29.66101,178.45520,2 29.66101,178.46285,2 29.66101,178.47051,2 29.66101,178.47816,1 29.66101,178.48582,1 29.66101,178.49347,1 29.66101,178.50113,1 " "29.66101,178.50879,0 29.66101,178.76154,0 29.66101,178.76920,1 29.66101,178.77686,1 29.66101,178.78452,1 29.66101,178.79219,1 29.66101,178.79985,1 29.66101,178.80751,1 " "34.57627,398.99589,0 34.57627,399.00734,1 34.57627,399.01878,1 34.57627,399.03023,1 34.57627,399.04168,1 34.57627,399.05313,2 34.40678,399.06457,0 34.57627,399.06457,2 " "34.40678,399.07602,1 34.57627,399.07602,3 34.40678,399.08747,1 34.57627,399.08747,4 34.40678,399.09892,1 34.57627,399.09892,5 34.40678,399.11036,1 34.57627,399.11036,5 " "34.40678,399.12181,1 34.57627,399.12181,6 34.40678,399.13326,1 34.57627,399.13326,7 34.40678,399.14471,1 34.57627,399.14471,7 34.40678,399.15616,1 34.57627,399.15616,7 " "34.40678,399.16761,1 34.57627,399.16761,7 34.40678,399.17906,1 34.57627,399.17906,7 34.40678,399.19051,1 34.57627,399.19051,7 34.40678,399.20196,1 34.57627,399.20196,7 " "34.40678,399.21341,1 34.57627,399.21341,6 34.40678,399.22486,1 34.57627,399.22486,5 34.40678,399.23631,1 34.57627,399.23631,5 34.40678,399.24776,1 34.57627,399.24776,4 " "34.40678,399.25921,1 34.57627,399.25921,3 34.57627,399.27066,2 34.57627,399.28211,2 34.57627,399.29356,1 34.57627,399.30501,1 34.57627,399.31646,1 34.57627,399.32791,1 " "34.57627,399.33936,0 34.57627,400.04968,0 34.57627,400.06114,1 34.57627,400.07260,1 34.57627,400.08406,1 34.57627,400.09552,1 34.57627,400.10699,1 34.57627,400.11845,1 " "34.57627,400.12991,2 34.57627,400.14138,2 34.57627,400.15284,2 34.57627,400.16430,2 34.57627,400.17577,2 34.57627,400.18723,2 34.57627,400.19869,2 34.57627,400.21016,2 " "34.57627,400.22162,1 34.57627,400.23309,1 34.57627,400.24455,1 34.57627,400.25601,1 34.57627,400.26748,1 34.57627,400.27894,1 48.13559,608.09487,0 48.13559,608.10900,1 " "44.23729,608.12313,0 48.13559,608.12313,1 44.23729,608.13726,1 48.13559,608.13726,1 44.23729,608.15139,1 48.13559,608.15139,1 44.23729,608.16553,1 48.13559,608.16553,1 " "44.23729,608.17966,1 48.13559,608.17966,1 44.23729,608.19379,1 48.13559,608.19379,1 44.23729,608.20792,1 48.13559,608.20792,1 44.23729,608.22206,1 48.13559,608.22206,1 " "44.23729,608.23619,1 48.13559,608.23619,2 44.23729,608.25032,1 48.13559,608.25032,2 44.23729,608.26445,1 48.13559,608.26445,2 44.23729,608.27859,1 48.13559,608.27859,2 " "44.23729,608.29272,1 48.13559,608.29272,2 44.23729,608.30685,1 48.13559,608.30685,2 44.23729,608.32099,1 48.13559,608.32099,2 44.23729,608.33512,1 48.13559,608.33512,1 " "44.23729,608.34926,1 48.13559,608.34926,1 44.23729,608.36339,1 48.13559,608.36339,1 44.23729,608.37753,1 48.13559,608.37753,1 44.23729,608.39166,1 48.13559,608.39166,1 " "44.23729,608.40579,1 48.13559,608.40579,1 48.13559,608.41993,1 48.13559,608.43406,1 48.13559,608.44820,0 48.13559,609.19760,0 48.13559,609.21175,1 48.13559,609.22589,1 " "48.13559,609.24004,1 48.13559,609.25418,1 48.13559,609.26832,1 48.13559,609.28247,1 48.13559,609.29661,1 48.13559,609.31076,1 48.13559,609.32491,1 48.13559,609.33905,1"); } // TODO: add a Waters test /*else if (bal::ends_with(filepath, "GFP_IMS_TEST.raw")) { MSDataFile msd(filepath, &readerList); // scans 529, 554, 557, 615, 638 test(msd, 2.03500008, "13.29-13.30 13.22-13.23 13.15-13.16", "13.15698,1,0 13.22623,1,0 13.29547,1,0"); }*/ } } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/spectrum_processing/SpectrumList_MZWindow.hpp0000664000175100017510000000332012664775615027433 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_MZWindow.hpp 1191 2009-08-14 19:33:05Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Center for Applied Molecular Medicine // University of Southern California, Los Angeles, CA // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_MZWINDOW_HPP_ #define _SPECTRUMLIST_MZWINDOW_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/SpectrumListWrapper.hpp" namespace pwiz { namespace analysis { /// SpectrumList filter, for creating Spectrum sub-lists class PWIZ_API_DECL SpectrumList_MZWindow : public msdata::SpectrumListWrapper { public: SpectrumList_MZWindow(const msdata::SpectrumListPtr original, double mzLow, double mzHigh); /// \name SpectrumList interface //@{ virtual msdata::SpectrumPtr spectrum(size_t index, bool getBinaryData = false) const; //@} private: double mzLow_; double mzHigh_; SpectrumList_MZWindow(SpectrumList_MZWindow&); SpectrumList_MZWindow& operator=(SpectrumList_MZWindow&); }; } // namespace analysis } // namespace pwiz #endif // _SPECTRUMLIST_MZWINDOW_HPP_ pwiz/pwiz/analysis/spectrum_processing/SpectrumList_ZeroSamplesFilter.hpp0000664000175100017510000000405612664775615031336 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_ZeroSamplesFilter.hpp 3550 2012-04-18 16:23:06Z chambm $ // // // Original author: Brian Pratt insilicos.com> // // Copyright 2012 Spielberg Family Center for Applied Proteomics // University of Southern California, Los Angeles, California 90033 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_ZEROSAMPLESFILTER_HPP_ #define _SPECTRUMLIST_ZEROSAMPLESFILTER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/utility/misc/IntegerSet.hpp" #include "pwiz/data/msdata/SpectrumListWrapper.hpp" namespace pwiz { namespace analysis { /// SpectrumList implementation to return spectra with or without extra zero samples class PWIZ_API_DECL SpectrumList_ZeroSamplesFilter : public msdata::SpectrumListWrapper { public: enum Mode {Mode_RemoveExtraZeros, Mode_AddMissingZeros}; SpectrumList_ZeroSamplesFilter(const msdata::SpectrumListPtr& inner, const util::IntegerSet& msLevelsToFilter, Mode mode, size_t FlankingZeroCount); static bool accept(const msdata::SpectrumListPtr& inner); virtual msdata::SpectrumPtr spectrum(size_t index, bool getBinaryData = false) const; private: const Mode mode_; // Mode_RemoveExtraZeros or Mode_AddMissingZeros const size_t flankingZeroCount_; // used if adding missing zeros const util::IntegerSet msLevelsToFilter_; }; } // namespace analysis } // namespace pwiz #endif // _SPECTRUMLIST_ZEROSAMPLESFILTER_HPP_ pwiz/pwiz/analysis/spectrum_processing/SpectrumList_ChargeStateCalculator.hpp0000664000175100017510000000446212664775615032131 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_ChargeStateCalculator.hpp 6826 2014-10-22 17:12:14Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_CHARGESTATECALCULATOR_HPP_ #define _SPECTRUMLIST_CHARGESTATECALCULATOR_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/utility/misc/IntegerSet.hpp" #include "pwiz/data/msdata/SpectrumListWrapper.hpp" namespace pwiz { namespace analysis { /// SpectrumList implementation that assigns (probable) charge states to tandem mass spectra class PWIZ_API_DECL SpectrumList_ChargeStateCalculator : public msdata::SpectrumListWrapper { public: SpectrumList_ChargeStateCalculator(const msdata::SpectrumListPtr& inner, bool overrideExistingChargeState = true, int maxMultipleCharge = 3, int minMultipleCharge = 2, double intensityFractionBelowPrecursorForSinglyCharged = 0.9, int maxKnownCharge = 0, bool makeMS2 = false); /// accepts any tandem mass spectrum static bool accept(const msdata::SpectrumListPtr& inner) {return true;} /// charge calculation requires binary data to function, so returned spectra will always provide the binary data virtual msdata::SpectrumPtr spectrum(size_t index, bool getBinaryData = true) const; private: bool override_; int maxCharge_; int minCharge_; double fraction_; int maxKnownCharge_; bool makeMS2_; }; } // namespace analysis } // namespace pwiz #endif // _SPECTRUMLIST_CHARGESTATECALCULATOR_HPP_ pwiz/pwiz/analysis/spectrum_processing/MS2DeisotoperTest.cpp0000664000175100017510000001245612664775614026502 0ustar teamcityteamcity00000000000000// // $Id: MS2DeisotoperTest.cpp 6389 2014-06-13 19:46:19Z frenchwr $ // // // Original author: William French vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "MS2Deisotoper.hpp" #include "SpectrumList_PeakFilter.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/data/msdata/examples.hpp" #include "pwiz/data/msdata/TextWriter.hpp" #include "pwiz/data/common/CVTranslator.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::msdata; using namespace pwiz::analysis; ostream* os_ = 0; ostream& operator<< (ostream& os, const vector& v) { os << "("; for (size_t i=0; i < v.size(); ++i) os << " " << v[i]; os << " )"; return os; } struct TestDeisotopeCalculator { // space-delimited doubles const char* inputMZArray; const char* inputIntensityArray; }; TestDeisotopeCalculator testDeisotopeCalculators[] = { { "300.0 302.1 303.11 304.12 305.20", "1.0 85.0 15.0 3.0 3.0"}, { "299.5 300.01 300.52 301.03", "10.0 75.0 25.0 40.0"}, { "302.1 302.435 302.77 302.94 303.11", "61.0 31.0 8.0 45.0 40.0"}, }; TestDeisotopeCalculator goldStandard[] = { { "300.0 302.1 305.20", "1.0 85.0 3.0"}, { "299.5 300.01 301.03", "10.0 75.0 40.0"}, { "302.1 302.94 303.11", "61.0 45.0 40.0"}, }; const size_t testDeisotopeSize = sizeof(testDeisotopeCalculators) / sizeof(TestDeisotopeCalculator); const size_t goldStandardSize = sizeof(goldStandard) / sizeof(TestDeisotopeCalculator); vector parseDoubleArray(const string& doubleArray) { vector doubleVector; vector tokens; bal::split(tokens, doubleArray, bal::is_space(), bal::token_compress_on); if (!tokens.empty()) for (size_t i=0; i < tokens.size(); ++i) if (!tokens[i].empty()) doubleVector.push_back(lexical_cast(tokens[i])); return doubleVector; } int test() { int failedTests = 0; // create the spectrum list SpectrumListSimple* sl = new SpectrumListSimple; SpectrumListPtr originalList(sl); for (size_t i=0; i < testDeisotopeSize; ++i) { TestDeisotopeCalculator& t = testDeisotopeCalculators[i]; // attach all the data to the spectrum list SpectrumPtr s(new Spectrum); s->set(MS_MSn_spectrum); s->set(MS_ms_level,2); s->precursors.push_back(Precursor(100.0)); // dummy precursor m/z vector inputMZArray = parseDoubleArray(t.inputMZArray); vector inputIntensityArray = parseDoubleArray(t.inputIntensityArray); s->setMZIntensityArrays(inputMZArray, inputIntensityArray, MS_number_of_detector_counts); s->defaultArrayLength = inputMZArray.size(); sl->spectra.push_back(s); } vector goldMZArray = parseDoubleArray(goldStandard[0].inputMZArray); vector goldIntensityArray = parseDoubleArray(goldStandard[0].inputIntensityArray); // construct the filter bool hires = false; MZTolerance mzt(hires? 0.01 : 0.5); bool poisson = true; int maxCharge = 3, minCharge = 1; SpectrumDataFilterPtr filter = SpectrumDataFilterPtr(new MS2Deisotoper(MS2Deisotoper::Config(mzt, hires, poisson, maxCharge, minCharge))); // run spectral summation try { SpectrumListPtr calculator(new SpectrumList_PeakFilter(originalList,filter)); for (size_t i=0; i < calculator->size(); ++i) { SpectrumPtr s = calculator->spectrum(i,true); vector& mzs = s->getMZArray()->data; vector& intensities = s->getIntensityArray()->data; vector goldMZArray = parseDoubleArray(goldStandard[i].inputMZArray); vector goldIntensityArray = parseDoubleArray(goldStandard[i].inputIntensityArray); unit_assert(mzs.size() == goldMZArray.size()); unit_assert(intensities.size() == goldIntensityArray.size()); for (size_t j=0; j < mzs.size(); ++j) { unit_assert_equal(mzs[j], goldMZArray[j], 1e-5); unit_assert_equal(intensities[j], goldIntensityArray[j], 1e-5); } } } catch (exception& e) { cerr << "Test failed:\n" << e.what() << endl; ++failedTests; } return failedTests; } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; int failedTests = test(); unit_assert_operator_equal(0, failedTests); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/analysis/spectrum_processing/SpectrumList_MZRefiner.cpp0000664000175100017510000033510112664775615027556 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_MZRefiner.cpp 8985 2015-10-12 22:38:57Z chambm $ // // // Original author: Bryson Gibbons // // Copyright 2014 Pacific Northwest National Laboratory // Richland, WA 99352 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_MZRefiner.hpp" #include "pwiz/data/vendor_readers/Agilent/SpectrumList_Agilent.hpp" #include "pwiz/data/common/CVTranslator.hpp" #include "pwiz/data/identdata/IdentDataFile.hpp" #include "pwiz/data/msdata/MSData.hpp" #include "pwiz/data/proteome/Peptide.hpp" #include "pwiz/utility/misc/optimized_lexical_cast.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Singleton.hpp" #include #include namespace pwiz { namespace analysis { using namespace pwiz::cv; using namespace pwiz::msdata; using namespace pwiz::identdata; // Constants specific to mzRefiner const unsigned int MINIMUM_RESULTS_FOR_GLOBAL_SHIFT = 100; // 500 is kind of arbitrary, but it seemed like a good number to use as a requirement for dependent data shifts // If there are only 500 data points, there will be very limited shift smoothing. const unsigned int MINIMUM_RESULTS_FOR_DEPENDENT_SHIFT = 500; // Forward declarations to allow having the comparison functions contained in the classes. class ShiftData; class ScanData; typedef boost::shared_ptr ShiftDataPtr; typedef boost::shared_ptr ScanDataPtr; // Can't use boost::dynamic_pointer_cast(ShiftDataPtr) because there are no virtual members. // dynamic_pointer_cast also has higher overhead // Data necessary to calculate the multiple types of shifts class ShiftData { public: double scanTime; // In Seconds double massError; double ppmError; double calcMz; double experMz; // Possible virtual member of msLevel or something similar? static bool byScanTime(const ShiftData& i, const ShiftData& j) { return i.scanTime < j.scanTime; } static bool byPpmError(const ShiftData& i, const ShiftData& j) { return i.ppmError < j.ppmError; } static bool byCalcMz(const ShiftData& i, const ShiftData& j) { return i.calcMz < j.calcMz; } static bool byExperMz(const ShiftData& i, const ShiftData& j) { return i.experMz < j.experMz; } static bool byScanTimePtr(ShiftDataPtr i, ShiftDataPtr j) { return i->scanTime < j->scanTime; } static bool byPpmErrorPtr(ShiftDataPtr i, ShiftDataPtr j) { return i->ppmError < j->ppmError; } static bool byCalcMzPtr(ShiftDataPtr i, ShiftDataPtr j) { return i->calcMz < j->calcMz; } static bool byExperMzPtr(ShiftDataPtr i, ShiftDataPtr j) { return i->experMz < j->experMz; } }; // Extra data needed for preparing the shifts, but not needed for calculating them class ScanData : public ShiftData { public: size_t scanId; string nativeID; int rank; string peptideSeq; int peptideSeqLength; int msLevel; double scoreValue; int charge; // Sorting functions for vector of ScanData static bool byScanId(const ScanData& i, const ScanData& j) { return i.scanId < j.scanId; } static bool byScanIdPtr(ScanDataPtr i, ScanDataPtr j) { return i->scanId < j->scanId; } // TODO: potentially unsafe casting, should fix (how?) static bool byScanIdPtr2(ShiftDataPtr i, ShiftDataPtr j) { return boost::static_pointer_cast(i)->scanId < boost::static_pointer_cast(j)->scanId; } // Not particularly useful, I think - depends on score used, and on other functions that would need to be added to CVConditionalFilter static bool byScore(const ScanData& i, const ScanData& j) { return i.scoreValue < j.scoreValue; } static bool byScorePtr(ScanDataPtr i, ScanDataPtr j) { return i->scoreValue < j->scoreValue; } }; class CVConditionalFilter { public: class CVConditionalFilterConfigData { public: CVConditionalFilterConfigData() : software(CVID_Unknown), step(0.0), maxSteps(0) {} CVConditionalFilterConfigData(const string& p_cvTerm, const string& p_rangeSet, double p_step, int p_maxSteps) : software(CVID_Unknown), cvTerm(p_cvTerm), rangeSet(p_rangeSet), step(p_step), maxSteps(p_maxSteps) {} CVID software; string cvTerm; string rangeSet; double step; int maxSteps; }; CVConditionalFilter(CVConditionalFilterConfigData configData); CVConditionalFilter(CVID software, const string& cvTerm, const string& rangeSet, double step = 0.0, int maxStep = 0); CVConditionalFilter(CVID software, const string& cvTerm, double maxValue, double minValue, bool useMax, bool useMin, double step = 0, int maxStep = 0); void updateFilter(CVID software, const string& cvTerm, double maxValue, double minValue, bool useMax, bool useMin, double step = 0, int maxStep = 0); void updateFilter(CVID software, const string& cvTerm, const string& rangeSet, double step = 0.0, int maxStep = 0); bool passesFilter(identdata::SpectrumIdentificationItemPtr& sii, double& scoreVal) const; bool isBetter(double lScoreVal, double rScoreVal) const; bool isBetter(const ScanDataPtr& lData, const ScanDataPtr& rData) const; bool adjustFilterByStep(); cv::CVID getCVID() const { return cvid; } double getMax() const { return max; } double getMin() const { return min; } bool getAnd() const { return isAnd; } const string& getScoreName() { return scoreName; } const string& getThreshold() { return threshold; } private: CVConditionalFilter(); string scoreName; string threshold; cv::CVID cvid; bool useName; double max; double min; double step; double maxSteps; int stepCount; bool isAnd; double center; bool isMin; bool isMax; }; typedef boost::shared_ptr CVConditionalFilterPtr; ostream& operator<<(ostream& out, CVConditionalFilter filter); // A functor for using STL sorts with an object instance struct sortFilter { CVConditionalFilterPtr filter; sortFilter(CVConditionalFilterPtr& f) : filter(f) {}; bool operator() (const ScanDataPtr& lData, const ScanDataPtr& rData) const { return filter->isBetter(lData, rData); } }; // Abstract class for a shift: common functionality required for all shifts class AdjustmentObject { public: AdjustmentObject(double gShift = 0.0, double gStDev = 0.0, double gMAD = 0.0) : globalShift(gShift), globalStDev(gStDev), globalMAD(gMAD) {} virtual ~AdjustmentObject() {} string getAdjustmentType() const { return adjustmentType; } string getPrettyAdjustment() const { return prettyAdjustment; } double getStDev() const { return stdev; } double getMAD() const { return mad; } double getPctImp() const { return percentImprovement; } double getPctImpMAD() const { return percentImprovementMAD; } double getGlobalShift() const { return globalShift; } double getGlobalStDev() const { return globalStDev; } double getGlobalMAD() const { return globalMAD; } virtual double shift(double scanTime, double mass) const = 0; virtual void calculate(vector& data) = 0; virtual string getShiftRange() const = 0; virtual string getShiftOutString() const = 0; protected: string adjustmentType; string prettyAdjustment; string adjTypeShort; double stdev; double mad; double percentImprovement; double percentImprovementMAD; double globalShift; double globalStDev; double globalMAD; }; typedef boost::shared_ptr AdjustmentObjectPtr; // A basic shift - everything is being shifted by the same approximate value class AdjustSimpleGlobal : public AdjustmentObject { public: double getShift() const { return shiftError; } double getModeError() const { return modeError; } double getMedianError() const { return medianError; } double getAvgError() const { return avgError; } double getAvgStDev() const { return avgStDev; } double getModeStDev() const { return modeStDev; } double getMedianStDev() const { return medianStDev; } AdjustSimpleGlobal() { adjustmentType = "SimpleGlobal"; adjTypeShort = "SG"; prettyAdjustment = "Global Shift"; } void setZeroShift() { shiftError = 0.0; } virtual double shift(double scanTime, double mass) const; virtual void calculate(vector& data); virtual string getShiftRange() const { return lexical_cast(shiftError); } virtual string getShiftOutString() const { return "Global PPM Shift"; } bool checkForPeak() const; private: vector freqHistBins; double freqHistBinSize; int freqHistBinCount; double shiftError; double avgError; double modeError; double medianError; double avgStDev; double modeStDev; double medianStDev; }; typedef boost::shared_ptr AdjustSimpleGlobalPtr; // Support common functionality for a "binned" dependency shift class BinnedAdjustmentObject : public AdjustmentObject { public: BinnedAdjustmentObject(double gShift, double gStDev, double gMAD) : AdjustmentObject(gShift, gStDev, gMAD) {} virtual double shift(double scanTime, double mass) const = 0; virtual void calculate(vector& data) = 0; virtual string getShiftRange() const; virtual string getShiftOutString() const = 0; double getRoughStDev() const { return roughStDev; } double getRoughPctImp() const { return percentImprovementRough; } double getSmoothedStDev() const { return smoothedStDev; } double getSmoothedPctImp() const { return percentImprovementSmoothed; } double getRoughMAD() const { return roughMAD; } double getRoughPctImpMAD() const { return percentImprovementRoughMAD; } double getSmoothedMAD() const { return smoothedMAD; } double getSmoothedPctImpMAD() const { return percentImprovementSmoothedMAD; } protected: virtual double binShift(double dependency, double mass) const; virtual void smoothBins(); virtual void cleanNoise(); virtual void cleanNoiseHelper(size_t start, int step); virtual void processBins(); virtual void getStats(double& stDev, double& mad); vector shifts; vector isValidBin; vector counts; double binSize; vector< vector > sortBins; size_t bins; size_t highestCountBin; size_t lowestValidBin; size_t highestValidBin; double roughStDev; double percentImprovementRough; double smoothedStDev; double percentImprovementSmoothed; double roughMAD; double percentImprovementRoughMAD; double smoothedMAD; double percentImprovementSmoothedMAD; }; typedef boost::shared_ptr BinnedAdjustmentObjectPtr; /******************************************************************************************************* * Sorts a list by the default sorting function, and returns the median * The parameter would be const, but we can't sort a const list. * Using pass-by-reference to avoid vector copy costs. * Returns: median, list is sorted in ascending order (by default comparison) ******************************************************************************************************/ double median(vector& list) { double median = 0.0; std::sort(list.begin(), list.end()); // Pseudo-median: use integer division to always get center (odd count) or next lower value (even count) //median = list[list.size() / 2]; // True median: average the two center values when the count is even. // Possibility of replacing this with Boost's statistical accumulators if (list.size() == 0) { return 0.0; } if (list.size() % 2) // Get "false" (0) if even, "true" (1) if odd { median = list[list.size() / 2]; } else { // list size / 2 gives the size divided by 2 - will always be the high index for the center (e.g., 2 / 2 = 1, the highest valid index...) // Subtract 1 to get the low index for the center double lShift = list[(list.size() / 2) - 1]; // next lower value double rShift = list[list.size() / 2]; // next higher value median = (lShift + rShift) / 2.0; } return median; } class AdjustByScanTime : public BinnedAdjustmentObject { public: // Bin size of 1.25 (min) captures 20 +/- 5 ms1 scans on Thermo Orbitrap // Changed to 75 seconds (make all references change to that as well) // Captures at least 14 scans, and up to 50, on Agilent QTOF // Should probably be made variable, but determining what it should be in the end is the challenge. AdjustByScanTime(double gShift, double gStDev, double gMAD) : BinnedAdjustmentObject(gShift, gStDev, gMAD) { adjustmentType = "ByScanTime"; adjTypeShort = "Time"; binSize = 75; prettyAdjustment = "Using scan time dependency"; } virtual double shift(double scanTime, double mass) const; virtual void calculate(vector& data); virtual string getShiftOutString() const { return "scan time dependent shift"; } private: }; typedef boost::shared_ptr AdjustByScanTimePtr; class AdjustByMassToCharge : public BinnedAdjustmentObject { public: AdjustByMassToCharge(double gShift, double gStDev, double gMAD) : BinnedAdjustmentObject(gShift, gStDev, gMAD) { adjustmentType = "ByMassToCharge"; adjTypeShort = "MZ"; binSize = 25; prettyAdjustment = "Using mass to charge dependency"; } virtual double shift(double scanTime, double mass) const; virtual void calculate(vector& data); virtual string getShiftOutString() const { return "m/z dependent shift"; } private: }; typedef boost::shared_ptr AdjustByMassToChargePtr; /********************************************************************************************* * Determine the mode within a specified accuracy for a global shift ********************************************************************************************/ void AdjustSimpleGlobal::calculate(vector& data) { std::sort(data.begin(), data.end(), ShiftData::byPpmErrorPtr); medianError = data[data.size() / 2]->ppmError; double sumPpmError = 0.0; freqHistBinSize = 0.5; /**************************************************************************************** * Decent ideas for bin size * 0.1 = 1001 bins * 0.2 = 501 bins * 0.4 = 251 bins * 0.5 = 201 bins * 0.8 = 126 bins * 1 = 101 bins * 2 = 51 bins ***************************************************************************************/ // -50 to 50 is 100 values, if we don't count zero freqHistBinCount = 100.0 / freqHistBinSize + 1.0; freqHistBins.resize(freqHistBinCount, 0); // -50 to 50, with extra for zero BOOST_FOREACH(const ShiftDataPtr &i, data) { if (-50 <= i->ppmError && i->ppmError <= 50) { // Add 50 to enter valid range, add .5 for rounding purposes, then truncate for valid rounding // -50.5+50.5 = 0, -0.5+50.5=50, -0.2+50.5 = 50.7=>50, 50.499+50.5=100.999=>100. // 0.5 for rounding is a constant - do not change. freqHistBins[(int)((i->ppmError + 50.0) * (1.0 / freqHistBinSize) + 0.5)]++; sumPpmError += i->ppmError; } } avgError = sumPpmError / (double)data.size(); double sumVariance = 0; double modeVariance = 0; double medianVariance = 0; vector madList; /// Output ppmError Histogram... int high = 0; for (int i = 0; i < freqHistBinCount; ++i) { if (freqHistBins[i] > high) { high = freqHistBins[i]; modeError = (i * freqHistBinSize) - 50.0; } } BOOST_FOREACH(const ShiftDataPtr &i, data) { sumVariance += pow(i->ppmError - avgError, 2); modeVariance += pow(i->ppmError - modeError, 2); medianVariance += pow(i->ppmError - medianError, 2); madList.push_back(abs(i->ppmError - medianError)); } // variance, average of squared differences from mean //double avgVariance = sumVariance / (double)data.size(); avgStDev = sqrt(sumVariance / (double)data.size()); modeStDev = sqrt(modeVariance / (double)data.size()); medianStDev = sqrt(medianVariance / (double)data.size()); mad = median(madList); // This is the global stdev, it's what we are trying to improve percentImprovement = 0.0; // Set the type of shift to use here. shiftError = medianError; stdev = medianStDev; ostringstream oss2; oss2 << ": " << shiftError << " ppm"; prettyAdjustment += oss2.str(); // Set the global shift/stdev values globalShift = shiftError; globalStDev = stdev; globalMAD = mad; } /********************************************************************************************* * Check for a peak where the median is found - if no significant peak, return false ********************************************************************************************/ bool AdjustSimpleGlobal::checkForPeak() const { if (freqHistBins.empty()) { return false; } // Checking 10 ppm to either side of the shift value size_t medianBin = (int)((shiftError + 50.0) * (1.0 / freqHistBinSize) + 0.5); size_t tenPpmBins = (1.0 / freqHistBinSize) * 10; size_t medianLessTenBin = medianBin >= tenPpmBins ? medianBin - tenPpmBins : 0; size_t medianPlusTenBin = medianBin < freqHistBinCount - tenPpmBins ? medianBin + tenPpmBins : freqHistBinCount - 1; // Find max // Use the mode; why re-find it? // We need the bin index size_t maxBin = (int)((modeError + 50.0) * (1.0 / freqHistBinSize) + 0.5); if (maxBin < medianLessTenBin || medianPlusTenBin < maxBin) { // The max is outside of +/- 10 ppm from the median; obvious problems ////////////// Or, severe bi-modal dataset; might be a nice quick check, but might exclude resonable data. //////////////////////////////////////////////////////////////////////////////////////////////////////// return false; } // Find average of all values not in the +/- 10 ppm range int sum = 0; int count = 0; for (size_t i = 0; i < freqHistBins.size(); i++) { if (medianLessTenBin <= i && i <= medianPlusTenBin) { continue; } // outside of +/- 10 ppm range - get average // Exclude zero counts - prevent bias if (freqHistBins[i] > 0) { sum += freqHistBins[i]; count++; } } if (count == 0) { // All data points were within 10 ppm of the median. return true; ////////////////////////////////////////////////// May warrant further evaluation? /////////////////////////////////////////////////////////////////////////////////////////////////////// } double average = (double)sum / (double)count; // Is max > average * 5? return freqHistBins[maxBin] >= average * 5; } /********************************************************************************************* * Return a value shifted by the global ppm mode ********************************************************************************************/ double AdjustSimpleGlobal::shift(double scanTime, double mass) const { return mass * (1 - shiftError / 1.0e6); } /********************************************************************************************* * Perform some basic smoothing to balance erratic or missing data ********************************************************************************************/ void BinnedAdjustmentObject::smoothBins() { // Do not store shifts on original data - We don't want bias based on the shifts vector newShifts(shifts.size(), globalShift); for (int i = lowestValidBin; (size_t)i <= highestValidBin; ++i) { int count = counts[i]; double sum = shifts[i] * (double)counts[i]; // Run at least once - we want to include next and previous values, as weights // We also want at least 100 scans to increase reliability for (int j = 1; (j < 2 || count < 100) && (size_t)j < shifts.size(); ++j) { if ((size_t)(i + j) <= highestValidBin) { count += counts[i + j]; sum += shifts[i + j] * (double)counts[i + j]; } // Prevent negatives, compared as signed values... if (i - j > 0 && (size_t)(i - j) >= lowestValidBin) { count += counts[i - j]; sum += shifts[i - j] * (double)counts[i - j]; } } // Stored the smoothed data isValidBin[i] = true; newShifts[i] = sum / (double)count; } // Overwrite the original shifts with the smoothed ones. shifts.swap(newShifts); } /********************************************************************************************* * Clean out the noise at the tail ends of the run * This can have some undesired effects, should probably be made optional * It may be useful for scores/datasets that are noisier, by limiting the dependency shifts * where data is sparse ********************************************************************************************/ void BinnedAdjustmentObject::cleanNoiseHelper(size_t start, int step) { // Enforce stepping one item at a time, in the set direction if (step < 0) step = -1; else step = 1; double stDevToUse = globalStDev; if (stDevToUse < 3.0) { // We have a pretty good dataset, we can probably just exit this function; //return; stDevToUse *= 2.0; // Set it to something not overly sensitive; 2 StDev } bool wipeoutRest = false; size_t lastNonZeroIndex = start; // Assume we are not starting at zero for (int i = start; i < (int)bins && i >= 0; i += step) { if (wipeoutRest) { // We've hit two zero counts in a row, clear out the rest. shifts[i] = globalShift; counts[i] = 0; continue; } else if (counts[i] > 20) { // Figure that it is probably good data lastNonZeroIndex = i; continue; } else if (counts[i] > 0) { double thisShift = shifts[i]; // Use lastNonZeroIndex to get the last one we considered valid. double lastShift = shifts[lastNonZeroIndex]; // Check to see if the difference from the last bin to this one is more than a reasonable amount (usually 1 StDev)... if ((thisShift + stDevToUse) < lastShift || (thisShift - stDevToUse) > lastShift) { // Reset to the global; This will later be wiped out during smoothing, if in range. shifts[i] = globalShift; counts[i] = 0; if (abs((int)i - (int)lastNonZeroIndex) > 1) { // We got two pretty bad sets in a row. Ignore whatever is left. wipeoutRest = true; } } else { lastNonZeroIndex = i; } } else { if (abs((int)i - (int)lastNonZeroIndex) > 1) { // Found two zero counts in a row. Assume no good data in rest of vector. wipeoutRest = true; } // Otherwise zero, don't do anything special. } } // Reset the lowest and highest valid bins to the new limits. if (step < 0) { lowestValidBin = lastNonZeroIndex; } else { highestValidBin = lastNonZeroIndex; } } /********************************************************************************************* * Clear out the noisy results on either end - this is risky, but the results if we don't do this * can be worthless. * This is more useful for identification tools that don't provide a score that easily lends * itself to this shift - MS-GF+'s SpecEValue seems to provide a pretty clean plot, but * MyriMatch's mvh and xcorr tend to provide a noisy plot in my experience. ********************************************************************************************/ void BinnedAdjustmentObject::cleanNoise() { cleanNoiseHelper(highestCountBin, -1); cleanNoiseHelper(highestCountBin, 1); } /********************************************************************************************* * Calculate bin medians and statistics ********************************************************************************************/ void BinnedAdjustmentObject::processBins() { // Need to eventually add some way of cleaning up noisy ends - where there is no apparent "quality data" // Ideas: Look for data density, significant changes in stdev, etc. shifts.resize(bins, globalShift); isValidBin.resize(bins, false); size_t maxCount = 0; for (size_t i = 0; i < bins; ++i) { if (sortBins[i].size() > 0) { // Get the median shifts[i] = median(sortBins[i]); // Find the bin with the highest number of scans if (maxCount < sortBins[i].size()) { highestCountBin = i; maxCount = sortBins[i].size(); } } } // Not sure how to work with this, or if it should just be removed. //cleanNoise(); getStats(roughStDev, roughMAD); // Run the smoothing algorithm smoothBins(); getStats(smoothedStDev, smoothedMAD); // Need all absolute to be accurate - we don't want worse values to come back as "better" percentImprovementRough = 100.0 * ((abs(globalStDev) - abs(roughStDev)) / abs(globalStDev)); percentImprovementSmoothed = 100.0 * ((abs(globalStDev) - abs(smoothedStDev)) / abs(globalStDev)); percentImprovementRoughMAD = 100.0 * ((abs(globalMAD) - abs(roughMAD)) / abs(globalMAD)); percentImprovementSmoothedMAD = 100.0 * ((abs(globalMAD) - abs(smoothedMAD)) / abs(globalMAD)); stdev = smoothedStDev; mad = smoothedMAD; percentImprovement = percentImprovementSmoothedMAD; } /********************************************************************************************* * Calculate the bin standard deviations and average, and bin median absolute deviations and median ********************************************************************************************/ void BinnedAdjustmentObject::getStats(double& stDev, double& mad) { int validBins = 0; vector binStDev(bins, 0.0); vector binMad; vector madWorker; double binStDevSum = 0.0; // This is kinda rough for a standard deviation calculation - it doesn't reflect what the final result would really be. // Should change this to use basic smoothing between bins, similar to the binShift() function. Would require using the scan time or calculated mass to charger, depending on the shift type... ////////////////////////////////////////////////////////////////////////// for (size_t i = lowestValidBin; i <= highestValidBin; ++i) { if (sortBins[i].size() > 0) { double varianceSumBin = 0.0; ++validBins; BOOST_FOREACH(double &j, sortBins[i]) { varianceSumBin += pow(j - shifts[i], 2); // For bin Median Absolute Deviation madWorker.push_back(abs(j - shifts[i])); } binStDev[i] = sqrt(varianceSumBin / (double)sortBins[i].size()); binStDevSum += binStDev[i]; // Bin Median Absolute Deviation: median of absolute deviations from the median binMad.push_back(median(madWorker)); // Clear out the helper madWorker.clear(); } } // Get final Median Absolute deviation: median of bin Median Absolute Deviation mad = median(binMad); stDev = binStDevSum / (double)validBins; } /********************************************************************************************* * Perform a shift on a mass, given a dependency ********************************************************************************************/ double BinnedAdjustmentObject::binShift(double dependency, double mass) const { size_t useBin = dependency / binSize; if (useBin >= lowestValidBin && useBin <= highestValidBin) { // Handle limits: no data points either before or after to slope to. if ((dependency <= ((double)lowestValidBin * binSize) + binSize / 2.0) || (dependency >= ((double)highestValidBin * binSize) + binSize / 2.0) ) { //return mass * (1 - globalShift / 1.0e6); return mass * (1 - shifts[useBin] / 1.0e6); } // Handle +/- 0.5 of center - no need to slope? double binCenter = ((double)useBin * binSize) + binSize / 2.0; int lowBin = lowestValidBin; int highBin = highestValidBin; // Set the low bin and high bin for smooth shifting between two points if (dependency < binCenter) { // since levelling is being done and the previous bin is at minimum the // lowestValidBin, we can just use: // lowBin = useBin - 1; lowBin = useBin - 1; highBin = useBin; } else if (dependency > binCenter) { // since levelling is being done and the next bin is at maximum the // highestValidBin, we can just use: // highBin = useBin + 1; highBin = useBin + 1; lowBin = useBin; } else { // The float comparisons thought it wasn't greater than or less than the bin center. Assume equal. return mass * (1 - shifts[useBin] / 1.0e6); } // Center index of lower bin double lowMid = ((double)lowBin * binSize) + binSize / 2.0; // Center index of higher bin double highMid = ((double)highBin * binSize) + binSize / 2.0; // Index difference between low and high bins //////////////////////////// This is probably only ever one, with smoothing in use. double rangeBin = highMid - lowMid; // Position in range of window - min 0, max rangeBin double inRange = dependency - lowMid; // Value difference from the low bin to the high bin double ctcDiff = shifts[highBin] - shifts[lowBin]; // Percentage position of dependency in range from lowMid to highMid double pctInRange = inRange / rangeBin; // The shifting value that we can now calculate double newShift = shifts[lowBin] + pctInRange * ctcDiff; return mass * (1 - newShift / 1.0e6); } // When dependency value is less than the lowest bin with valid data, use the lowestValidBin for the shift if (useBin < lowestValidBin) { return mass * (1 - shifts[lowestValidBin] / 1.0e6); } // When dependency value is greater than the highest bin with valid data, use the highestValidBin for the shift if (useBin > highestValidBin) { return mass * (1 - shifts[highestValidBin] / 1.0e6); } // If all else fails, default to whatever bin it falls into. Should never be used, the above should catch everything this one does if (useBin < counts.size() && counts[useBin] > 0) { return mass * (1 - shifts[useBin] / 1.0e6); } // If the data we got is out of the shift range, just use the global shift. return mass * (1 - globalShift / 1.0e6); } /********************************************************************************************* * Output the range of shifts being performed ********************************************************************************************/ string BinnedAdjustmentObject::getShiftRange() const { double min = shifts[lowestValidBin]; double max = shifts[lowestValidBin]; for (size_t i = lowestValidBin; i <= highestValidBin; i++) { if (shifts[i] < min) { min = shifts[i]; } if (shifts[i] > max) { max = shifts[i]; } } // May want to use an ostringstream to set a specific precision return lexical_cast(min) + " to " + lexical_cast(max); } /********************************************************************************************* * Configure the shifting object, populate data bins, and run calculations ********************************************************************************************/ void AdjustByScanTime::calculate(vector& data) { // Sort the data by scan time, and populate the bins std::sort(data.begin(), data.end(), ShiftData::byScanTimePtr); // Set the store the highest and lowest valid bins lowestValidBin = data.front()->scanTime / binSize; highestValidBin = data.back()->scanTime / binSize; // Calculate the number of bins needed; add 3-4 extra bins to avoid going out of bounds bins = (data.back()->scanTime + (binSize * 4.0)) / binSize; // Resize the data vectors to the appropriate size sortBins.resize(bins); counts.resize(bins, 0); // Populate the data vectors BOOST_FOREACH(const ShiftDataPtr &i, data) { int useBin = i->scanTime / binSize; sortBins[useBin].push_back(i->ppmError); counts[useBin]++; } // The generic bin-based shift calculation can take care of the rest. processBins(); } /********************************************************************************************* * Perform a shift on a mass, given a dependency ********************************************************************************************/ double AdjustByScanTime::shift(double scanTime, double mass) const { return binShift(scanTime, mass); } /********************************************************************************************* * Configure the shifting object, populate data bins, and run calculations ********************************************************************************************/ void AdjustByMassToCharge::calculate(vector& data) { // Sort the data by mass, and populate the bins std::sort(data.begin(), data.end(), ShiftData::byExperMzPtr); // Set the store the highest and lowest valid bins lowestValidBin = data.front()->experMz / binSize; highestValidBin = data.back()->experMz / binSize; // Calculate the number of bins needed; add 3-4 extra bins to avoid going out of bounds bins = (data.back()->experMz + (binSize * 4)) / binSize; // Resize the data vectors to the appropriate size sortBins.resize(bins); counts.resize(bins, 0); // Populate the data vectors BOOST_FOREACH(const ShiftDataPtr &i, data) { int useBin = i->experMz / binSize; sortBins[useBin].push_back(i->ppmError); counts[useBin]++; } // The generic bin-based shift calculation can take care of the rest. processBins(); } /********************************************************************************************* * Perform a shift on a mass, given a dependency ********************************************************************************************/ double AdjustByMassToCharge::shift(double scanTime, double mass) const { return binShift(mass, mass); } /******************************************************************************************************************************************* * Chunk of code copied from pwiz/data/identdata/Serializer_pepXML.cpp * Seemed useful for users inputting score names. ********************************************************************************************************************************************/ struct ScoreTranslation { CVID softwareCVID; CVID scoreCVID; const char* scoreNames; // first name is the preferred one }; struct ci_less { bool operator() (const string& lhs, const string& rhs) const { if (lhs.length() != rhs.length()) return lhs.length() < rhs.length(); for (size_t i = 0; i < lhs.length(); ++i) if (tolower(lhs[i]) != tolower(rhs[i])) return tolower(lhs[i]) < tolower(rhs[i]); return false; } }; const ScoreTranslation scoreTranslationTable[] = { { MS_SEQUEST, MS_SEQUEST_xcorr, "xcorr" }, { MS_SEQUEST, MS_SEQUEST_deltacn, "deltacn;deltcn" }, { MS_Mascot, MS_Mascot_score, "ionscore;score" }, { MS_Mascot, MS_Mascot_identity_threshold, "identityscore" }, { MS_Mascot, MS_Mascot_homology_threshold, "homologyscore" }, { MS_Mascot, MS_Mascot_expectation_value, "expect" }, // ?? { MS_OMSSA, MS_OMSSA_pvalue, "pvalue" }, { MS_OMSSA, MS_OMSSA_evalue, "expect" }, { MS_Phenyx, MS_Phenyx_Pepzscore, "zscore" }, { MS_Phenyx, MS_Phenyx_PepPvalue, "zvalue" }, //{MS_greylag, MS_greylag_??, "??"}, //{MS_Phenyx, MS_Phenyx_Score, "??"}, //{MS_ProteinPilot_Software, MS_Paragon_score, "??"}, //{MS_ProteinLynx_Global_Server, MS_ProteinLynx_Ladder_Score, "??"}, //{MS_ProteinLynx_Global_Server, MS_ProteinLynx_Log_Likelihood, "??"}, { MS_MyriMatch, MS_MyriMatch_MVH, "mvh" }, { MS_TagRecon, MS_MyriMatch_MVH, "mvh" }, { MS_Pepitome, MS_MyriMatch_MVH, "mvh" }, { MS_MyriMatch, MS_MyriMatch_mzFidelity, "mzFidelity" }, { MS_TagRecon, MS_MyriMatch_mzFidelity, "mzFidelity" }, { MS_Pepitome, MS_MyriMatch_mzFidelity, "mzFidelity" }, { MS_X_Tandem, MS_X_Tandem_hyperscore, "hyperscore" }, { MS_X_Tandem, MS_X_Tandem_expect, "expect" }, //{MS_Spectrum_Mill_for_MassHunter_Workstation, MS_SpectrumMill_Score, "??"}, //{MS_Spectrum_Mill_for_MassHunter_Workstation, MS_SpectrumMill_Discriminant_Score, "??"}, //{MS_Spectrum_Mill_for_MassHunter_Workstation, MS_SpectrumMill_SPI, "??"}, //{MS_Proteios, MS_Proteios_??, "??"}, { MS_MS_GF, MS_MS_GF_RawScore, "raw" }, { MS_MS_GF, MS_MS_GF_DeNovoScore, "denovo" }, { MS_MS_GF, MS_MS_GF_Energy, "energy" }, { MS_MS_GF, MS_MS_GF_EValue, "EValue" }, { MS_MS_GF, MS_MS_GF_QValue, "QValue" }, { MS_MS_GF, MS_MS_GF_SpecEValue, "SpecEValue" }, { MS_MS_GF, MS_MS_GF_PepQValue, "PepQValue" }, { MS_MS_GF, MS_MS_GF_PEP, "PEP" }, { MS_MS_GF_, MS_MS_GF_RawScore, "raw" }, { MS_MS_GF_, MS_MS_GF_DeNovoScore, "denovo" }, { MS_MS_GF_, MS_MS_GF_Energy, "energy" }, { MS_MS_GF_, MS_MS_GF_EValue, "EValue" }, { MS_MS_GF_, MS_MS_GF_QValue, "QValue" }, { MS_MS_GF_, MS_MS_GF_SpecEValue, "SpecEValue" }, { MS_MS_GF_, MS_MS_GF_PepQValue, "PepQValue" }, { MS_MS_GF_, MS_MS_GF_PEP, "PEP" }, { MS_Comet, MS_Comet_xcorr, "xcorr" }, { MS_Comet, MS_Comet_deltacn, "deltacn" }, { MS_Comet, MS_Comet_deltacnstar, "deltacnstar" }, { MS_Comet, MS_Comet_sprank, "sprank" }, { MS_Comet, MS_Comet_spscore, "spscore" }, { MS_Comet, MS_Comet_expectation_value, "expect" } }; const size_t scoreTranslationTableSize = sizeof(scoreTranslationTable) / sizeof(ScoreTranslation); struct ScoreTranslator : public boost::singleton { ScoreTranslator(boost::restricted) { preferredScoreNameBySoftwareAndScoreCVID[CVID_Unknown][CVID_Unknown] = ""; for (size_t i = 0; i < scoreTranslationTableSize; ++i) { const ScoreTranslation& st = scoreTranslationTable[i]; vector names; bal::split(names, st.scoreNames, bal::is_any_of(";")); if (names.empty()) throw runtime_error("[mzRefiner::ScoreTranslator] Invalid software name list."); preferredScoreNameBySoftwareAndScoreCVID[st.softwareCVID][st.scoreCVID] = names[0]; for (size_t j = 0; j < names.size(); ++j) scoreCVIDBySoftwareAndScoreName[st.softwareCVID][names[j]] = st.scoreCVID; } } CVID translate(CVID softwareCVID, const string& scoreName) const { map >::const_iterator itr = scoreCVIDBySoftwareAndScoreName.find(softwareCVID); if (itr == scoreCVIDBySoftwareAndScoreName.end()) return CVID_Unknown; map::const_iterator itr2 = itr->second.find(scoreName); if (itr2 == itr->second.end()) return CVID_Unknown; return itr2->second; } const string& translate(CVID softwareCVID, CVID scoreCVID) const { map >::const_iterator itr = preferredScoreNameBySoftwareAndScoreCVID.find(softwareCVID); if (itr == preferredScoreNameBySoftwareAndScoreCVID.end()) return empty; map::const_iterator itr2 = itr->second.find(scoreCVID); if (itr2 == itr->second.end()) return empty; return itr2->second; } private: // TODO: use boost::multi_index? map > preferredScoreNameBySoftwareAndScoreCVID; map > scoreCVIDBySoftwareAndScoreName; const string empty; }; /******************************************************************************************************************************************* * END Chunk of code copied from pwiz/data/identdata/Serializer_pepXML.cpp ********************************************************************************************************************************************/ // // CVConditionalFilter // CVConditionalFilter::CVConditionalFilter(CVConditionalFilterConfigData configData) { updateFilter(configData.software, configData.cvTerm, configData.rangeSet, configData.step, configData.maxSteps); } CVConditionalFilter::CVConditionalFilter(CVID software, const string& cvTerm, const string& rangeSet, double step, int maxStep) { updateFilter(software, cvTerm, rangeSet, step, maxStep); } CVConditionalFilter::CVConditionalFilter(CVID software, const string& cvTerm, double maxValue, double minValue, bool useMax, bool useMin, double step, int maxStep) { updateFilter(software, cvTerm, maxValue, minValue, useMax, useMin, step, maxStep); } void CVConditionalFilter::updateFilter(CVID software, const string& cvTerm, double maxValue, double minValue, bool useMax, bool useMin, double step, int maxStep) { scoreName = cvTerm; useName = false; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Matt Chambers // Let the user specify a score name to look for. I think cvTermInfo() can also look up a term by name? Could be misremembering that though. // You're probably better off just taking the name of the score the user wants to use, iterating through each param in the SpectrumIdentificationItem, // doing cvTermInfo() and then doing a search for the score name as a substring of cvTermInfo::name // (actually, use bal::iends_with(cvTermInfo(cvid).name(), userSpecifiedScore) // // // -Actually, what I was thinking of was how the pepXML conversion process can go back and forth from short names // This is contained only in pwiz/data/identdata/Serializer_pepXML.cpp // I copied the desired code from that file to this one. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // This score translator is cheap - will run pretty fast - small subset of full CV cvid = ScoreTranslator::instance->translate(software, cvTerm); if (cvid == CVID_Unknown) { // Then run the more expensive one. CVTranslator findCV; cvid = findCV.translate(cvTerm); if (cvid == CVID_Unknown) { // TODO: log output at a high detail level. //cout << "Warning: cvTerm for \"" << cvTerm << "\" not found. Will search scores for the provided term." << endl; useName = true; } } if (!useName) { scoreName = cvTermInfo(cvid).name; } string threshold = ""; isMin = false; isMax = false; if (!useMax) { maxValue = numeric_limits::max(); threshold = ">= " + lexical_cast(minValue); isMin = true; } else if (!useMin) { minValue = -maxValue; threshold = "<= " + lexical_cast(maxValue); isMax = true; } else { threshold = lexical_cast(minValue) + " <= MME <= " + lexical_cast(maxValue); } this->threshold = threshold; max = maxValue; min = minValue; this->step = step; maxSteps = maxStep; stepCount = 0; center = (min + max) / 2.0; // Allow for tests where the value must be outside of a certain range isAnd = minValue < maxValue; } /************************************************************************************* * Implementation of a DoubleSet, like an IntSet * There is probably a better way, but I couldn't find one. * The return value is a vector of two doubles, with minValue at 0 and maxValue at 1 * If the range was something like "-1" or "1-", the minValue/maxValue (whichever was not specified) * is set to lowest/highest (respectively) possible value for double **************************************************************************************/ vector parseDoubleSet(const string& rangeSet) { double maxValue = numeric_limits::max(); double minValue = -maxValue; // [200,] [,-200] [-5,5] [5,-5] [1,5] if (rangeSet[0] == '[') { string inner = rangeSet.substr(1, rangeSet.length() - 2); string lower = inner.substr(0, inner.rfind(',')); if (lower.length() > 0) { minValue = boost::lexical_cast(lower); } if (inner.rfind(',') != string::npos) { string upper = inner.substr(inner.rfind(',') + 1); if (upper.length() > 0) { maxValue = boost::lexical_cast(upper); } } } else { // for less than negative value, use "--(number)" // "-(number)" will interpret as less than (positive number) // allowed formats: "-(num)" "(num)-(num)" "(num)-" // -1.0e-10, --1.0e-10, 5.0-, 1-5 vector numbers; string numBuilder = ""; string numTester = "1234567890.eE"; bool startMinus = false; bool endMinus = false; bool separated = false; for (size_t i = 0; i < rangeSet.length(); i++) { if (numTester.find(rangeSet[i]) != string::npos) { // all digits, plus '.' and 'e'/'E' numBuilder += rangeSet[i]; } else if (rangeSet[i] == '-' && i != 0 && rangeSet[i - 1] == 'e') { // A '-' that modifies an exponent numBuilder += rangeSet[i]; } else if (rangeSet[i] == '-') { //handle other '-' if (i == 0) { startMinus = true; } else if (i == 1) { numBuilder += rangeSet[i]; } else if (i == rangeSet.length() - 1) { if (!separated) { endMinus = true; if (startMinus) { startMinus = false; numBuilder = "-" + numBuilder; } } else { //report error throw pwiz::util::user_error("[mzRefiner::parseRange] syntax error (start and end specified, with an infinite end also)"); } } else { if (!separated) { separated = true; if (startMinus && numBuilder[0] != '-') { numBuilder = "-" + numBuilder; startMinus = false; } numbers.push_back(numBuilder); numBuilder = ""; } else { numBuilder += rangeSet[i]; } } } else { // Error: not a valid digit/character throw pwiz::util::user_error("[mzRefiner::parseRange] invalid characters"); } } numbers.push_back(numBuilder); if ((startMinus && endMinus) || ((startMinus || endMinus) && separated)) { //report error - searching both directions from a value, or other invalid syntax throw pwiz::util::user_error("[mzRefiner::parseRange] invalid syntax"); } vector numbers2(numbers.size(), 0.0); for (size_t i = 0; i < numbers.size(); i++) { numbers2[i] = lexical_cast(numbers[i]); } if (startMinus) { maxValue = numbers2[0]; } else if (endMinus) { minValue = numbers2[0]; } else { minValue = numbers2[0]; maxValue = numbers2[1]; } } vector set; set.push_back(minValue); set.push_back(maxValue); return set; } /************************************************************************************* * Step in the creation of a filter when using a DoubleSet for the threshold. **************************************************************************************/ void CVConditionalFilter::updateFilter(CVID software, const string& cvTerm, const string& rangeSet, double step, int maxStep) { double maxValue; double minValue; bool useMax = false; bool useMin = false; vector threshold = parseDoubleSet(rangeSet); useMin = true; useMax = true; minValue = threshold[0]; maxValue = threshold[1]; updateFilter(software, cvTerm, maxValue, minValue, useMax, useMin, step, maxStep); } /***************************************************************************************************************** * Evaluate if the spectrum identification item passes the filter *****************************************************************************************************************/ bool CVConditionalFilter::passesFilter(SpectrumIdentificationItemPtr& sii, double& scoreVal) const { bool found = false; double value = 0; if (!useName) { vector::iterator it = find_if(sii->cvParams.begin(), sii->cvParams.end(), CVParamIs(cvid)); if (it == sii->cvParams.end()) { return false; } found = true; value = it->valueAs(); } else { // Handle search userParams and cvParams for the score name // Search the userParams first, under the assumption that we would have matched a CVID if it was a cvParam. BOOST_FOREACH(UserParam &up, sii->userParams) { if (bal::iends_with(up.name, scoreName)) { found = true; value = up.valueAs(); break; } } if (!found) { BOOST_FOREACH(CVParam &cvp, sii->cvParams) { if (bal::iends_with(cvp.name(), scoreName)) { found = true; value = cvp.valueAs(); break; } } } } if (found) { scoreVal = value; if (!isAnd) { return (value <= max) || (value >= min); } return (value <= max) && (value >= min); } return false; } /********************************************************************************** * A function to allow us to sort a set of values from best to worst, * depending on the threshold values definition of "better" ***********************************************************************************/ bool CVConditionalFilter::isBetter(double lScoreVal, double rScoreVal) const { if (!isAnd && isMin) { // Return true if the left value is larger return lScoreVal > rScoreVal; } if (!isAnd && isMax) { // Return true if the left value is smaller return lScoreVal < rScoreVal; } double left = abs(lScoreVal - center); double right = abs(rScoreVal - center); // Assumptions: If a score is based in a range (like -5 to 5), closer to the center is better. // If a score excludes a range (value < -5 or 5 < value), further from the center is better. if (isAnd) { // Return true if the left value is closer to "center" return left < right; } else { // Return true if the left value is further from "center" return left > right; } } /*********************************************************************************** * Comparison function for sorting by score. * Should probably change to prefer rank first, and the sort identical rank by score. ***********************************************************************************/ bool CVConditionalFilter::isBetter(const ScanDataPtr& lData, const ScanDataPtr& rData) const { // If rank == 0, probably PMF data, rely on the score used; otherwise, sort by rank unless it is equal if (lData->rank != 0 && rData->rank != 0 && lData->rank != rData->rank) { // A lower rank is better if (lData->rank < rData->rank) { return true; } return false; } return isBetter(lData->scoreValue, rData->scoreValue); } /******************************************************************************************** * For the edge case where you just have to have an adjustment and therefore you want values from * poorer scoring identifications gradually included until you have the required number of data points. * (For the record, Sam Payne is against this, and Matt Monroe wants it.) ********************************************************************************************/ bool CVConditionalFilter::adjustFilterByStep() { bool hasStep = false; ostringstream oss; oss << "Adjusted filters: " << endl; oss << "\tOld: " << *this << endl; if (step != 0.0 && stepCount < maxSteps) { hasStep = true; if (fabs(max) != numeric_limits::max()) { max = max * step; } if (fabs(min) != numeric_limits::max()) { min = min * step; } stepCount++; } if (hasStep) { oss << "\tNew: " << *this << endl; cout << oss.str() << endl; } return hasStep; } /*************************************************************************************************************** * Overloaded output to easily output filter state ***************************************************************************************************************/ ostream& operator<<(ostream& out, CVConditionalFilter filter) { CVID temp = filter.getCVID(); double max = filter.getMax(); double min = filter.getMin(); bool isAnd = filter.getAnd(); CVTermInfo cv = cvTermInfo(temp); out << filter.getScoreName() << "; " << min << " <= value " << (isAnd ? "&&" : "||") << " value <= " << max; return out; } /********************************************************************************************** * Check an instrument configuration for a final high-res analyzer ***********************************************************************************************/ bool configurationIsHighRes(const InstrumentConfigurationPtr& ic) { Component* la = &(ic->componentList.analyzer(0)); // Get the last analyzer BOOST_FOREACH(Component &c, ic->componentList) { if (c.type == ComponentType_Analyzer) { la = &c; } } // Look for Orbitrap, FT, or TOF to test for high-res if (la->hasCVParam(MS_orbitrap) || la->hasCVParam(MS_time_of_flight) || la->hasCVParam(MS_fourier_transform_ion_cyclotron_resonance_mass_spectrometer) || la->hasCVParam(MS_stored_waveform_inverse_fourier_transform)) { return true; } return false; } /********************************************************************************************* * Check a spectrum to determine if it is high res; also, return the first scan start time found. * Returns true if spectrum is high-resolution, and changes the start time if the value is available *********************************************************************************************/ bool getSpectrumHighResAndStartTime(const vector& scans, double& startTime) { bool isHighRes = false; CVParam scanStartTime; BOOST_FOREACH(const Scan &sls, scans) { // Set isHighRes to true, don't allow it to be set back to false after it has been set to true. if (configurationIsHighRes(sls.instrumentConfigurationPtr)) { isHighRes = true; } if (scanStartTime.empty()) { scanStartTime = sls.cvParam(MS_scan_start_time); } } // Only attempt to change the start time if we have a valid CVParam. if (!scanStartTime.empty()) { startTime = scanStartTime.timeInSeconds(); // Use seconds } return isHighRes; } // // SpectrumList_MZRefiner::Impl // class SpectrumList_MZRefiner::Impl { public: Impl(util::IntegerSet p_msLevelsToRefine, CVConditionalFilter::CVConditionalFilterConfigData filterConfigData) : msLevelsToRefine(p_msLevelsToRefine), filterConfigData_(filterConfigData), bad_(0), badByScore_(0), badByMassError_(0) {} AdjustmentObjectPtr adjust; AdjustmentObjectPtr ms2Adjust; string identFilePath; vector data; // Will hold ScanDataPtr, but must be ShiftDataPtr because polymorphism on collections doesn't work (can't pass vector to vector parameter) vector ms2Data; SpectrumListPtr spectrumList; // store a reference to the spectrum list for checking precursor information. void configureShift(const MSData& msd, const string& identFile, pwiz::util::IterationListenerRegistry* ilr); bool getPrecursorHighResAndStartTime(const Precursor& p, double& scanStartTime) const; bool containsHighResData(const MSData& msd); bool isAllHighRes() { return allHighRes_; } util::IntegerSet msLevelsToRefine; string getFilterScoreName() { return filterScoreName_; } string getFilterThreshold() { return filterThreshold_; } private: shared_ptr statStream_; int bad_, badByScore_, badByMassError_; bool allHighRes_; CVConditionalFilter::CVConditionalFilterConfigData filterConfigData_; void processIdentData(const MSData& msd, pwiz::util::IterationListenerRegistry* ilr); void getMSDataData(const MSData& msd, pwiz::util::IterationListenerRegistry* ilr); void shiftCalculator(pwiz::util::IterationListenerRegistry* ilr); void shiftCalculator(pwiz::util::IterationListenerRegistry* ilr, vector& shiftData, AdjustSimpleGlobalPtr& globalShift, AdjustByScanTimePtr& scanTimeShift, AdjustByMassToChargePtr& mzShift, AdjustmentObjectPtr& adjustment, string shiftDataType) const; void fragmentationIonPpmErrors(const string& peptideSeq, const int& peptideSeqLength, const SpectrumPtr& s); bool cleanIsotopes(ScanDataPtr& sd) const; // Utility function. Doesn't really need to be a member function, but it isn't used anywhere else than in processIdentData string filterScoreName_; string filterThreshold_; // Identification precision filters; Stored here to facilitate future modification via user input double isotopeScreenAdj_; // Filtering threshold for measurement accuracy/precision: Maximum measurement error where isotopic peak correction will be attempted double isotopeFilter_; // Filtering threshold for measurement accuracy/precision: Maximum measurement error double ppmErrorLimit_; // Filtering threshold for measurement accuracy/precision: Maximum PPM error }; /********************************************************************************* * Checks the instrument configuration data to determine if there are high-resolution spectra in the file. * Also checks and sets the allHighRes_ member variable based on if all spectra will be high-resolution. * This is a bad, dual-purpose function: the return value and the value stored to the member variable are related, but not the same. *********************************************************************************/ bool SpectrumList_MZRefiner::Impl::containsHighResData(const MSData& msd) { bool hasHighRes = false; allHighRes_ = true; BOOST_FOREACH(const InstrumentConfigurationPtr& ic, msd.instrumentConfigurationPtrs) { // Set hasHighRes to true, don't allow it to be set back to false after it has been set to true. if (configurationIsHighRes(ic)) { hasHighRes = true; } else { allHighRes_ = false; } } return hasHighRes; } shared_ptr openFilestreamIfWritable(const bfs::path& filepath, bool& fileExists) { fileExists = bfs::exists(filepath); shared_ptr tmp = boost::make_shared(filepath.string().c_str(), std::ios::app); if (!*tmp) return shared_ptr(); // return null ptr if open failed (probably because file or path is read-only) return tmp; } /******************************************************************************** * Primary function for SpectrumList_MZRefiner::Impl * Performs the entire workflow for creating the shift. *******************************************************************************/ void SpectrumList_MZRefiner::Impl::configureShift(const MSData& msd, const string& identFile, pwiz::util::IterationListenerRegistry* ilr) { bfs::path statFilepath = bfs::path(identFile).replace_extension("mzRefinement.tsv"); bool fileExists; statStream_ = openFilestreamIfWritable(statFilepath, fileExists); if (!statStream_) statStream_ = openFilestreamIfWritable(statFilepath.filename(), fileExists); if (!statStream_) statStream_ = openFilestreamIfWritable(bfs::temp_directory_path() / statFilepath.filename(), fileExists); if (!statStream_) throw runtime_error("[SpectrumList_MZRefiner::configureShift] unable to open a writable mzRefinement stats file"); // if the file was just created, write headers if (!fileExists) *statStream_ << "ThresholdScore\tThresholdValue\tExcluded (score)\tExcluded (mass error)" << "\tMS1 Included" //<< "\tMS1 Drift (mean)\tMS1 Drift (median)\tMS1 Global MAD\tMS1 Dependent MAD (scan)\tMS1 Dependent MAD (smoothed scan)\tMS1 Dependent MAD (mz)\tMS1 Dependent MAD (smoothed mz)\tMS1 %Improvement (scan)\tMS1 %Improvement (smoothed scan)\tMS1 %Improvement (mz)\tMS1 %Improvement (smoothed mz)" << "\tMS1 Shift method\tMS1 Final stDev\tMS1 Tolerance for 99%\tMS1 Final MAD\tMS1 MAD Tolerance for 99%" << "\tMS2 Included" //<< "\tMS2 Drift (mean)\tMS2 Drift (median)\tMS2 Global MAD\tMS2 Dependent MAD (scan)\tMS2 Dependent MAD (smoothed scan)\tMS2 Dependent MAD (mz)\tMS2 Dependent MAD (smoothed mz)\tMS2 %Improvement (scan)\tMS2 %Improvement (smoothed scan)\tMS2 %Improvement (mz)\tMS2 %Improvement (smoothed mz)" << "\tMS2 Shift method\tMS2 Final stDev\tMS2 Tolerance for 99%\tMS2 Final MAD\tMS2 MAD Tolerance for 99%" << "\n"; isotopeScreenAdj_ = 0.15; // 0.05 less than charge 5 error isotopeFilter_ = 0.20; // May include charge 5 unadjusted error, but it is not common ppmErrorLimit_ = 50.0; // Used as the negative and positive limit. /* Notes on isotopeFilter_ and ppmErrorLimit: Current values of 0.20 and 50 ppm - 50ppm is more restrictive below 4000 m/z, the 0.20 mass error is more restrictive at and above 4000 m/z Several other examples of where that threshold lies: ppmErrorLimit_ isotopeFilter_ ppmMoreRestrictive < m/z <= massErrorMoreRestrictive 50 0.2 4000 80 0.2 2500 100 0.2 2000 125 0.2 1600 150 0.2 1333 200 0.2 1000 50 0.25 5000 80 0.25 3125 100 0.25 2500 125 0.25 2000 150 0.25 1667 200 0.25 1250 50 0.3 6000 80 0.3 3750 100 0.3 3000 125 0.3 2400 150 0.3 2000 200 0.3 1500 */ identFilePath = identFile; bad_ = 0; containsHighResData(msd); // not worried about return value, just making sure allHighRes_ is set properly. adjust.reset(); ms2Adjust.reset(); spectrumList = SpectrumListPtr(msd.run.spectrumListPtr); // Will initialize the filter, using the software cv if necessary processIdentData(msd, ilr); // Read data from the MSData to supply missing scan start times and to calculate the MS2 shift, if MS2 are high-resolution getMSDataData(msd, ilr); shiftCalculator(ilr); } /********************************************************************************* * Try to get precursor high-res and scan start time information. * Returns false if the spectrum is unavailable or low resolution, unless there are only high-resolution instrument configurations in the data * scanStartTime is only modified if the needed CVParam is available. *********************************************************************************/ bool SpectrumList_MZRefiner::Impl::getPrecursorHighResAndStartTime(const Precursor& p, double& scanStartTime) const { if (p.sourceFilePtr != NULL) { // skip it - it's external, and therefore may not be locally available return false; } size_t precursorIndex = spectrumList->find(p.spectrumID); SpectrumPtr precursorData; // If the precursor index is present and valid, use the precursor scan time instead of the MSn scan time if (precursorIndex != spectrumList->size()) { precursorData = spectrumList->spectrum(precursorIndex, false); // Check to see if the precursor is high resolution, and get the precursor scan start time. if (!getSpectrumHighResAndStartTime(precursorData->scanList.scans, scanStartTime)) { // Precursor is not high resolution. Leave as-is. return false; } } else if (!allHighRes_) { // Assume precursor is low-res. return false; } // else: If all high-res and precursor data is not available, use the MSn scan start time, since it should be pretty close (assuming only one high-res analyzer exists in the run) return true; } /**************************************************************************************** * Some identification programs output the experimental m/z with isotope error removed, some do not. * This gives a way to clean up a good number of the results so they are usable * There is undoubtedly room for improvement. *****************************************************************************************/ bool SpectrumList_MZRefiner::Impl::cleanIsotopes(ScanDataPtr& sd) const { double windowAdj = 0.05; double chargeWithSign = sd->charge; if (sd->massError < 0) { chargeWithSign = -chargeWithSign; } bool changed = false; if (sd->charge != 0) { for (int i = 1; i <= 5; ++i) { double adjustment = (double)i / chargeWithSign; // Check to see if the adjustment will put the mass error inside of a tight window if ((adjustment - windowAdj) <= sd->massError && sd->massError <= (adjustment + windowAdj)) { sd->experMz = sd->experMz - adjustment; sd->massError = sd->experMz - sd->calcMz; sd->ppmError = (sd->massError / sd->calcMz) * 1.0e6; changed = true; break; } } } return changed; } /******************************************************************************************* * Read the mzid file, and pull out the necessary data. ******************************************************************************************* * There is some console output in this function which may not be very useful in the final version. ******************************************************************************************/ void SpectrumList_MZRefiner::Impl::processIdentData(const MSData& msd, pwiz::util::IterationListenerRegistry* ilr) { // TODO: log output at a high detail level... //cout << "Reading file \"" << identFilePath << "\"" << endl; IdentDataFile b(identFilePath, 0, ilr); BOOST_FOREACH(const AnalysisSoftwarePtr &as, b.analysisSoftwareList) { // softwareName must have either a cvParam or a userParam // If it has a userParam, we don't really care - the identification software probably doesn't have any score cvParams either if (!as->softwareName.cvParams.empty()) { filterConfigData_.software = as->softwareName.cvParams.front().cvid; /// Get the analysis software name..... break; // Get the name of the first analysis software only; might need to change to the last one. } } CVConditionalFilterPtr filter = CVConditionalFilterPtr(new CVConditionalFilter(filterConfigData_)); filterScoreName_ = filter->getScoreName(); filterThreshold_ = filter->getThreshold(); sortFilter f(filter); // Make a functor out of the filter. // Use the iteration listener registry to provide information to anything that will use it. int totalResults = 0; BOOST_FOREACH(const SpectrumIdentificationListPtr& sil, b.dataCollection.analysisData.spectrumIdentificationList) { totalResults += sil->spectrumIdentificationResult.size(); } // Set the total count to the number of results times the max steps; if the progress bar jumps forward, people don't care, but having it move backwards usually isn't appreciated. pwiz::util::IterationListener::UpdateMessage message(0, totalResults * (filterConfigData_.maxSteps > 0 ? filterConfigData_.maxSteps : 1), "Processing and filtering spectrum identifications..."); if (ilr && ilr->broadcastUpdateMessage(message) == pwiz::util::IterationListener::Status_Cancel) { // Cancel requested, return. return; } int specCounter = 0; int stepCounter = -1; // Becomes '0' for the first pass. int lessBad = 0; int excess = 0; bool adjustedFilter = true; vector tempData; while (adjustedFilter) { stepCounter++; specCounter = 0; adjustedFilter = false; data.clear(); bad_ = 0; lessBad = 0; excess = 0; BOOST_FOREACH(const SpectrumIdentificationListPtr& sil, b.dataCollection.analysisData.spectrumIdentificationList) { BOOST_FOREACH(const SpectrumIdentificationResultPtr& sir, sil->spectrumIdentificationResult) { specCounter++; if (ilr) { message.iterationIndex = specCounter + (stepCounter * totalResults); // Show some form of smooth progress across step iterations. pwiz::util::IterationListener::Status status = ilr->broadcastUpdateMessage(message); if (status == pwiz::util::IterationListener::Status_Cancel) { return; } } size_t scanId; string nativeID = sir->spectrumID; /******************************************************************************************************** * Formats and scan id/native id: * Ident formats: * * mzIdentML: Has Native ID, not necessarily a scan number * * pepXML: Has Native ID, start/end scan may constitute a scan number * * MSData formats: * * Format_Text: (similar to mzML, without XML tags) Has Native ID Tested (as input): No * * Format_mzXML: Has a scan number (no Native ID) Tested (as input): No * * Format_mzML: Has Native ID Tested (as input): Yes * * Format_MGF: No scan number or Native ID (only RTINSECONDS) Tested (as input): No * * Format_MS1: No Native ID Tested (as input): No * * Format_CMS1: No Native ID Tested (as input): No * * Format_MS2: No Native ID Tested (as input): No * * Format_CMS2: No Native ID Tested (as input): No * * Format_MZ5: ???? Tested (as input): No * * This chunk of code will probably only be useful in limited cases. The native ID and scan number are * now only used when we need to read the scan start times from the data file, because they will (hopefully) * allow us to match up the identifications with their respective spectra in the data file. * The mzIdentML output from MS-GF+ currently does not have scan start times, so this has been tested with * mzML and mzIdentML input for Thermo data and Bruker QqTof data. Will be tested on Agilent QTOF data. * The scanId/scan number will be a problem with older Waters instruments in its current implementation. *********************************************************************************************************/ // Backwards compatibility, it is correct on older files (where the spectrumID value is inaccurate) // This is part of the output from MS-GF+; but not reliable for anything else that I know of. CVParam scanNum; scanNum = sir->cvParam(MS_scan_number_s__OBSOLETE); CVParam peakScan = sir->cvParam(MS_peak_list_scans); if (scanNum.empty()) { scanNum = sir->cvParam(MS_peak_list_scans); } if (scanNum.empty()) { CVID natIdType = pwiz::msdata::id::getDefaultNativeIDFormat(msd); string scanNumber = pwiz::msdata::id::translateNativeIDToScanNumber(natIdType, sir->spectrumID); if (!scanNumber.empty()) scanId = lexical_cast(scanNumber); else scanId = specCounter; } else { scanId = scanNum.valueAs(); } tempData.clear(); // Check for and store the scan start time, if provided. double scanStartTime = 0.0; CVParam scanTime = sir->cvParam(MS_scan_start_time); if (scanTime.empty()) { scanTime = sir->cvParam(MS_retention_time); } if (scanTime.empty()) { scanTime = sir->cvParam(MS_retention_time_s__OBSOLETE); } if (!scanTime.empty()) { scanStartTime = scanTime.timeInSeconds(); // Make sure to store it as seconds. } BOOST_FOREACH(SpectrumIdentificationItemPtr& sii, sir->spectrumIdentificationItem) { double scoreVal = 0.0; if (filter->passesFilter(sii, scoreVal)) { ScanDataPtr sd(new ScanData); sd->scanId = scanId; sd->nativeID = nativeID; sd->scanTime = scanStartTime; sd->calcMz = sii->calculatedMassToCharge; sd->experMz = sii->experimentalMassToCharge; sd->charge = sii->chargeState; sd->rank = sii->rank; sd->massError = sd->experMz - sd->calcMz; sd->ppmError = (sd->massError / sd->calcMz) * 1.0e6; sd->scoreValue = scoreVal; sd->peptideSeq = sii->peptidePtr->peptideSequence; sd->peptideSeqLength = sd->peptideSeq.length(); // Insert modifications if (sii->peptidePtr->modification.size() > 0) { vector mods(sd->peptideSeq.length() + 2, ""); BOOST_FOREACH(const ModificationPtr& m, sii->peptidePtr->modification) { if (mods[m->location] != "") { mods[m->location] += ","; } mods[m->location] += boost::lexical_cast(m->monoisotopicMassDelta); } for (int i = mods.size() - 1; i >= 0; i--) { if (mods[i] != "") { sd->peptideSeq.insert(i, "(" + mods[i] + ")"); } } } bool cleaned = false; bool worked = false; // If the isotopeScreenAdj is greater than 0.20, there is increasing likelihood that a false isotopic peak error will be found and corrected. // Instead, just skip this step, which will reduce the number of threshold-passing spectral identifications. if (isotopeScreenAdj_ <= 0.20 && abs(sd->massError) >= isotopeScreenAdj_) { cleaned = true; worked = cleanIsotopes(sd); } if (abs(sd->massError) < isotopeFilter_ && abs(sd->ppmError) <= ppmErrorLimit_) { // If there is only one match for the spectrum, use it if (sir->spectrumIdentificationItem.size() == 1) { data.push_back(sd); } else { // Since there are multiple identifications for this spectrum, we will temporarily store them to only use the best one. tempData.push_back(sd); } } else { ++bad_; ++lessBad; } } else { ++bad_; } } // End BOOST_FOREACH SpectrumIdentificationItem // Sort multiple SpectrumIdentificationItems by score, and only keep the best. if (!tempData.empty()) { if (tempData.size() == 1) { // Only one of the multiple matches passed the threshold... data.push_back(tempData.front()); } else { // Sort by score value // could also use : (but requires more allocations, or something of the sort.) // std::sort(tempData.begin(), tempData.end(), sortFilter(filter)); std::sort(tempData.begin(), tempData.end(), f); // Select and insert highest score value data.push_back(tempData.front()); // increment excess by number not used excess += tempData.size() - 1; } } } // End BOOST_FOREACH SpectrumIdentificationResult } // End BOOST_FOREACH SpectrumIdentificationList if (data.size() < MINIMUM_RESULTS_FOR_DEPENDENT_SHIFT) { adjustedFilter = filter->adjustFilterByStep(); } } if (data.size() < MINIMUM_RESULTS_FOR_GLOBAL_SHIFT) { // If there are less than 100 high-quality data points, it's not worth shifting cout << "Excluding file \"" << identFilePath << "\" from data set." << endl; cout << "\tLess than " << MINIMUM_RESULTS_FOR_GLOBAL_SHIFT << " (" << data.size() << ") results after filtering." << endl; data.clear(); throw runtime_error("[mzRefiner::ctor] Less than " + lexical_cast(MINIMUM_RESULTS_FOR_GLOBAL_SHIFT)+" (" + lexical_cast(data.size()) + ") values in identfile that pass the threshold."); } else if (data.size() < MINIMUM_RESULTS_FOR_DEPENDENT_SHIFT) { // 500 is kind of arbitrary, but it seemed like a good number to use as a requirement for dependent data shifts // If there are only 500 data points, there will be very limited shift smoothing. cout << "Low number of good identifications found. Will not perform dependent shifts." << endl; cout << "\tLess than " << MINIMUM_RESULTS_FOR_DEPENDENT_SHIFT << " (" << data.size() << ") results after filtering." << endl; } // Number if identifications that didn't pass the threshold. badByScore_ = bad_ - lessBad; // Number of identifications that passed the threshold, but the isotope error couldn't be fixed (out of range) badByMassError_ = lessBad; } /*************************************************************** * Basic function to read the scan times from an MSData object * A good improvement would be to use nativeID indexes to only get the spectra we need. * But that improvement would be limited in use to files input from native, mzML, mzXML, and (maybe) text. ****************************************************************/ void SpectrumList_MZRefiner::Impl::getMSDataData(const MSData& msd, pwiz::util::IterationListenerRegistry* ilr) { if (data.size() < MINIMUM_RESULTS_FOR_DEPENDENT_SHIFT) { // Don't bother reading the scan start times/MS2 data if we don't have enough results to run the dependent shifts return; } // TODO: Log at a high detail level //cout << "Reading scan start times and/or data arrays from the data file...." << endl; // Report what is going on using the iteration listener... pwiz::util::IterationListener::UpdateMessage message(0, msd.run.spectrumListPtr->size(), "Reading scan start times and/or data arrays from data file..."); if (ilr && ilr->broadcastUpdateMessage(message) == pwiz::util::IterationListener::Status_Cancel) { return; } const SpectrumListPtr& sl = msd.run.spectrumListPtr; sl.get(); ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Probably need to get something better than scanId to sort by, but needs to be reliable. // Searching would be really expensive // (Using nativeID indexes would remove this issue) (but would not be applicable to all possible MSData input types) ////////////////////////////////////////////////////////////////////////////////////////////////////////////// std::sort(data.begin(), data.end(), ScanData::byScanIdPtr2); size_t dataIndex = 0; for (size_t i = 0; i < sl->size() && dataIndex < data.size(); ++i) { if (ilr) { message.iterationIndex = i; // + 1? pwiz::util::IterationListener::Status status = ilr->broadcastUpdateMessage(message); if (status == pwiz::util::IterationListener::Status_Cancel) { return; } } // Don't read the binary data right now - it can take a long time to read, and we don't know if we need it until we have other information about the spectrum. // It is significantly faster than reading binary data by default. SpectrumPtr s = sl->spectrum(i, false); // Not interested in the binary data right now. // TODO: potentially unsafe casting, should fix (how?) ScanDataPtr datum = boost::static_pointer_cast(data[dataIndex]); if (!s) { continue; } if (s->id != datum->nativeID) { continue; } double scanStartTime = 0; bool isHighRes = getSpectrumHighResAndStartTime(s->scanList.scans, scanStartTime); BOOST_FOREACH(Precursor &p, s->precursors) { // Not worried about precursor resolution right now. getPrecursorHighResAndStartTime(p, scanStartTime); // Only worried about the first scan start time. break; } int msLevel = 0; if (s->hasCVParam(MS_MS1_spectrum)) { msLevel = 1; } else if (s->hasCVParam(MS_ms_level)) { msLevel = s->cvParam(MS_ms_level).valueAs(); } while (s->id == datum->nativeID) { datum->scanTime = scanStartTime; datum->msLevel = msLevel; if (isHighRes && msLevel > 1 && msLevelsToRefine.contains(msLevel)) { // We need the binary data now, so re-read the spectrum with binary data. if (!s->hasBinaryData()) { s = sl->spectrum(i, true); // Need binary data for MSn error calculation. } // Add fragmentation ion data to the ms2Data for a separate shift. fragmentationIonPpmErrors(datum->peptideSeq, datum->peptideSeqLength, s); } ++dataIndex; if (dataIndex >= data.size()) { break; } // TODO: potentially unsafe casting, should fix (how?) datum = boost::static_pointer_cast(data[dataIndex]); } } } /******************************************************************************** * Insert the fragmentation ion and error data into ms2Data for the specified peptide and spectrum ********************************************************************************/ void SpectrumList_MZRefiner::Impl::fragmentationIonPpmErrors(const string& peptideSeq, const int& peptideSeqLength, const SpectrumPtr& s) { const double mzErrorThreshold = 0.1; const double ppmErrorThreshold = 25; // Get the scan start time. (passed in...) double scanStartTime = 0; if (!getSpectrumHighResAndStartTime(s->scanList.scans, scanStartTime)) { // exit out of function - we don't do shifts on low-res data. return; } // Stash a reference to the m/z array pwiz::msdata::BinaryDataArrayPtr mzArray = s->getMZArray(); double maxMZ = mzArray->data.back(); int maxMap = maxMZ + 5; // Create a mapping of sorts to decrease search times for close ions vector mapping(maxMap, 0); int j = 0; for (int i = 0; i < mapping.size(); i++) { while (j < mzArray->data.size() && i > mzArray->data[j]) { j++; } mapping[i] = j; } // Get the dissociation type: HCD, CID, ETD (from spectrum->precursorlist->precursor->activation->cvparams) // Get the likely present ion types /* Dissociation types available in CV: MS_collision_induced_dissociation MS_trap_type_collision_induced_dissociation MS_beam_type_collision_induced_dissociation MS_higher_energy_beam_type_collision_induced_dissociation MS_in_source_collision_induced_dissociation MS_plasma_desorption MS_post_source_decay MS_surface_induced_dissociation MS_blackbody_infrared_radiative_dissociation MS_electron_capture_dissociation MS_electron_transfer_dissociation MS_infrared_multiphoton_dissociation MS_sustained_off_resonance_irradiation MS_low_energy_collision_induced_dissociation MS_photodissociation MS_pulsed_q_dissociation MS_LIFT */ // see http://www.matrixscience.com/help/fragmentation_help.html vector cvps; BOOST_FOREACH(const Precursor &p, s->precursors) { vector cvpt = p.activation.cvParamChildren(MS_dissociation_method); BOOST_FOREACH(CVParam& cvp, cvpt) { cvps.push_back(cvp); } } bool hasAIons = false; bool hasBIons = false; bool hasCIons = false; bool hasXIons = false; bool hasYIons = false; bool hasZIons = false; BOOST_FOREACH(const CVParam& cvp, cvps) { CVID dissociation = cvp.cvid; if (dissociation == MS_collision_induced_dissociation /*CID*/ || dissociation == MS_trap_type_collision_induced_dissociation /*CID*/ || dissociation == MS_in_source_collision_induced_dissociation) { //hasAIons = true; hasBIons = true; hasYIons = true; // Notes: fragments with "RKNQ" can have lost ammonia (-17 Da) // Notes: fragments with "STED" can have lost water (-18 Da) (neutral loss) } if (dissociation == MS_beam_type_collision_induced_dissociation /*HCD*/ || dissociation == MS_higher_energy_beam_type_collision_induced_dissociation /*HCD*/) { //hasAIons = true; hasBIons = true; hasYIons = true; } if (dissociation == MS_post_source_decay /*PSD*/) { //hasAIons = true; hasBIons = true; hasYIons = true; } if (dissociation == MS_electron_capture_dissociation /*HCD*/ || dissociation == MS_electron_transfer_dissociation /*HCD*/) { hasCIons = true; //hasYIons = true; hasZIons = true; // z+1, z+2 } } // Get the proper theoretical ions for the sequence // Include parsing and use of modifications. pwiz::proteome::Peptide pep(peptideSeq, pwiz::proteome::ModificationParsing_ByMass, pwiz::proteome::ModificationDelimiter_Parentheses); pwiz::proteome::Fragmentation frag = pep.fragmentation(true, true); vector ions; // frag.type(0, charge) returns the n- or c-term fragmentation, and frag.type(peptideLength, charge) is valid for most types. // No point in using the '0' charge masses, since the mass spectrometer can't detect them anyway. for (int i = 0; i <= peptideSeqLength; i++) { if (hasAIons) { ions.push_back(frag.a(i, 1)); ions.push_back(frag.a(i, 2)); ions.push_back(frag.a(i, 3)); } if (hasBIons) { ions.push_back(frag.b(i, 1)); ions.push_back(frag.b(i, 2)); ions.push_back(frag.b(i, 3)); } if (hasCIons && i != peptideSeqLength) { ions.push_back(frag.c(i, 1)); ions.push_back(frag.c(i, 2)); ions.push_back(frag.c(i, 3)); } if (hasXIons && i != peptideSeqLength) { ions.push_back(frag.x(i, 1)); ions.push_back(frag.x(i, 2)); ions.push_back(frag.x(i, 3)); } if (hasYIons) { ions.push_back(frag.y(i, 1)); ions.push_back(frag.y(i, 2)); ions.push_back(frag.y(i, 3)); } if (hasZIons) { ions.push_back(frag.z(i, 1)); ions.push_back(frag.z(i, 2)); ions.push_back(frag.z(i, 3)); } } // Find the best match actual ions for the theoretical ions // Calculate and store the ppm error for each match BOOST_FOREACH(double ion, ions) { if (ion >= 0 && ion < mapping.size()) { int closeIndex = mapping[(int)ion]; int lowSearch = closeIndex - 10; int highSearch = closeIndex + 10; if (lowSearch < 0) { lowSearch = 0; } if (highSearch > mzArray->data.size()) { highSearch = mzArray->data.size(); } double closestError = 100; double experMass = 0; double closestPpm = 100; for (int i = lowSearch; i < highSearch; i++) { if (abs(ion - mzArray->data[i]) < abs(closestError)) { experMass = mzArray->data[i]; closestError = ion - mzArray->data[i]; closestPpm = ((mzArray->data[i] - ion) / ion) * 1.0e6; } } if (abs(closestError) <= mzErrorThreshold && abs(closestPpm) <= ppmErrorThreshold) { // Add to the collection of MS2 data points for shift calculation. ShiftDataPtr datum(new ShiftData); datum->calcMz = ion; datum->experMz = experMass; datum->massError = closestError; datum->ppmError = closestPpm; datum->scanTime = scanStartTime; ms2Data.push_back(datum); } } } } /******************************************************************************** * Run the shift calculator for all data sets *******************************************************************************/ void SpectrumList_MZRefiner::Impl::shiftCalculator(pwiz::util::IterationListenerRegistry* ilr) { AdjustSimpleGlobalPtr globalShift; AdjustByScanTimePtr scanTimeShift; AdjustByMassToChargePtr mzShift; ostringstream statsRow; // Output excluded identifications statsRow << filterScoreName_ << '\t' << filterThreshold_ << '\t' << badByScore_ << '\t' << badByMassError_ << '\t'; if (msLevelsToRefine.contains(1)) { //cout << "Calculating MS1 shift" << endl; shiftCalculator(ilr, data, globalShift, scanTimeShift, mzShift, adjust, "MS1"); // Output MS1 shift stats statsRow << data.size() << '\t'; /*statsRow << globalShift->getAvgError() << '\t' << globalShift->getMedianError() << '\t' << globalShift->getMAD() << '\t'; if (adjust != globalShift) statsRow << scanTimeShift->getRoughMAD() << '\t' << scanTimeShift->getSmoothedMAD() << '\t' << mzShift->getRoughMAD() << '\t' << mzShift->getSmoothedMAD() << '\t' << scanTimeShift->getRoughPctImpMAD() << '\t' << scanTimeShift->getSmoothedPctImpMAD() << '\t' << mzShift->getRoughPctImpMAD() << '\t' << mzShift->getSmoothedPctImpMAD() << '\t'; else statsRow << "\t\t\t\t\t\t\t\t";*/ if (adjust == globalShift) statsRow << "global\t"; else if (adjust == scanTimeShift) statsRow << "scan time\t"; else if (adjust == mzShift) statsRow << "m/z\t"; else throw runtime_error("[SpectrumList_MZRefiner::shiftCalculator] could not determine chosen shift method"); statsRow << adjust->getStDev() << '\t' << adjust->getStDev() * 3 << '\t' << adjust->getMAD() << '\t' << adjust->getMAD() * (3 * 1.4826); // Estimated conversion scale from MAD to StDev, Normal Population: 1 StDev ~= 1.4826 MAD } else { statsRow << "\t" /*\t\t\t\t\t\t\t\t\t\t\t*/ "\t\t\t\t"; } statsRow << '\t'; if (msLevelsToRefine.contains(2)) { // Only calculate the MS2 shift if there are sufficient results. // if there aren't, default to the MS1 shift, which will not be used for low-res MS2 data shifting anyway. if (ms2Data.size() >= 100) { //cout << "Calculating MS2 shift" << endl; shiftCalculator(ilr, ms2Data, globalShift, scanTimeShift, mzShift, ms2Adjust, "MS2"); } else { // use the ms1 adjustment for MS2? ms2Adjust = adjust; } // Output MS2 shift stats statsRow << ms2Data.size() << '\t'; /*statsRow << globalShift->getAvgError() << '\t' << globalShift->getMedianError() << '\t' << globalShift->getMAD() << '\t'; if (ms2Adjust != globalShift) statsRow << scanTimeShift->getRoughMAD() << '\t' << scanTimeShift->getSmoothedMAD() << '\t' << mzShift->getRoughMAD() << '\t' << mzShift->getSmoothedMAD() << '\t' << scanTimeShift->getRoughPctImpMAD() << '\t' << scanTimeShift->getSmoothedPctImpMAD() << '\t' << mzShift->getRoughPctImpMAD() << '\t' << mzShift->getSmoothedPctImpMAD() << '\t'; else statsRow << "\t\t\t\t\t\t\t\t";*/ if (ms2Adjust == globalShift) statsRow << "global\t"; else if (ms2Adjust == scanTimeShift) statsRow << "scan time\t"; else if (ms2Adjust == mzShift) statsRow << "m/z\t"; else if (ms2Adjust == adjust) statsRow << "same as MS1\t"; else throw runtime_error("[SpectrumList_MZRefiner::shiftCalculator] could not determine chosen shift method"); statsRow << ms2Adjust->getStDev() << '\t' << ms2Adjust->getStDev() * 3 << '\t' << ms2Adjust->getMAD() << '\t' << ms2Adjust->getMAD() * (3 * 1.4826); // Estimated conversion scale from MAD to StDev, Normal Population: 1 StDev ~= 1.4826 MAD } else { statsRow << "\t" /*\t\t\t\t\t\t\t\t\t\t\t*/ "\t\t\t\t"; } statsRow << endl; *statStream_ << statsRow.str(); statStream_->close(); } /******************************************************************************** * Calculate statistics, and determine best shifting strategy ******************************************************************************** * This function has a lot of output that has been useful in development, * most of which will probably be removed from the final version, depending * on how useful it is for further analysis. *******************************************************************************/ void SpectrumList_MZRefiner::Impl::shiftCalculator(pwiz::util::IterationListenerRegistry* ilr, vector& shiftData, AdjustSimpleGlobalPtr& globalShift, AdjustByScanTimePtr& scanTimeShift, AdjustByMassToChargePtr& mzShift, AdjustmentObjectPtr& adjustment, string shiftDataType) const { pwiz::util::IterationListener::UpdateMessage message(0, 4, "Calculating and comparing possible adjustments"); if (ilr && ilr->broadcastUpdateMessage(message) == pwiz::util::IterationListener::Status_Cancel) { // Cancel requested, return. return; } adjustment.reset(); // Sanity check if (shiftData.size() < MINIMUM_RESULTS_FOR_GLOBAL_SHIFT) return; // Get the global shift data globalShift.reset(new AdjustSimpleGlobal); globalShift->calculate(shiftData); // Check for a decent peak; if we don't have one, exit/throw exception - but only for MS1 shifts. if (!(globalShift->checkForPeak()) && shiftDataType == "MS1") { // Return null - no shift will be performed //cout << "Chose no shift - poor histogram peak." << endl; throw runtime_error("[mzRefiner::shiftCalculator] No significant peak (ppm error histogram) found."); } message.iterationIndex = 1; if (ilr && ilr->broadcastUpdateMessage(message) == pwiz::util::IterationListener::Status_Cancel) { // Cancel requested, return. return; } string chosen = ""; // Only calculate the dependent shifts if there is enough data. if (shiftData.size() >= MINIMUM_RESULTS_FOR_DEPENDENT_SHIFT) { double gShift = globalShift->getShift(); double gStDev = globalShift->getStDev(); double gMAD = globalShift->getMAD(); scanTimeShift.reset(new AdjustByScanTime(gShift, gStDev, gMAD)); message.iterationIndex = 2; if (ilr && ilr->broadcastUpdateMessage(message) == pwiz::util::IterationListener::Status_Cancel) { // Cancel requested, return. return; } mzShift.reset(new AdjustByMassToCharge(gShift, gStDev, gMAD)); message.iterationIndex = 3; if (ilr && ilr->broadcastUpdateMessage(message) == pwiz::util::IterationListener::Status_Cancel) { // Cancel requested, return. return; } // Perform their respective calculations scanTimeShift->calculate(shiftData); mzShift->calculate(shiftData); double improvThreshold = 3.0; // Determine the best solution // Prefer a scan time shift over a mass to charge shift if the improvement for the mass to charge shift is less than 10% more //if (scanTimeShift->getPctImp() > improvThreshold && scanTimeShift->getPctImp() > (mzShift->getPctImp() - 10.0)) if (scanTimeShift->getPctImp() > improvThreshold && scanTimeShift->getPctImp() > mzShift->getPctImp()) { chosen = "Chose scan time shift..."; adjustment = scanTimeShift; } else if (mzShift->getPctImp() > improvThreshold) { chosen = "Chose mass to charge shift..."; adjustment = mzShift; } } // If we didn't/couldn't choose a dependent shift, do a global shift if (!adjustment) { chosen = "Chose global shift..."; adjustment = globalShift; } message.iterationIndex = 4; if (ilr && ilr->broadcastUpdateMessage(message) == pwiz::util::IterationListener::Status_Cancel) { // Cancel requested, return. return; } } // // SpectrumList_MZRefiner // PWIZ_API_DECL SpectrumList_MZRefiner::SpectrumList_MZRefiner( const MSData& msd, const string& identFilePath, const string& cvTerm, const string& rangeSet, const util::IntegerSet& msLevelsToRefine, double step, int maxStep, pwiz::util::IterationListenerRegistry* ilr) : SpectrumListWrapper(msd.run.spectrumListPtr), impl_(new Impl(msLevelsToRefine, CVConditionalFilter::CVConditionalFilterConfigData(cvTerm, rangeSet, step, maxStep))) { // Determine if file has High-res scans... // Exit if we don't have any high-res data if (!impl_->containsHighResData(msd)) { cerr << "\tError: No high-resolution data in input file.\n\tSkipping mzRefiner." << endl; throw pwiz::util::user_error("[mzRefiner::ctor] No high-resolution data in input file."); } // Configure and run shift calculations impl_->configureShift(msd, identFilePath, ilr); // Exit if the shift calculations did not succeed for some reason if (impl_->data.size() == 0 || !impl_->adjust) { // Throw exception: Could not shift - Reason unknown (specific reasons are thrown where they occur) throw runtime_error("[mzRefiner::ctor] Shift calculation failed."); } // add processing methods to the copy of the inner SpectrumList's data processing ProcessingMethod method; method.order = dp_->processingMethods.size(); method.cvParams.push_back(CVParam(MS_m_z_calibration)); // userparams: // All parameters that affect the outcome that are not available as cvParams // add identfile name, path method.userParams.push_back(UserParam("Identification File", identFilePath)); // filter score param name method.userParams.push_back(UserParam("Filter score name", impl_->getFilterScoreName())); // filter score threshold method.userParams.push_back(UserParam("Filter score threshold", impl_->getFilterThreshold())); // shift type method.userParams.push_back(UserParam("Shift dependency", impl_->adjust->getPrettyAdjustment())); // shift range method.userParams.push_back(UserParam("Shift range", impl_->adjust->getShiftRange())); // global ppm error (on all) method.userParams.push_back(UserParam("Global Median Mass Measurement Error (PPM)", lexical_cast(impl_->adjust->getGlobalShift()))); if (!dp_->processingMethods.empty()) method.softwarePtr = dp_->processingMethods[0].softwarePtr; dp_->processingMethods.push_back(method); } PWIZ_API_DECL SpectrumPtr SpectrumList_MZRefiner::spectrum(size_t index, bool getBinaryData) const { if (!impl_->adjust) { // This shouldn't be hit with the exceptions being thrown elsewhere; still here for safety // May be useful in the future with chained filters and a user option to continue with failed filters. return inner_->spectrum(index, getBinaryData); } SpectrumPtr originalSpectrum = inner_->spectrum(index, getBinaryData); // Determine if is High-res scan, and get the start time as well - they should both be available in the scans bool isHighRes = false; double scanTime = 0.0; isHighRes = getSpectrumHighResAndStartTime(originalSpectrum->scanList.scans, scanTime); // Commonly used items, declare them only once - each use is atomic: // get a iterator to the desired CVParam, read and store shifted value to 'value', // convert 'value' to string and overwrite the CVParam's value variable. vector::iterator it; double value = 0; // Get the msLevel to reliably choose the right data shift CVParam msLevel = originalSpectrum->cvParam(MS_ms_level); int msLevelInt = 1; if (!msLevel.empty()) { msLevelInt = msLevel.valueAs(); } // On a high-res result, we want to adjust more than just precursor data; we can shift the m/z values in the data array if (isHighRes && impl_->msLevelsToRefine.contains(msLevelInt)) { // use the ms2 shift for MSn scans AdjustmentObjectPtr adjust = impl_->adjust; if (msLevelInt > 1) { adjust = impl_->ms2Adjust; } double value = 0; // Adjust the metadata // Using an iterator to allow direct overwrite of the value - other methods return a copy of the CVParam it = find_if(originalSpectrum->cvParams.begin(), originalSpectrum->cvParams.end(), CVParamIs(MS_base_peak_m_z)); if (it != originalSpectrum->cvParams.end()) { value = adjust->shift(scanTime, it->valueAs()); it->value = boost::lexical_cast(value); } it = find_if(originalSpectrum->cvParams.begin(), originalSpectrum->cvParams.end(), CVParamIs(MS_lowest_observed_m_z)); if (it != originalSpectrum->cvParams.end()) { value = adjust->shift(scanTime, it->valueAs()); it->value = boost::lexical_cast(value); } it = find_if(originalSpectrum->cvParams.begin(), originalSpectrum->cvParams.end(), CVParamIs(MS_highest_observed_m_z)); if (it != originalSpectrum->cvParams.end()) { value = adjust->shift(scanTime, it->valueAs()); it->value = boost::lexical_cast(value); } // Adjust the spectrum data (all m/z values) BOOST_FOREACH(BinaryDataArrayPtr &bda, originalSpectrum->binaryDataArrayPtrs) { if (bda->hasCVParam(MS_m_z_array)) { BOOST_FOREACH(double &mass, bda->data) { mass = adjust->shift(scanTime, mass); } } } } // High res adjustments // return MS1 without precursor adjustments... // MS/MS precursor adjustment : Find and check the precursor for high-res-ness, if possible. if (!msLevel.empty() && msLevelInt >= 2 && impl_->msLevelsToRefine.contains(msLevelInt - 1)) { double pScanTime = scanTime; // MSn spectrum precursor adjustment BOOST_FOREACH(Precursor &p, originalSpectrum->precursors) { pScanTime = scanTime; // Don't adjust low-resolution precursors, and get the precursor scan time if available. if (!impl_->getPrecursorHighResAndStartTime(p, pScanTime)) { continue; } // else: If all high-res and precursor data is not available, use the MSn scan start time, since it should be pretty close (assuming only one high-res analyzer exists in the run) it = find_if(p.isolationWindow.cvParams.begin(), p.isolationWindow.cvParams.end(), CVParamIs(MS_isolation_window_target_m_z)); if (it != p.isolationWindow.cvParams.end()) { value = impl_->adjust->shift(pScanTime, it->valueAs()); it->value = boost::lexical_cast(value); } BOOST_FOREACH(SelectedIon &si, p.selectedIons) { it = find_if(si.cvParams.begin(), si.cvParams.end(), CVParamIs(MS_selected_ion_m_z)); if (it != si.cvParams.end()) { value = impl_->adjust->shift(pScanTime, it->valueAs()); it->value = boost::lexical_cast(value); } } } BOOST_FOREACH(Scan &s, originalSpectrum->scanList.scans) { // Adjust the thermo-specific Monoisotopic m/z BOOST_FOREACH(UserParam &up, s.userParams) { if (up.name == "[Thermo Trailer Extra]Monoisotopic M/Z:") { value = impl_->adjust->shift(pScanTime, up.valueAs()); up.value = boost::lexical_cast(value); } } } } // MS/MS precursor adjustment return originalSpectrum; } } // namespace analysis } // namespace pwiz pwiz/pwiz/analysis/spectrum_processing/SpectrumList_ScanSummer.hpp0000664000175100017510000000551512664775615030002 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_ScanSummer.hpp 6567 2014-08-01 20:14:32Z pcbrefugee $ // // // Original author: William French // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_SCANSUMMER_HPP_ #define _SPECTRUMLIST_SCANSUMMER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/SpectrumListWrapper.hpp" typedef struct { double mz; double intensity; } parentIon; typedef struct { double precursorMZ; double rTimeStart; std::vector indexList; } precursorGroup; namespace pwiz { namespace analysis { /// Provides a custom-sorted spectrum list class PWIZ_API_DECL SpectrumList_ScanSummer : public msdata::SpectrumListWrapper { public: SpectrumList_ScanSummer(const msdata::SpectrumListPtr& inner, double precursorTol, double rTimeTol); void pushSpectrum(const msdata::SpectrumIdentity&); double getPrecursorMz(const msdata::Spectrum&) const; //void sumSubScansResample( std::vector &, std::vector &, size_t, msdata::DetailLevel) const; void sumSubScansNaive( std::vector &, std::vector &, size_t, msdata::DetailLevel) const; virtual size_t size() const; virtual const msdata::SpectrumIdentity& spectrumIdentity(size_t index) const; virtual msdata::SpectrumPtr spectrum(size_t index, bool getBinaryData = false) const; virtual msdata::SpectrumPtr spectrum(size_t index, msdata::DetailLevel) const; private: double lowerMZlimit; double upperMZlimit; double TotalDaltons; double precursorTol_; double rTimeTol_; mutable int ms2cnt; std::vector spectrumIdentities; // local cache, with fixed up index fields std::vector indexMap; // maps index -> original index std::vector< precursorGroup > precursorList; std::vector< precursorGroup > ms2RetentionTimes; SpectrumList_ScanSummer(SpectrumList_ScanSummer&); //copy constructor SpectrumList_ScanSummer& operator=(SpectrumList_ScanSummer&); //assignment operator }; } // namespace analysis } // namespace pwiz #endif // _SPECTRUMLIST_SCANSUMMER_HPP_ pwiz/pwiz/data/msdata/ChromatogramList_mzML.hpp0000664000175100017510000000275012664775621023661 0ustar teamcityteamcity00000000000000// // $Id: ChromatogramList_mzML.hpp 2898 2011-08-01 17:55:13Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _CHROMATOGRAMLIST_MZML_HPP_ #define _CHROMATOGRAMLIST_MZML_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "ChromatogramListBase.hpp" #include "Index_mzML.hpp" #include namespace pwiz { namespace msdata { /// implementation of ChromatogramList, backed by an mzML file class PWIZ_API_DECL ChromatogramList_mzML : public ChromatogramListBase { public: static ChromatogramListPtr create(boost::shared_ptr is, const MSData& msd, const Index_mzML_Ptr& indexPtr); }; } // namespace msdata } // namespace pwiz #endif // _CHROMATOGRAMLIST_MZML_HPP_ pwiz/pwiz/data/msdata/SpectrumListBase.hpp0000664000175100017510000000421112664775620022665 0ustar teamcityteamcity00000000000000// // $Id: SpectrumListBase.hpp 8725 2015-08-04 15:49:57Z pcbrefugee $ // // // Original author: Darren Kessner // // Copyright 2009 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLISTBASE_HPP_ #define _SPECTRUMLISTBASE_HPP_ #include "pwiz/data/msdata/MSData.hpp" #include "pwiz/utility/misc/IntegerSet.hpp" #include #include #include namespace pwiz { namespace msdata { /// common functionality for base SpectrumList implementations class PWIZ_API_DECL SpectrumListBase : public SpectrumList { public: SpectrumListBase() : MSLevelsNone() {}; /// implementation of SpectrumList virtual const boost::shared_ptr dataProcessingPtr() const {return dp_;} /// set DataProcessing virtual void setDataProcessingPtr(DataProcessingPtr dp) { dp_ = dp; } /// issues a warning once per SpectrumList instance (based on string hash) virtual void warn_once(const char* msg) const { boost::hash H; if (warn_msg_hashes.insert(H(msg)).second) // .second is true iff value is new { std::cerr << msg << std::endl; } } protected: DataProcessingPtr dp_; // Useful for avoiding repeated ctor when you just want an empty set const pwiz::util::IntegerSet MSLevelsNone; private: mutable std::set warn_msg_hashes; // for warn_once use }; } // namespace msdata } // namespace pwiz #endif // _SPECTRUMLISTBASE_HPP_ pwiz/pwiz/data/msdata/DefaultReaderList.cpp0000775000175100017510000004064712664775620023012 0ustar teamcityteamcity00000000000000// // $Id: DefaultReaderList.cpp 5759 2014-02-19 22:26:29Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/minimxml/SAXParser.hpp" #include "DefaultReaderList.hpp" #include "SpectrumList_mzXML.hpp" #include "SpectrumList_MGF.hpp" #include "SpectrumList_MSn.hpp" #include "SpectrumList_BTDX.hpp" #include "Serializer_mzML.hpp" #include "Serializer_mzXML.hpp" #include "Serializer_MGF.hpp" #include "Serializer_MSn.hpp" #ifndef WITHOUT_MZ5 #include "Serializer_mz5.hpp" #endif #include "References.hpp" #include "ChromatogramListBase.hpp" #include "pwiz/data/msdata/Version.hpp" #ifndef WITHOUT_MZ5 #include "mz5/Connection_mz5.hpp" #endif namespace pwiz { namespace msdata { using namespace pwiz::minimxml; namespace { void appendSourceFile(const string& filename, MSData& msd) { SourceFilePtr sourceFile(new SourceFile); bfs::path p(filename); sourceFile->id = sourceFile->name = BFS_STRING(p.leaf()); sourceFile->location = "file:///" + BFS_COMPLETE(p.branch_path()).string(); msd.fileDescription.sourceFilePtrs.push_back(sourceFile); } SoftwarePtr getSoftwarePwiz(vector& softwarePtrs) { string version = pwiz::msdata::Version::str(); for (vector::const_iterator it=softwarePtrs.begin(); it!=softwarePtrs.end(); ++it) if ((*it)->hasCVParam(MS_pwiz) && (*it)->version==version) return *it; SoftwarePtr sp(new Software); sp->id = "pwiz_" + version; sp->set(MS_pwiz); sp->version = pwiz::msdata::Version::str(); softwarePtrs.push_back(sp); return sp; } void fillInCommonMetadata(const string& filename, MSData& msd) { appendSourceFile(filename, msd); msd.cvs = defaultCVList(); SoftwarePtr softwarePwiz = getSoftwarePwiz(msd.softwarePtrs); DataProcessingPtr dpPwiz(new DataProcessing); dpPwiz->id = "pwiz_Reader_conversion"; dpPwiz->processingMethods.push_back(ProcessingMethod()); dpPwiz->processingMethods.back().softwarePtr = softwarePwiz; dpPwiz->processingMethods.back().cvParams.push_back(MS_Conversion_to_mzML); // give ownership of dpPwiz to the SpectrumList (and ChromatogramList) SpectrumListBase* sl = dynamic_cast(msd.run.spectrumListPtr.get()); ChromatogramListBase* cl = dynamic_cast(msd.run.chromatogramListPtr.get()); if (sl) sl->setDataProcessingPtr(dpPwiz); if (cl) cl->setDataProcessingPtr(dpPwiz); // the file-level ids can't be empty if (msd.id.empty() || msd.run.id.empty()) msd.id = msd.run.id = bfs::basename(filename); } // return true if filename has form xxxx.ext or xxxx.ext.gz static bool has_extension(std::string const &test_filename,const char *ext) { std::string filename(test_filename); if (bal::iends_with(filename, ".gz")) filename.erase(filename.length()-3); return bal::iends_with(filename, ext); } } // namespace // // Reader_mzML // PWIZ_API_DECL std::string Reader_mzML::identify(const std::string& filename, const std::string& head) const { istringstream iss(head); return std::string((type(iss) != Type_Unknown)?getType():""); } PWIZ_API_DECL void Reader_mzML::read(const std::string& filename, const std::string& head, MSData& result, int runIndex, const Config& config) const { if (runIndex != 0) throw ReaderFail("[Reader_mzML::read] multiple runs not supported"); shared_ptr is(new pwiz::util::random_access_compressed_ifstream(filename.c_str())); if (!is.get() || !*is) throw runtime_error(("[Reader_mzML::read] Unable to open file " + filename).c_str()); switch (type(*is)) { case Type_mzML: { Serializer_mzML::Config config; config.indexed = false; Serializer_mzML serializer(config); serializer.read(is, result); break; } case Type_mzML_Indexed: { Serializer_mzML serializer; serializer.read(is, result); break; } case Type_Unknown: default: { throw runtime_error("[MSDataFile::Reader_mzML] This isn't happening."); } } fillInCommonMetadata(filename, result); } PWIZ_API_DECL void Reader_mzML::read(const std::string& filename, const std::string& head, std::vector& results, const Config& config) const { results.push_back(MSDataPtr(new MSData)); read(filename, head, *results.back(), 0, config); } Reader_mzML::Type Reader_mzML::type(istream& is) const { try { string rootElement = xml_root_element(is); if (rootElement == "indexedmzML") return Type_mzML_Indexed; if (rootElement == "mzML") return Type_mzML; } catch (runtime_error&) { } return Type_Unknown; } // // Reader_mzXML // PWIZ_API_DECL std::string Reader_mzXML::identify(const std::string& filename, const std::string& head) const { std::string result; try { string rootElement = xml_root_element(head); result = (rootElement == "mzXML" || rootElement == "msRun")?getType():""; } catch (runtime_error&) { } return result; } PWIZ_API_DECL void Reader_mzXML::read(const std::string& filename, const std::string& head, MSData& result, int runsIndex, const Config& config) const { if (runsIndex != 0) throw ReaderFail("[Reader_mzXML::read] multiple runs not supported"); shared_ptr is(new pwiz::util::random_access_compressed_ifstream(filename.c_str())); if (!is.get() || !*is) throw runtime_error(("[Reader_mzXML::read] Unable to open file " + filename).c_str()); try { // assume there is a scan index Serializer_mzXML serializer; serializer.read(is, result); fillInCommonMetadata(filename, result); result.fileDescription.sourceFilePtrs.back()->set(MS_scan_number_only_nativeID_format); result.fileDescription.sourceFilePtrs.back()->set(MS_ISB_mzXML_format); return; } catch (SpectrumList_mzXML::index_not_found&) {} // error looking for index -- try again, but generate index is->seekg(0); Serializer_mzXML::Config serializerConfig; serializerConfig.indexed = false; Serializer_mzXML serializer(serializerConfig); serializer.read(is, result); fillInCommonMetadata(filename, result); result.fileDescription.sourceFilePtrs.back()->set(MS_scan_number_only_nativeID_format); result.fileDescription.sourceFilePtrs.back()->set(MS_ISB_mzXML_format); return; } PWIZ_API_DECL void Reader_mzXML::read(const std::string& filename, const std::string& head, std::vector& results, const Config& config) const { results.push_back(MSDataPtr(new MSData)); read(filename, head, *results.back(), 0, config); } // // Reader_MGF // PWIZ_API_DECL std::string Reader_MGF::identify(const string& filename, const string& head) const { return std::string(((bal::to_lower_copy(bfs::extension(filename)) == ".mgf"))?getType():""); } PWIZ_API_DECL void Reader_MGF::read(const string& filename, const string& head, MSData& result, int runIndex, const Config& config) const { if (runIndex != 0) throw ReaderFail("[Reader_MGF::read] multiple runs not supported"); shared_ptr is(new pwiz::util::random_access_compressed_ifstream(filename.c_str())); if (!is.get() || !*is) throw runtime_error(("[Reader_MGF::read] Unable to open file " + filename)); Serializer_MGF serializer; serializer.read(is, result); fillInCommonMetadata(filename, result); result.fileDescription.sourceFilePtrs.back()->set(MS_multiple_peak_list_nativeID_format); result.fileDescription.sourceFilePtrs.back()->set(MS_Mascot_MGF_format); return; } PWIZ_API_DECL void Reader_MGF::read(const std::string& filename, const std::string& head, std::vector& results, const Config& config) const { results.push_back(MSDataPtr(new MSData)); read(filename, head, *results.back()); } // // Reader_MSn // PWIZ_API_DECL std::string Reader_MSn::identify(const string& filename, const string& head) const { bool isOK = has_extension(filename, ".ms1") || has_extension(filename, ".cms1") || has_extension(filename, ".bms1") || has_extension(filename, ".ms2") || has_extension(filename, ".cms2") || has_extension(filename, ".bms2"); return std::string( isOK ? getType() : "" ); } PWIZ_API_DECL void Reader_MSn::read(const string& filename, const string& head, MSData& result, int runIndex, const Config& config) const { if (runIndex != 0) throw ReaderFail("[Reader_MSn::read] multiple runs not supported"); MSn_Type filetype = MSn_Type_UNKNOWN; if (has_extension(filename, ".ms1")) filetype = MSn_Type_MS1; else if (has_extension(filename, ".cms1")) filetype = MSn_Type_CMS1; else if (has_extension(filename, ".bms1")) filetype = MSn_Type_BMS1; else if (has_extension(filename, ".ms2")) filetype = MSn_Type_MS2; else if (has_extension(filename, ".cms2")) filetype = MSn_Type_CMS2; else if (has_extension(filename, ".bms2")) filetype = MSn_Type_BMS2; shared_ptr is(new pwiz::util::random_access_compressed_ifstream(filename.c_str())); if (!is.get() || !*is) throw runtime_error(("[Reader_MSn::read] Unable to open file " + filename)); Serializer_MSn serializer(filetype); serializer.read(is, result); fillInCommonMetadata(filename, result); result.fileDescription.sourceFilePtrs.back()->set(MS_scan_number_only_nativeID_format); result.fileDescription.sourceFilePtrs.back()->set(MS_MS2_format); } PWIZ_API_DECL void Reader_MSn::read(const std::string& filename, const std::string& head, std::vector& results, const Config& config) const { results.push_back(MSDataPtr(new MSData)); read(filename, head, *results.back()); } // // Reader_BTDX // PWIZ_API_DECL std::string Reader_BTDX::identify(const string& filename, const string& head) const { std::string result; try { // TODO: congratulate Bruker for their unique root element name string rootElement = xml_root_element(head); result = (rootElement == "root")?getType():""; } catch (runtime_error&) { } return result; } PWIZ_API_DECL void Reader_BTDX::read(const string& filename, const string& head, MSData& result, int runIndex, const Config& config) const { if (runIndex != 0) throw ReaderFail("[Reader_BTDX::read] multiple runs not supported"); shared_ptr is(new pwiz::util::random_access_compressed_ifstream(filename.c_str())); if (!is.get() || !*is) throw runtime_error(("[Reader_BTDX::read] Unable to open file " + filename)); result.fileDescription.fileContent.set(MS_MSn_spectrum); result.fileDescription.fileContent.set(MS_centroid_spectrum); SourceFilePtr sourceFile(new SourceFile); sourceFile->id = "BTDX1"; bfs::path p(filename); sourceFile->name = BFS_STRING(p.leaf()); sourceFile->location = "file:///" + BFS_COMPLETE(p.branch_path()).string(); result.fileDescription.sourceFilePtrs.push_back(sourceFile); result.id = result.run.id = bfs::basename(filename); result.run.spectrumListPtr = SpectrumListPtr(SpectrumList_BTDX::create(is, result)); result.run.chromatogramListPtr = ChromatogramListPtr(new ChromatogramListSimple); return; } PWIZ_API_DECL void Reader_BTDX::read(const std::string& filename, const std::string& head, std::vector& results, const Config& config) const { results.push_back(MSDataPtr(new MSData)); read(filename, head, *results.back()); } // // Reader_mz5 // // TODO: add mz5 specific header and check this. This version only checks whether the file is a HDF5 file. namespace { const char mz5Header[] = {'\x89', '\x48', '\x44', '\x46', '\x0d', '\x0a', '\x1a', '\x0a'}; const size_t mz5HeaderSize = sizeof(mz5Header) / sizeof(char); } // namespace PWIZ_API_DECL std::string Reader_mz5::identify(const string& filename, const string& head) const { if (head.length() < mz5HeaderSize) return ""; for (size_t i=0; i < mz5HeaderSize; ++i) if (head[i] != mz5Header[i]) return ""; try { #ifndef WITHOUT_MZ5 mz5::Connection_mz5 c(filename, mz5::Connection_mz5::ReadOnly); #endif return getType(); } catch (std::runtime_error&) { return ""; } return ""; } PWIZ_API_DECL void Reader_mz5::read(const string& filename, const string& head, MSData& result, int runIndex, const Config& config) const { #ifdef WITHOUT_MZ5 throw ReaderFail("[Reader_mz5::read] library was not built with mz5 support."); #else if (runIndex != 0) throw ReaderFail("[Reader_mz5::read] multiple runs not supported, yet..."); Serializer_mz5 serializer; serializer.read(filename, result); // TODO: add "conversion to mz5 tag", sourceFile history and pwiz // the file-level ids can't be empty if (result.id.empty() || result.run.id.empty()) result.id = result.run.id = bfs::basename(filename); #endif } PWIZ_API_DECL void Reader_mz5::read(const std::string& filename, const std::string& head, std::vector& results, const Config& config) const { // TODO multiple read mz5 results.push_back(MSDataPtr(new MSData)); read(filename, head, *results.back()); } /// default Reader list PWIZ_API_DECL DefaultReaderList::DefaultReaderList() { push_back(ReaderPtr(new Reader_mzML)); push_back(ReaderPtr(new Reader_mzXML)); push_back(ReaderPtr(new Reader_MGF)); push_back(ReaderPtr(new Reader_MSn)); push_back(ReaderPtr(new Reader_BTDX)); push_back(ReaderPtr(new Reader_mz5)); } } // namespace msdata } // namespace pwiz pwiz/pwiz/data/msdata/MSDataMerger.cpp0000664000175100017510000002022212664775620021702 0ustar teamcityteamcity00000000000000// // $Id: MSDataMerger.cpp 2908 2011-08-05 16:41:41Z chambm $ // // // Original author: Matt Chambers // // Copyright 2010 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "MSDataMerger.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/DateTime.hpp" #include "Diff.hpp" #include "References.hpp" using boost::shared_ptr; using namespace pwiz::util; namespace pwiz { namespace msdata { namespace { void mergeParamContainers(ParamContainer& target, const ParamContainer& source) { Diff diff(target, source); if (diff) { const ParamContainer& source_minus_target = diff.b_a; target.cvParams.insert(target.cvParams.end(), source_minus_target.cvParams.begin(), source_minus_target.cvParams.end()); target.userParams.insert(target.userParams.end(), source_minus_target.userParams.begin(), source_minus_target.userParams.end()); target.paramGroupPtrs.insert(target.paramGroupPtrs.end(), source_minus_target.paramGroupPtrs.begin(), source_minus_target.paramGroupPtrs.end()); } } class SpectrumListMerger : public SpectrumList { struct IndexEntry : public SpectrumIdentity { SpectrumListPtr spectrumListPtr; SourceFilePtr sourceFilePtr; size_t originalIndex; }; const MSData& msd_; vector inputMSDataPtrs_; vector index_; map idToIndexes_; public: SpectrumListMerger(const MSData& msd, const vector& inputs) : msd_(msd), inputMSDataPtrs_(inputs) { BOOST_FOREACH(const MSDataPtr& input, inputs) for (size_t i=0; i < input->run.spectrumListPtr->size(); ++i) { SpectrumPtr s = input->run.spectrumListPtr->spectrum(i); Spectrum& oldIdentity = *s; idToIndexes_[oldIdentity.id].push_back(index_.size()); IndexEntry ie; ie.id = oldIdentity.id; ie.index = index_.size(); ie.originalIndex = i; ie.spectrumListPtr = input->run.spectrumListPtr; // because of the high chance of duplicate ids, sourceFilePtrs are always explicit SourceFilePtr oldSourceFilePtr = oldIdentity.sourceFilePtr.get() ? oldIdentity.sourceFilePtr : input->run.defaultSourceFilePtr; if (oldSourceFilePtr.get()) ie.sourceFilePtr = SourceFilePtr(new SourceFile(input->run.id + "_" + oldSourceFilePtr->id)); index_.push_back(ie); } } virtual size_t size() const {return index_.size();} virtual const SpectrumIdentity& spectrumIdentity(size_t index) const { if (index >= size()) throw runtime_error("[SpectrumListMerger::spectrumIdentity()] Bad index: " + lexical_cast(index)); return index_[index]; } virtual size_t find(const string& id) const { map::const_iterator itr = idToIndexes_.find(id); if (itr == idToIndexes_.end()) return size(); return itr->second[0]; // TODO: address duplicate ids when sourceFilePtr is disregarded... } virtual SpectrumPtr spectrum(size_t index, bool getBinaryData) const { if (index >= size()) throw runtime_error("[SpectrumListMerger::spectrum()] Bad index: " + lexical_cast(index)); const IndexEntry& ie = index_[index]; SpectrumPtr result = ie.spectrumListPtr->spectrum(ie.originalIndex, getBinaryData); result->index = ie.index; // because of the high chance of duplicate ids, sourceFilePtrs are always explicit result->sourceFilePtr = ie.sourceFilePtr; // resolve references into MSData::*Ptrs that may be invalidated after merging References::resolve(*result, msd_); return result; } }; } // namespace PWIZ_API_DECL MSDataMerger::MSDataMerger(const vector& inputs) : inputMSDataPtrs_(inputs) { // MSData::id and Run::id are set to the longest common prefix of all inputs' Run::ids, // or if there is no common prefix, to a concatenation of all inputs' Run::ids vector runIds; // Run::startTimeStamp is set to the earliest timestamp vector runTimestamps; BOOST_FOREACH(const MSDataPtr& input, inputs) { const MSData& msd = *input; // merge fileDescription/sourceFilePtrs (prepend each source file with its source run id) BOOST_FOREACH(const SourceFilePtr& sourceFilePtr, msd.fileDescription.sourceFilePtrs) { this->fileDescription.sourceFilePtrs.push_back(SourceFilePtr(new SourceFile(*sourceFilePtr))); SourceFile& sf = *this->fileDescription.sourceFilePtrs.back(); sf.id = msd.run.id + "_" + sf.id; } runIds.push_back(msd.run.id); if (!msd.run.startTimeStamp.empty()) runTimestamps.push_back(decode_xml_datetime(msd.run.startTimeStamp)); DiffConfig config; config.ignoreSpectra = config.ignoreChromatograms = true; Diff diff(*this, msd, config); // merge cvs this->cvs.insert(this->cvs.end(), diff.b_a.cvs.begin(), diff.b_a.cvs.end()); // merge fileDescription/fileContent mergeParamContainers(this->fileDescription.fileContent, diff.b_a.fileDescription.fileContent); // merge fileDescription/contacts this->fileDescription.contacts.insert(this->fileDescription.contacts.end(), diff.b_a.fileDescription.contacts.begin(), diff.b_a.fileDescription.contacts.end()); // merge file-level shared *Ptrs this->paramGroupPtrs.insert(this->paramGroupPtrs.end(), diff.b_a.paramGroupPtrs.begin(), diff.b_a.paramGroupPtrs.end()); this->samplePtrs.insert(this->samplePtrs.end(), diff.b_a.samplePtrs.begin(), diff.b_a.samplePtrs.end()); this->softwarePtrs.insert(this->softwarePtrs.end(), diff.b_a.softwarePtrs.begin(), diff.b_a.softwarePtrs.end()); this->instrumentConfigurationPtrs.insert(this->instrumentConfigurationPtrs.end(), diff.b_a.instrumentConfigurationPtrs.begin(), diff.b_a.instrumentConfigurationPtrs.end()); this->dataProcessingPtrs.insert(this->dataProcessingPtrs.end(), diff.b_a.dataProcessingPtrs.begin(), diff.b_a.dataProcessingPtrs.end()); // merge run? } string lcp = pwiz::util::longestCommonPrefix(runIds); // trim typical separator characters from the end of the LCP bal::trim_right_if(lcp, bal::is_any_of(" _-.")); if (lcp.empty()) this->id = this->run.id = "merged-spectra"; else this->id = this->run.id = lcp; if (!runTimestamps.empty()) this->run.startTimeStamp = encode_xml_datetime(*std::min_element(runTimestamps.begin(), runTimestamps.end())); this->run.spectrumListPtr = SpectrumListPtr(new SpectrumListMerger(*this, inputMSDataPtrs_)); } } // namespace msdata } // namespace pwiz pwiz/pwiz/data/msdata/Serializer_mzXML_Test.cpp0000664000175100017510000000575712664775621023647 0ustar teamcityteamcity00000000000000// // $Id: Serializer_mzXML_Test.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "Serializer_mzXML.hpp" #include "Serializer_mzML.hpp" #include "Diff.hpp" #include "TextWriter.hpp" #include "examples.hpp" #include "pwiz/utility/misc/unit.hpp" #include "boost/iostreams/positioning.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::data; using namespace pwiz::msdata; ostream* os_ = 0; void testWriteRead(const MSData& msd, const Serializer_mzXML::Config& config) { if (os_) *os_ << "testWriteRead() " << config << endl; Serializer_mzXML mzxmlSerializer(config); ostringstream oss; mzxmlSerializer.write(oss, msd); if (os_) *os_ << "oss:\n" << oss.str() << endl; shared_ptr iss(new istringstream(oss.str())); MSData msd2; mzxmlSerializer.read(iss, msd2); DiffConfig diffConfig; diffConfig.ignoreMetadata = true; diffConfig.ignoreChromatograms = true; Diff diff(msd, msd2, diffConfig); if (os_ && diff) *os_ << diff << endl; unit_assert(!diff); if (os_) { *os_ << "msd2:\n"; Serializer_mzML mzmlSerializer; mzmlSerializer.write(*os_, msd2); *os_ << endl; *os_ << "msd2::"; TextWriter write(*os_); write(msd2); *os_ << endl; } } void testWriteRead() { MSData msd; examples::initializeTiny(msd); // remove s22 since it is not written to mzXML static_cast(*msd.run.spectrumListPtr).spectra.pop_back(); Serializer_mzXML::Config config; unit_assert(config.binaryDataEncoderConfig.precision == BinaryDataEncoder::Precision_64); testWriteRead(msd, config); config.binaryDataEncoderConfig.precision = BinaryDataEncoder::Precision_32; testWriteRead(msd, config); config.indexed = false; testWriteRead(msd, config); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; testWriteRead(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/msdata/Version.hpp0000664000175100017510000000236312664775621021070 0ustar teamcityteamcity00000000000000// // $Id: Version.hpp 1188 2009-08-14 17:19:55Z chambm $ // // // Original author: Matt Chambers // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PWIZ_MSDATA_VERSION_HPP_ #define _PWIZ_MSDATA_VERSION_HPP_ #include namespace pwiz { namespace msdata { struct Version { static int Major(); static int Minor(); static int Revision(); static std::string str(); static std::string LastModified(); }; } // namespace msdata } // namespace pwiz #endif // _PWIZ_MSDATA_VERSION_HPP_ pwiz/pwiz/data/msdata/ChromatogramList_mzML.cpp0000664000175100017510000001026212664775621023651 0ustar teamcityteamcity00000000000000// // $Id: ChromatogramList_mzML.cpp 2898 2011-08-01 17:55:13Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "ChromatogramList_mzML.hpp" #include "IO.hpp" #include "References.hpp" #include "pwiz/utility/minimxml/SAXParser.hpp" #include "boost/iostreams/positioning.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace msdata { using namespace pwiz::minimxml; using namespace pwiz::cv; using boost::iostreams::offset_to_position; namespace { class ChromatogramList_mzMLImpl : public ChromatogramList_mzML { public: ChromatogramList_mzMLImpl(shared_ptr is, const MSData& msd, const Index_mzML_Ptr& index); // ChromatogramList implementation virtual size_t size() const {return index_->chromatogramCount();} virtual const ChromatogramIdentity& chromatogramIdentity(size_t index) const; virtual size_t find(const std::string& id) const; virtual ChromatogramPtr chromatogram(size_t index, bool getBinaryData) const; private: shared_ptr is_; const MSData& msd_; Index_mzML_Ptr index_; }; ChromatogramList_mzMLImpl::ChromatogramList_mzMLImpl(shared_ptr is, const MSData& msd, const Index_mzML_Ptr& index) : is_(is), msd_(msd), index_(index) { } const ChromatogramIdentity& ChromatogramList_mzMLImpl::chromatogramIdentity(size_t index) const { if (index >= index_->chromatogramCount()) throw runtime_error("[ChromatogramList_mzML::chromatogramIdentity()] Index out of bounds."); return index_->chromatogramIdentity(index); } size_t ChromatogramList_mzMLImpl::find(const string& id) const { return index_->findChromatogramId(id); } ChromatogramPtr ChromatogramList_mzMLImpl::chromatogram(size_t index, bool getBinaryData) const { if (index >= index_->chromatogramCount()) throw runtime_error("[ChromatogramList_mzML::chromatogram()] Index out of bounds."); // allocate Chromatogram object and read it in ChromatogramPtr result(new Chromatogram); if (!result.get()) throw runtime_error("[ChromatogramList_mzML::chromatogram()] Out of memory."); IO::BinaryDataFlag binaryDataFlag = getBinaryData ? IO::ReadBinaryData : IO::IgnoreBinaryData; try { is_->seekg(offset_to_position(index_->chromatogramIdentity(index).sourceFilePosition)); if (!*is_) throw runtime_error("[ChromatogramList_mzML::chromatogram()] Error seeking to ."); IO::read(*is_, *result, binaryDataFlag); // test for reading the wrong chromatogram if (result->index != index) throw runtime_error("[ChromatogramList_mzML::chromatogram()] Index entry points to the wrong chromatogram."); } catch (runtime_error&) { // TODO: log warning about missing/corrupt index // recreate index index_->recreate(); is_->seekg(offset_to_position(index_->chromatogramIdentity(index).sourceFilePosition)); IO::read(*is_, *result, binaryDataFlag); } // resolve any references into the MSData object References::resolve(*result, msd_); return result; } } // namespace PWIZ_API_DECL ChromatogramListPtr ChromatogramList_mzML::create(shared_ptr is, const MSData& msd, const Index_mzML_Ptr& indexPtr) { if (!is.get() || !*is) throw runtime_error("[ChromatogramList_mzML::create()] Bad istream."); return ChromatogramListPtr(new ChromatogramList_mzMLImpl(is, msd, indexPtr)); } } // namespace msdata } // namespace pwiz pwiz/pwiz/data/msdata/Serializer_MSn.hpp0000664000175100017510000000371312664775621022331 0ustar teamcityteamcity00000000000000// // $Id: Serializer_MSn.hpp 1852 2010-03-01 17:49:01Z tabaker $ // // // Original author: Barbara Frewen // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SERIALIZER_MSn_HPP_ #define _SERIALIZER_MSn_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "MSData.hpp" #include "BinaryDataEncoder.hpp" #include "pwiz/utility/misc/IterationListener.hpp" #include "SpectrumList_MSn.hpp" namespace pwiz { namespace msdata { /// MSData <-> MSn stream serialization class PWIZ_API_DECL Serializer_MSn { public: /// constructor Serializer_MSn(MSn_Type filetype); /// write MSData object to ostream as MSn; /// iterationListenerRegistry may be used to receive progress updates void write(std::ostream& os, const MSData& msd, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry = 0) const; /// read in MSData object from an MGF istream /// note: istream may be managed by MSData's SpectrumList, to allow for /// lazy evaluation of Spectrum data void read(boost::shared_ptr is, MSData& msd) const; private: class Impl; boost::shared_ptr impl_; Serializer_MSn(Serializer_MSn&); Serializer_MSn& operator=(Serializer_MSn&); }; } // namespace msdata } // namespace pwiz #endif // _SERIALIZER_MSn_HPP_ pwiz/pwiz/data/msdata/LegacyAdapterTest.cpp0000664000175100017510000002027212664775621023002 0ustar teamcityteamcity00000000000000// // $Id: LegacyAdapterTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "LegacyAdapter.hpp" #include "pwiz/data/common/CVTranslator.hpp" #include "TextWriter.hpp" #include "pwiz/utility/misc/unit.hpp" #include "boost/lambda/lambda.hpp" #include "boost/lambda/bind.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::msdata; using namespace boost::lambda; ostream* os_ = 0; void testModelAndManufacturer() { if (os_) *os_ << "testModelAndManufacturer()\n"; InstrumentConfiguration instrumentConfiguration; CVTranslator cvTranslator; LegacyAdapter_Instrument adapter(instrumentConfiguration, cvTranslator); unit_assert(instrumentConfiguration.cvParams.empty() && instrumentConfiguration.userParams.empty()); adapter.manufacturerAndModel("dummy", "LTQ-FT"); if (os_) *os_ << "manufacturer: " << adapter.manufacturer() << endl << "model: " << adapter.model() << endl; unit_assert(instrumentConfiguration.cvParams.size() == 1); unit_assert(instrumentConfiguration.userParams.empty()); unit_assert(adapter.manufacturer() == "Thermo Scientific"); unit_assert(adapter.model() == "LTQ FT"); adapter.manufacturerAndModel("doobie", "420"); if (os_) *os_ << "manufacturer: " << adapter.manufacturer() << endl << "model: " << adapter.model() << endl; unit_assert(instrumentConfiguration.cvParams.empty()); unit_assert(instrumentConfiguration.userParams.size() == 2); unit_assert(adapter.manufacturer() == "doobie"); unit_assert(adapter.model() == "420"); adapter.manufacturerAndModel("dummy", "LTQ-FT"); if (os_) *os_ << "manufacturer: " << adapter.manufacturer() << endl << "model: " << adapter.model() << endl; unit_assert(instrumentConfiguration.cvParams.size() == 1); unit_assert(instrumentConfiguration.userParams.empty()); unit_assert(adapter.manufacturer() == "Thermo Scientific"); unit_assert(adapter.model() == "LTQ FT"); } void testIonisation() { InstrumentConfiguration instrumentConfiguration; instrumentConfiguration.componentList.push_back(Component(ComponentType_Source, 2)); CVTranslator cvTranslator; LegacyAdapter_Instrument adapter(instrumentConfiguration, cvTranslator); adapter.ionisation(" esi\t"); if (os_) *os_ << "ionisation: " << adapter.ionisation() << endl; unit_assert(instrumentConfiguration.componentList.source(0).cvParams.size() == 1); unit_assert(instrumentConfiguration.componentList.source(0).userParams.empty()); unit_assert(adapter.ionisation() == "electrospray ionization"); adapter.ionisation("goober"); if (os_) *os_ << "ionisation: " << adapter.ionisation() << endl; unit_assert(instrumentConfiguration.componentList.source(0).cvParams.empty()); unit_assert(instrumentConfiguration.componentList.source(0).userParams.size() == 1); unit_assert(adapter.ionisation() == "goober"); adapter.ionisation(" Electrospray-Ionization"); if (os_) *os_ << "ionisation: " << adapter.ionisation() << endl; unit_assert(instrumentConfiguration.componentList.source(0).cvParams.size() == 1); unit_assert(instrumentConfiguration.componentList.source(0).userParams.empty()); unit_assert(adapter.ionisation() == "electrospray ionization"); } void testAnalyzer() { InstrumentConfiguration instrumentConfiguration; instrumentConfiguration.componentList.push_back(Component(ComponentType_Analyzer, 2)); CVTranslator cvTranslator; LegacyAdapter_Instrument adapter(instrumentConfiguration, cvTranslator); adapter.analyzer("IT"); if (os_) *os_ << "analyzer: " << adapter.analyzer() << endl; unit_assert(instrumentConfiguration.componentList.analyzer(0).cvParams.size() == 1); unit_assert(instrumentConfiguration.componentList.analyzer(0).userParams.empty()); unit_assert(adapter.analyzer() == "ion trap"); adapter.analyzer("goober"); if (os_) *os_ << "analyzer: " << adapter.analyzer() << endl; unit_assert(instrumentConfiguration.componentList.analyzer(0).cvParams.empty()); unit_assert(instrumentConfiguration.componentList.analyzer(0).userParams.size() == 1); unit_assert(adapter.analyzer() == "goober"); adapter.analyzer(" qit"); if (os_) *os_ << "analyzer: " << adapter.analyzer() << endl; unit_assert(instrumentConfiguration.componentList.analyzer(0).cvParams.size() == 1); unit_assert(instrumentConfiguration.componentList.analyzer(0).userParams.empty()); unit_assert(adapter.analyzer() == "quadrupole ion trap"); } void testDetector() { InstrumentConfiguration instrumentConfiguration; instrumentConfiguration.componentList.push_back(Component(ComponentType_Detector, 3)); CVTranslator cvTranslator; LegacyAdapter_Instrument adapter(instrumentConfiguration, cvTranslator); adapter.detector("emt"); if (os_) *os_ << "detector: " << adapter.detector() << endl; unit_assert(instrumentConfiguration.componentList.detector(0).cvParams.size() == 1); unit_assert(instrumentConfiguration.componentList.detector(0).userParams.empty()); unit_assert(adapter.detector() == "electron multiplier tube"); adapter.detector("goober"); if (os_) *os_ << "detector: " << adapter.detector() << endl; unit_assert(instrumentConfiguration.componentList.detector(0).cvParams.empty()); unit_assert(instrumentConfiguration.componentList.detector(0).userParams.size() == 1); unit_assert(adapter.detector() == "goober"); adapter.detector(" Electron Multiplier "); if (os_) *os_ << "detector: " << adapter.detector() << endl; unit_assert(instrumentConfiguration.componentList.detector(0).cvParams.size() == 1); unit_assert(instrumentConfiguration.componentList.detector(0).userParams.empty()); unit_assert(adapter.detector() == "electron multiplier"); } void testInstrumentConfiguration() { testModelAndManufacturer(); testIonisation(); testAnalyzer(); testDetector(); } void testSoftware() { SoftwarePtr software(new Software("abcd")); MSData msd; CVTranslator cvTranslator; LegacyAdapter_Software adapter(software, msd, cvTranslator); adapter.name(" XcaLibur "); if (os_) *os_ << "software name: " << adapter.name() << endl; CVParam softwareParam = software->cvParamChild(MS_software); unit_assert(softwareParam.cvid == MS_Xcalibur); unit_assert(adapter.name() == "Xcalibur"); adapter.name("goober"); if (os_) *os_ << "software name: " << adapter.name() << endl; softwareParam = software->cvParamChild(MS_software); unit_assert(softwareParam.cvid == CVID_Unknown); unit_assert(adapter.name() == "goober"); adapter.version("4.20"); if (os_) *os_ << "software version: " << adapter.version() << endl; unit_assert(adapter.version() == "4.20"); //adapter.type("acquisition"); //if (os_) *os_ << "software type: " << adapter.type() << endl; //unit_assert(adapter.type() == "acquisition"); adapter.type("analysis"); if (os_) *os_ << "software type: " << adapter.type() << endl; unit_assert(adapter.type() == "analysis"); } void test() { testInstrumentConfiguration(); testSoftware(); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/msdata/SHA1OutputObserver.hpp0000664000175100017510000000276212664775621023073 0ustar teamcityteamcity00000000000000// // $Id: SHA1OutputObserver.hpp 1189 2009-08-14 17:36:06Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SHA1OUTPUTOBSERVER_HPP_ #define _SHA1OUTPUTOBSERVER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/utility/minimxml/XMLWriter.hpp" #include "pwiz/utility/misc/SHA1Calculator.hpp" namespace pwiz { namespace msdata { class PWIZ_API_DECL SHA1OutputObserver : public minimxml::XMLWriter::OutputObserver { public: virtual void update(const std::string& output) {sha1Calculator_.update(output);} std::string hash() {return sha1Calculator_.hashProjected();} private: util::SHA1Calculator sha1Calculator_; }; } // namespace msdata } // namespace pwiz #endif // _SHA1OUTPUTOBSERVER_HPP_ pwiz/pwiz/data/msdata/SpectrumIteratorTest.cpp0000664000175100017510000001636612664775621023622 0ustar teamcityteamcity00000000000000// // $Id: SpectrumIteratorTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "SpectrumIterator.hpp" #include "MSData.hpp" #include "pwiz/utility/misc/IntegerSet.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::cv; using namespace pwiz::msdata; using namespace pwiz::util; ostream* os_ = 0; void initializeSpectrumList(SpectrumListSimple& spectrumList) { // initialize with scans: // scan 0: IT // scan 5: FT (1,100) // scan 10: IT (1,100), (2,200) // scan 15: FT (1,100), (2,200), (3,300) // scan 20: IT (1,100), (2,200), (3,300), (4,400) // ... for (int i=0; i<=10; i++) { SpectrumPtr spectrum(new Spectrum); spectrum->id = lexical_cast(i*5); spectrum->cvParams.push_back(i%2 ? MS_FT_ICR : MS_ion_trap); BinaryDataArrayPtr bdMZ(new BinaryDataArray); bdMZ->cvParams.push_back(MS_m_z_array); spectrum->binaryDataArrayPtrs.push_back(bdMZ); BinaryDataArrayPtr bdIntensity(new BinaryDataArray); bdIntensity->cvParams.push_back(MS_intensity_array); spectrum->binaryDataArrayPtrs.push_back(bdIntensity); for (int j=1; j<=i; j++) { bdMZ->data.push_back(j); bdIntensity->data.push_back(100*j); } spectrum->defaultArrayLength = i; spectrumList.spectra.push_back(spectrum); } } const char* anal(const CVParam& cvParam) { if (cvParam == MS_FT_ICR) return "FT"; else if (cvParam == MS_ion_trap) return "IT"; else return "Unknown"; } void printSpectrumList(ostream& os, const SpectrumList& sl) { if (os_) *os_ << "printSpectrumList()\n"; for (unsigned int i=0; iid << " " << anal(spectrum->cvParamChild(MS_mass_analyzer)) << endl; vector mziPairs; spectrum->getMZIntensityPairs(mziPairs); copy(mziPairs.begin(), mziPairs.end(), ostream_iterator(os,"")); os << endl; } } void testBasic(const SpectrumList& sl) { if (os_) *os_ << "testBasic()\n"; SpectrumIterator it(sl); unit_assert(it->id == "0"); unit_assert((*it).cvParamChild(MS_mass_analyzer_type) == MS_ion_trap); unit_assert(it->binaryDataArrayPtrs.size() == 2); ++it; ++it; ++it; ++it; ++it; // advance to scan 5 unit_assert(it->id == "25"); unit_assert(it->cvParamChild(MS_mass_analyzer_type) == MS_FT_ICR); unit_assert(it->binaryDataArrayPtrs.size() == 2 && it->binaryDataArrayPtrs[0]->data.size() == 5); } void doSomething(const Spectrum& spectrum) { if (os_) *os_ << "spectrum: " << spectrum.id << " " << anal(spectrum.cvParamChild(MS_mass_analyzer)) << endl; vector pairs; spectrum.getMZIntensityPairs(pairs); if (os_) { copy(pairs.begin(), pairs.end(), ostream_iterator(*os_,"")); *os_ << endl; } unit_assert((int)pairs.size()*5 == lexical_cast(spectrum.id)); } void testForEach(const SpectrumList& spectrumList) { if (os_) *os_ << "testForEach(): \n"; for_each(SpectrumIterator(spectrumList), SpectrumIterator(), doSomething); } void testIntegerSet(const SpectrumList& spectrumList) { // iterate through even scan numbers if (os_) *os_ << "testIntegerSet():\n"; IntegerSet scanNumbers; for (int i=2; i<=50; i+=2) // note that some scan numbers don't exist in spectrumList scanNumbers.insert(i); // loop written for illustration // note automatic conversion from IntegerSet to SpectrumIterator::Config for (SpectrumIterator it(spectrumList, scanNumbers); it!=SpectrumIterator(); ++it) doSomething(*it); // using for_each: for_each(SpectrumIterator(spectrumList, scanNumbers), SpectrumIterator(), doSomething); } inline int getScanNumber(const Spectrum& spectrum) { return lexical_cast(spectrum.id); } class FTSieve : public SpectrumIterator::Sieve { public: virtual bool accept(const Spectrum& spectrum) const { return (spectrum.cvParamChild(MS_mass_analyzer_type) == MS_FT_ICR); } }; void testSieve(const SpectrumList& spectrumList) { vector ftScanNumbers; FTSieve sieve; SpectrumIterator::Config config(sieve, false); transform(SpectrumIterator(spectrumList, config), SpectrumIterator(), back_inserter(ftScanNumbers), getScanNumber); if (os_) { *os_ << "testSieve():\n"; copy(ftScanNumbers.begin(), ftScanNumbers.end(), ostream_iterator(*os_, " ")); *os_ << endl; } unit_assert(ftScanNumbers.size() == 5); unit_assert(ftScanNumbers[0] == 5); unit_assert(ftScanNumbers[1] == 15); unit_assert(ftScanNumbers[2] == 25); unit_assert(ftScanNumbers[3] == 35); unit_assert(ftScanNumbers[4] == 45); } void testIteratorEquality(const SpectrumList& spectrumList) { if (os_) *os_ << "testIteratorEquality()\n"; SpectrumIterator it(spectrumList); ++it; ++it; ++it; SpectrumIterator jt(spectrumList); unit_assert(it!=jt); ++jt; unit_assert(it!=jt); ++jt; unit_assert(it!=jt); ++jt; unit_assert(it==jt); } void testMSDataConstruction() { if (os_) *os_ << "testMSDataConstruction()\n"; SpectrumListSimplePtr sl(new SpectrumListSimple()); initializeSpectrumList(*sl); MSData msd; msd.run.spectrumListPtr = sl; int i = 0; FTSieve sieve; for (SpectrumIterator it(msd, sieve); it!=SpectrumIterator(); ++it, ++i) { if (os_) *os_ << it->id << " " << anal(it->cvParamChild(MS_mass_analyzer)) << endl; unit_assert(it->id == lexical_cast(5+i*10)); } } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; SpectrumListSimple spectrumList; initializeSpectrumList(spectrumList); if (os_) printSpectrumList(*os_, spectrumList); testBasic(spectrumList); testForEach(spectrumList); testIntegerSet(spectrumList); testSieve(spectrumList); testIteratorEquality(spectrumList); testMSDataConstruction(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/msdata/SpectrumList_MGF_Test.cpp0000664000175100017510000001354012664775621023563 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_MGF_Test.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "SpectrumList_MGF.hpp" #include "TextWriter.hpp" #include "pwiz/utility/minimxml/XMLWriter.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::cv; using namespace pwiz::msdata; using namespace pwiz::util; using namespace pwiz::minimxml; ostream* os_ = 0; const char* testMGF = "BEGIN IONS\n" "PEPMASS=810.790000\n" "TITLE=small.pwiz.0003.0003.2\n" "231.388840 26.545113\n" "233.339828 20.447954\n" "239.396149 17.999159\n" "END IONS\n" "BEGIN IONS\n" "PEPMASS=837.340000\n" "TITLE=small.pwiz.0004.0004.2\n" "RTINSECONDS=123.456\n" "CHARGE=2+\n" "236.047043 11.674493\n" "237.237091 24.431984\n" "238.824036 10.019409\n" "239.531403 6.842983\n" "243.128693 89.586212\n" "END IONS\n"; void test() { if (os_) *os_ << "test()\n"; if (os_) *os_ << "mgf:\n" << testMGF << endl; shared_ptr is(new istringstream(testMGF)); // dummy would normally be read in from file MSData dummy; dummy.instrumentConfigurationPtrs.push_back(InstrumentConfigurationPtr(new InstrumentConfiguration("LCQDeca"))); dummy.instrumentConfigurationPtrs.back()->cvParams.push_back(MS_LCQ_Deca); dummy.instrumentConfigurationPtrs.back()->userParams.push_back(UserParam("doobie", "420")); SpectrumListPtr sl = SpectrumList_MGF::create(is, dummy); if (os_) { TextWriter write(*os_); write(*sl); *os_ << endl; } // check easy functions unit_assert(sl.get()); unit_assert(sl->size() == 2); unit_assert(sl->find("index=0") == 0); unit_assert(sl->find("index=1") == 1); // find the second spectrum by TITLE field IndexList list = sl->findSpotID("small.pwiz.0004.0004.2"); unit_assert(list.size() == 1); unit_assert(list[0] == 1); // look for a non-existent TITLE field list.clear(); list = sl->findSpotID("fake title string"); unit_assert(list.size() == 0); // check scan 0 unit_assert(sl->spectrumIdentity(0).index == 0); unit_assert(sl->spectrumIdentity(0).id == "index=0"); unit_assert(sl->spectrumIdentity(0).sourceFilePosition != -1); SpectrumPtr s = sl->spectrum(0, false); unit_assert(s.get()); unit_assert(s->id == "index=0"); unit_assert(s->index == 0); unit_assert(s->sourceFilePosition != -1); unit_assert(s->cvParam(MS_spectrum_title).value == "small.pwiz.0003.0003.2"); unit_assert(s->cvParam(MS_ms_level).valueAs() == 2); unit_assert_equal(s->cvParam(MS_total_ion_current).valueAs(), 64.992226, 1e-5); unit_assert_equal(s->cvParam(MS_base_peak_m_z).valueAs(), 231.38884, 1e-5); unit_assert_equal(s->cvParam(MS_base_peak_intensity).valueAs(), 26.545113, 1e-5); unit_assert(s->precursors.size() == 1); Precursor& precursor0 = s->precursors[0]; unit_assert(precursor0.selectedIons.size() == 1); unit_assert_equal(precursor0.selectedIons[0].cvParam(MS_selected_ion_m_z).valueAs(), 810.79, 1e-5); unit_assert(s->defaultArrayLength == 3); unit_assert(s->binaryDataArrayPtrs.empty()); s = sl->spectrum(0, true); unit_assert(s->defaultArrayLength == 3); unit_assert(s->binaryDataArrayPtrs.size() == 2); unit_assert(!s->binaryDataArrayPtrs[0]->data.empty() && !s->binaryDataArrayPtrs[1]->data.empty()); vector pairs; s->getMZIntensityPairs(pairs); if (os_) { *os_ << "scan 0:\n"; copy(pairs.begin(), pairs.end(), ostream_iterator(*os_, "\n")); *os_ << endl; } // check scan 1 unit_assert(sl->spectrumIdentity(1).index == 1); unit_assert(sl->spectrumIdentity(1).id == "index=1"); s = sl->spectrum(1, true); unit_assert(s.get()); unit_assert(s->id == "index=1"); unit_assert(s->index == 1); unit_assert(s->sourceFilePosition != -1); unit_assert(s->cvParam(MS_spectrum_title).value == "small.pwiz.0004.0004.2"); unit_assert(s->cvParam(MS_ms_level).valueAs() == 2); unit_assert(s->scanList.scans.size() == 1); unit_assert_equal(s->scanList.scans[0].cvParam(MS_scan_start_time).timeInSeconds(), 123.456, 1e-5); unit_assert(s->precursors.size() == 1); Precursor& precursor1 = s->precursors[0]; unit_assert(precursor1.selectedIons.size() == 1); unit_assert_equal(precursor1.selectedIons[0].cvParam(MS_selected_ion_m_z).valueAs(), 837.34, 1e-5); unit_assert(precursor1.selectedIons[0].cvParam(MS_charge_state).value == "2"); unit_assert(s->defaultArrayLength == 5); pairs.clear(); s->getMZIntensityPairs(pairs); unit_assert(s->defaultArrayLength == pairs.size()); if (os_) { *os_ << "scan 1:\n"; copy(pairs.begin(), pairs.end(), ostream_iterator(*os_, "\n")); *os_ << endl; } } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/msdata/Diff.cpp0000664000175100017510000010060112664775621020300 0ustar teamcityteamcity00000000000000// // $Id: Diff.cpp 6557 2014-07-30 22:51:16Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Diff.hpp" #include "TextWriter.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::msdata; namespace pwiz { namespace data { namespace diff_impl { PWIZ_API_DECL void diff(const SourceFile& a, const SourceFile& b, SourceFile& a_b, SourceFile& b_a, const DiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); diff(a.id, b.id, a_b.id, b_a.id, config); diff(a.name, b.name, a_b.name, b_a.name, config); diff(a.location, b.location, a_b.location, b_a.location, config); // provide id for context if (!a_b.empty() || !b_a.empty()) { a_b.id = a.id; b_a.id = b.id; } } PWIZ_API_DECL void diff(const FileDescription& a, const FileDescription& b, FileDescription& a_b, FileDescription& b_a, const DiffConfig& config) { diff(static_cast(a.fileContent), b.fileContent, a_b.fileContent, b_a.fileContent, config); vector_diff_deep(a.sourceFilePtrs, b.sourceFilePtrs, a_b.sourceFilePtrs, b_a.sourceFilePtrs, config); vector_diff_diff(a.contacts, b.contacts, a_b.contacts, b_a.contacts, config); } PWIZ_API_DECL void diff(const Sample& a, const Sample& b, Sample& a_b, Sample& b_a, const DiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); diff(a.id, b.id, a_b.id, b_a.id, config); diff(a.name, b.name, a_b.name, b_a.name, config); // provide id for context if (!a_b.empty() || !b_a.empty()) { a_b.id = a.id; b_a.id = b.id; } } PWIZ_API_DECL void diff(const Component& a, const Component& b, Component& a_b, Component& b_a, const DiffConfig& config) { int a_bType, b_aType; // TODO: how to take the difference of enum types? diff(static_cast(a), b, a_b, b_a, config); diff_integral(a.order, b.order, a_b.order, b_a.order, config); diff_integral((int)a.type, (int)b.type, a_bType, b_aType, config); } PWIZ_API_DECL void diff(const ComponentList& a, const ComponentList& b, ComponentList& a_b, ComponentList& b_a, const DiffConfig& config) { //size_t a_bSize, b_aSize; // TODO: what to do with this? //diff_numeric(a.size(), b.size(), a_bSize, b_aSize, config); //for (size_t i=0; i < a.size(); ++i) // diff(a[i], b[i], a_b[i], b_a[i], config); vector_diff_diff(static_cast&>(a), static_cast&>(b), static_cast&>(a_b), static_cast&>(b_a), config); } PWIZ_API_DECL void diff(const Software& a, const Software& b, Software& a_b, Software& b_a, const DiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); diff(a.id, b.id, a_b.id, b_a.id, config); if (!config.ignoreVersions) diff(a.version, b.version, a_b.version, b_a.version, config); // provide id for context if (!a_b.empty() || !b_a.empty()) { a_b.id = a.id; b_a.id = b.id; } } PWIZ_API_DECL void diff(const InstrumentConfiguration& a, const InstrumentConfiguration& b, InstrumentConfiguration& a_b, InstrumentConfiguration& b_a, const DiffConfig& config) { diff(a.id, b.id, a_b.id, b_a.id, config); diff(a.componentList, b.componentList, a_b.componentList, b_a.componentList, config); ptr_diff(a.softwarePtr, b.softwarePtr, a_b.softwarePtr, b_a.softwarePtr, config); diff(static_cast(a), b, a_b, b_a, config); // provide id for context if (!a_b.empty() || !b_a.empty()) { a_b.id = a.id; b_a.id = b.id; } } PWIZ_API_DECL void diff(const ProcessingMethod& a, const ProcessingMethod& b, ProcessingMethod& a_b, ProcessingMethod& b_a, const DiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); diff_integral(a.order, b.order, a_b.order, b_a.order, config); ptr_diff(a.softwarePtr, b.softwarePtr, a_b.softwarePtr, b_a.softwarePtr, config); } PWIZ_API_DECL void diff(const DataProcessing& a, const DataProcessing& b, DataProcessing& a_b, DataProcessing& b_a, const DiffConfig& config) { diff(a.id, b.id, a_b.id, b_a.id, config); vector_diff_diff(a.processingMethods, b.processingMethods, a_b.processingMethods, b_a.processingMethods, config); // provide id for context if (!a_b.empty() || !b_a.empty()) { a_b.id = a.id; b_a.id = b.id; } } PWIZ_API_DECL void diff(const ScanSettings& a, const ScanSettings& b, ScanSettings& a_b, ScanSettings& b_a, const DiffConfig& config) { diff(a.id, b.id, a_b.id, b_a.id, config); vector_diff_deep(a.sourceFilePtrs, b.sourceFilePtrs, a_b.sourceFilePtrs, b_a.sourceFilePtrs, config); vector_diff_diff(a.targets, b.targets, a_b.targets, b_a.targets, config); // provide id for context if (!a_b.empty() || !b_a.empty()) { a_b.id = a.id; b_a.id = b.id; } } PWIZ_API_DECL void diff(const Precursor& a, const Precursor& b, Precursor& a_b, Precursor& b_a, const DiffConfig& config) { a_b = Precursor(); b_a = Precursor(); // important scan metadata vector_diff_diff(a.selectedIons, b.selectedIons, a_b.selectedIons, b_a.selectedIons, config); if (!config.ignoreMetadata) { if (!config.ignoreIdentity) diff(a.spectrumID, b.spectrumID, a_b.spectrumID, b_a.spectrumID, config); diff(static_cast(a.isolationWindow), b.isolationWindow, a_b.isolationWindow, b_a.isolationWindow, config); diff(static_cast(a.activation), b.activation, a_b.activation, b_a.activation, config); diff(static_cast(a), b, a_b, b_a, config); } // provide spectrumID for context if (!a_b.empty() || !b_a.empty()) { a_b.spectrumID = a.spectrumID; b_a.spectrumID = b.spectrumID; } } PWIZ_API_DECL void diff(const Product& a, const Product& b, Product& a_b, Product& b_a, const DiffConfig& config) { a_b = Product(); b_a = Product(); if (!config.ignoreMetadata) { diff(static_cast(a.isolationWindow), b.isolationWindow, a_b.isolationWindow, b_a.isolationWindow, config); } } PWIZ_API_DECL void diff(const Scan& a, const Scan& b, Scan& a_b, Scan& b_a, const DiffConfig& config) { ptr_diff(a.instrumentConfigurationPtr, b.instrumentConfigurationPtr, a_b.instrumentConfigurationPtr, b_a.instrumentConfigurationPtr, config); vector_diff_diff(a.scanWindows, b.scanWindows, a_b.scanWindows, b_a.scanWindows, config); diff(static_cast(a), b, a_b, b_a, config); // provide instrumentConfigurationPtr for context if (!a_b.empty() || !b_a.empty()) { a_b.instrumentConfigurationPtr = a.instrumentConfigurationPtr; b_a.instrumentConfigurationPtr = b.instrumentConfigurationPtr; } } PWIZ_API_DECL void diff(const ScanList& a, const ScanList& b, ScanList& a_b, ScanList& b_a, const DiffConfig& config) { vector_diff_diff(a.scans, b.scans, a_b.scans, b_a.scans, config); diff(static_cast(a), b, a_b, b_a, config); } // measure maximum relative difference between elements in the vectors; // returns the index and magnitude of the largest difference pair maxdiff(const vector& a, const vector& b) { if (a.size() != b.size()) throw runtime_error("[Diff::maxdiff()] Sizes differ."); vector::const_iterator i = a.begin(); vector::const_iterator j = b.begin(); pair max; for (; i!=a.end(); ++i, ++j) { double denominator = min(*i, *j); if (denominator == 0) denominator = 1; double current = fabs(*i - *j)/denominator; if (max.second < current) max = make_pair(i-a.begin(), current); } return max; } const char* userParamName_BinaryDataArrayDifference_ = "Binary data array difference"; const char* userParamName_BinaryDataArrayDifferenceAtIndex_ = "Binary data array difference at index"; PWIZ_API_DECL void diff(const BinaryDataArray& a, const BinaryDataArray& b, BinaryDataArray& a_b, BinaryDataArray& b_a, const DiffConfig& config) { if (!config.ignoreMetadata) { ptr_diff(a.dataProcessingPtr, b.dataProcessingPtr, a_b.dataProcessingPtr, b_a.dataProcessingPtr, config); diff(static_cast(a), b, a_b, b_a, config); } if (a.data.size() != b.data.size()) { a_b.userParams.push_back(UserParam("Binary data array size: " + lexical_cast(a.data.size()))); b_a.userParams.push_back(UserParam("Binary data array size: " + lexical_cast(b.data.size()))); } else { pair max = maxdiff(a.data, b.data); if (max.second > config.precision + numeric_limits::epsilon()) { a_b.userParams.push_back(UserParam(userParamName_BinaryDataArrayDifference_, lexical_cast(max.second), "xsd:float")); b_a.userParams.push_back(a_b.userParams.back()); a_b.userParams.push_back(UserParam(userParamName_BinaryDataArrayDifferenceAtIndex_, lexical_cast(max.first), "xsd:float")); b_a.userParams.push_back(a_b.userParams.back()); } } // provide context if (!a_b.empty() || !b_a.empty()) { a_b.cvParams = a.cvParams; b_a.cvParams = b.cvParams; } } PWIZ_API_DECL void diff(const vector& a, const vector& b, vector& a_b, vector& b_a, const DiffConfig& config, pair& maxPrecisionDiff) { if (a.size() != b.size()) throw runtime_error("[Diff::diff(vector)] Sizes differ."); a_b.clear(); b_a.clear(); for (vector::const_iterator i=a.begin(), j=b.begin(); i!=a.end(); ++i, ++j) { BinaryDataArrayPtr temp_a_b(new BinaryDataArray); BinaryDataArrayPtr temp_b_a(new BinaryDataArray); diff(**i, **j, *temp_a_b, *temp_b_a, config); if (!temp_a_b->empty() || !temp_b_a->empty()) { a_b.push_back(temp_a_b); b_a.push_back(temp_b_a); //if UserParam with binary data diff exists, cast it to a double and compare with maxPrecisionDiff if(!temp_a_b->userParam(userParamName_BinaryDataArrayDifference_).empty()) { double max = lexical_cast(temp_a_b->userParam(userParamName_BinaryDataArrayDifference_).value); if (max>maxPrecisionDiff.second) { size_t maxIndex = lexical_cast(temp_a_b->userParam(userParamName_BinaryDataArrayDifferenceAtIndex_).value); maxPrecisionDiff.first = maxIndex; maxPrecisionDiff.second = max; } } } } } static void diff_index(const size_t& a, const size_t& b, size_t& a_b, size_t& b_a) { if (a != b) { a_b = a; b_a = b; } else { a_b = IDENTITY_INDEX_NONE; b_a = IDENTITY_INDEX_NONE; } } PWIZ_API_DECL void diff(const Spectrum& a, const Spectrum& b, Spectrum& a_b, Spectrum& b_a, const DiffConfig& config) { a_b = Spectrum(); b_a = Spectrum(); if (!config.ignoreIdentity) { diff(a.id, b.id, a_b.id, b_a.id, config); diff_index(a.index, b.index, a_b.index, b_a.index); } // important scan metadata diff_integral(a.defaultArrayLength, b.defaultArrayLength, a_b.defaultArrayLength, b_a.defaultArrayLength, config); vector_diff_diff(a.precursors, b.precursors, a_b.precursors, b_a.precursors, config); vector_diff_diff(a.products, b.products, a_b.products, b_a.products, config); if (!config.ignoreMetadata) { ptr_diff(a.dataProcessingPtr, b.dataProcessingPtr, a_b.dataProcessingPtr, b_a.dataProcessingPtr, config); ptr_diff(a.sourceFilePtr, b.sourceFilePtr, a_b.sourceFilePtr, b_a.sourceFilePtr, config); diff(static_cast(a), b, a_b, b_a, config); diff(a.scanList, b.scanList, a_b.scanList, b_a.scanList, config); } // special handling for binary data arrays if (a.binaryDataArrayPtrs.size() != b.binaryDataArrayPtrs.size()) { a_b.userParams.push_back(UserParam("Binary data array count: " + lexical_cast(a.binaryDataArrayPtrs.size()))); b_a.userParams.push_back(UserParam("Binary data array count: " + lexical_cast(b.binaryDataArrayPtrs.size()))); } else { pair maxPrecisionDiff(0, 0); diff(a.binaryDataArrayPtrs, b.binaryDataArrayPtrs, a_b.binaryDataArrayPtrs, b_a.binaryDataArrayPtrs, config, maxPrecisionDiff); if (maxPrecisionDiff.second>(config.precision+numeric_limits::epsilon())) { a_b.userParams.push_back(UserParam(userParamName_BinaryDataArrayDifference_, lexical_cast(maxPrecisionDiff.second), "xsd:float")); b_a.userParams.push_back(a_b.userParams.back()); a_b.userParams.push_back(UserParam(userParamName_BinaryDataArrayDifferenceAtIndex_, lexical_cast(maxPrecisionDiff.first), "xsd:float")); b_a.userParams.push_back(a_b.userParams.back()); } } // provide context if (!a_b.empty() || !b_a.empty()) { a_b.id = a.id; b_a.id = b.id; a_b.index = a.index; b_a.index = b.index; } } PWIZ_API_DECL void diff(const Chromatogram& a, const Chromatogram& b, Chromatogram& a_b, Chromatogram& b_a, const DiffConfig& config) { a_b = Chromatogram(); b_a = Chromatogram(); if (!config.ignoreIdentity) { diff(a.id, b.id, a_b.id, b_a.id, config); diff_index(a.index, b.index, a_b.index, b_a.index); } // important scan metadata diff_integral(a.defaultArrayLength, b.defaultArrayLength, a_b.defaultArrayLength, b_a.defaultArrayLength, config); if (!config.ignoreMetadata) { ptr_diff(a.dataProcessingPtr, b.dataProcessingPtr, a_b.dataProcessingPtr, b_a.dataProcessingPtr, config); diff(static_cast(a), b, a_b, b_a, config); diff(a.precursor, b.precursor, a_b.precursor, b_a.precursor, config); diff(a.product, b.product, a_b.product, b_a.product, config); } // special handling for binary data arrays if (a.binaryDataArrayPtrs.size() != b.binaryDataArrayPtrs.size()) { a_b.userParams.push_back(UserParam("Binary data array count: " + lexical_cast(a.binaryDataArrayPtrs.size()))); b_a.userParams.push_back(UserParam("Binary data array count: " + lexical_cast(b.binaryDataArrayPtrs.size()))); } else { pair maxPrecisionDiff(0, 0); diff(a.binaryDataArrayPtrs, b.binaryDataArrayPtrs, a_b.binaryDataArrayPtrs, b_a.binaryDataArrayPtrs, config, maxPrecisionDiff); if (maxPrecisionDiff.second>(config.precision+numeric_limits::epsilon())) { a_b.userParams.push_back(UserParam(userParamName_BinaryDataArrayDifference_, lexical_cast(maxPrecisionDiff.second), "xsd:float")); b_a.userParams.push_back(a_b.userParams.back()); a_b.userParams.push_back(UserParam(userParamName_BinaryDataArrayDifferenceAtIndex_, lexical_cast(maxPrecisionDiff.first), "xsd:float")); b_a.userParams.push_back(a_b.userParams.back()); } } // provide context if (!a_b.empty() || !b_a.empty()) { a_b.id = a.id; b_a.id = b.id; a_b.index = a.index; b_a.index = b.index; } } static const char* userParamName_MaxBinaryDataArrayDifference_ = "Maximum binary data array difference"; PWIZ_API_DECL void diff(const SpectrumList& a, const SpectrumList& b, SpectrumListSimple& a_b, SpectrumListSimple& b_a, const DiffConfig& config) { a_b.spectra.clear(); b_a.spectra.clear(); a_b.dp = DataProcessingPtr(); b_a.dp = DataProcessingPtr(); DataProcessingPtr temp_a_dp(a.dataProcessingPtr().get() ? new DataProcessing(*a.dataProcessingPtr()) : 0); DataProcessingPtr temp_b_dp(b.dataProcessingPtr().get() ? new DataProcessing(*b.dataProcessingPtr()) : 0); if (!config.ignoreMetadata && !config.ignoreDataProcessing) ptr_diff(temp_a_dp, temp_b_dp, a_b.dp, b_a.dp, config); if (a.size() != b.size()) { SpectrumPtr dummy(new Spectrum); dummy->userParams.push_back(UserParam("SpectrumList sizes differ")); a_b.spectra.push_back(dummy); return; } double maxPrecisionDiff = 0; for (unsigned int i=0; iid == b_spectrum->id; size_t a_find = config.ignoreIdentity || !sameId ? 0 : a.find(a_spectrum->id); size_t b_find = config.ignoreIdentity || !sameId ? 0 : b.find(b_spectrum->id); if (!temp_a_b->empty() || !temp_b_a->empty() || a_find != b_find) { a_b.spectra.push_back(temp_a_b); b_a.spectra.push_back(temp_b_a); if (a_find != b_find) { temp_a_b->index = a_spectrum->index; temp_a_b->id = a_spectrum->id; temp_b_a->index = b_spectrum->index; temp_b_a->id = b_spectrum->id; temp_a_b->userParams.push_back(UserParam("find() result", lexical_cast(a_find))); temp_b_a->userParams.push_back(UserParam("find() result", lexical_cast(b_find))); } if (!temp_a_b->userParam(userParamName_BinaryDataArrayDifference_).empty()) { double max=lexical_cast(temp_a_b->userParam(userParamName_BinaryDataArrayDifference_).value); if (max>maxPrecisionDiff) maxPrecisionDiff=max; } } } if (maxPrecisionDiff > 0) { if (!a_b.dp.get()) a_b.dp = DataProcessingPtr(new DataProcessing); if (a_b.dp->processingMethods.empty()) a_b.dp->processingMethods.push_back(ProcessingMethod()); ProcessingMethod& listDiffMethod = a_b.dp->processingMethods.back(); if (listDiffMethod.userParam(userParamName_MaxBinaryDataArrayDifference_).empty()) listDiffMethod.userParams.push_back(UserParam(userParamName_MaxBinaryDataArrayDifference_, lexical_cast(maxPrecisionDiff))); else listDiffMethod.userParam(userParamName_MaxBinaryDataArrayDifference_).value = lexical_cast(maxPrecisionDiff); } } PWIZ_API_DECL void diff(const ChromatogramList& a, const ChromatogramList& b, ChromatogramListSimple& a_b, ChromatogramListSimple& b_a, const DiffConfig& config) { a_b.chromatograms.clear(); b_a.chromatograms.clear(); a_b.dp = DataProcessingPtr(); b_a.dp = DataProcessingPtr(); if (config.ignoreChromatograms) return; DataProcessingPtr temp_a_dp(a.dataProcessingPtr().get() ? new DataProcessing(*a.dataProcessingPtr()) : 0); DataProcessingPtr temp_b_dp(b.dataProcessingPtr().get() ? new DataProcessing(*b.dataProcessingPtr()) : 0); if (!config.ignoreMetadata && !config.ignoreDataProcessing) ptr_diff(temp_a_dp, temp_b_dp, a_b.dp, b_a.dp, config); if (a.size() != b.size()) { ChromatogramPtr dummy(new Chromatogram); dummy->userParams.push_back(UserParam("ChromatogramList sizes differ")); a_b.chromatograms.push_back(dummy); return; } double maxPrecisionDiff = 0; for (unsigned int i=0; iid == b_chromatogram->id; size_t a_find = config.ignoreIdentity || !sameId ? 0 : a.find(a_chromatogram->id); size_t b_find = config.ignoreIdentity || !sameId ? 0 : b.find(b_chromatogram->id); if (!temp_a_b->empty() || !temp_b_a->empty() || a_find != b_find) { a_b.chromatograms.push_back(temp_a_b); b_a.chromatograms.push_back(temp_b_a); if (a_find != b_find) { temp_a_b->index = a_chromatogram->index; temp_a_b->id = a_chromatogram->id; temp_b_a->index = b_chromatogram->index; temp_b_a->id = b_chromatogram->id; temp_a_b->userParams.push_back(UserParam("find() result", lexical_cast(a_find))); temp_b_a->userParams.push_back(UserParam("find() result", lexical_cast(b_find))); } if (!temp_a_b->userParam(userParamName_BinaryDataArrayDifference_).empty()) { double max=lexical_cast(temp_a_b->userParam(userParamName_BinaryDataArrayDifference_).value); if(max>maxPrecisionDiff) maxPrecisionDiff=max; } } } if (maxPrecisionDiff > 0) { if (!a_b.dp.get()) a_b.dp = DataProcessingPtr(new DataProcessing); if (a_b.dp->processingMethods.empty()) a_b.dp->processingMethods.push_back(ProcessingMethod()); ProcessingMethod& listDiffMethod = a_b.dp->processingMethods.back(); if (listDiffMethod.userParam(userParamName_MaxBinaryDataArrayDifference_).empty()) listDiffMethod.userParams.push_back(UserParam(userParamName_MaxBinaryDataArrayDifference_, lexical_cast(maxPrecisionDiff))); else listDiffMethod.userParam(userParamName_MaxBinaryDataArrayDifference_).value = lexical_cast(maxPrecisionDiff); } } PWIZ_API_DECL void diff(const Run& a, const Run& b, Run& a_b, Run& b_a, const DiffConfig& config) { if (!config.ignoreMetadata) { diff(a.id, b.id, a_b.id, b_a.id, config); ptr_diff(a.defaultInstrumentConfigurationPtr, b.defaultInstrumentConfigurationPtr, a_b.defaultInstrumentConfigurationPtr, b_a.defaultInstrumentConfigurationPtr, config); ptr_diff(a.samplePtr, b.samplePtr, a_b.samplePtr, b_a.samplePtr, config); diff(a.startTimeStamp, b.startTimeStamp, a_b.startTimeStamp, b_a.startTimeStamp, config); ptr_diff(a.defaultSourceFilePtr, b.defaultSourceFilePtr, a_b.defaultSourceFilePtr, b_a.defaultSourceFilePtr, config); diff(static_cast(a), b, a_b, b_a, config); } if (!config.ignoreSpectra) { // special handling for SpectrumList diff shared_ptr temp_a_b(new SpectrumListSimple); shared_ptr temp_b_a(new SpectrumListSimple); a_b.spectrumListPtr = temp_a_b; b_a.spectrumListPtr = temp_b_a; SpectrumListPtr temp_a = a.spectrumListPtr.get() ? a.spectrumListPtr : SpectrumListPtr(new SpectrumListSimple); SpectrumListPtr temp_b = b.spectrumListPtr.get() ? b.spectrumListPtr : SpectrumListPtr(new SpectrumListSimple); diff(*temp_a, *temp_b, *temp_a_b, *temp_b_a, config); double maxPrecisionDiffSpec = 0; DataProcessingPtr sl_a_b_dp = temp_a_b->dp; if (sl_a_b_dp.get() && !sl_a_b_dp->processingMethods.empty() && !sl_a_b_dp->processingMethods.back().userParam(userParamName_MaxBinaryDataArrayDifference_).empty()) maxPrecisionDiffSpec = lexical_cast(sl_a_b_dp->processingMethods.back().userParam(userParamName_MaxBinaryDataArrayDifference_).value); if (maxPrecisionDiffSpec>(config.precision+numeric_limits::epsilon())) { a_b.userParams.push_back(UserParam("Spectrum binary data array difference", lexical_cast(maxPrecisionDiffSpec), "xsd:float")); b_a.userParams.push_back(UserParam("Spectrum binary data array difference", lexical_cast(maxPrecisionDiffSpec), "xsd:float")); } } if (!config.ignoreChromatograms) { // special handling for ChromatogramList diff shared_ptr cl_temp_a_b(new ChromatogramListSimple); shared_ptr cl_temp_b_a(new ChromatogramListSimple); a_b.chromatogramListPtr = cl_temp_a_b; b_a.chromatogramListPtr = cl_temp_b_a; ChromatogramListPtr cl_temp_a = a.chromatogramListPtr.get() ? a.chromatogramListPtr : ChromatogramListPtr(new ChromatogramListSimple); ChromatogramListPtr cl_temp_b = b.chromatogramListPtr.get() ? b.chromatogramListPtr : ChromatogramListPtr(new ChromatogramListSimple); diff(*cl_temp_a, *cl_temp_b, *cl_temp_a_b, *cl_temp_b_a, config); double maxPrecisionDiffChr = 0; DataProcessingPtr cl_a_b_dp = cl_temp_a_b->dp; if (cl_a_b_dp.get() && !cl_a_b_dp->processingMethods.empty() && !cl_a_b_dp->processingMethods.back().userParam(userParamName_MaxBinaryDataArrayDifference_).empty()) maxPrecisionDiffChr = lexical_cast(cl_a_b_dp->processingMethods.back().userParam(userParamName_MaxBinaryDataArrayDifference_).value); if (maxPrecisionDiffChr>(config.precision+numeric_limits::epsilon())) { a_b.userParams.push_back(UserParam("Chromatogram binary data array difference", lexical_cast(maxPrecisionDiffChr), "xsd:float")); b_a.userParams.push_back(UserParam("Chromatogram binary data array difference", lexical_cast(maxPrecisionDiffChr), "xsd:float")); } } // provide context if (!a_b.empty() || !b_a.empty()) { a_b.id = a.id; b_a.id = b.id; } } PWIZ_API_DECL void diff(const MSData& a, const MSData& b, MSData& a_b, MSData& b_a, const DiffConfig& config) { string a_b_version, b_a_version; if (!config.ignoreMetadata) { diff(a.accession, b.accession, a_b.accession, b_a.accession, config); diff(a.id, b.id, a_b.id, b_a.id, config); if (!config.ignoreVersions) diff(a.version(), b.version(), a_b_version, b_a_version, config); vector_diff_diff(a.cvs, b.cvs, a_b.cvs, b_a.cvs, config); diff(a.fileDescription, b.fileDescription, a_b.fileDescription, b_a.fileDescription, config); vector_diff_deep(a.paramGroupPtrs, b.paramGroupPtrs, a_b.paramGroupPtrs, b_a.paramGroupPtrs, config); vector_diff_deep(a.samplePtrs, b.samplePtrs, a_b.samplePtrs, b_a.samplePtrs, config); vector_diff_deep(a.softwarePtrs, b.softwarePtrs, a_b.softwarePtrs, b_a.softwarePtrs, config); vector_diff_deep(a.scanSettingsPtrs, b.scanSettingsPtrs, a_b.scanSettingsPtrs, b_a.scanSettingsPtrs, config); vector_diff_deep(a.instrumentConfigurationPtrs, b.instrumentConfigurationPtrs, a_b.instrumentConfigurationPtrs, b_a.instrumentConfigurationPtrs, config); // do diff on full DataProcessing list vector_diff_deep(a.allDataProcessingPtrs(), b.allDataProcessingPtrs(), a_b.dataProcessingPtrs, b_a.dataProcessingPtrs, config); } // ignore DataProcessing in SpectrumList/ChromatogramList DiffConfig config_ignoreDataProcessing(config); config_ignoreDataProcessing.ignoreDataProcessing = true; diff(a.run, b.run, a_b.run, b_a.run, config_ignoreDataProcessing); // provide context if (!a_b.empty() || !b_a.empty() || !a_b_version.empty() || !b_a_version.empty()) { a_b.id = a.id + (a_b_version.empty() ? "" : " (" + a_b_version + ")"); b_a.id = b.id + (b_a_version.empty() ? "" : " (" + b_a_version + ")"); } } } // namespace diff_impl } // namespace data namespace msdata { std::ostream& os_write_spectra(std::ostream& os, const SpectrumListPtr a_b, const SpectrumListPtr b_a) { TextWriter write(os, 1); if(a_b->size()!=b_a->size()) { os<<"in SpectrumList diff: SpectrumList sizes differ"<spectrum(index))); os<<"-\n"; write(*(b_a->spectrum(index))); } return os; } std::ostream& os_write_chromatograms(std::ostream& os, const ChromatogramListPtr a_b, const ChromatogramListPtr b_a) { TextWriter write(os,1); if((a_b==NULL) != (b_a==NULL)) { os<<"in ChromatogramList diff: one of two ChromatogramList pointers is NULL"<size()!=b_a->size()) { os<<"in ChromatogramList diff: ChromatogramList sizes differ"<size();index++) { os<<"+\n"; write(*(a_b->chromatogram(index))); os<<"-\n"; write(*(b_a->chromatogram(index))); } return os; } PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const data::Diff& diff) { TextWriter write(os,1); if(!diff.a_b.empty()|| !diff.b_a.empty()) { os<<"+\n"; write(diff.a_b,true); os<<"-\n"; write(diff.b_a,true); os_write_spectra(os,diff.a_b.run.spectrumListPtr,diff.b_a.run.spectrumListPtr); os_write_chromatograms(os,diff.a_b.run.chromatogramListPtr, diff.b_a.run.chromatogramListPtr); } return os; } } // namespace msdata } // namespace pwiz pwiz/pwiz/data/msdata/SpectrumList_MSn_Test.cpp0000664000175100017510000014371312664775621023655 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_MSn_Test.cpp 7331 2015-03-24 16:11:12Z chambm $ // // // Original author: Barbara Frewen // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "SpectrumList_MSn.hpp" #include "Serializer_MSn.hpp" #include "TextWriter.hpp" #include "pwiz/utility/minimxml/XMLWriter.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/Base64.hpp" #include #include #include using namespace pwiz::msdata; using namespace pwiz::util; using namespace pwiz::minimxml; ostream* os_ = 0; const char *testMS1 = "H CreationDate 10-6-2007\n" "H Extractor MakeMS2\n" "H ExtractorVersion 2.0\n" "H Comments MakeMS2 written by Michael J. MacCoss, Michael R. Hoopmann, 2007\n" "H ExtractorOptions MS1\n" "S 116 116\n" "I RTime 0.4462\n" "175.4067 0.6\n" "195.9831 0.9\n" "236.2524 0.7\n" "266.1989 0.8\n" "276.3145 0.6\n" "278.6099 0.7\n" "281.1050 62.6\n" "298.4888 9.2\n" "299.1033 4\n" "303.5076 1.8\n" "330.1379 1.9\n" "337.1581 0.6\n" "341.0460 1.8\n" "342.3756 0.8\n" "359.0190 1.7\n" "363.0510 1.1\n" "373.2335 1.7\n" "377.2952 1\n" "399.2092 1.6\n" "399.8853 1\n" "403.3747 2.2\n" "405.3385 0.6\n" "408.1845 0.8\n" "409.8174 0.8\n" "414.0231 1.2\n" "415.0792 1.8\n" "417.1754 1.6\n" "419.3268 1.2\n" "420.4443 1.5\n" "421.3249 1.1\n" "429.1662 2.5\n" "435.1794 0.8\n" "436.3020 1.9\n" "439.8971 1\n" "440.6216 1.1\n" "443.7952 0.6\n" "444.5042 1.2\n" "447.0575 0.6\n" "448.5712 1.8\n" "451.1549 2\n" "452.1009 0.8\n" "453.0457 0.7\n" "461.8017 0.7\n" "464.1340 2.7\n" "469.8256 1.8\n" "471.8412 1\n" "473.1831 3.2\n" "474.2579 1\n" "479.8830 1.1\n" "482.2438 1.7\n" "483.1778 2.8\n" "483.8499 0.8\n" "486.1272 2.8\n" "487.5856 0.7\n" "489.5583 4.5\n" "490.6985 4.2\n" "491.4770 5.2\n" "492.3076 7.9\n" "496.1183 1.2\n" "498.5404 2.6\n" "500.5744 7.8\n" "501.2284 6.6\n" "501.9958 3.9\n" "503.0387 37.4\n" "505.0599 2.9\n" "507.2243 1.2\n" "508.2107 0.8\n" "509.1219 2.4\n" "510.4375 0.9\n" "511.3940 0.7\n" "513.4534 3.5\n" "514.4604 4.5\n" "517.0839 6.3\n" "518.1203 18.8\n" "519.0070 65\n" "525.1636 3.1\n" "526.4990 9.4\n" "527.5856 12.2\n" "560.5077 1.2\n" "585.4477 2\n" "621.8749 0.7\n" "632.6031 1\n" "634.1111 0.7\n" "636.3641 1.2\n" "638.4987 1.1\n" "640.5447 1.7\n" "650.5433 0.9\n" "664.1221 0.8\n" "698.4615 0.9\n" "709.7639 1.1\n" "711.2064 1.1\n" "726.0311 1.2\n" "740.0786 0.8\n" "745.3728 0.6\n" "757.8849 1\n" "761.9862 0.8\n" "774.4131 1.3\n" "788.2714 1\n" "829.2268 0.7\n" "840.0249 2\n" "856.4430 0.8\n" "857.6420 0.7\n" "898.4391 0.8\n" "902.4149 0.7\n" "942.4218 1.4\n" "1026.6023 1\n" "S 118 118\n" "I RTime 0.4573\n" "159.1265 1\n" "176.0755 1.4\n" "189.2380 1.3\n" "199.4232 0.8\n" "205.2997 0.6\n" "213.3207 1.4\n" "221.2078 0.9\n" "231.0154 1.6\n" "238.9865 1\n" "244.2399 1.4\n" "249.2524 1.1\n" "252.1188 0.9\n" "253.2228 0.9\n" "263.1987 0.8\n" "269.3484 0.8\n" "272.3980 0.9\n" "273.2263 0.9\n" "276.9475 2.2\n" "279.2698 1.4\n" "299.1149 0.8\n" "302.9478 0.8\n" "305.6744 1.4\n" "308.3992 1.2\n" "317.9594 1.3\n" "322.2583 1.2\n" "332.9634 0.7\n" "337.3151 0.8\n" "346.9624 1.3\n" "349.1566 2.3\n" "351.1241 1.3\n" "357.0767 1.8\n" "361.8666 0.9\n" "363.1213 2.1\n" "365.3057 1.3\n" "370.7582 2.3\n" "375.0994 1.5\n" "377.1262 4.7\n" "383.2674 2.4\n" "385.3204 1.1\n" "386.8699 0.8\n" "390.2235 2\n" "391.1315 1.8\n" "393.2798 1.3\n" "399.0021 0.7\n" "399.8439 1\n" "401.0514 2\n" "401.9986 2.1\n" "405.0557 2.3\n" "406.2401 1.8\n" "407.1901 2.9\n" "409.2251 0.9\n" "410.0710 1.1\n" "411.0744 4.5\n" "412.0661 3.5\n" "416.1904 0.8\n" "418.3093 0.8\n" "419.3824 4.1\n" "420.0984 3.3\n" "421.1917 10.7\n" "422.2375 2.3\n" "423.5126 1.9\n" "424.3980 1.3\n" "426.1027 0.9\n" "426.8067 0.8\n" "428.1773 5.9\n" "429.0244 4.4\n" "430.1233 1.5\n" "433.7563 1.5\n" "435.2169 1.1\n" "435.9414 0.9\n" "437.1042 2.3\n" "438.0438 1.2\n" "442.4830 4.6\n" "443.4222 1.6\n" "446.2477 23.2\n" "447.0900 44.6\n" "447.9651 5.1\n" "452.9314 2.1\n" "455.4204 6.1\n" "456.3987 3\n" "464.9924 12\n" "466.0859 1.3\n" "482.7336 1.8\n" "531.3920 0.8\n" "646.3096 1.8\n" ; const char *testBMS1 = "AQAAAAMAAABDcmVhdGlvbkRhdGUJMTAtNi0yMDA3CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEV4dHJhY3RvcglNYWtlTVMyCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARXh0cmFjdG9yVmVyc2lvbgkyLjAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABDb21tZW50cwlNYWtlTVMyIHdyaXR0ZW4gYnkgTWljaGFlbCBKLiBNYWNDb3NzLCBNaWNoYWVsIFIuIEhvb3BtYW5uLCAyMDA3CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEV4dHJhY3Rvck9wdGlvbnMJTVMxCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOjsAAAAA4LNaC/9/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgENzAAAAAAA/AAAAAAAAAGe2Wgv/fwAAACiWEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAAAAAAAAYBITgAAAAAAACmWEAAAAADRa0wAAAAAAAAAAAAAAAAALY1OAAAAAAAAAAAAAAAAAJ6BTwAAAAAAsCWWEAAAAAAHAAAAAAAAAAAAAAAAAAAA0LRaC/9/AAAAtloL/38AAFAflhAAAAAA8M9aC/9/AADAZUcAAAAAAIBlRwAAAAAARolMAAAAAAAvbmV0L2dzL3ZvbDMvc29mdHdhcmUvbW9kdWxlcy1zdy9nY2MvNC41LjEvTGludXgvUkhFTDUveDg2XzY0L2xpYjY0LwAvbmV0L2dzL3ZvbHQAAAB0AAAAAAAAAAAAAABUdOQ+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAagAAABDpt68D7WVAmpkZP1OWIY51f2hAZmZmP1UwKqkTiG1AMzMzP8oyxLEuo3BAzcxMP3npJjEIRXFAmpkZP0mdgCbCaXFAMzMzP0jhehSukXFAZmZ6Qo/k8h/Sp3JAMzMTQdSa5h2nsXJAAACAQDJ3LSEf+HJAZmbmP+VhodY0onRAMzPzP/aX3ZOHEnVAmpkZP9v5fmq8UHVAZmbmPwtGJXUCZnVAzcxMP/yp8dJNcHZAmpnZP4lBYOXQsHZAzcyMP9v5fmq8U3dAmpnZP3icoiO5lHdAAACAPyxlGeJY83hAzczMP2EyVTAq/nhAAACAP/tcbcX+NXlAzcwMQCPb+X5qVXlAmpkZP8uhRbbzgnlAzcxMPwK8BRIUnXlAzcxMP5oIG55e4HlAmpmZP34dOGdE8XlAZmbmP3/7OnDOEnpAzczMP1MFo5I6NXpAmpmZP84ZUdobR3pAAADAP4enV8oyVXpAzcyMP4bJVMGo0npAAAAgQHDOiNLeMntAzcxMP0a28/3URHtAMzPzP96Th4VafntAAACAPxlz1xLyiXtAzcyMP3icoiO5vHtAmpkZP0vqBDQRyHtAmpmZP1K4HoXr8HtAmpkZP5p3nKIjCXxAZmbmP2gibHh6MnxAAAAAQKqCUUmdQXxAzcxMP9ZW7C+7UHxAMzMzP0ATYcPT3HxAMzMzP6AaL90kAn1AzcwsQD55WKg1XX1AZmbmP1OWIY51fX1AAACAP13+Q/rtkn1AzcxMQDcawFsgpH1AAACAP+Olm8Qg/n1AzcyMPz0s1JrmI35AmpnZP6kT0ETYMn5AMzMzQO0NvjCZPX5AzcxMP9IA3gIJYn5AMzMzQJoIG55eeX5AMzMzP7UV+8vumH5AAACQQBkEVg4tq35AZmaGQBKDwMqht35AZmamQP5D+u3rxH5Azcz8QN5xio7kAX9AmpmZPyJseHqlKH9AZmYmQCntDb4wSX9Ampn5QIEmwoanU39AMzPTQLUV+8vuX39Ampl5QK8l5IOecH9AmpkVQn3Qs1n1kH9Ampk5QOPHmLuWs39AmpmZP0aU9gZfw39AzcxMPx4Wak3z0X9AmpkZQAAAAAAA539AZmZmP/yp8dJN9n9AMzMzPw3gLZCgC4BAAABgQKH4MeauE4BAAACQQBNhw9OrKIBAmpnJQKyt2F/2MIBAZmaWQZMYBFYOOIBAAACCQgFNhA1PaYBAZmZGQKJFtvP9c4BAZmYWQU2EDU+vfIBAMzNDQW+BBMUPhIFAmpmZP1vTvOOUS4JAAAAAQCo6ksv/boNAMzMzP77BFybTxINAAACAP6+UZYjj0INAMzMzP8rDQq3p4oNAmpmZPx/0bFb984NAzcyMPw1xrItbBIRAmpnZP1afq61YVIRAZmZmP7yWkA/6wIRAzcxMP9V46Sax04VAZmZmP1FrmnccLoZAzcyMPygPC7WmOYZAzcyMPz9XW7E/sIZAmpmZP7prCfmgIIdAzcxMP5f/kH77SodAmpkZP9iBc0YUr4dAAACAP4Za07zjz4dAzcxMP9JvXwdOM4hAZmamPxNhw9MroohAAACAP921hHzQ6YlAMzMzP11txf4yQIpAAAAAQAaBlUOLw4pAzcxMP0Jg5dAizYpAMzMzP2Rd3EaDE4xAzcxMP+JYF7dRM4xAMzMzP5+rrdhfc41AMzOzP4bJVMFoCpBAAACAP3YAAAB2AAAAAAAAAAAAAAA6I+o+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVQAAADVeukkM5GNAAACAPyPb+X5qAmZAMzOzP1YOLbKdp2dAZmamP1r1udqK7WhAzcxMP49TdCSXqWlAmpkZP3h6pSxDqmpAMzOzP3uDL0ympmtAZmZmP3gLJCh+4GxAzczMPyGwcmiR321AAACAP+/Jw0Kth25AMzOzP1UwKqkTKG9AzcyMP3lYqDXNg29AZmZmP5Axdy0hp29AZmZmP3EbDeAtc3BAzcxMP9Pe4AuT1XBAzcxMP+58PzVeBnFAZmZmP1uxv+yeE3FAZmZmP1yPwvUoT3FAzcwMQF8HzhlRdHFAMzOzP/fkYaHWsXJAzcxMP2EyVTAq73JAzcxMP8KGp1fKGnNAMzOzPwMJih9jRnNAmpmZP4V80LNZ33NAZmamP+lILv8hJHRAmpmZP3ZPHhZqz3RAMzMzP4MvTKYKFXVAzcxMP7raiv1lr3VAZmamP9xoAG+B0nVAMzMTQPAWSFD88XVAZmamP6d5xyk6UXZAZmbmP2sr9pfdnXZAZmZmPxTQRNjwsXZAZmYGQDLmriXk1HZAZmamPzy9UpYhLHdAMzMTQI9TdCSXcXdAAADAPxWMSuoEkndAZmaWQDXvOEVH9HdAmpkZQDcawFsgFXhAzcyMP6UsQxzrLXhAzcxMP39qvHSTY3hAAAAAQMl2vp8acnhAZmbmP7yWkA96lHhAZmamPyV1ApoI8HhAMzMzP4NRSZ2A/XhAAACAPztwzojSEHlAAAAAQJJc/kP6H3lAZmYGQDLmriXkUHlAMzMTQFD8GHPXY3lAZmbmP4MvTKYKc3lAmpk5QEYldQKak3lAZmZmP0Jg5dAioXlAzcyMPyntDb4wsXlAAACQQECk374OwXlAAABgQInS3uALA3pAzcxMP3KKjuTyJHpAzcxMP9lfdk8eNnpAMzODQNPe4AuTQXpAMzNTQEvqBDQRU3pAMzMrQc3MzMzMY3pAMzMTQOC+DpwzeHpAMzPzP+58PzVehnpAZmamP8pUwaikoXpAZmZmP+5aQj7orHpAzcxMP0tZhjjWwnpAzcy8QFwgQfFj0HpAzcyMQIy5awn54XpAAADAP3BfB84ZHHtAAADAPwpoImx4M3tAzcyMP0VHcvkPP3tAZmZmP+SDns2qUXtAMzMTQAn5oGezYHtAmpmZP30/NV66p3tAMzOTQPCFyVTBtntAzczMP4JzRpT243tAmpm5QT0K16Nw8XtAZmYyQuqVsgxx/3tAMzOjQOm3rwPnTnxAZmYGQNCzWfW5dnxAMzPDQKVOQBNhhnxAAABAQM6I0t7gD31AAABAQZ+rrdhfIX1AZmamP4iFWtO8K35AZmbmP0Jg5dAim4BAzcxMP7yWkA96MoRAZmbmPw=="; const char *testCMS1_v3 = "AgAAAAMAAABDcmVhdGlvbkRhdGUJMTEtMjAtMjAwOAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEV4dHJhY3RvcglNYWtlTVMyCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARXh0cmFjdG9yVmVyc2lvbgkyLjAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABDb21tZW50cwlNYWtlTVMyIHdyaXR0ZW4gYnkgTWljaGFlbCBKLiBNYWNDb3NzLCBNaWNoYWVsIFIuIEhvb3BtYW5uLCAyMDA3CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEV4dHJhY3Rvck9wdGlvbnMJTVMxL01TMgoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOjsAAAAAcDeURv9/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgENzAAAAAAA/AAAAAAAAAPc5lEb/fwAAAFijBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAAAAAAAAYBITgAAAAAAAFmjBAAAAADRa0wAAAAAAAAAAAAAAAAALY1OAAAAAAAAAAAAAAAAAJ6BTwAAAAAAsFWjBAAAAAAHAAAAAAAAAAAAAAAAAAAAYDiURv9/AAAAOpRG/38AAFBPowQAAAAA8F+URv9/AADAZUcAAAAAAIBlRwAAAAAARolMAAAAAAAvbmV0L2dzL3ZvbDMvc29mdHdhcmUvbW9kdWxlcy1zdy9nY2MvNC41LjEvTGludXgvUkhFTDUveDg2XzY0L2xpYjY0LwAvbmV0L2dzL3ZvbCQAAAAkAAAA7FG4HoUhg0AJG94+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQAAANMAAABOAAAAeJwByAA3/8KGp1fKoGtA1lbsL7vHa0Dl0CLb+eRrQDj4wmSqAm5AyxDHurg9b0D+ZffkYWFvQNuK/WX3nm9A1zTvOEWRcEA0ETY8vbFwQIenV8oywXBAoBov3STQcEDOGVHaG5JxQH/ZPXlYoXFAS8gHPZuxcUCWQ4ts59FxQApoImx44HFAImx4eqXwcUCY3ZOHhZRyQGTMXUvIqnJAyxDHurjAckCJQWDl0G51QIhjXdxGsnVAnYAmwoYxdkALRiV1AkF2QHgLJCh+UXZAsJRfOnicMzZudmBgcHA4e2YPkIYDh1kzZ9qDGGfPuDgyMBwA8i0djY0/O6SlsQHZO4H4pn1a2jP7s2d6kPXBwdkzE5wYGEycZs285QQAfAkb/fwBAAD8AQAAAAAAAAAAAABwzshAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAOsAAABRAAAAeJwB4AAf/7WmeccpJmBAC7WmecdBYECdEaW9wWNgQMDsnjwsCGFAEce6uI0+YUC8BRIUP1xhQPmgZ7PqhWFA48eYu5akYUAYldQJaORhQG40gLdAZmJA3bWEfNDFYkArhxbZzuViQMuhRbbzAWNAeekmMQhiY0Bg5dAi24NjQEtZhjjWpWNAKqkT0ETMY0C1N/jCZCZkQPkx5q4lwmRAnu+nxksnZUC/DpwzolJlQJayDHGso2VAg8DKoUXkZUAWak3zjgNmQH2utmJ/Q2ZAI0p7gy+EZkBgdk8eFqhmQIj029eB32ZAwPlnynicmzWz0ImB4YCDsfFmewYgSEtjcwDRMP7ZMzwOs2YaOjKAwQH7WTNngnFamhpUnbADRK4BLM4ABWlpdo5nz/QA1S2zB9EgvQwMCg4ANGkdIA=="; const char *testMS2 = "H CreationDate 10-6-2007\n" "H Extractor MakeMS2\n" "H ExtractorVersion 2.0\n" "H Comments MakeMS2 written by Michael J. MacCoss, Michael R. Hoopmann, 2007\n" "H ExtractorOptions MS2\n" "S 116 116 536.39\n" "Z 2 1071.77\n" "Z 3 1607.15\n" "I RTime 0.4462\n" "175.4067 0.6\n" "195.9831 0.9\n" "236.2524 0.7\n" "266.1989 0.8\n" "276.3145 0.6\n" "278.6099 0.7\n" "281.1050 62.6\n" "298.4888 9.2\n" "299.1033 4\n" "303.5076 1.8\n" "330.1379 1.9\n" "337.1581 0.6\n" "341.0460 1.8\n" "342.3756 0.8\n" "359.0190 1.7\n" "363.0510 1.1\n" "373.2335 1.7\n" "377.2952 1\n" "399.2092 1.6\n" "399.8853 1\n" "403.3747 2.2\n" "405.3385 0.6\n" "408.1845 0.8\n" "409.8174 0.8\n" "414.0231 1.2\n" "415.0792 1.8\n" "417.1754 1.6\n" "419.3268 1.2\n" "420.4443 1.5\n" "421.3249 1.1\n" "429.1662 2.5\n" "435.1794 0.8\n" "436.3020 1.9\n" "439.8971 1\n" "440.6216 1.1\n" "443.7952 0.6\n" "444.5042 1.2\n" "447.0575 0.6\n" "448.5712 1.8\n" "451.1549 2\n" "452.1009 0.8\n" "453.0457 0.7\n" "461.8017 0.7\n" "464.1340 2.7\n" "469.8256 1.8\n" "471.8412 1\n" "473.1831 3.2\n" "474.2579 1\n" "479.8830 1.1\n" "482.2438 1.7\n" "483.1778 2.8\n" "483.8499 0.8\n" "486.1272 2.8\n" "487.5856 0.7\n" "489.5583 4.5\n" "490.6985 4.2\n" "491.4770 5.2\n" "492.3076 7.9\n" "496.1183 1.2\n" "498.5404 2.6\n" "500.5744 7.8\n" "501.2284 6.6\n" "501.9958 3.9\n" "503.0387 37.4\n" "505.0599 2.9\n" "507.2243 1.2\n" "508.2107 0.8\n" "509.1219 2.4\n" "510.4375 0.9\n" "511.3940 0.7\n" "513.4534 3.5\n" "514.4604 4.5\n" "517.0839 6.3\n" "518.1203 18.8\n" "519.0070 65\n" "525.1636 3.1\n" "526.4990 9.4\n" "527.5856 12.2\n" "560.5077 1.2\n" "585.4477 2\n" "621.8749 0.7\n" "632.6031 1\n" "634.1111 0.7\n" "636.3641 1.2\n" "638.4987 1.1\n" "640.5447 1.7\n" "650.5433 0.9\n" "664.1221 0.8\n" "698.4615 0.9\n" "709.7639 1.1\n" "711.2064 1.1\n" "726.0311 1.2\n" "740.0786 0.8\n" "745.3728 0.6\n" "757.8849 1\n" "761.9862 0.8\n" "774.4131 1.3\n" "788.2714 1\n" "829.2268 0.7\n" "840.0249 2\n" "856.4430 0.8\n" "857.6420 0.7\n" "898.4391 0.8\n" "902.4149 0.7\n" "942.4218 1.4\n" "1026.6023 1\n" "S 118 118 464.98\n" "Z 2 928.95\n" "Z 3 1392.92\n" "I RTime 0.4573\n" "159.1265 1\n" "176.0755 1.4\n" "189.2380 1.3\n" "199.4232 0.8\n" "205.2997 0.6\n" "213.3207 1.4\n" "221.2078 0.9\n" "231.0154 1.6\n" "238.9865 1\n" "244.2399 1.4\n" "249.2524 1.1\n" "252.1188 0.9\n" "253.2228 0.9\n" "263.1987 0.8\n" "269.3484 0.8\n" "272.3980 0.9\n" "273.2263 0.9\n" "276.9475 2.2\n" "279.2698 1.4\n" "299.1149 0.8\n" "302.9478 0.8\n" "305.6744 1.4\n" "308.3992 1.2\n" "317.9594 1.3\n" "322.2583 1.2\n" "332.9634 0.7\n" "337.3151 0.8\n" "346.9624 1.3\n" "349.1566 2.3\n" "351.1241 1.3\n" "357.0767 1.8\n" "361.8666 0.9\n" "363.1213 2.1\n" "365.3057 1.3\n" "370.7582 2.3\n" "375.0994 1.5\n" "377.1262 4.7\n" "383.2674 2.4\n" "385.3204 1.1\n" "386.8699 0.8\n" "390.2235 2\n" "391.1315 1.8\n" "393.2798 1.3\n" "399.0021 0.7\n" "399.8439 1\n" "401.0514 2\n" "401.9986 2.1\n" "405.0557 2.3\n" "406.2401 1.8\n" "407.1901 2.9\n" "409.2251 0.9\n" "410.0710 1.1\n" "411.0744 4.5\n" "412.0661 3.5\n" "416.1904 0.8\n" "418.3093 0.8\n" "419.3824 4.1\n" "420.0984 3.3\n" "421.1917 10.7\n" "422.2375 2.3\n" "423.5126 1.9\n" "424.3980 1.3\n" "426.1027 0.9\n" "426.8067 0.8\n" "428.1773 5.9\n" "429.0244 4.4\n" "430.1233 1.5\n" "433.7563 1.5\n" "435.2169 1.1\n" "435.9414 0.9\n" "437.1042 2.3\n" "438.0438 1.2\n" "442.4830 4.6\n" "443.4222 1.6\n" "446.2477 23.2\n" "447.0900 44.6\n" "447.9651 5.1\n" "452.9314 2.1\n" "455.4204 6.1\n" "456.3987 3\n" "464.9924 12\n" "466.0859 1.3\n" "482.7336 1.8\n" "531.3920 0.8\n" "646.3096 1.8\n" ; const char *testBMS2 = "AwAAAAIAAABDcmVhdGlvbkRhdGUJMTAtNi0yMDA3CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEV4dHJhY3RvcglNYWtlTVMyCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARXh0cmFjdG9yVmVyc2lvbgkyLjAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABDb21tZW50cwlNYWtlTVMyIHdyaXR0ZW4gYnkgTWljaGFlbCBKLiBNYWNDb3NzLCBNaWNoYWVsIFIuIEhvb3BtYW5uLCAyMDA3CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEV4dHJhY3Rvck9wdGlvbnMJTVMyCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgjlkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDOfwAAAAAAAAAAAAAAAAAAAAAAAAAAACGcUwAAAAAA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"; const char *testCMS2 = "BAAAAAIAAABDcmVhdGlvbkRhdGUJMTAtNi0yMDA3CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEV4dHJhY3RvcglNYWtlTVMyCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARXh0cmFjdG9yVmVyc2lvbgkyLjAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABDb21tZW50cwlNYWtlTVMyIHdyaXR0ZW4gYnkgTWljaGFlbCBKLiBNYWNDb3NzLCBNaWNoYWVsIFIuIEhvb3BtYW5uLCAyMDA3CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEV4dHJhY3Rvck9wdGlvbnMJTVMyCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgjlkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDOfwAAAAAAAAAAAAAAAAAAAAAAAAAAACGcUwAAAAAA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"; const char* testMS2_v3 = "H CreationDate 11-20-2008\n" "H Extractor MakeMS2\n" "H ExtractorVersion 2.0\n" "H Comments MakeMS2 written by Michael J. MacCoss, Michael R. Hoopmann, 2007\n" "H ExtractorOptions MS1/MS2\n" "S 36 36 612.1900\n" "I RTime 0.4338\n" "I BPM 0.0000\n" "I ConvA 0.0000\n" "I TIC 0.00\n" "I IIT 0.0000\n" "I EZ 1 611.1855 0.8897 27106.6\n" "Z 1 611.1855\n" "221.0247 4.1\n" "222.2416 3\n" "223.1555 5.9\n" "240.0833 0\n" "249.9288 0\n" "251.0432 2\n" "252.9677 1.2\n" "265.0794 0\n" "267.1087 12.3\n" "268.0749 6\n" "269.0090 11.6\n" "281.1318 7.6\n" "282.0841 2.1\n" "283.1004 5.8\n" "285.1190 1.7\n" "286.0294 1.8\n" "287.0404 4.4\n" "297.2826 0\n" "298.6739 0\n" "300.0451 0\n" "342.9260 0\n" "347.1423 0\n" "355.0954 72.4\n" "356.0631 45\n" "357.0933 109.3\n" "S 508 508 441.2300\n" "I RTime 6.2752\n" "I ConvA 0.0000\n" "I ConvB 0.0000\n" "I TIC 0.00\n" "I IIT 0.0000\n" "I EZ 3 1318.7270 5.9467 28240.3\n" "I EZ 2 880.4527 6.2403 34674.3\n" "Z 3 1318.7270\n" "Z 2 880.4527\n" "129.1926 60.4\n" "130.0556 6\n" "131.1174 1.4\n" "136.2554 0\n" "137.9548 2.1\n" "138.8827 0\n" "140.1849 1.4\n" "141.1434 0\n" "143.1377 2.2\n" "147.1954 11.1\n" "150.1817 0\n" "151.1815 1.5\n" "152.0610 1.2\n" "155.0635 1.2\n" "156.1205 2.6\n" "157.1824 0\n" "158.3834 2.3\n" "161.1998 0\n" "166.0671 1\n" "169.2280 1.2\n" "170.5823 0\n" "173.1148 0\n" "175.1335 11.9\n" "176.1112 1.1\n" "178.1093 1.3\n" "180.1308 1.1\n" "181.2527 1.5\n" "182.9846 2.5\n" ; const char* testCMS2_v3 = "BAAAAAMAAAAgICAgICBDcmVhdGlvbkRhdGUgICAgMTEtMjAtMjAwOAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAgICAgIEV4dHJhY3RvciAgICAgICBNYWtlTVMyCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAgICAgRXh0cmFjdG9yVmVyc2lvbiAgICAgICAgMi4wCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgICAgICBDb21tZW50cyAgICAgICAgTWFrZU1TMiB3cml0dGVuIGJ5IE1pY2hhZWwgSi4gTWFjQ29zcywgTWljaGFlbCBSLiBIb29wbWFubiwgMjAwNwoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAgICAgIEV4dHJhY3Rvck9wdGlvbnMgICAgICAgIE1TMS9NUzIKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD21UoAAAAAACQAAAAkAAAA7FG4HoUhg0AJG94+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAGQAAAAEAAABEi2znexmDQAEAAABEi2znexmDQGHDYz8zxdNG0wAAAE4AAAB4nAHIADf/woanV8qga0DWVuwvu8drQOXQItv55GtAOPjCZKoCbkDLEMe6uD1vQP5l9+RhYW9A24r9Zfeeb0DXNO84RZFwQDQRNjy9sXBAh6dXyjLBcECgGi/dJNBwQM4ZUdobknFAf9k9eVihcUBLyAc9m7FxQJZDi2zn0XFACmgibHjgcUAibHh6pfBxQJjdk4eFlHJAZMxdS8iqckDLEMe6uMByQIlBYOXQbnVAiGNd3EaydUCdgCbChjF2QAtGJXUCQXZAeAskKH5RdkCwlF86eJwzNm52YGBwcDh7Zg+QhgOHWTNn2oMYZ8+4ODIwHADyLR2NjT87pKWxAdk7gfimfVraM/uzZ3qQ9cHB2TMTnBgYTJxmzbzlBAB8CRv9/AEAAPwBAABI4XoUrpN7QHDOyEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAIAAAAcAAAAAwAAAMUgsHLompRAAgAAADJ3LSGfg4tAAwAAAMUgsHLompRAXku+QJqg3EYCAAAAMnctIZ+Di0CKsMdATXIHR+sAAABRAAAAeJwB4AAf/7WmeccpJmBAC7WmecdBYECdEaW9wWNgQMDsnjwsCGFAEce6uI0+YUC8BRIUP1xhQPmgZ7PqhWFA48eYu5akYUAYldQJaORhQG40gLdAZmJA3bWEfNDFYkArhxbZzuViQMuhRbbzAWNAeekmMQhiY0Bg5dAi24NjQEtZhjjWpWNAKqkT0ETMY0C1N/jCZCZkQPkx5q4lwmRAnu+nxksnZUC/DpwzolJlQJayDHGso2VAg8DKoUXkZUAWak3zjgNmQH2utmJ/Q2ZAI0p7gy+EZkBgdk8eFqhmQIj029eB32ZAwPlnynicmzWz0ImB4YCDsfFmewYgSEtjcwDRMP7ZMzwOs2YaOjKAwQH7WTNngnFamhpUnbADRK4BLM4ABWlpdo5nz/QA1S2zB9EgvQwMCg4ANGkdIA=="; void test(SpectrumListPtr sl, int msLevel) { if (os_) { TextWriter write(*os_); write(*sl); *os_ << endl; } // check easy functions unit_assert(sl.get()); unit_assert(sl->size() == 2); unit_assert(sl->find("scan=116") == 0); unit_assert(sl->find("scan=118") == 1); // check scan 0 unit_assert(sl->spectrumIdentity(0).index == 0); unit_assert(sl->spectrumIdentity(0).id == "scan=116"); unit_assert(sl->spectrumIdentity(0).sourceFilePosition != -1); SpectrumPtr s = sl->spectrum(0, false); unit_assert(s.get()); unit_assert(s->id == "scan=116"); unit_assert(s->index == 0); unit_assert(s->sourceFilePosition != -1); unit_assert(s->cvParam(MS_ms_level).valueAs() == msLevel); unit_assert_equal(s->cvParam(MS_total_ion_current).valueAs(), 385.4, 5e-1); unit_assert_equal(s->cvParam(MS_base_peak_intensity).valueAs(), 65.0, 5e-1); if (msLevel == 1) { unit_assert(s->precursors.size() == 0); } else { unit_assert(s->precursors.size() == 1); Precursor& precursor0 = s->precursors[0]; unit_assert(precursor0.selectedIons.size() == 1); unit_assert_equal(precursor0.isolationWindow.cvParam(MS_isolation_window_target_m_z).valueAs(), 536.39, 5e-2); // This test spectrum only has possible charge states (2 total, values 2,3) unit_assert(precursor0.selectedIons[0].cvParam(MS_charge_state).value.empty()); vector charges; BOOST_FOREACH(CVParam& param, precursor0.selectedIons[0].cvParams) { if (param.cvid == MS_possible_charge_state) { charges.push_back(param.value); } } unit_assert(charges.size() == 2); vector::const_iterator charge_it = charges.begin(); unit_assert(*charge_it == "2"); unit_assert(*(++charge_it) == "3"); } unit_assert(s->defaultArrayLength == 106); unit_assert(s->binaryDataArrayPtrs.size() == 2); unit_assert(s->binaryDataArrayPtrs[0]->hasCVParam(MS_m_z_array)); unit_assert(s->binaryDataArrayPtrs[1]->hasCVParam(MS_intensity_array)); unit_assert(s->binaryDataArrayPtrs[0]->data.empty() && s->binaryDataArrayPtrs[1]->data.empty()); s = sl->spectrum(0, true); unit_assert(s->defaultArrayLength == 106); unit_assert(s->binaryDataArrayPtrs.size() == 2); unit_assert(!s->binaryDataArrayPtrs[0]->data.empty() && !s->binaryDataArrayPtrs[1]->data.empty()); vector pairs; s->getMZIntensityPairs(pairs); if (os_) { *os_ << "scan 0:\n"; copy(pairs.begin(), pairs.end(), ostream_iterator(*os_, "\n")); *os_ << endl; } // check scan 1 unit_assert(sl->spectrumIdentity(1).index == 1); unit_assert(sl->spectrumIdentity(1).id == "scan=118"); s = sl->spectrum(1, true); unit_assert(s.get()); unit_assert(s->id == "scan=118"); unit_assert(s->index == 1); unit_assert(s->sourceFilePosition != -1); unit_assert(s->cvParam(MS_ms_level).valueAs() == msLevel); unit_assert(s->scanList.scans.size() == 1); unit_assert_equal(s->scanList.scans[0].cvParam(MS_scan_start_time).timeInSeconds(), 0.4573*60, 5e-4); if (msLevel == 1) { unit_assert(s->precursors.size() == 0); } else { unit_assert(s->precursors.size() == 1); Precursor& precursor1 = s->precursors[0]; unit_assert(precursor1.selectedIons.size() == 1); unit_assert_equal(precursor1.isolationWindow.cvParam(MS_isolation_window_target_m_z).valueAs(), 464.98, 1e-5); // This test spectrum only has possible charge states (2 total, values 2,3) unit_assert(precursor1.selectedIons[0].cvParam(MS_charge_state).value.empty()); vector charges; BOOST_FOREACH(CVParam& param, precursor1.selectedIons[0].cvParams) { if (param.cvid == MS_possible_charge_state) { charges.push_back(param.value); } } unit_assert(charges.size() == 2); vector::const_iterator charge_it = charges.begin(); unit_assert(*charge_it == "2"); unit_assert(*(++charge_it) == "3"); } unit_assert(s->defaultArrayLength == 85); pairs.clear(); s->getMZIntensityPairs(pairs); unit_assert(s->defaultArrayLength == pairs.size()); if (os_) { *os_ << "scan 1:\n"; copy(pairs.begin(), pairs.end(), ostream_iterator(*os_, "\n")); *os_ << endl; } } void test_v3(SpectrumListPtr sl, int msLevel) { if (os_) { TextWriter write(*os_); write(*sl); *os_ << endl; } // check easy functions unit_assert(sl.get()); unit_assert(sl->size() == 2); unit_assert(sl->find("scan=36") == 0); unit_assert(sl->find("scan=508") == 1); // check scan 0 unit_assert(sl->spectrumIdentity(0).index == 0); unit_assert(sl->spectrumIdentity(0).id == "scan=36"); unit_assert(sl->spectrumIdentity(0).sourceFilePosition != -1); SpectrumPtr s = sl->spectrum(0, false); unit_assert(s.get()); unit_assert(s->id == "scan=36"); unit_assert(s->index == 0); unit_assert(s->sourceFilePosition != -1); unit_assert(s->cvParam(MS_ms_level).valueAs() == msLevel); unit_assert_equal(s->cvParam(MS_total_ion_current).valueAs(), 296.2, 5e-1); unit_assert_equal(s->cvParam(MS_base_peak_intensity).valueAs(), 109.3, 5e-1); if (msLevel == 1) { unit_assert(s->precursors.size() == 0); } else { unit_assert(s->precursors.size() == 1); Precursor& precursor0 = s->precursors[0]; unit_assert(precursor0.selectedIons.size() == 1); // isolated precursor m/z on S line unit_assert_equal(precursor0.isolationWindow.cvParam(MS_isolation_window_target_m_z).valueAs(), 612.19, 5e-2); // m/z of calculated accurate mass unit_assert_equal(precursor0.selectedIons[0].cvParam(MS_selected_ion_m_z).valueAs(), 611.1855, 5e-2); // This test spectrum one charge state, so no possible charge states unit_assert(precursor0.selectedIons[0].cvParam(MS_possible_charge_state).value.empty()); vector charges; vector masses; BOOST_FOREACH(CVParam& param, precursor0.selectedIons[0].cvParams) { if (param.cvid == MS_charge_state) { charges.push_back(param.value); } if (param.cvid == MS_accurate_mass_OBSOLETE) { masses.push_back(lexical_cast(param.value)); } } unit_assert(charges.size() == 1); vector::const_iterator charge_it = charges.begin(); unit_assert(*charge_it == "1"); unit_assert(masses.size() == 1); vector::const_iterator mass_it = masses.begin(); unit_assert_equal(*mass_it, 611.1855, 5e-4); } unit_assert(s->defaultArrayLength == 25); unit_assert(s->binaryDataArrayPtrs.size() == 2); unit_assert(s->binaryDataArrayPtrs[0]->hasCVParam(MS_m_z_array)); unit_assert(s->binaryDataArrayPtrs[1]->hasCVParam(MS_intensity_array)); unit_assert(s->binaryDataArrayPtrs[0]->data.empty() && s->binaryDataArrayPtrs[1]->data.empty()); s = sl->spectrum(0, true); unit_assert(s->defaultArrayLength == 25); unit_assert(s->binaryDataArrayPtrs.size() == 2); unit_assert(!s->binaryDataArrayPtrs[0]->data.empty() && !s->binaryDataArrayPtrs[1]->data.empty()); vector pairs; s->getMZIntensityPairs(pairs); if (os_) { *os_ << "scan 0:\n"; copy(pairs.begin(), pairs.end(), ostream_iterator(*os_, "\n")); *os_ << endl; } // check scan 1 unit_assert(sl->spectrumIdentity(1).index == 1); unit_assert(sl->spectrumIdentity(1).id == "scan=508"); s = sl->spectrum(1, true); unit_assert(s.get()); unit_assert(s->id == "scan=508"); unit_assert(s->index == 1); unit_assert(s->sourceFilePosition != -1); unit_assert(s->cvParam(MS_ms_level).valueAs() == msLevel); unit_assert(s->scanList.scans.size() == 1); unit_assert_equal(s->scanList.scans[0].cvParam(MS_scan_start_time).timeInSeconds()/60, 6.2752, 5e-4); if (msLevel == 1) { unit_assert(s->precursors.size() == 0); } else { unit_assert(s->precursors.size() == 1); Precursor& precursor1 = s->precursors[0]; unit_assert(precursor1.selectedIons.size() == 2); // precursor m/z on S line unit_assert_equal(precursor1.isolationWindow.cvParam(MS_isolation_window_target_m_z).valueAs(), 441.23, 5e-2); // m/z computed from accurate mass on Z line unit_assert_equal(precursor1.selectedIons[0].cvParam(MS_selected_ion_m_z).valueAs(), 440.2471843, 1e-4); // This test spectrum has two charge states, both known so no possible charges unit_assert(precursor1.selectedIons[0].cvParam(MS_possible_charge_state).value.empty()); vector charges; vector masses; BOOST_FOREACH(SelectedIon& si, precursor1.selectedIons) { BOOST_FOREACH(CVParam& param, si.cvParams) { if (param.cvid == MS_charge_state) { charges.push_back(param.value); } if (param.cvid == MS_accurate_mass_OBSOLETE) { masses.push_back(lexical_cast(param.value)); } } } unit_assert(charges.size() == 2); vector::const_iterator charge_it = charges.begin(); unit_assert(*charge_it == "3"); unit_assert(*(++charge_it) == "2"); unit_assert(masses.size() == 2); vector::const_iterator mass_it = masses.begin(); unit_assert_equal(*mass_it, 1318.7270, 5e-4); unit_assert_equal(*(++mass_it), 880.4527, 5e-4); } unit_assert(s->defaultArrayLength == 28); pairs.clear(); s->getMZIntensityPairs(pairs); unit_assert(s->defaultArrayLength == pairs.size()); if (os_) { *os_ << "scan 1:\n"; copy(pairs.begin(), pairs.end(), ostream_iterator(*os_, "\n")); *os_ << endl; } } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; // dummy would normally be read in from file MSData dummy; dummy.instrumentConfigurationPtrs.push_back(InstrumentConfigurationPtr(new InstrumentConfiguration("LCQDeca"))); dummy.instrumentConfigurationPtrs.back()->cvParams.push_back(MS_LCQ_Deca); dummy.instrumentConfigurationPtrs.back()->userParams.push_back(UserParam("doobie", "420")); if (os_) { *os_ << "test()\n"; *os_ << "ms1:\n" << testMS1 << endl; *os_ << "ms2:\n" << testMS2 << endl; } // TEST MS1 TEXT FORMAT shared_ptr isMS1(new istringstream(testMS1)); SpectrumListPtr slMS1 = SpectrumList_MSn::create(isMS1, dummy, MSn_Type_MS1); test(slMS1, 1); // TEST BMS1 BINARY FORMAT const string& testBMS1Base64Str = testBMS1; vector binaryBufferBMS1; binaryBufferBMS1.resize(Base64::textToBinarySize(testBMS1Base64Str.size()) + 1, '\0'); Base64::textToBinary(testBMS1Base64Str.c_str(), testBMS1Base64Str.size(), &binaryBufferBMS1[0]); string binaryStringBMS1; for (size_t i = 0; i < binaryBufferBMS1.size(); i++) { binaryStringBMS1 += binaryBufferBMS1[i]; } shared_ptr isBMS1(new istringstream(binaryStringBMS1)); SpectrumListPtr slBMS1 = SpectrumList_MSn::create(isBMS1, dummy, MSn_Type_BMS1); test(slBMS1, 1); // TEST CMS1 COMPRESSED BINARY FORMAT (version 3) const string& testCMS1_v3Base64Str = testCMS1_v3; vector binaryBufferCMS1_v3; binaryBufferCMS1_v3.resize(Base64::textToBinarySize(testCMS1_v3Base64Str.size()) + 1, '\0'); Base64::textToBinary(testCMS1_v3Base64Str.c_str(), testCMS1_v3Base64Str.size(), &binaryBufferCMS1_v3[0]); string binaryStringCMS1_v3; for (size_t i = 0; i < binaryBufferCMS1_v3.size(); i++) { binaryStringCMS1_v3 += binaryBufferCMS1_v3[i]; } shared_ptr isCMS1_v3(new istringstream(binaryStringCMS1_v3)); SpectrumListPtr slCMS1_v3 = SpectrumList_MSn::create(isCMS1_v3, dummy, MSn_Type_CMS1); test_v3(slCMS1_v3, 1); // TEST MS2 TEXT FORMAT shared_ptr isMS2(new istringstream(testMS2)); SpectrumListPtr slMS2 = SpectrumList_MSn::create(isMS2, dummy, MSn_Type_MS2); test(slMS2, 2); // TEST BMS2 BINARY FORMAT const string& testBMS2Base64Str = testBMS2; vector binaryBufferBMS2; binaryBufferBMS2.resize(Base64::textToBinarySize(testBMS2Base64Str.size()) + 1, '\0'); Base64::textToBinary(testBMS2Base64Str.c_str(), testBMS2Base64Str.size(), &binaryBufferBMS2[0]); string binaryStringBMS2; for (size_t i = 0; i < binaryBufferBMS2.size(); i++) { binaryStringBMS2 += binaryBufferBMS2[i]; } shared_ptr isBMS2(new istringstream(binaryStringBMS2)); SpectrumListPtr slBMS2 = SpectrumList_MSn::create(isBMS2, dummy, MSn_Type_BMS2); test(slBMS2, 2); // TEST CMS2 COMPRESSED BINARY FORMAT (version 2) const string& testCMS2Base64Str = testCMS2; vector binaryBufferCMS2; binaryBufferCMS2.resize(Base64::textToBinarySize(testCMS2Base64Str.size()) + 1, '\0'); Base64::textToBinary(testCMS2Base64Str.c_str(), testCMS2Base64Str.size(), &binaryBufferCMS2[0]); string binaryStringCMS2; for (size_t i = 0; i < binaryBufferCMS2.size(); i++) { binaryStringCMS2 += binaryBufferCMS2[i]; } shared_ptr isCMS2(new istringstream(binaryStringCMS2)); SpectrumListPtr slCMS2 = SpectrumList_MSn::create(isCMS2, dummy, MSn_Type_CMS2); test(slCMS2, 2); // TEST MS2 TEXT FORMAT WITH EZ LINES (version 3) shared_ptr isMS2_v3(new istringstream(testMS2_v3)); SpectrumListPtr slMS2_v3 = SpectrumList_MSn::create(isMS2_v3, dummy, MSn_Type_MS2); test_v3(slMS2_v3, 2); // TEST CMS2 COMPRESSED BINARY FORMAT (version 3) const string& testCMS2_v3Base64Str = testCMS2_v3; vector binaryBufferCMS2_v3; binaryBufferCMS2_v3.resize(Base64::textToBinarySize(testCMS2_v3Base64Str.size()) + 1, '\0'); Base64::textToBinary(testCMS2_v3Base64Str.c_str(), testCMS2_v3Base64Str.size(), &binaryBufferCMS2_v3[0]); string binaryStringCMS2_v3; for (size_t i = 0; i < binaryBufferCMS2_v3.size(); i++) { binaryStringCMS2_v3 += binaryBufferCMS2_v3[i]; } shared_ptr isCMS2_v3(new istringstream(binaryStringCMS2_v3)); SpectrumListPtr slCMS2_v3 = SpectrumList_MSn::create(isCMS2_v3, dummy, MSn_Type_CMS2); test_v3(slCMS2_v3, 2); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/msdata/MSDataMergerTest.cpp0000664000175100017510000001017112664775621022545 0ustar teamcityteamcity00000000000000// // $Id: MSDataMergerTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Matt Chambers // // Copyright 2010 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/unit.hpp" #include "MSDataMerger.hpp" #include "examples.hpp" #include "TextWriter.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::msdata; using namespace pwiz::util; ostream* os_ = 0; void test() { MSData tinyReference; examples::initializeTiny(tinyReference); const size_t tinyCopyCount = 3; vector tinyExamples; for (size_t i=0; i < tinyCopyCount; ++i) { tinyExamples.push_back(MSDataPtr(new MSData)); MSData& msd = *tinyExamples.back(); examples::initializeTiny(msd); msd.id = msd.run.id = "tiny" + lexical_cast(i); } MSDataMerger tinyMerged(tinyExamples); if (os_) { TextWriter writer(*os_); writer(tinyMerged); } unit_assert(tinyMerged.id == "tiny"); // longest common prefix of tiny[012] unit_assert(tinyMerged.run.id == "tiny"); // longest common prefix of tiny[012] unit_assert(tinyMerged.fileDescription.fileContent.hasCVParam(MS_MSn_spectrum)); unit_assert(tinyMerged.fileDescription.fileContent.hasCVParam(MS_centroid_spectrum)); unit_assert(tinyMerged.fileDescription.sourceFilePtrs.size() == tinyReference.fileDescription.sourceFilePtrs.size() * tinyCopyCount); for (size_t i=0; i < tinyCopyCount; ++i) for (size_t j=0; j < tinyReference.fileDescription.sourceFilePtrs.size(); ++j) { string expectedPrefix = "tiny" + lexical_cast(i) + "_"; size_t expectedIndex = j + (i * tinyReference.fileDescription.sourceFilePtrs.size()); unit_assert(tinyMerged.fileDescription.sourceFilePtrs[expectedIndex]->id == expectedPrefix + tinyReference.fileDescription.sourceFilePtrs[j]->id); } //unit_assert(tinyMerged.fileDescription.contacts.size() == tinyReference.fileDescription.contacts.size()); SpectrumList& sl = *tinyMerged.run.spectrumListPtr; unit_assert(sl.size() == 3 * tinyReference.run.spectrumListPtr->size()); for (size_t index=0; index < sl.size(); ++index) { size_t referenceIndex = index % tinyReference.run.spectrumListPtr->size(); const SpectrumIdentity& identity = sl.spectrumIdentity(index); const SpectrumIdentity& referenceIdentity = tinyReference.run.spectrumListPtr->spectrumIdentity(referenceIndex); unit_assert(identity.index == index); unit_assert(identity.id == referenceIdentity.id); SpectrumPtr spectrum = sl.spectrum(index); SpectrumPtr referenceSpectrum = tinyReference.run.spectrumListPtr->spectrum(referenceIndex); unit_assert(spectrum->index == index); unit_assert(spectrum->id == referenceSpectrum->id); vector::const_iterator foundSourceFile = find(tinyMerged.fileDescription.sourceFilePtrs.begin(), tinyMerged.fileDescription.sourceFilePtrs.end(), spectrum->sourceFilePtr); unit_assert(foundSourceFile != tinyMerged.fileDescription.sourceFilePtrs.end()); } } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/msdata/MSData.hpp0000664000175100017510000010707612664775621020563 0ustar teamcityteamcity00000000000000// // $Id: MSData.hpp 6452 2014-07-03 19:01:15Z pcbrefugee $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _MSDATA_HPP_ #define _MSDATA_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/common/ParamTypes.hpp" #include "boost/shared_ptr.hpp" #include "boost/iostreams/positioning.hpp" #include #include #include #include namespace pwiz { namespace msdata { using namespace pwiz::data; PWIZ_API_DECL std::vector defaultCVList(); /// This summarizes the different types of spectra that can be expected in the file. This is expected to aid processing software in skipping files that do not contain appropriate spectrum types for it. struct PWIZ_API_DECL FileContent : public ParamContainer {}; /// Description of the source file, including location and type. struct PWIZ_API_DECL SourceFile : public ParamContainer { /// an identifier for this file. std::string id; /// name of the source file, without reference to location (either URI or local path). std::string name; /// URI-formatted location where the file was retrieved. std::string location; SourceFile(const std::string _id = "", const std::string _name = "", const std::string _location = ""); /// returns true iff the element contains no params and all members are empty or null bool empty() const; }; /// Description of the source file, including location and type. typedef boost::shared_ptr SourceFilePtr; /// Structure allowing the use of a controlled (cvParam) or uncontrolled vocabulary (userParam), or a reference to a predefined set of these in this mzML file (paramGroupRef). struct PWIZ_API_DECL Contact : public ParamContainer {}; /// Information pertaining to the entire mzML file (i.e. not specific to any part of the data set) is stored here. struct PWIZ_API_DECL FileDescription { /// this summarizes the different types of spectra that can be expected in the file. This is expected to aid processing software in skipping files that do not contain appropriate spectrum types for it. FileContent fileContent; /// list and descriptions of the source files this mzML document was generated or derived from. std::vector sourceFilePtrs; /// structure allowing the use of a controlled (cvParam) or uncontrolled vocabulary (userParam), or a reference to a predefined set of these in this mzML file (paramGroupRef) std::vector contacts; /// returns true iff all members are empty or null bool empty() const; }; /// Expansible description of the sample used to generate the dataset, named in sampleName. struct PWIZ_API_DECL Sample : public ParamContainer { /// a unique identifier across the samples with which to reference this sample description. std::string id; /// an optional name for the sample description, mostly intended as a quick mnemonic. std::string name; Sample(const std::string _id = "", const std::string _name = ""); /// returns true iff the element contains no params and all members are empty or null bool empty() const; }; typedef boost::shared_ptr SamplePtr; enum ComponentType { ComponentType_Unknown = -1, ComponentType_Source = 0, ComponentType_Analyzer, ComponentType_Detector }; /// A component of an instrument corresponding to a source (i.e. ion source), an analyzer (i.e. mass analyzer), or a detector (i.e. ion detector) struct PWIZ_API_DECL Component : public ParamContainer { /// the type of component (Source, Analyzer, or Detector) ComponentType type; /// this attribute MUST be used to indicate the order in which the components are encountered from source to detector (e.g., in a Q-TOF, the quadrupole would have the lower order number, and the TOF the higher number of the two). int order; Component() : type(ComponentType_Unknown), order(0) {} Component(ComponentType type, int order) : type(type), order(order) {} Component(CVID cvid, int order) { define(cvid, order); } void define(CVID cvid, int order); /// returns true iff the element contains no params and all members are empty or null bool empty() const; }; //struct PWIZ_API_DECL Source : public Component {}; //struct PWIZ_API_DECL Analyzer : public Component {}; //struct PWIZ_API_DECL Detector : public Component {}; /// List with the different components used in the mass spectrometer. At least one source, one mass analyzer and one detector need to be specified. struct PWIZ_API_DECL ComponentList : public std::vector { /// returns the source component with ordinal Component& source(size_t index); /// returns the analyzer component with ordinal Component& analyzer(size_t index); /// returns the detector component with ordinal Component& detector(size_t index); /// returns the source component with ordinal const Component& source(size_t index) const; /// returns the analyzer component with ordinal const Component& analyzer(size_t index) const; /// returns the detector component with ordinal const Component& detector(size_t index) const; }; /// A piece of software. struct PWIZ_API_DECL Software : public ParamContainer { /// an identifier for this software that is unique across all SoftwareTypes. std::string id; /// the software version. std::string version; Software(const std::string& _id = ""); Software(const std::string& _id, const CVParam& _param, const std::string& _version); /// returns true iff all members are empty or null bool empty() const; }; typedef boost::shared_ptr SoftwarePtr; /// TODO struct PWIZ_API_DECL Target : public ParamContainer {}; /// Description of the acquisition settings of the instrument prior to the start of the run. struct PWIZ_API_DECL ScanSettings { /// a unique identifier for this acquisition setting. std::string id; /// container for a list of source file references. std::vector sourceFilePtrs; /// target list (or 'inclusion list') configured prior to the run. std::vector targets; ScanSettings(const std::string& _id = ""); /// returns true iff the element contains no params and all members are empty or null bool empty() const; }; typedef boost::shared_ptr ScanSettingsPtr; /// Description of a particular hardware configuration of a mass spectrometer. Each configuration MUST have one (and only one) of the three different components used for an analysis. For hybrid instruments, such as an LTQ-FT, there MUST be one configuration for each permutation of the components that is used in the document. For software configuration, reference the appropriate ScanSettings element. struct PWIZ_API_DECL InstrumentConfiguration : public ParamContainer { /// an identifier for this instrument configuration. std::string id; /// list with the different components used in the mass spectrometer. At least one source, one mass analyzer and one detector need to be specified. ComponentList componentList; /// reference to a previously defined software element. SoftwarePtr softwarePtr; /// reference to a scan settings element defining global scan settings used by this configuration ScanSettingsPtr scanSettingsPtr; InstrumentConfiguration(const std::string& _id = ""); /// returns true iff the element contains no params and all members are empty or null bool empty() const; }; typedef boost::shared_ptr InstrumentConfigurationPtr; /// Description of the default peak processing method. This element describes the base method used in the generation of a particular mzML file. Variable methods should be described in the appropriate acquisition section - if no acquisition-specific details are found, then this information serves as the default. struct PWIZ_API_DECL ProcessingMethod : public ParamContainer { /// this attributes allows a series of consecutive steps to be placed in the correct order. int order; /// this attribute MUST reference the 'id' of the appropriate SoftwareType. SoftwarePtr softwarePtr; ProcessingMethod() : order(0) {} /// returns true iff the element contains no params and all members are empty or null bool empty() const; }; typedef boost::shared_ptr ProcessingMethodPtr; /// Description of the way in which a particular software was used. struct PWIZ_API_DECL DataProcessing { /// a unique identifier for this data processing that is unique across all DataProcessingTypes. std::string id; /// description of the default peak processing method(s). This element describes the base method used in the generation of a particular mzML file. Variable methods should be described in the appropriate acquisition section - if no acquisition-specific details are found, then this information serves as the default. std::vector processingMethods; DataProcessing(const std::string& _id = ""); /// returns true iff the element contains no params and all members are empty or null bool empty() const; }; typedef boost::shared_ptr DataProcessingPtr; /// This element captures the isolation (or 'selection') window configured to isolate one or more precursors. struct PWIZ_API_DECL IsolationWindow : public ParamContainer {}; /// TODO struct PWIZ_API_DECL SelectedIon : public ParamContainer { SelectedIon() {} explicit SelectedIon(double mz); explicit SelectedIon(double mz, double intensity, CVID intensityUnit); explicit SelectedIon(double mz, int chargeState); explicit SelectedIon(double mz, double intensity, int chargeState, CVID intensityUnit); }; /// The type and energy level used for activation. struct PWIZ_API_DECL Activation : public ParamContainer {}; /// The method of precursor ion selection and activation struct PWIZ_API_DECL Precursor : public ParamContainer { /// for precursor spectra that are external to this document, this attribute MUST reference the 'id' attribute of a sourceFile representing that external document. /// note: this attribute is mutually exclusive with spectrumID; i.e. use one or the other but not both SourceFilePtr sourceFilePtr; /// for precursor spectra that are external to this document, this string MUST correspond to the 'id' attribute of a spectrum in the external document indicated by 'sourceFileRef'. /// note: this attribute is mutually exclusive with spectrumID; i.e. use one or the other but not both std::string externalSpectrumID; /// reference to the id attribute of the spectrum from which the precursor was selected. /// note: this attribute is mutually exclusive with externalSpectrumID; i.e. use one or the other but not both std::string spectrumID; /// this element captures the isolation (or 'selection') window configured to isolate one or more precursors. IsolationWindow isolationWindow; /// this list of precursor ions that were selected. std::vector selectedIons; /// the type and energy level used for activation. Activation activation; Precursor() {} explicit Precursor(double mz); explicit Precursor(double mz, double intensity, CVID intensityUnit); explicit Precursor(double mz, int chargeState); explicit Precursor(double mz, double intensity, int chargeState, CVID intensityUnit); /// returns true iff the element contains no params and all members are empty or null bool empty() const; }; /// product ion information struct PWIZ_API_DECL Product { /// this element captures the isolation (or 'selection') window configured to isolate one or more precursors. IsolationWindow isolationWindow; /// returns true iff the element contains no params and all members are empty or null bool empty() const; /// returns true iff this product's isolation window is equal to that product's bool operator==(const Product& that) const; }; /// TODO struct PWIZ_API_DECL ScanWindow : public ParamContainer { ScanWindow(){} ScanWindow(double low, double high, CVID unit); }; /// Scan or acquisition from original raw file used to create this peak list, as specified in sourceFile. struct PWIZ_API_DECL Scan : public ParamContainer { /// if this attribute is set, it must reference the 'id' attribute of a sourceFile representing the external document containing the spectrum referred to by 'externalSpectrumID'. /// note: this attribute is mutually exclusive with spectrumID; i.e. use one or the other but not both SourceFilePtr sourceFilePtr; /// for scans that are external to this document, this string must correspond to the 'id' attribute of a spectrum in the external document indicated by 'sourceFileRef'. /// note: this attribute is mutually exclusive with spectrumID; i.e. use one or the other but not both std::string externalSpectrumID; /// for scans that are local to this document, this attribute can be used to reference the 'id' attribute of the spectrum corresponding to the scan. /// note: this attribute is mutually exclusive with externalSpectrumID; i.e. use one or the other but not both std::string spectrumID; /// this attribute MUST reference the 'id' attribute of the appropriate instrument configuration. InstrumentConfigurationPtr instrumentConfigurationPtr; /// container for a list of select windows. std::vector scanWindows; /// returns true iff the element contains no params and all members are empty or null bool empty() const; }; /// List and descriptions of scans. struct PWIZ_API_DECL ScanList : public ParamContainer { std::vector scans; bool empty() const; }; /// The structure into which encoded binary data goes. Byte ordering is always little endian (Intel style). Computers using a different endian style MUST convert to/from little endian when writing/reading mzML struct PWIZ_API_DECL BinaryDataArray : public ParamContainer { /// this optional attribute may reference the 'id' attribute of the appropriate dataProcessing. DataProcessingPtr dataProcessingPtr; /// the binary data. std::vector data; /// returns true iff the element contains no params and all members are empty or null bool empty() const; }; typedef boost::shared_ptr BinaryDataArrayPtr; #pragma pack(1) /// The data point type of a mass spectrum. struct PWIZ_API_DECL MZIntensityPair { double mz; double intensity; MZIntensityPair() : mz(0), intensity(0) {} MZIntensityPair(double mz, double intensity) : mz(mz), intensity(intensity) {} /// returns true iff mz and intensity are pairwise equal bool operator==(const MZIntensityPair& that) const; }; #pragma pack() PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const MZIntensityPair& mzi); #pragma pack(1) /// The data point type of a chromatogram. struct PWIZ_API_DECL TimeIntensityPair { double time; double intensity; TimeIntensityPair() : time(0), intensity(0) {} TimeIntensityPair(double time, double intensity) : time(time), intensity(intensity) {} /// returns true iff time and intensity are pairwise equal bool operator==(const TimeIntensityPair& that) const; }; #pragma pack() PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const TimeIntensityPair& ti); const size_t IDENTITY_INDEX_NONE = (size_t)-1; /// Identifying information for a spectrum struct PWIZ_API_DECL SpectrumIdentity { /// the zero-based, consecutive index of the spectrum in the SpectrumList. size_t index; /// a unique identifier for this spectrum. It should be expected that external files may use this identifier together with the mzML filename or accession to reference a particular spectrum. std::string id; /// the identifier for the spot from which this spectrum was derived, if a MALDI or similar run. std::string spotID; /// for file-based MSData implementations, this attribute may refer to the spectrum's position in the file boost::iostreams::stream_offset sourceFilePosition; SpectrumIdentity() : index(IDENTITY_INDEX_NONE), sourceFilePosition((boost::iostreams::stream_offset)-1) {} }; /// Identifying information for a chromatogram struct PWIZ_API_DECL ChromatogramIdentity { /// the zero-based, consecutive index of the chromatogram in the ChromatogramList. size_t index; /// a unique identifier for this chromatogram. It should be expected that external files may use this identifier together with the mzML filename or accession to reference a particular chromatogram. std::string id; /// for file-based MSData implementations, this attribute may refer to the chromatogram's position in the file boost::iostreams::stream_offset sourceFilePosition; ChromatogramIdentity() : index(IDENTITY_INDEX_NONE), sourceFilePosition(-1) {} }; /// The structure that captures the generation of a peak list (including the underlying acquisitions) struct PWIZ_API_DECL Spectrum : public SpectrumIdentity, public ParamContainer { /// default length of binary data arrays contained in this element. size_t defaultArrayLength; /// this attribute can optionally reference the 'id' of the appropriate dataProcessing. DataProcessingPtr dataProcessingPtr; /// this attribute can optionally reference the 'id' of the appropriate sourceFile. SourceFilePtr sourceFilePtr; /// list of scans ScanList scanList; /// list and descriptions of precursors to the spectrum currently being described. std::vector precursors; /// list and descriptions of product ion information std::vector products; /// list of binary data arrays. std::vector binaryDataArrayPtrs; Spectrum() : defaultArrayLength(0) {} /// returns true iff the element contains no params and all members are empty or null bool empty() const; /// returns true iff has nonnull and nonempty BinaryDataArrayPtr bool hasBinaryData() const { return binaryDataArrayPtrs.size() && binaryDataArrayPtrs[0] && !binaryDataArrayPtrs[0]->data.empty(); }; /// copy binary data arrays into m/z-intensity pair array void getMZIntensityPairs(std::vector& output) const; /// copy binary data arrays into m/z-intensity pair array /// note: this overload is to allow client to allocate own buffer; the client /// must determine the correct size beforehand, or an exception will be thrown void getMZIntensityPairs(MZIntensityPair* output, size_t expectedSize) const; /// get m/z array (may be null) BinaryDataArrayPtr getMZArray() const; /// get intensity array (may be null) BinaryDataArrayPtr getIntensityArray() const; /// set binary data arrays void setMZIntensityPairs(const std::vector& input, CVID intensityUnits); /// set binary data arrays void setMZIntensityPairs(const MZIntensityPair* input, size_t size, CVID intensityUnits); /// set m/z and intensity arrays separately (they must be the same size) void setMZIntensityArrays(const std::vector& mzArray, const std::vector& intensityArray, CVID intensityUnits); /// set m/z and intensity arrays separately (they must be the same size) by swapping the vector contents /// this allows for a more nearly zero copy setup. Contents of mzArray and intensityArray are undefined after calling. void swapMZIntensityArrays(std::vector& mzArray, std::vector& intensityArray, CVID intensityUnits); }; typedef boost::shared_ptr SpectrumPtr; /// A single chromatogram. struct PWIZ_API_DECL Chromatogram : public ChromatogramIdentity, public ParamContainer { /// default length of binary data arrays contained in this element. size_t defaultArrayLength; /// this attribute can optionally reference the 'id' of the appropriate dataProcessing. DataProcessingPtr dataProcessingPtr; /// description of precursor ion information (i.e. Q1 settings) Precursor precursor; /// description of product ion information (i.e. Q3 settings) Product product; /// list of binary data arrays. std::vector binaryDataArrayPtrs; Chromatogram() : defaultArrayLength(0) {} /// returns true iff the element contains no params and all members are empty or null bool empty() const; /// copy binary data arrays into time-intensity pair array void getTimeIntensityPairs(std::vector& output) const; /// copy binary data arrays into time-intensity pair array /// note: this overload is to allow client to allocate own buffer; the client /// must determine the correct size beforehand, or an exception will be thrown void getTimeIntensityPairs(TimeIntensityPair* output, size_t expectedSize) const; /// get time array (may be null) BinaryDataArrayPtr getTimeArray() const; /// get intensity array (may be null) BinaryDataArrayPtr getIntensityArray() const; /// set binary data arrays void setTimeIntensityPairs(const std::vector& input, CVID timeUnits, CVID intensityUnits); /// set binary data arrays void setTimeIntensityPairs(const TimeIntensityPair* input, size_t size, CVID timeUnits, CVID intensityUnits); /// set time and intensity arrays separately (they must be the same size) void setTimeIntensityArrays(const std::vector& timeArray, const std::vector& intensityArray, CVID timeUnits, CVID intensityUnits); }; typedef boost::shared_ptr ChromatogramPtr; // note: derived container to support dynamic linking on Windows class IndexList : public std::vector {}; enum DetailLevel { DetailLevel_InstantMetadata, DetailLevel_FastMetadata, DetailLevel_FullMetadata, DetailLevel_FullData }; /// /// Interface for accessing spectra, which may be stored in memory /// or backed by a data file (RAW, mzXML, mzML). /// /// Implementation notes: /// /// - Implementations are expected to keep a spectrum index in the form of /// vector or equivalent. The default find*() functions search /// the index linearly. Implementations may provide constant time indexing. /// /// - The semantics of spectrum() may vary slightly with implementation. In particular, /// a SpectrumList implementation that is backed by a file may choose either to cache /// or discard the SpectrumPtrs for future access, with the caveat that the client /// may write to the underlying data. /// /// - It is the implementation's responsibility to return a valid SpectrumPtr from spectrum(). /// If this cannot be done, an exception must be thrown. /// /// - The 'getBinaryData' flag is a hint if false : implementations may provide valid /// BinaryDataArrayPtrs on spectrum(index, false); implementations *must* provide /// valid BinaryDataArrayPtrs on spectrum(index, true). /// class PWIZ_API_DECL SpectrumList { public: /// returns the number of spectra virtual size_t size() const = 0; /// returns true iff (size() == 0) and (dataProcessingPtr.get() == NULL) virtual bool empty() const; /// access to a spectrum index virtual const SpectrumIdentity& spectrumIdentity(size_t index) const = 0; /// find id in the spectrum index (returns size() on failure) virtual size_t find(const std::string& id) const; /// find an abbreviated id (e.g. "1.1.123.2" for "sample=1 period=1 cycle=123 experiment=2") in the spectrum index (returns size() on failure) virtual size_t findAbbreviated(const std::string& abbreviatedId, char delimiter = '.') const; /// find all spectrum indexes with specified name/value pair virtual IndexList findNameValue(const std::string& name, const std::string& value) const; /// find all spectrum indexes with spotID (returns empty vector on failure) virtual IndexList findSpotID(const std::string& spotID) const; /// retrieve a spectrum by index /// - binary data arrays will be provided if (getBinaryData == true); /// - client may assume the underlying Spectrum* is valid virtual SpectrumPtr spectrum(size_t index, bool getBinaryData = false) const = 0; /// get a copy of the seed spectrum, optionally with its binary data populated /// this is useful for formats like mzML that can delay loading of binary data /// - client may assume the underlying Spectrum* is valid virtual SpectrumPtr spectrum(const SpectrumPtr& seed, bool getBinaryData) const; /// retrieve a spectrum by index /// - detailLevel determines what fields are guaranteed present on the spectrum after the call /// - client may assume the underlying Spectrum* is valid virtual SpectrumPtr spectrum(size_t index, DetailLevel detailLevel) const; /// returns the data processing affecting spectra retrieved through this interface /// - may return a null shared pointer virtual const boost::shared_ptr dataProcessingPtr() const; /// issues a warning once per SpectrumList instance (based on string hash) virtual void warn_once(const char* msg) const; virtual ~SpectrumList(){} }; typedef boost::shared_ptr SpectrumListPtr; /// Simple writeable in-memory implementation of SpectrumList. /// Note: This spectrum() implementation returns internal SpectrumPtrs. struct PWIZ_API_DECL SpectrumListSimple : public SpectrumList { std::vector spectra; DataProcessingPtr dp; // SpectrumList implementation virtual size_t size() const {return spectra.size();} virtual bool empty() const {return spectra.empty() && !dp.get();} virtual const SpectrumIdentity& spectrumIdentity(size_t index) const; virtual SpectrumPtr spectrum(size_t index, bool getBinaryData) const; virtual const boost::shared_ptr dataProcessingPtr() const; }; typedef boost::shared_ptr SpectrumListSimplePtr; /// /// Interface for accessing chromatograms, which may be stored in memory /// or backed by a data file (RAW, mzXML, mzML). /// /// Implementation notes: /// /// - Implementations are expected to keep a chromatogram index in the form of /// vector or equivalent. The default find*() functions search /// the index linearly. Implementations may provide constant time indexing. /// /// - The semantics of chromatogram() may vary slightly with implementation. In particular, /// a ChromatogramList implementation that is backed by a file may choose either to cache /// or discard the ChromatogramPtrs for future access, with the caveat that the client /// may write to the underlying data. /// /// - It is the implementation's responsibility to return a valid ChromatogramPtr from chromatogram(). /// If this cannot be done, an exception must be thrown. /// /// - The 'getBinaryData' flag is a hint if false : implementations may provide valid /// BinaryDataArrayPtrs on chromatogram(index, false); implementations *must* provide /// valid BinaryDataArrayPtrs on chromatogram(index, true). /// class PWIZ_API_DECL ChromatogramList { public: /// returns the number of chromatograms virtual size_t size() const = 0; /// returns true iff (size() == 0) and (dataProcessingPtr.get() == NULL) bool empty() const; /// access to a chromatogram index virtual const ChromatogramIdentity& chromatogramIdentity(size_t index) const = 0; /// find id in the chromatogram index (returns size() on failure) virtual size_t find(const std::string& id) const; /// retrieve a chromatogram by index /// - binary data arrays will be provided if (getBinaryData == true); /// - client may assume the underlying Chromatogram* is valid virtual ChromatogramPtr chromatogram(size_t index, bool getBinaryData = false) const = 0; /// returns the data processing affecting spectra retrieved through this interface /// - may return a null shared pointer virtual const boost::shared_ptr dataProcessingPtr() const; virtual ~ChromatogramList(){} }; typedef boost::shared_ptr ChromatogramListPtr; /// Simple writeable in-memory implementation of ChromatogramList. /// Note: This chromatogram() implementation returns internal ChromatogramPtrs. struct PWIZ_API_DECL ChromatogramListSimple : public ChromatogramList { std::vector chromatograms; DataProcessingPtr dp; // ChromatogramList implementation virtual size_t size() const {return chromatograms.size();} virtual bool empty() const {return chromatograms.empty() && !dp.get();} virtual const ChromatogramIdentity& chromatogramIdentity(size_t index) const; virtual ChromatogramPtr chromatogram(size_t index, bool getBinaryData) const; virtual const boost::shared_ptr dataProcessingPtr() const; }; typedef boost::shared_ptr ChromatogramListSimplePtr; /// A run in mzML should correspond to a single, consecutive and coherent set of scans on an instrument. struct PWIZ_API_DECL Run : public ParamContainer { /// a unique identifier for this run. std::string id; /// this attribute MUST reference the 'id' of the default instrument configuration. If a scan does not reference an instrument configuration, it implicitly refers to this configuration. InstrumentConfigurationPtr defaultInstrumentConfigurationPtr; /// this attribute MUST reference the 'id' of the appropriate sample. SamplePtr samplePtr; /// the optional start timestamp of the run, in UT. std::string startTimeStamp; /// default source file reference SourceFilePtr defaultSourceFilePtr; /// all mass spectra and the acquisitions underlying them are described and attached here. Subsidiary data arrays are also both described and attached here. SpectrumListPtr spectrumListPtr; /// all chromatograms for this run. ChromatogramListPtr chromatogramListPtr; Run(){} bool empty() const; private: // no copying - any implementation must handle: // - SpectrumList cloning // - internal cross-references to heap-allocated objects Run(const Run&); Run& operator=(const Run&); }; namespace IO {struct HandlerMSData;} // forward declaration for friend /// This is the root element of ProteoWizard; it represents the mzML element, defined as: /// intended to capture the use of a mass spectrometer, the data generated, and the initial processing of that data (to the level of the peak list). struct PWIZ_API_DECL MSData { /// an optional accession number for the mzML document. std::string accession; /// an optional id for the mzML document. It is recommended to use LSIDs when possible. std::string id; /// container for one or more controlled vocabulary definitions. /// note: one of the elements in this list MUST be the PSI MS controlled vocabulary. All elements in the document MUST refer to one of the elements in this list. std::vector cvs; /// information pertaining to the entire mzML file (i.e. not specific to any part of the data set) is stored here. FileDescription fileDescription; /// container for a list of referenceableParamGroups std::vector paramGroupPtrs; /// list and descriptions of samples. std::vector samplePtrs; /// list and descriptions of software used to acquire and/or process the data in this mzML file. std::vector softwarePtrs; /// list with the descriptions of the acquisition settings applied prior to the start of data acquisition. std::vector scanSettingsPtrs; /// list and descriptions of instrument configurations. std::vector instrumentConfigurationPtrs; /// list and descriptions of data processing applied to this data. std::vector dataProcessingPtrs; /// return dataProcessingPtrs augmented by the dataProcessingPtr() set in SpectrumList and/or ChromatogramList std::vector allDataProcessingPtrs() const; /// a run in mzML should correspond to a single, consecutive and coherent set of scans on an instrument. Run run; MSData(); virtual ~MSData(); bool empty() const; /// returns the version of this mzML document; /// for a document created programmatically, the version is the current release version of mzML; /// for a document created from a file/stream, the version is the schema version read from the file/stream const std::string& version() const; // for detecting out of order filters void filterApplied() {nFiltersApplied_++;}; int countFiltersApplied() const {return nFiltersApplied_;}; private: // no copying MSData(const MSData&); MSData& operator=(const MSData&); protected: std::string version_; // schema version read from the file/stream friend struct IO::HandlerMSData; int nFiltersApplied_; // useful for flagging filters that need to be first, like vendor centroiding }; typedef boost::shared_ptr MSDataPtr; namespace id { /// parses an id string into a map PWIZ_API_DECL std::map parse(const std::string& id); /// convenience function to extract a named value from an id string PWIZ_API_DECL std::string value(const std::string& id, const std::string& name); /// templated convenience function to extract a named value from an id string template value_type valueAs(const std::string& id, const std::string& name) { std::string result = value(id, name); return !result.empty() ? boost::lexical_cast(result) : boost::lexical_cast(0); } /// returns the nativeID format from the defaultSourceFilePtr if set, /// or from sourceFilePtrs[0] if the list isn't empty, /// or CVID_Unknown PWIZ_API_DECL CVID getDefaultNativeIDFormat(const MSData& msd); /// translates a "scan number" to a string that is correct for the given nativeID format; /// semantic validity requires that scanNumber be parseable as an integer; /// some nativeID formats cannot be translated to and will always return an empty string /// currently supported formats: Thermo, Bruker/Agilent YEP, Bruker BAF, mzXML, MGF, and mzData PWIZ_API_DECL std::string translateScanNumberToNativeID(CVID nativeIDFormat, const std::string& scanNumber); /// translates a nativeID in the given nativeID format to a simple integer "scan number"; /// some nativeID formats cannot be translated from and will always return an empty string /// currently supported formats: Thermo, Bruker/Agilent YEP, Bruker BAF, mzXML, MGF, and mzData PWIZ_API_DECL std::string translateNativeIDToScanNumber(CVID nativeIDFormat, const std::string& id); /// abbreviates a nativeID ("name1=value1 name2=value2" translates to "value1.value2") PWIZ_API_DECL std::string abbreviate(const std::string& id, char delimiter = '.'); } // namespace id } // namespace msdata } // namespace pwiz #endif // _MSDATA_HPP_ pwiz/pwiz/data/msdata/DefaultReaderList.hpp0000775000175100017510000001072012664775621023005 0ustar teamcityteamcity00000000000000// // $Id: DefaultReaderList.hpp 3808 2012-07-24 20:31:10Z donmarsh $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _DEFAULTREADERLIST_HPP_ #define _DEFAULTREADERLIST_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "Reader.hpp" namespace pwiz { namespace msdata { class PWIZ_API_DECL Reader_mzML : public Reader { public: virtual std::string identify(const std::string& filename, const std::string& head) const; virtual void read(const std::string& filename, const std::string& head, MSData& result, int runIndex = 0, const Config& config = Config()) const; virtual void read(const std::string& filename, const std::string& head, std::vector& results, const Config& config = Config()) const; virtual const char* getType() const {return "mzML";} private: enum Type { Type_mzML, Type_mzML_Indexed, Type_Unknown }; Type type(std::istream& is) const; }; class PWIZ_API_DECL Reader_mzXML : public Reader { public: virtual std::string identify(const std::string& filename, const std::string& head) const; virtual void read(const std::string& filename, const std::string& head, MSData& result, int runIndex = 0, const Config& config = Config()) const; virtual void read(const std::string& filename, const std::string& head, std::vector& results, const Config& config = Config()) const; virtual const char* getType() const {return "mzXML";} }; class PWIZ_API_DECL Reader_MGF : public Reader { public: virtual std::string identify(const std::string& filename, const std::string& head) const; virtual void read(const std::string& filename, const std::string& head, MSData& result, int runIndex = 0, const Config& config = Config()) const; virtual void read(const std::string& filename, const std::string& head, std::vector& results, const Config& config = Config()) const; virtual const char* getType() const {return "Mascot Generic";} }; class PWIZ_API_DECL Reader_MSn : public Reader { public: virtual std::string identify(const std::string& filename, const std::string& head) const; virtual void read(const std::string& filename, const std::string& head, MSData& result, int runIndex = 0, const Config& config = Config()) const; virtual void read(const std::string& filename, const std::string& head, std::vector& results, const Config& config = Config()) const; virtual const char* getType() const {return "MSn";} }; class PWIZ_API_DECL Reader_BTDX : public Reader { public: virtual std::string identify(const std::string& filename, const std::string& head) const; virtual void read(const std::string& filename, const std::string& head, MSData& result, int runIndex = 0, const Config& config = Config()) const; virtual void read(const std::string& filename, const std::string& head, std::vector& results, const Config& config = Config()) const; virtual const char* getType() const {return "Bruker Data Exchange";} }; class PWIZ_API_DECL Reader_mz5 : public Reader { public: virtual std::string identify(const std::string& filename, const std::string& head) const; virtual void read(const std::string& filename, const std::string& head, MSData& result, int runIndex = 0, const Config& config = Config()) const; virtual void read(const std::string& filename, const std::string& head, std::vector& results, const Config& config = Config()) const; virtual const char* getType() const {return "MZ5";} }; /// default Reader list class PWIZ_API_DECL DefaultReaderList : public ReaderList { public: DefaultReaderList(); }; } // namespace msdata } // namespace pwiz #endif // _DEFAULTREADERLIST_HPP_ pwiz/pwiz/data/msdata/MSNumpress.hpp0000664000175100017510000002063512664775621021521 0ustar teamcityteamcity00000000000000// // $Id: MSNumpress.hpp 6945 2014-11-26 18:58:33Z chambm $ // // // Original author: Johan Teleman // // Copyright 2013 Johan Teleman // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* ==================== encodeInt ==================== Some of the encodings described below use a integer compression refered to simply as encodeInt() This encoding works on a 4 byte integer, by truncating initial zeros or ones. If the initial (most significant) half byte is 0x0 or 0xf, the number of such halfbytes starting from the most significant is stored in a halfbyte. This initial count is then followed by the rest of the ints halfbytes, in little-endian order. A count halfbyte c of 0 <= c <= 8 is interpreted as an initial c 0x0 halfbytes 9 <= c <= 15 is interpreted as an initial (c-8) 0xf halfbytes Ex: int c rest 0 => 0x8 -1 => 0xf 0xf 23 => 0x6 0x7 0x1 */ #ifndef _MSNUMPRESS_HPP_ #define _MSNUMPRESS_HPP_ #include "pwiz/utility/misc/Export.hpp" #include #include namespace pwiz { namespace msdata { namespace MSNumpress { double PWIZ_API_DECL optimalLinearFixedPoint( const double *data, size_t dataSize); /** * Encodes the doubles in data by first using a * - lossy conversion to a 4 byte 5 decimal fixed point repressentation * - storing the residuals from a linear prediction after first to values * - encoding by encodeInt (see above) * * The resulting binary is maximally dataSize * 5 bytes, but much less if the * data is reasonably smooth on the first order. * * This encoding is suitable for typical m/z or retention time binary arrays. * For masses above 100 m/z the encoding is accurate to at least 0.1 ppm. * * @data pointer to array of double to be encoded (need memorycont. repr.) * @dataSize number of doubles from *data to encode * @result pointer to were resulting bytes should be stored * @fixedPoint the scaling factor used for getting the fixed point repr. * This is stored in the binary and automatically extracted * on decoding. Automatically (and maybe slowly) determined if 0. * @return the number of encoded bytes */ size_t PWIZ_API_DECL encodeLinear( const double *data, const size_t dataSize, unsigned char *result, double fixedPoint); /** * Calls lower level encodeLinear while handling vector sizes appropriately * * @data vector of doubles to be encoded * @result vector of resulting bytes (will be resized to the number of bytes) */ void PWIZ_API_DECL encodeLinear( const std::vector &data, std::vector &result, double fixedPoint); /** * Decodes data encoded by encodeLinear. Note that the compression * discard any information < 1e-5, so data is only guaranteed * to be within +- 5e-6 of the original value. * * Further, values > ~42000 will also be truncated because of the * fixed point representation, so this scheme is stronly discouraged * if values above might be above this size. * * result vector guaranteedly shorter than twice the data length (in nbr of values) * * @data pointer to array of bytes to be decoded (need memorycont. repr.) * @dataSize number of bytes from *data to decode * @result pointer to were resulting doubles should be stored * @return the number of decoded doubles, or -1 if dataSize < 4 or 4 < dataSize < 8 */ size_t PWIZ_API_DECL decodeLinear( const unsigned char *data, const size_t dataSize, double *result); /** * Calls lower level decodeLinear while handling vector sizes appropriately * * @data vector of bytes to be decoded * @result vector of resulting double (will be resized to the number of doubles) */ void PWIZ_API_DECL decodeLinear( const std::vector &data, std::vector &result); ///////////////////////////////////////////////////////////// /** * Encodes ion counts by simply rounding to the nearest 4 byte integer, * and compressing each integer with encodeInt. * * The handleable range is therefore 0 -> 4294967294. * The resulting binary is maximally dataSize * 5 bytes, but much less if the * data is close to 0 on average. * * @data pointer to array of double to be encoded (need memorycont. repr.) * @dataSize number of doubles from *data to encode * @result pointer to were resulting bytes should be stored * @return the number of encoded bytes */ size_t PWIZ_API_DECL encodePic( const double *data, const size_t dataSize, unsigned char *result); /** * Calls lower level encodePic while handling vector sizes appropriately * * @data vector of doubles to be encoded * @result vector of resulting bytes (will be resized to the number of bytes) */ void PWIZ_API_DECL encodePic( const std::vector &data, std::vector &result); /** * Decodes data encoded by encodePic * * result vector guaranteedly shorter than twice the data length (in nbr of values) * * @data pointer to array of bytes to be decoded (need memorycont. repr.) * @dataSize number of bytes from *data to decode * @result pointer to were resulting doubles should be stored * @return the number of decoded doubles */ void PWIZ_API_DECL decodePic( const std::vector &data, std::vector &result); /** * Calls lower level decodePic while handling vector sizes appropriately * * @data vector of bytes to be decoded * @result vector of resulting double (will be resized to the number of doubles) */ size_t PWIZ_API_DECL decodePic( const unsigned char *data, const size_t dataSize, double *result); ///////////////////////////////////////////////////////////// double PWIZ_API_DECL optimalSlofFixedPoint( const double *data, size_t dataSize); /** * Encodes ion counts by taking the natural logarithm, and storing a * fixed point representation of this. This is calculated as * * unsigned short fp = log(d + 1) * 3000.0 + 0.5 * * Note that this fixed point will mean any d < 0.00016667 will be * stored as a zero and mapped back to a zero. * * result vector is exactly twice the data length (in nbr of values) * * @data pointer to array of double to be encoded (need memorycont. repr.) * @dataSize number of doubles from *data to encode * @result pointer to were resulting bytes should be stored * &fixedPoint automatically (and maybe slowly) determined if 0. * @return the number of encoded bytes */ size_t PWIZ_API_DECL encodeSlof( const double *data, const size_t dataSize, unsigned char *result, double fixedPoint); /** * Calls lower level encodeSlof while handling vector sizes appropriately * * @data vector of doubles to be encoded * @result vector of resulting bytes (will be resized to the number of bytes) */ void PWIZ_API_DECL encodeSlof( const std::vector &data, std::vector &result, double fixedPoint); /** * Decodes data encoded by encodeSlof * * @data pointer to array of bytes to be decoded (need memorycont. repr.) * @dataSize number of bytes from *data to decode * @result pointer to were resulting doubles should be stored * @return the number of decoded doubles */ size_t PWIZ_API_DECL decodeSlof( const unsigned char *data, const size_t dataSize, double *result); /** * Calls lower level decodeSlof while handling vector sizes appropriately * * @data vector of bytes to be decoded * @result vector of resulting double (will be resized to the number of doubles) */ void PWIZ_API_DECL decodeSlof( const std::vector &data, std::vector &result); } // namespace MSNumpress } // namespace msdata } // namespace pwiz #endif // _MSNUMPRESS_HPP_ pwiz/pwiz/data/msdata/SpectrumList_MGF.cpp0000664000175100017510000004037212664775621022567 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_MGF.cpp 6585 2014-08-07 22:49:28Z chambm $ // // // Original author: Matt Chambers // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // Copyright 2011 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_MGF.hpp" #include "References.hpp" #include "pwiz/utility/misc/Std.hpp" #include namespace pwiz { namespace msdata { using boost::iostreams::stream_offset; using boost::iostreams::offset_to_position; namespace { class SpectrumList_MGFImpl : public SpectrumList_MGF { public: SpectrumList_MGFImpl(shared_ptr is, const MSData& msd) : is_(is), msd_(msd) { createIndex(); } size_t size() const {return index_.size();} const SpectrumIdentity& spectrumIdentity(size_t index) const { return index_[index]; } size_t find(const string& id) const { map::const_iterator it = idToIndex_.find(id); return it != idToIndex_.end() ? it->second : size(); } size_t findNative(const string& nativeID) const { size_t index; try { index = lexical_cast(nativeID); } catch (boost::bad_lexical_cast&) { throw runtime_error("[SpectrumList_MGF::findNative] invalid nativeID format (expected a positive integer)"); } if (index < size()) return index; else return size(); } // returns the IndexList for a given TITLE=string IndexList findSpotID(const string& titleID) const { map::const_iterator it=titleIDToIndexList_.find(titleID); return it!=titleIDToIndexList_.end() ? it->second : IndexList(); } SpectrumPtr spectrum(size_t index, bool getBinaryData) const { boost::lock_guard lock(readMutex); // lock_guard will unlock mutex when out of scope or when exception thrown (during destruction) if (index > index_.size()) throw runtime_error("[SpectrumList_MGF::spectrum] Index out of bounds"); // allocate Spectrum object and read it in SpectrumPtr result(new Spectrum); if (!result.get()) throw runtime_error("[SpectrumList_MGF::spectrum] Out of memory"); result->index = index; result->sourceFilePosition = index_[index].sourceFilePosition; is_->seekg(bio::offset_to_position(result->sourceFilePosition)); if (!*is_) throw runtime_error("[SpectrumList_MGF::spectrum] Error seeking to BEGIN IONS tag"); parseSpectrum(*result, getBinaryData); // resolve any references into the MSData object References::resolve(*result, msd_); return result; } private: shared_ptr is_; const MSData& msd_; vector index_; map idToIndex_; map titleIDToIndexList_; mutable boost::mutex readMutex; void parseSpectrum(Spectrum& spectrum, bool getBinaryData) const { // Every MGF spectrum is assumed to be: // * MSn spectrum // * MS level 2 // * from a single precursor // * a peak list (centroided) // * not deisotoped (even though it may actually be, there's no way to tell) spectrum.id = "index=" + lexical_cast(spectrum.index); spectrum.set(MS_MSn_spectrum); spectrum.set(MS_ms_level, 2); spectrum.set(MS_centroid_spectrum); spectrum.scanList.set(MS_no_combination); spectrum.scanList.scans.push_back(Scan()); Scan& scan = spectrum.scanList.scans[0]; spectrum.precursors.push_back(Precursor()); Precursor& precursor = spectrum.precursors.back(); precursor.selectedIons.push_back(SelectedIon()); SelectedIon& selectedIon = precursor.selectedIons.back(); string lineStr; bool inBeginIons = false; bool inPeakList = false; bool negativePolarity = false; double lowMZ = std::numeric_limits::max(); double highMZ = 0; double tic = 0; double basePeakMZ = 0; double basePeakIntensity = 0; spectrum.defaultArrayLength = 0; spectrum.setMZIntensityArrays(vector(), vector(), MS_number_of_detector_counts); vector& mzArray = spectrum.getMZArray()->data; vector& intensityArray = spectrum.getIntensityArray()->data; while (getline(*is_, lineStr)) { size_t lineBegin = lineStr.find_first_not_of(" \t"); if (lineBegin == string::npos) { // Skip blank lines continue; } else if (lineBegin > 0) { // Trim leading whitespace lineStr.erase(0, lineBegin); } if (!inBeginIons && (lineStr[0] == '#' || lineStr[0] == ';' || lineStr[0] == '!' || lineStr[0] == '/')) { // Skip comment lines (lines beginning with #;!/ outside of BEGIN IONS) continue; } if (lineStr.find("BEGIN IONS") == 0) { if (inBeginIons) { throw runtime_error(("[SpectrumList_MGF::parseSpectrum] BEGIN IONS tag found without previous BEGIN IONS being closed at offset " + lexical_cast(size_t(is_->tellg())-lineStr.length()-1) + "\n")); } inBeginIons = true; } else if (lineStr.find("END IONS") == 0) { if (!inBeginIons) throw runtime_error(("[SpectrumList_MGF::parseSpectrum] END IONS tag found without opening BEGIN IONS tag at offset " + lexical_cast(size_t(is_->tellg())-lineStr.length()-1) + "\n")); inBeginIons = false; inPeakList = false; break; } else { try { if (!inPeakList) { size_t delim = lineStr.find('='); if (delim == string::npos) { inPeakList = true; } else { string name = lineStr.substr(0, delim); string value = lineStr.substr(delim+1); if (name == "TITLE") { bal::trim(value); // Some formats omit RTINSECONDS and store the retention time // in the title field instead. double scanTimeMin = getRetentionTimeFromTitle(value); if (scanTimeMin > 0) scan.set(MS_scan_start_time, scanTimeMin * 60, UO_second); spectrum.set(MS_spectrum_title, value); } else if (name == "PEPMASS") { bal::trim(value); size_t delim2 = value.find(' '); if (delim2 != string::npos) { selectedIon.set(MS_selected_ion_m_z, value.substr(0, delim2), MS_m_z); selectedIon.set(MS_peak_intensity, value.substr(delim2+1), MS_number_of_detector_counts); } else selectedIon.set(MS_selected_ion_m_z, value, MS_m_z); } else if (name == "CHARGE") { bal::trim_if(value, bal::is_any_of(" \t\r")); negativePolarity = bal::ends_with(value, "-"); vector charges; bal::split(charges, value, bal::is_any_of(" ")); if (charges.size() > 1) { BOOST_FOREACH(const string& charge, charges) if (charge != "and") selectedIon.cvParams.push_back(CVParam(MS_possible_charge_state, lexical_cast(charge))); } else selectedIon.set(MS_charge_state, lexical_cast(value)); } else if (name == "RTINSECONDS") { bal::trim(value); // TODO: handle (multiple) time ranges? double scanTime = lexical_cast(value); scan.set(MS_scan_start_time, scanTime, UO_second); } else if (name == "SCANS") { spectrum.set(MS_peak_list_scans, value); } else if (name == "RAWSCANS") { spectrum.set(MS_peak_list_raw_scans, value); } else { continue; // ignored attribute } } } } catch(bad_lexical_cast&) { throw runtime_error(("[SpectrumList_MGF::parseSpectrum] Error parsing line at offset " + lexical_cast(size_t(is_->tellg())-lineStr.length()-1) + ": " + lineStr + "\n")); } if (inPeakList) { // always parse the peaks (intensity must be summed to build TIC) size_t delim = lineStr.find_first_of(" \t"); if(delim == string::npos) continue; size_t delim2 = lineStr.find_first_not_of(" \t", delim+1); if(delim2 == string::npos) continue; size_t delim3 = lineStr.find_first_of(" \t\r\n", delim2); if(delim3 == string::npos) delim3 = lineStr.length(); double mz = lexical_cast(lineStr.substr(0, delim)); double inten = lexical_cast(lineStr.substr(delim2, delim3-delim2)); tic += inten; if (inten > basePeakIntensity) { basePeakMZ = mz; basePeakIntensity = inten; } lowMZ = std::min(lowMZ, mz); highMZ = std::max(highMZ, mz); ++spectrum.defaultArrayLength; if (getBinaryData) { mzArray.push_back(mz); intensityArray.push_back(inten); } } } } if (!getBinaryData) spectrum.binaryDataArrayPtrs.clear(); spectrum.set(negativePolarity ? MS_negative_scan : MS_positive_scan); spectrum.set(MS_lowest_observed_m_z, lowMZ); spectrum.set(MS_highest_observed_m_z, highMZ); spectrum.set(MS_total_ion_current, tic); spectrum.set(MS_base_peak_m_z, basePeakMZ); spectrum.set(MS_base_peak_intensity, basePeakIntensity); } /** * Parse the spectrum title to look for retention times. If there are * two times, return the center of the range. Possible formats to look * for are "Elution: end tags // TODO(dkessner): add unit test to make sure this never breaks // hack: avoid reading nested elements // TODO: use nested scans to indicate precursor relationships return Status::Done; } return Status::Ok; } unsigned int getPeaksCount() const { return peaksCount; } private: Spectrum& spectrum_; BinaryDataEncoder::Config config_; }; class HandlerScan : public SAXParser::Handler { public: HandlerScan(const MSData& msd, Spectrum& spectrum, const SpectrumIdentityFromMzXML &spectrum_id, bool getBinaryData,size_t peakscount) : msd_(msd), spectrum_(spectrum), spectrum_id_(spectrum_id), getBinaryData_(getBinaryData), handlerPeaks_(spectrum,peakscount), handlerPrecursor_(), nativeIdFormat_(id::getDefaultNativeIDFormat(msd)) { handlerPrecursor_.nativeIdFormat = nativeIdFormat_; } virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "scan") { if (scanNumber_.length()) { // we're in a nested scan declaration, we can quit return Status::Done; } string /*scanEvent,*/ msLevel, polarity, retentionTime, lowMz, highMz, basePeakMz, basePeakIntensity, totIonCurrent, msInstrumentID, centroided, deisotoped, chargeDeconvoluted, scanType, ionisationEnergy, cidGasPressure; unsigned int peaksCount; double startMz, endMz; getAttribute(attributes, "num", scanNumber_); //getAttribute(attributes, "scanEvent", scanEvent); getAttribute(attributes, "msLevel", msLevel); getAttribute(attributes, "peaksCount", peaksCount); getAttribute(attributes, "polarity", polarity); getAttribute(attributes, "collisionEnergy", collisionEnergy_); getAttribute(attributes, "retentionTime", retentionTime); getAttribute(attributes, "lowMz", lowMz); getAttribute(attributes, "highMz", highMz); getAttribute(attributes, "basePeakMz", basePeakMz); getAttribute(attributes, "basePeakIntensity", basePeakIntensity); getAttribute(attributes, "totIonCurrent", totIonCurrent); getAttribute(attributes, "msInstrumentID", msInstrumentID); getAttribute(attributes, "centroided", centroided); getAttribute(attributes, "deisotoped", deisotoped); //TODO: use this: getAttribute(attributes, "chargeDeconvoluted", chargeDeconvoluted); getAttribute(attributes, "scanType", scanType); //TODO: use this: getAttribute(attributes, "ionisationEnergy", ionisationEnergy); //TODO: use this: getAttribute(attributes, "cidGasPressure", cidGasPressure); getAttribute(attributes, "startMz", startMz); getAttribute(attributes, "endMz", endMz); spectrum_.id = id::translateScanNumberToNativeID(nativeIdFormat_, scanNumber_); if (spectrum_.id.empty()) spectrum_.id = "scan=" + lexical_cast(spectrum_.index+1); spectrum_.sourceFilePosition = position; boost::trim(msLevel); if (msLevel.empty()) msLevel = "1"; spectrum_.set(MS_ms_level, msLevel); handlerPeaks_.peaksCount = peaksCount; spectrum_.scanList.set(MS_no_combination); spectrum_.scanList.scans.push_back(Scan()); Scan& scan = spectrum_.scanList.scans.back(); //scan.set(MS_preset_scan_configuration, scanEvent); if (polarity == "+") spectrum_.set(MS_positive_scan); else if (polarity == "-") spectrum_.set(MS_negative_scan); // set spectrum and scan type by scanType attribute (assume MSn/Full if absent) boost::to_lower(scanType); if (scanType.empty() || scanType == "full") { spectrum_.set(msLevel == "1" ? MS_MS1_spectrum : MS_MSn_spectrum); } else if (scanType == "zoom") { spectrum_.set(MS_MSn_spectrum); scan.set(MS_zoom_scan); } else if (scanType == "sim") { spectrum_.set(MS_SIM_spectrum); scan.set(MS_SIM); } else if (scanType == "srm" || scanType == "mrm" || // hack: mzWiff (ABI) and wolf-mrm (Waters) use this value scanType == "multiplereaction" || // hack: Trapper (Agilent) uses this value scanType == "srm_ionprep") // hack: (Bruker) uses this value { spectrum_.set(MS_SRM_spectrum); scan.set(MS_SRM); } else if (scanType == "crm") { spectrum_.set(MS_CRM_spectrum); scan.set(MS_CRM_OBSOLETE); } else if (scanType == "q1") { spectrum_.set(MS_precursor_ion_spectrum); scan.set(MS_precursor_ion_spectrum); } else if (scanType == "q3") { spectrum_.set(MS_product_ion_spectrum); scan.set(MS_product_ion_spectrum); } // TODO: make this more robust bool hasCentroidDataProcessing = true; if (!msd_.dataProcessingPtrs.empty() && !msd_.dataProcessingPtrs[0]->processingMethods.empty()) hasCentroidDataProcessing = msd_.dataProcessingPtrs[0]->processingMethods[0].hasCVParam(MS_peak_picking); if (centroided.empty()) spectrum_.set(hasCentroidDataProcessing ? MS_centroid_spectrum : MS_profile_spectrum); else if (centroided == "1") spectrum_.set(MS_centroid_spectrum); else spectrum_.set(MS_profile_spectrum); if (msInstrumentID.empty() && !msd_.instrumentConfigurationPtrs.empty()) msInstrumentID = msd_.instrumentConfigurationPtrs[0]->id; if (!msInstrumentID.empty()) scan.instrumentConfigurationPtr = InstrumentConfigurationPtr(new InstrumentConfiguration(msInstrumentID)); // placeholder if (!retentionTime.empty()) { if (retentionTime.size()>3 && retentionTime.substr(0,2)=="PT" && retentionTime[retentionTime.size()-1]=='S') retentionTime = retentionTime.substr(2,retentionTime.size()-3); else throw runtime_error("[SpectrumList_mzXML::HandlerScan] Invalid retention time in scan " + scanNumber_); scan.set(MS_scan_start_time, retentionTime, UO_second); } if (endMz > 0) scan.scanWindows.push_back(ScanWindow(startMz, endMz, MS_m_z)); if (!lowMz.empty()) spectrum_.set(MS_lowest_observed_m_z, lowMz); if (!highMz.empty()) spectrum_.set(MS_highest_observed_m_z, highMz); if (!basePeakMz.empty()) spectrum_.set(MS_base_peak_m_z, basePeakMz); if (!basePeakIntensity.empty()) spectrum_.set(MS_base_peak_intensity, basePeakIntensity); if (!totIonCurrent.empty()) spectrum_.set(MS_total_ion_current, totIonCurrent); return Status::Ok; } else if (name == "precursorMz") { spectrum_.precursors.push_back(Precursor()); Precursor& precursor = spectrum_.precursors.back(); if (!collisionEnergy_.empty()) precursor.activation.set(MS_collision_energy, collisionEnergy_, UO_electronvolt); handlerPrecursor_.precursor = &precursor; return Status(Status::Delegate, &handlerPrecursor_); } else if (name == "peaks") { // pretty likely to come right back here and read the // binary data once the header info has been inspected, // so note position spectrum_id_.sourceFilePositionForBinarySpectrumData = position; if (!getBinaryData_ || handlerPeaks_.peaksCount == 0) { spectrum_.setMZIntensityArrays(vector(), vector(), MS_number_of_detector_counts); spectrum_.defaultArrayLength = handlerPeaks_.peaksCount; return Status::Ok; } return Status(Status::Delegate, &handlerPeaks_); } else if (name == "nameValue") { // arbitrary name value pairs are converted to UserParams string name, value; getAttribute(attributes, "name", name); getAttribute(attributes, "value", value); spectrum_.userParams.push_back(UserParam(name, value, "xsd:string")); return Status::Ok; } else if (name == "scanOrigin") { // just ignore return Status::Ok; } else if (name == "nativeScanRef" || name == "coordinate") // mzXML 3.0 beta tags { // just ignore return Status::Ok; } else if (name == "comment") { // just ignore return Status::Ok; } throw runtime_error("[SpectrumList_mzXML::HandlerScan] Unexpected element name \"" + name + "\" in scan " + scanNumber_); } unsigned int getPeaksCount() const { return handlerPeaks_.getPeaksCount(); } private: const MSData& msd_; Spectrum& spectrum_; const SpectrumIdentityFromMzXML& spectrum_id_; // for noting binary data position bool getBinaryData_; string scanNumber_; string collisionEnergy_; string activationMethod_; HandlerPeaks handlerPeaks_; HandlerPrecursor handlerPrecursor_; CVID nativeIdFormat_; }; /// retrieve a spectrum by index /// - detailLevel determines what fields are guaranteed present on the spectrum after the call /// - client may assume the underlying Spectrum* is valid SpectrumPtr SpectrumList_mzXMLImpl::spectrum(size_t index, DetailLevel detailLevel) const { return spectrum(index,(detailLevel == DetailLevel_FullData) ? IO::ReadBinaryData : IO::IgnoreBinaryData, detailLevel, NULL, false); } SpectrumPtr SpectrumList_mzXMLImpl::spectrum(size_t index, bool getBinaryData) const { return spectrum(index, getBinaryData ? IO::ReadBinaryData : IO::IgnoreBinaryData, getBinaryData ? DetailLevel_FullData : DetailLevel_FullMetadata, NULL, false); } /// get a copy of the seed spectrum with its binary data populated /// this is useful for formats like mzXML that can delay loading of binary data /// - client may assume the underlying Spectrum* is valid SpectrumPtr SpectrumList_mzXMLImpl::spectrum(const SpectrumPtr &seed, bool getBinaryData) const { return spectrum(seed->index, getBinaryData ? IO::ReadBinaryDataOnly: IO::IgnoreBinaryData, DetailLevel_InstantMetadata, // assume full metadata is already loaded &seed, false); } SpectrumPtr SpectrumList_mzXMLImpl::spectrum(size_t index, IO::BinaryDataFlag binaryDataFlag, const SpectrumPtr *defaults) const { DetailLevel detailLevel; switch (binaryDataFlag) { case IO::IgnoreBinaryData: detailLevel = DetailLevel_FullMetadata; break; case IO::ReadBinaryDataOnly: detailLevel = DetailLevel_InstantMetadata; break; case IO::ReadBinaryData: default: detailLevel = DetailLevel_FullData; break; } return spectrum(index, binaryDataFlag, detailLevel, defaults, false); } SpectrumPtr SpectrumList_mzXMLImpl::spectrum(size_t index, IO::BinaryDataFlag binaryDataFlag, DetailLevel detailLevel, const SpectrumPtr *defaults, bool isRecursiveCall) const { boost::lock_guard lock(readMutex); // lock_guard will unlock mutex when out of scope or when exception thrown (during destruction) if (index > index_.size()) throw runtime_error("[SpectrumList_mzXML::spectrum()] Index out of bounds."); // allocate Spectrum object and read it in SpectrumPtr result(new Spectrum); if (!result.get()) throw runtime_error("[SpectrumList_mzXML::spectrum()] Out of memory."); if (defaults) { // provide some context from previous parser runs result = *defaults; // copy in anything we may have cached before } result->index = index; // we may just be here to get binary data of otherwise previously read spectrum const SpectrumIdentityFromMzXML &id = index_[index]; boost::iostreams::stream_offset seekto; unsigned int peakscount; if (binaryDataFlag==IO::ReadBinaryDataOnly && (id.sourceFilePositionForBinarySpectrumData != (boost::iostreams::stream_offset)-1)) { // we're here to add binary data to an already parsed header seekto = id.sourceFilePositionForBinarySpectrumData; peakscount = id.peaksCount; // expecting this many peaks } else { seekto = id.sourceFilePosition; // read from start of scan peakscount = 0; // don't know how many peaks to expect yet } is_->seekg(offset_to_position(seekto)); if (!*is_) throw runtime_error("[SpectrumList_mzXML::spectrum()] Error seeking to ."); HandlerScan handler(msd_, *result, id, binaryDataFlag!=IO::IgnoreBinaryData, peakscount); SAXParser::parse(*is_, handler); // note the binary data size in case we come back around to read full data if (!id.peaksCount) { id.peaksCount = handler.getPeaksCount(); } int msLevel = result->cvParam(MS_ms_level).valueAs(); scanMsLevelCache_[index] = msLevel; if (detailLevel >= DetailLevel_FullMetadata) { // hack to get parent scanNumber if precursorScanNum wasn't set if (msLevel > 1 && !isRecursiveCall && // in an all-MS2 file we can run out of stack !result->precursors.empty() && result->precursors.front().spectrumID.empty()) { // MCC: I see your hack and I raise you a hack! // * precursorScanNum is optional // * the precursor scan is not necessarily in the mzXML if (result->precursors.front().spectrumID == "0") result->precursors.front().spectrumID.clear(); else result->precursors.front().spectrumID = getPrecursorID(msLevel-1, index); } } // resolve any references into the MSData object References::resolve(*result, msd_); return result; } class HandlerIndexOffset : public SAXParser::Handler { public: HandlerIndexOffset(stream_offset& indexOffset) : indexOffset_(indexOffset) { parseCharacters = true; autoUnescapeCharacters = false; } virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name != "indexOffset") throw runtime_error(("[SpectrumList_mzXML::HandlerIndexOffset] Unexpected element name: " + name).c_str()); return Status::Ok; } virtual Status characters(const SAXParser::saxstring& text, stream_offset position) { indexOffset_ = lexical_cast(text); return Status::Ok; } private: stream_offset& indexOffset_; }; struct HandlerOffset : public SAXParser::Handler { SpectrumIdentityFromMzXML* spectrumIdentity; CVID nativeIdFormat; HandlerOffset(const MSData& msd) : spectrumIdentity(0), nativeIdFormat(id::getDefaultNativeIDFormat(msd)) { parseCharacters = true; autoUnescapeCharacters = false; } virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!spectrumIdentity) throw runtime_error("[SpectrumList_mzXML::HandlerOffset] Null spectrumIdentity."); if (name != "offset") throw runtime_error(("[SpectrumList_mzXML::HandlerOffset] Unexpected element name: " + name).c_str()); string scanNumber; getAttribute(attributes, "id", scanNumber); spectrumIdentity->id = id::translateScanNumberToNativeID(nativeIdFormat, scanNumber); if (spectrumIdentity->id.empty()) spectrumIdentity->id = "scan=" + scanNumber; return Status::Ok; } virtual Status characters(const SAXParser::saxstring& text, stream_offset position) { if (!spectrumIdentity) throw runtime_error("[SpectrumList_mzXML::HandlerOffset] Null spectrumIdentity."); spectrumIdentity->sourceFilePosition = lexical_cast(text); return Status::Ok; } }; class HandlerIndex : public SAXParser::Handler { public: HandlerIndex(vector& index, const MSData& msd) : index_(index), handlerOffset_(msd) { parseCharacters = true; autoUnescapeCharacters = false; } virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "index") { return Status::Ok; } else if (name == "offset") { index_.push_back(SpectrumIdentityFromMzXML()); index_.back().index = index_.size()-1; handlerOffset_.spectrumIdentity = &index_.back(); return Status(Status::Delegate, &handlerOffset_); } else throw SpectrumList_mzXML::index_not_found(("[SpectrumList_mzXML::HandlerIndex] Unexpected element name: " + name).c_str()); } virtual Status characters(const SAXParser::saxstring& text, stream_offset position) { throw SpectrumList_mzXML::index_not_found("[SpectrumList_mzXML::HandlerIndex] not found."); } private: vector& index_; HandlerOffset handlerOffset_; }; bool SpectrumList_mzXMLImpl::readIndex() { // find const int bufferSize = 512; string buffer(bufferSize, '\0'); is_->seekg(-bufferSize, std::ios::end); if (!*is_) throw index_not_found("[SpectrumList_mzXML::readIndex()] Error seeking to end."); is_->read(&buffer[0], bufferSize); if (!*is_) throw index_not_found("[SpectrumList_mzXML::readIndex()] istream not ios::binary?"); string::size_type indexIndexOffset = buffer.find(""); if (indexIndexOffset == string::npos) return false; // no index present is_->seekg(-bufferSize + static_cast(indexIndexOffset), std::ios::end); if (!*is_) throw index_not_found("[SpectrumList_mzXML::readIndex()] Error seeking to ."); // read stream_offset indexOffset = 0; HandlerIndexOffset handlerIndexOffset(indexOffset); SAXParser::parse(*is_, handlerIndexOffset); if (indexOffset == 0) throw index_not_found("[SpectrumList_mzXML::readIndex()] Error parsing ."); // read is_->seekg(offset_to_position(indexOffset)); if (!*is_) throw index_not_found("[SpectrumList_mzXML::readIndex()] Error seeking to ."); HandlerIndex handlerIndex(index_, msd_); SAXParser::parse(*is_, handlerIndex); if (index_.empty()) throw index_not_found("[SpectrumList_mzXML::readIndex()] is empty."); return true; } class HandlerIndexCreator : public SAXParser::Handler { public: HandlerIndexCreator(vector& index, const MSData& msd) : index_(index), nativeIdFormat_(id::getDefaultNativeIDFormat(msd)) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "scan") { string scanNumber; getAttribute(attributes, "num", scanNumber); SpectrumIdentityFromMzXML si; si.index = index_.size(); si.id = id::translateScanNumberToNativeID(nativeIdFormat_, scanNumber); if (si.id.empty()) si.id = "scan=" + lexical_cast(si.index+1); si.sourceFilePosition = position; index_.push_back(si); } return Status::Ok; } virtual Status endElement(const string& name, stream_offset position) { if (name == "msRun") return Status::Done; return Status::Ok; } private: vector& index_; CVID nativeIdFormat_; }; void SpectrumList_mzXMLImpl::createIndex() { is_->seekg(0); HandlerIndexCreator handler(index_, msd_); SAXParser::parse(*is_, handler); } void SpectrumList_mzXMLImpl::createMaps() { vector::const_iterator it=index_.begin(); for (unsigned int i=0; i!=index_.size(); ++i, ++it) idToIndex_[it->id] = i; } string SpectrumList_mzXMLImpl::getPrecursorID(int precursorMsLevel, size_t index) const { // for MSn spectra (n > 1): return first scan with MSn-1 while (index > 0) { --index; int& cachedMsLevel = scanMsLevelCache_[index]; if (index && (cachedMsLevel == 0)) { // populate the missing MS level SpectrumPtr s = spectrum(index, DetailLevel_FastMetadata); // avoid excessive recursion cachedMsLevel = s->cvParam(MS_ms_level).valueAs(); } if (cachedMsLevel == precursorMsLevel) { SpectrumPtr s = spectrum(index, DetailLevel_FastMetadata); return s ? s->id : lexical_cast(index); } } return ""; } } // namespace PWIZ_API_DECL SpectrumListPtr SpectrumList_mzXML::create(shared_ptr is, const MSData& msd, bool indexed) { if (!is.get() || !*is) throw runtime_error("[SpectrumList_mzXML::create()] Bad istream."); return SpectrumListPtr(new SpectrumList_mzXMLImpl(is, msd, indexed)); } } // namespace msdata } // namespace pwiz pwiz/pwiz/data/msdata/SpectrumWorkerThreads.cpp0000664000175100017510000002235712664775621023752 0ustar teamcityteamcity00000000000000// // $Id: SpectrumWorkerThreads.cpp 7230 2015-02-26 17:23:51Z chambm $ // // // Original author: William French // // Copyright 2014 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "pwiz/utility/misc/Std.hpp" #include "pwiz/data/msdata/SpectrumWorkerThreads.hpp" #include "pwiz/data/msdata/SpectrumListWrapper.hpp" #include "pwiz/utility/misc/mru_list.hpp" #include #include using std::deque; using namespace pwiz::util; namespace pwiz { namespace msdata { class SpectrumWorkerThreads::Impl { public: Impl(const SpectrumList& sl) : sl_(sl) , numThreads_(boost::thread::hardware_concurrency()) , maxProcessedTaskCount_(numThreads_ * 4) , taskMRU_(maxProcessedTaskCount_) { InstrumentConfigurationPtr icPtr; if (sl.size() > 0) { SpectrumPtr s0 = sl.spectrum(0, false); if (s0->scanList.scans.size() > 0) icPtr = s0->scanList.scans[0].instrumentConfigurationPtr; } bool isBruker = icPtr.get() && icPtr->hasCVParamChild(MS_Bruker_Daltonics_instrument_model); useThreads_ = !isBruker; // Bruker library is not thread-friendly if (sl.size() > 0 && useThreads_) { // create one task per spectrum tasks_.resize(sl.size(), Task()); // create and start worker threads for (size_t i = 0; i < numThreads_; ++i) { workers_.push_back(TaskWorker()); workers_.back().start(this); } } } ~Impl() { BOOST_FOREACH(TaskWorker& worker, workers_) if (worker.thread) { worker.thread->interrupt(); worker.thread->join(); } } SpectrumPtr spectrum(size_t index, bool getBinaryData) { if (!useThreads_) return sl_.spectrum(index, getBinaryData); boost::unique_lock taskLock(taskMutex_); // if the task is already finished and has binary data if getBinaryData is true, return it as-is Task& task = tasks_[index]; if (task.result && (!getBinaryData || task.getBinaryData)) return task.result; // otherwise, add this task and the numThreads following tasks to the queue (skipping the tasks that are already processed or being worked on) for (size_t i = index; taskQueue_.size() < numThreads_ && i < tasks_.size(); ++i) { Task& task = tasks_[i]; // if the task result is already ready if (task.result) { // if it has binary data and getBinaryData is true, the task need not be queued if (task.getBinaryData || !getBinaryData) continue; // otherwise the current result is cleared task.result.reset(); } // if the task is already being worked on and the existing task will get binary data or binary data isn't being requested, the task need not be requeued else if (task.worker != NULL && (task.getBinaryData || !getBinaryData)) continue; // if the task is already queued, set its getBinaryData variable to the logical OR of the current task and the current spectrum request if (!task.isQueued) { taskQueue_.push_back(i); task.isQueued = true; } task.getBinaryData |= getBinaryData; } // wait for the result to be set while (!task.result) { // notify workers that tasks are available taskQueuedCondition_.notify_all(); taskFinishedCondition_.wait_for(taskLock, boost::chrono::milliseconds(100)); } return task.result; } private: struct TaskWorker { void start(Impl* instance) { if (!thread) thread.reset(new boost::thread(boost::bind(&SpectrumWorkerThreads::Impl::work, instance, this))); } shared_ptr thread; }; // each spectrum in the list is a task struct Task { Task() : worker(NULL), getBinaryData(false), isQueued(false) {} TaskWorker* worker; // the thread currently working on this task SpectrumPtr result; // the spectrum produced by this task bool getBinaryData; bool isQueued; // true if the task is currently in the taskQueue }; friend struct TaskWorker; // function executed by worker threads static void work(Impl* instance, TaskWorker* worker) { vector& tasks = instance->tasks_; TaskQueue& taskQueue = instance->taskQueue_; mru_list& taskMRU = instance->taskMRU_; // loop until the main thread kills the worker threads; the condition_variable::wait() call is an interruption point try { boost::unique_lock taskLock(instance->taskMutex_, boost::defer_lock); while (true) { taskLock.lock(); // wait for a new spectrum to be queued (while the task queue is either empty or the task at the end of the queue already has a worker assigned) while (instance->taskQueue_.empty()) instance->taskQueuedCondition_.wait(taskLock); // get the next queued Task TaskQueue::value_type queuedTask = taskQueue.front(); taskQueue.pop_front(); // set worker pointer on the Task size_t taskIndex = queuedTask; Task& task = tasks[taskIndex]; bool getBinaryData = task.getBinaryData; task.worker = worker; task.isQueued = false; //cout << taskIndex << " " << task.worker << " " << getBinaryData << endl; // unlock taskLock taskLock.unlock(); // get the spectrum SpectrumPtr result = instance->sl_.spectrum(taskIndex, getBinaryData); // lock the taskLock taskLock.lock(); // set the result on the Task, and set its worker to empty // if not getting binary data, check if another thread already finished this task which did get binary data if (getBinaryData || !task.getBinaryData) { task.result = result; task.getBinaryData = getBinaryData; } task.worker = NULL; // notify the main thread that a task has finished instance->taskFinishedCondition_.notify_one(); // add the task to the MRU; if doing so will push an old task off the MRU, then reset the oldest (LRU) task; // to know whether an old task was pushed off, keep a copy of the LRU item before adding the task boost::optional lruToReset; if (taskMRU.size() == taskMRU.max_size()) { lruToReset = taskMRU.lru(); } taskMRU.insert(taskIndex); // if the MRU list's LRU is different now, it means the LRU was popped and needs to be reset; if the popped LRU is the current task, don't reset it if (lruToReset.is_initialized() && lruToReset.get() != taskMRU.lru() && lruToReset.get() != taskIndex) { tasks[lruToReset.get()].result.reset(); } taskLock.unlock(); } } catch (boost::thread_interrupted&) { // return } catch (exception& e) { // TODO: log this cerr << "[SpectrumWorkerThreads::work] error in thread: " << e.what() << endl; } catch (...) { cerr << "[SpectrumWorkerThreads::work] unknown exception in worker thread" << endl; } } const SpectrumList& sl_; bool useThreads_; size_t numThreads_; const size_t maxProcessedTaskCount_; vector tasks_; typedef deque TaskQueue; TaskQueue taskQueue_; mru_list taskMRU_; boost::mutex taskMutex_; boost::condition_variable taskQueuedCondition_, taskFinishedCondition_; vector workers_; }; SpectrumWorkerThreads::SpectrumWorkerThreads(const SpectrumList& sl) : impl_(new Impl(sl)) {} SpectrumWorkerThreads::~SpectrumWorkerThreads() {} SpectrumPtr SpectrumWorkerThreads::processBatch(size_t index, bool getBinaryData) { return impl_->spectrum(index, getBinaryData); } } // namespace msdata } // namespace pwiz pwiz/pwiz/data/msdata/SpectrumList_mzML.cpp0000664000175100017510000001552112664775621023033 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_mzML.cpp 8725 2015-08-04 15:49:57Z pcbrefugee $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_mzML.hpp" #include "IO.hpp" #include "References.hpp" #include "pwiz/utility/minimxml/SAXParser.hpp" #include "pwiz/utility/misc/Std.hpp" #include #include namespace pwiz { namespace msdata { using namespace pwiz::minimxml; using boost::iostreams::offset_to_position; namespace { class SpectrumList_mzMLImpl : public SpectrumList_mzML { public: SpectrumList_mzMLImpl(shared_ptr is, const MSData& msd, const Index_mzML_Ptr& index); // SpectrumList implementation virtual size_t size() const; virtual const SpectrumIdentity& spectrumIdentity(size_t index) const; virtual size_t find(const std::string& id) const; virtual IndexList findSpotID(const std::string& spotID) const; virtual SpectrumPtr spectrum(size_t index, bool getBinaryData) const; virtual SpectrumPtr spectrum(size_t index, DetailLevel detailLevel) const; virtual SpectrumPtr spectrum(const SpectrumPtr &seed, bool getBinaryData) const; virtual SpectrumPtr spectrum(size_t index, IO::BinaryDataFlag binaryDataFlag, const SpectrumPtr *defaults) const; private: shared_ptr is_; const MSData& msd_; int schemaVersion_; mutable bool indexed_; mutable boost::mutex readMutex; Index_mzML_Ptr index_; }; SpectrumList_mzMLImpl::SpectrumList_mzMLImpl(shared_ptr is, const MSData& msd, const Index_mzML_Ptr& index) : is_(is), msd_(msd), index_(index) { schemaVersion_ = bal::starts_with(msd_.version(), "1.0") ? 1 : 0; } size_t SpectrumList_mzMLImpl::size() const { //boost::call_once(indexSizeSet_.flag, boost::bind(&SpectrumList_mzMLImpl::setIndexSize, this)); return index_->spectrumCount(); } const SpectrumIdentity& SpectrumList_mzMLImpl::spectrumIdentity(size_t index) const { //boost::call_once(indexInitialized_.flag, boost::bind(&SpectrumList_mzMLImpl::createIndex, this)); if (index >= index_->spectrumCount()) throw runtime_error("[SpectrumList_mzML::spectrumIdentity()] Index out of bounds."); return index_->spectrumIdentity(index); } size_t SpectrumList_mzMLImpl::find(const string& id) const { //boost::call_once(indexInitialized_.flag, boost::bind(&SpectrumList_mzMLImpl::createIndex, this)); return index_->findSpectrumId(id); } IndexList SpectrumList_mzMLImpl::findSpotID(const string& spotID) const { //boost::call_once(indexInitialized_.flag, boost::bind(&SpectrumList_mzMLImpl::createIndex, this)); return index_->findSpectrumBySpotID(spotID); } SpectrumPtr SpectrumList_mzMLImpl::spectrum(size_t index, DetailLevel detailLevel) const { return spectrum(index, (detailLevel == DetailLevel_FullData) ? IO::ReadBinaryData : IO::IgnoreBinaryData, NULL); } SpectrumPtr SpectrumList_mzMLImpl::spectrum(size_t index, bool getBinaryData) const { return spectrum(index, getBinaryData ? IO::ReadBinaryData : IO::IgnoreBinaryData, NULL); } /// get a copy of the seed spectrum with its binary data populated /// this is useful for formats like mzML that can delay loading of binary data /// - client may assume the underlying Spectrum* is valid SpectrumPtr SpectrumList_mzMLImpl::spectrum(const SpectrumPtr &seed, bool getBinaryData) const { return spectrum(seed->index, getBinaryData ? IO::ReadBinaryDataOnly: IO::IgnoreBinaryData, &seed); } SpectrumPtr SpectrumList_mzMLImpl::spectrum(size_t index, IO::BinaryDataFlag binaryDataFlag, const SpectrumPtr *defaults) const { boost::lock_guard lock(readMutex); // lock_guard will unlock mutex when out of scope or when exception thrown (during destruction) //boost::call_once(indexInitialized_.flag, boost::bind(&SpectrumList_mzMLImpl::createIndex, this)); if (index >= index_->spectrumCount()) throw runtime_error("[SpectrumList_mzML::spectrum()] Index out of bounds."); // allocate Spectrum object and read it in SpectrumPtr result(new Spectrum); if (!result.get()) throw runtime_error("[SpectrumList_mzML::spectrum()] Out of memory."); if (defaults) { // provide some context from previous parser runs result = *defaults; // copy in anything we may have cached before } try { // we may just be here to get binary data of otherwise previously read spectrum const SpectrumIdentityFromXML &id = index_->spectrumIdentity(index); boost::iostreams::stream_offset seekto = binaryDataFlag==IO::ReadBinaryDataOnly ? id.sourceFilePositionForBinarySpectrumData : // might be set, might be -1 (boost::iostreams::stream_offset)-1; if (seekto == (boost::iostreams::stream_offset)-1) { seekto = id.sourceFilePosition; } is_->seekg(offset_to_position(seekto)); if (!*is_) throw runtime_error("[SpectrumList_mzML::spectrum()] Error seeking to ."); IO::read(*is_, *result, binaryDataFlag, schemaVersion_, &index_->legacyIdRefToNativeId(), &msd_, &id); // test for reading the wrong spectrum if (result->index != index) throw runtime_error("[SpectrumList_mzML::spectrum()] Index entry points to the wrong spectrum."); } catch (runtime_error&) { // TODO: log warning about missing/corrupt index // recreate index indexed_ = false; index_->recreate(); const SpectrumIdentityFromXML &id = index_->spectrumIdentity(index); is_->seekg(offset_to_position(id.sourceFilePosition)); IO::read(*is_, *result, binaryDataFlag, schemaVersion_, &index_->legacyIdRefToNativeId(), &msd_, &id); } // resolve any references into the MSData object References::resolve(*result, msd_); return result; } } // namespace PWIZ_API_DECL SpectrumListPtr SpectrumList_mzML::create(shared_ptr is, const MSData& msd, const Index_mzML_Ptr& indexPtr) { if (!is.get() || !*is) throw runtime_error("[SpectrumList_mzML::create()] Bad istream."); return SpectrumListPtr(new SpectrumList_mzMLImpl(is, msd, indexPtr)); } } // namespace msdata } // namespace pwiz pwiz/pwiz/data/msdata/SpectrumList_MSn.hpp0000664000175100017510000000354012664775621022654 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_MSn.hpp 4009 2012-10-17 18:40:44Z kaipot $ // // // Original author: Barbara Frewen // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_MSn_HPP_ #define _SPECTRUMLIST_MSn_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "SpectrumListBase.hpp" #include "SpectrumList_MSn.hpp" #include #include namespace pwiz { namespace msdata { enum MSn_Type {MSn_Type_UNKNOWN, MSn_Type_BMS1, MSn_Type_CMS1, MSn_Type_BMS2, MSn_Type_CMS2, MSn_Type_MS1, MSn_Type_MS2}; struct MSnHeader { char header[16][128]; MSnHeader() { for(int i=0; i<16; i++) { header[i][0] = '\0'; } } }; /// implementation of SpectrumList, backed by an MGF file class PWIZ_API_DECL SpectrumList_MSn : public SpectrumListBase { public: static SpectrumListPtr create(boost::shared_ptr is, const MSData& msd, MSn_Type filetype); }; } // namespace msdata } // namespace pwiz #endif // _SPECTRUMLIST_MSn_HPP_ pwiz/pwiz/data/msdata/Serializer_MGF_Test.cpp0000664000175100017510000001351012664775620023232 0ustar teamcityteamcity00000000000000// // $Id: Serializer_MGF_Test.cpp 5759 2014-02-19 22:26:29Z chambm $ // // // Original author: Matt Chambers // // Copyright 2011 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "Serializer_MGF.hpp" #include "Serializer_mzML.hpp" #include "Diff.hpp" #include "TextWriter.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::data; using namespace pwiz::msdata; ostream* os_ = 0; void initializeTinyMGF(MSData& msd) { FileContent& fc = msd.fileDescription.fileContent; fc.set(MS_MSn_spectrum); fc.set(MS_centroid_spectrum); //SourceFilePtr sourceFile(new SourceFile); //sourceFile->set(MS_multiple_peak_list_nativeID_format); // TODO: sourceFile->set(MS_Matrix_Science_MGF_format); //msd.fileDescription.sourceFilePtrs.push_back(sourceFile); shared_ptr spectrumList(new SpectrumListSimple); msd.run.spectrumListPtr = spectrumList; spectrumList->spectra.push_back(SpectrumPtr(new Spectrum)); spectrumList->spectra.push_back(SpectrumPtr(new Spectrum)); Spectrum& s20 = *spectrumList->spectra[0]; s20.id = "index=0"; s20.index = 0; s20.set(MS_spectrum_title, s20.id); s20.set(MS_MSn_spectrum); s20.set(MS_ms_level, 2); s20.set(MS_centroid_spectrum); s20.set(MS_positive_scan); s20.set(MS_lowest_observed_m_z, 0.0); s20.set(MS_highest_observed_m_z, 18.0); s20.set(MS_base_peak_m_z, 0.0); s20.set(MS_base_peak_intensity, 20.0); s20.set(MS_total_ion_current, 110.0); s20.precursors.resize(1); Precursor& s20precursor = s20.precursors.front(); s20precursor.selectedIons.resize(1); s20precursor.selectedIons[0].set(MS_selected_ion_m_z, 445.34, MS_m_z); s20precursor.selectedIons[0].set(MS_peak_intensity, 120053.0, MS_number_of_detector_counts); s20precursor.selectedIons[0].set(MS_charge_state, 2); s20.scanList.set(MS_no_combination); s20.scanList.scans.push_back(Scan()); Scan& s20scan = s20.scanList.scans.back(); s20scan.set(MS_scan_start_time, 4.0, UO_second); s20.setMZIntensityArrays(vector(), vector(), MS_number_of_detector_counts); vector& s20_mz = s20.getMZArray()->data; vector& s20_intensity = s20.getIntensityArray()->data; for (int i=0; i<10; i++) s20_mz.push_back(i*2); for (int i=0; i<10; i++) s20_intensity.push_back((10-i)*2); s20.defaultArrayLength = s20_mz.size(); Spectrum& s21 = *spectrumList->spectra[1]; s21.id = "index=1"; s21.index = 1; s21.set(MS_spectrum_title, s21.id); s21.set(MS_MSn_spectrum); s21.set(MS_ms_level, 2); s21.set(MS_centroid_spectrum); s21.set(MS_negative_scan); s21.set(MS_lowest_observed_m_z, 3.0); s21.set(MS_highest_observed_m_z, 30.0); s21.set(MS_base_peak_m_z, 3.0); s21.set(MS_base_peak_intensity, 30.0); s21.set(MS_total_ion_current, 165.0); s21.precursors.resize(1); Precursor& s21precursor = s21.precursors.front(); s21precursor.selectedIons.resize(1); s21precursor.selectedIons[0].set(MS_selected_ion_m_z, 424.24, MS_m_z); s21precursor.selectedIons[0].set(MS_peak_intensity, 4242.0, MS_number_of_detector_counts); s21precursor.selectedIons[0].cvParams.push_back(CVParam(MS_possible_charge_state, 2)); s21precursor.selectedIons[0].cvParams.push_back(CVParam(MS_possible_charge_state, 3)); s21.scanList.set(MS_no_combination); s21.scanList.scans.push_back(Scan()); Scan& s21scan = s21.scanList.scans.back(); s21scan.set(MS_scan_start_time, 42.0, UO_second); s21.setMZIntensityArrays(vector(), vector(), MS_number_of_detector_counts); vector& s21_mz = s21.getMZArray()->data; vector& s21_intensity = s21.getIntensityArray()->data; for (int i=1; i<=10; i++) s21_mz.push_back(i*3); for (int i=0; i<10; i++) s21_intensity.push_back((10-i)*3); s21.defaultArrayLength = s21_mz.size(); } // initializeTinyMGF() void testWriteRead(const MSData& msd) { Serializer_MGF serializer; ostringstream oss; serializer.write(oss, msd); if (os_) *os_ << "oss:\n" << oss.str() << endl; shared_ptr iss(new istringstream(oss.str())); MSData msd2; serializer.read(iss, msd2); DiffConfig diffConfig; diffConfig.ignoreIdentity = true; diffConfig.ignoreChromatograms = true; Diff diff(msd, msd2, diffConfig); if (os_ && diff) *os_ << diff << endl; unit_assert(!diff); if (os_) { *os_ << "msd2:\n"; Serializer_mzML mzmlSerializer; mzmlSerializer.write(*os_, msd2); *os_ << endl; *os_ << "msd2::"; TextWriter write(*os_); write(msd2); *os_ << endl; } } void testWriteRead() { MSData msd; initializeTinyMGF(msd); testWriteRead(msd); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; testWriteRead(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/msdata/DiffTest.cpp0000664000175100017510000011627212664775621021153 0ustar teamcityteamcity00000000000000// // $Id: DiffTest.cpp 5759 2014-02-19 22:26:29Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "Diff.hpp" #include "TextWriter.hpp" #include "examples.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::data; using namespace pwiz::data::diff_impl; using namespace pwiz::msdata; ostream* os_ = 0; void testFileContent() { if (os_) *os_ << "testFileContent()\n"; FileContent a, b; a.userParams.push_back(UserParam("common")); b.userParams.push_back(UserParam("common")); Diff diff(a, b); unit_assert(!diff); a.userParams.push_back(UserParam("different", "1")); b.userParams.push_back(UserParam("different", "2")); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.userParams.size() == 1); unit_assert(diff.a_b.userParams[0] == UserParam("different","1")); unit_assert(diff.b_a.userParams.size() == 1); unit_assert(diff.b_a.userParams[0] == UserParam("different","2")); } void testSourceFile() { if (os_) *os_ << "testSourceFile()\n"; SourceFile a("id1","name1","location1"), b("id1","name1","location1"); a.userParams.push_back(UserParam("common")); b.userParams.push_back(UserParam("common")); Diff diff(a, b); unit_assert(!diff); b.location = "location2"; diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testFileDescription() { if (os_) *os_ << "testFileDescription()\n"; FileDescription a, b; a.fileContent.userParams.push_back(UserParam("user param 1")); b.fileContent.userParams.push_back(UserParam("user param 1")); Contact contact1, contact2, contact3, contact4; contact1.cvParams.push_back(CVParam(MS_contact_name, "Darren")); contact2.cvParams.push_back(CVParam(MS_contact_name, "Laura Jane")); contact3.cvParams.push_back(CVParam(MS_contact_name, "Emma Lee")); contact4.cvParams.push_back(CVParam(MS_contact_name, "Isabelle Lynn")); // verify vector_diff_diff with differently ordered vectors a.contacts.push_back(contact2); a.contacts.push_back(contact1); b.contacts.push_back(contact1); b.contacts.push_back(contact2); SourceFilePtr source1(new SourceFile("id1")); SourceFilePtr source2a(new SourceFile("id2")); SourceFilePtr source2b(new SourceFile("id2")); source2a->cvParams.push_back(MS_Thermo_RAW_format); a.sourceFilePtrs.push_back(source1); b.sourceFilePtrs.push_back(source1); Diff diff(a, b); unit_assert(!diff); a.contacts.push_back(contact3); b.contacts.push_back(contact4); a.sourceFilePtrs.push_back(source2a); b.sourceFilePtrs.push_back(source2b); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.contacts.size() == 1); unit_assert(diff.a_b.contacts[0].cvParam(MS_contact_name).value == "Emma Lee"); unit_assert(diff.b_a.contacts.size() == 1); unit_assert(diff.b_a.contacts[0].cvParam(MS_contact_name).value == "Isabelle Lynn"); unit_assert(diff.a_b.sourceFilePtrs.size() == 1); unit_assert(diff.a_b.sourceFilePtrs[0]->hasCVParam(MS_Thermo_RAW_format)); unit_assert(diff.b_a.sourceFilePtrs.size() == 1); unit_assert(!diff.b_a.sourceFilePtrs[0]->hasCVParam(MS_Thermo_RAW_format)); } void testSample() { if (os_) *os_ << "testSample()\n"; Sample a("id1","name1"), b("id1","name1"); a.userParams.push_back(UserParam("common")); b.userParams.push_back(UserParam("common")); Diff diff(a, b); unit_assert(!diff); a.cvParams.push_back(MS_peak_intensity); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testComponent() { if (os_) *os_ << "testComponent()\n"; Component a, b; a.userParams.push_back(UserParam("common")); b.userParams.push_back(UserParam("common")); Diff diff(a, b); unit_assert(!diff); a.order = 420; b.order = 421; diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testSource() { if (os_) *os_ << "testSource()\n"; Component a, b; a.userParams.push_back(UserParam("common")); b.userParams.push_back(UserParam("common")); Diff diff(a, b); unit_assert(!diff); a.order = 420; b.order = 421; diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testComponentList() { if (os_) *os_ << "testComponentList()\n"; ComponentList a, b; a.push_back(Component(ComponentType_Source, 1)); b.push_back(Component(ComponentType_Source, 1)); a.push_back(Component(ComponentType_Analyzer, 2)); b.push_back(Component(ComponentType_Analyzer, 2)); a.push_back(Component(ComponentType_Detector, 3)); b.push_back(Component(ComponentType_Detector, 3)); a[0].userParams.push_back(UserParam("common")); b[0].userParams.push_back(UserParam("common")); Diff diff(a, b); unit_assert(!diff); a[1].userParams.push_back(UserParam("common")); b[1].userParams.push_back(UserParam("common")); a[1].userParams.push_back(UserParam("a only")); b[1].userParams.push_back(UserParam("b only")); a[2].userParams.push_back(UserParam("a only")); b[2].userParams.push_back(UserParam("b only")); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testSoftware() { if (os_) *os_ << "testSoftware()\n"; Software a, b; a.id = "msdata"; a.version = "4.20"; a.set(MS_ionization_type); b = a; Diff diff(a, b); unit_assert(!diff); b.version = "4.21"; diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testInstrumentConfiguration() { InstrumentConfiguration a, b; a.id = "LCQ Deca"; a.cvParams.push_back(MS_LCQ_Deca); a.cvParams.push_back(CVParam(MS_instrument_serial_number, 23433)); a.componentList.push_back(Component(MS_nanoelectrospray, 1)); a.componentList.push_back(Component(MS_quadrupole_ion_trap, 2)); a.componentList.push_back(Component(MS_electron_multiplier, 3)); b = a; a.softwarePtr = SoftwarePtr(new Software("XCalibur")); a.softwarePtr->version = "4.20"; b.softwarePtr = SoftwarePtr(new Software("XCalibur")); b.softwarePtr->version = "4.20"; Diff diff(a, b); unit_assert(!diff); b.set(MS_reflectron_off); b.componentList.source(0).order = 2; b.componentList.detector(0).order = 1; diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testProcessingMethod() { if (os_) *os_ << "testProcessingMethod()\n"; ProcessingMethod a, b; a.userParams.push_back(UserParam("common")); b.userParams.push_back(UserParam("common")); Diff diff(a, b); unit_assert(!diff); a.order = 420; b.order = 421; diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); b.order = 420; diff(a, b); if (os_) *os_ << diff << endl; unit_assert(!diff); a.softwarePtr = SoftwarePtr(new Software("pwiz")); b.softwarePtr = SoftwarePtr(new Software("pwiz2")); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testDataProcessing() { if (os_) *os_ << "testDataProcessing()\n"; DataProcessing a, b; a.id = "dp1"; b = a; ProcessingMethod pm1, pm2, pm3; pm1.userParams.push_back(UserParam("abc")); pm2.userParams.push_back(UserParam("def")); pm3.userParams.push_back(UserParam("ghi")); pm1.softwarePtr = SoftwarePtr(new Software("msdata")); pm1.softwarePtr->version = "4.20"; pm2.softwarePtr = SoftwarePtr(new Software("msdata")); pm2.softwarePtr->version = "4.20"; a.processingMethods.push_back(pm1); a.processingMethods.push_back(pm2); b.processingMethods.push_back(pm2); b.processingMethods.push_back(pm1); Diff diff(a, b); unit_assert(!diff); pm2.softwarePtr = SoftwarePtr(new Software("Xcalibur")); a.processingMethods.push_back(pm3); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testScanSettings() { if (os_) *os_ << "testScanSettings()\n"; ScanSettings a, b; a.id = "as1"; b = a; Diff diff(a, b); unit_assert(!diff); b.sourceFilePtrs.push_back(SourceFilePtr(new SourceFile("source file"))); a.targets.resize(2); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.sourceFilePtrs.empty()); unit_assert(diff.b_a.sourceFilePtrs.size() == 1); unit_assert(diff.a_b.targets.size() == 2); unit_assert(diff.b_a.targets.empty()); } void testPrecursor() { if (os_) *os_ << "testPrecursor()\n"; Precursor a, b; a.spectrumID = "1234"; a.activation.cvParams.push_back(CVParam(MS_ionization_type, 420)); a.selectedIons.resize(1); a.selectedIons[0].cvParams.push_back(MS_reflectron_on); a.cvParams.push_back(MS_reflectron_off); b = a; Diff diff(a, b); unit_assert(!diff); a.cvParams.push_back(MS_reflectron_on); a.selectedIons[0].userParams.push_back(UserParam("aaaa")); b.activation.userParams.push_back(UserParam("bbbb")); b.isolationWindow.set(MS_m_z, 200); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(!diff.a_b.selectedIons.empty()); unit_assert(!diff.a_b.selectedIons[0].userParams.empty()); unit_assert(!diff.b_a.selectedIons.empty()); unit_assert(diff.b_a.isolationWindow.cvParam(MS_m_z).valueAs() == 200); } void testProduct() { if (os_) *os_ << "testProduct()\n"; Product a, b; a.isolationWindow.set(MS_ionization_type, 420); b = a; Diff diff(a, b); unit_assert(!diff); b.isolationWindow.set(MS_m_z, 200); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.isolationWindow.cvParams.empty()); unit_assert(diff.b_a.isolationWindow.cvParams.size() == 1); } void testScan() { if (os_) *os_ << "testScan()\n"; Scan a, b; InstrumentConfigurationPtr ip = InstrumentConfigurationPtr(new InstrumentConfiguration); ip->id = "LTQ FT"; a.cvParams.push_back(CVParam(MS_ionization_type, 420)); a.instrumentConfigurationPtr = ip; a.scanWindows.push_back(ScanWindow()); b = a; Diff diff(a, b); unit_assert(!diff); b.scanWindows.push_back(ScanWindow(250.0, 2000.0, MS_m_z)); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.b_a.scanWindows.size() == 1); } void testScanList() { if (os_) *os_ << "testScanList()\n"; ScanList a, b; Scan a1; a1.set(MS_filter_string, "booger"); a1.set(MS_scan_start_time, "4.20", UO_minute); Scan a2; a1.set(MS_filter_string, "goober"); a1.set(MS_scan_start_time, "6.66", UO_minute); a.scans.push_back(a1); a.scans.push_back(a2); b.scans.push_back(a2); b.scans.push_back(a1); Diff diff(a, b); unit_assert(!diff); a.cvParams.push_back(MS_reflectron_on); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); } void testBinaryDataArray() { if (os_) *os_ << "testBinaryDataArray()\n"; vector data; for (int i=0; i<10; i++) data.push_back(i); BinaryDataArray a, b; a.data = data; a.dataProcessingPtr = DataProcessingPtr(new DataProcessing("dp1")); b = a; DiffConfig config; config.precision = 1e-4; a.data[9] = 1.00001e10; b.data[9] = 1.00000e10; // we want to verify relative precision diff (1e-5), // not absolute diff (1e5) Diff diff(a, b, config); if (diff && os_) *os_ << diff << endl; unit_assert(!diff); b.data[9] = 1.0002e10; diff(a, b); if (diff && os_) *os_ << diff << endl; unit_assert(diff); } void testSpectrum() { if (os_) *os_ << "testSpectrum()\n"; Spectrum a, b; a.id = "goober"; a.index = 1; a.dataProcessingPtr = DataProcessingPtr(new DataProcessing("msdata")); a.scanList.scans.push_back(Scan()); a.scanList.scans.back().instrumentConfigurationPtr = InstrumentConfigurationPtr(new InstrumentConfiguration("LTQ FT")); a.scanList.scans.back().paramGroupPtrs.push_back(ParamGroupPtr(new ParamGroup("CommonMS1SpectrumParams"))); a.scanList.scans.back().cvParams.push_back(CVParam(MS_scan_start_time, 5.890500, UO_minute)); a.scanList.scans.back().cvParams.push_back(CVParam(MS_filter_string, "+ c NSI Full ms [ 400.00-1800.00]")); a.scanList.scans.back().scanWindows.push_back(ScanWindow(400.0, 1800.0, MS_m_z)); b = a; DiffConfig config; config.precision = 1e-6; Diff diff(a, b, config); if (diff) cout << diff; unit_assert(!diff); b.index = 4; b.defaultArrayLength = 22; a.dataProcessingPtr = DataProcessingPtr(new DataProcessing("msdata 2")); b.sourceFilePtr = SourceFilePtr(new SourceFile("test.raw")); a.precursors.push_back(Precursor()); a.precursors.back().spectrumID = "666"; b.products.push_back(Product()); b.products.back().isolationWindow.set(MS_ionization_type, 420); a.binaryDataArrayPtrs.push_back(BinaryDataArrayPtr(new BinaryDataArray)); a.binaryDataArrayPtrs.back()->data.resize(6); b.binaryDataArrayPtrs.push_back(BinaryDataArrayPtr(new BinaryDataArray)); b.binaryDataArrayPtrs.back()->data.resize(7); b.binaryDataArrayPtrs.push_back(a.binaryDataArrayPtrs[0]); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.index == 1); unit_assert(diff.a_b.id == "goober"); unit_assert(diff.a_b.defaultArrayLength == 0); unit_assert(diff.a_b.dataProcessingPtr->id == "msdata 2"); unit_assert(diff.a_b.precursors.size() == 1); unit_assert(diff.a_b.products.empty()); unit_assert(diff.a_b.binaryDataArrayPtrs.empty()); unit_assert(diff.b_a.index == 4); unit_assert(diff.b_a.id == "goober"); unit_assert(diff.b_a.defaultArrayLength == 22); unit_assert(diff.b_a.dataProcessingPtr->id == "msdata"); unit_assert(diff.b_a.precursors.empty()); unit_assert(diff.b_a.products.size() == 1); unit_assert(diff.b_a.binaryDataArrayPtrs.empty()); b = a; unit_assert(a.binaryDataArrayPtrs.size() == 1); b.binaryDataArrayPtrs[0] = BinaryDataArrayPtr(new BinaryDataArray); b.binaryDataArrayPtrs[0]->data.resize(6); a.binaryDataArrayPtrs[0]->data[0] = 420; b.binaryDataArrayPtrs[0]->data[0] = 420 + 1e-12; diff(a,b); if (os_ && diff) *os_ << diff << endl; unit_assert(!diff); b.binaryDataArrayPtrs[0]->data[0] += 1e-3; diff(a,b); if (os_ && diff) *os_ << diff << endl; unit_assert(diff); } void testChromatogram() { if (os_) *os_ << "testChromatogram()\n"; Chromatogram a, b; a.id = "goober"; a.index = 1; a.dataProcessingPtr = DataProcessingPtr(new DataProcessing("msdata")); a.binaryDataArrayPtrs.push_back(BinaryDataArrayPtr(new BinaryDataArray)); a.binaryDataArrayPtrs.back()->data.resize(6); b = a; DiffConfig config; config.precision = 1e-6; Diff diff(a, b, config); if (diff) cout << diff; unit_assert(!diff); b.binaryDataArrayPtrs[0] = BinaryDataArrayPtr(new BinaryDataArray); b.binaryDataArrayPtrs[0]->data.resize(6); a.binaryDataArrayPtrs[0]->data[0] = 420; b.binaryDataArrayPtrs[0]->data[0] = 420 + 1e-12; diff(a,b); if (os_ && diff) *os_ << diff << endl; unit_assert(!diff); b.binaryDataArrayPtrs[0]->data[0] += 1e-3; diff(a,b); if (os_ && diff) *os_ << diff << endl; unit_assert(diff); } void testSpectrumList() { if (os_) *os_ << "testSpectrumList()\n"; SpectrumListSimple aSimple, bSimple; SpectrumPtr spectrum1a = SpectrumPtr(new Spectrum); spectrum1a->id = "420"; SpectrumPtr spectrum1b = SpectrumPtr(new Spectrum); spectrum1b->id = "420"; aSimple.spectra.push_back(spectrum1a); bSimple.spectra.push_back(spectrum1b); SpectrumList& a = aSimple; SpectrumList& b = bSimple; Diff diff(a, b); unit_assert(!diff); // check: dataProcessingPtr aSimple.dp = DataProcessingPtr(new DataProcessing("dp")); diff(a, b); unit_assert(diff); DiffConfig config_ignore; config_ignore.ignoreDataProcessing = true; Diff diff_ignore(a, b, config_ignore); unit_assert(!diff_ignore); aSimple.dp = DataProcessingPtr(); diff(a, b); unit_assert(!diff); // check: different SpectrumList::size() SpectrumPtr spectrum2 = SpectrumPtr(new Spectrum); spectrum2->id = "421"; aSimple.spectra.push_back(spectrum2); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.spectra.size() == 1); unit_assert(diff.a_b.spectra[0]->userParams.size() == 1); // check: same SpectrumList::size(), different last scan number SpectrumPtr spectrum3 = SpectrumPtr(new Spectrum); spectrum3->id = "422"; bSimple.spectra.push_back(spectrum3); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.spectra.size() == 1); unit_assert(diff.a_b.spectra[0]->id == "421"); unit_assert(diff.b_a.spectra.size() == 1); unit_assert(diff.b_a.spectra[0]->id == "422"); // check: scan numbers match, binary data slightly different spectrum3->id = "421"; BinaryDataArrayPtr b1(new BinaryDataArray); BinaryDataArrayPtr b2(new BinaryDataArray); b1->data.resize(10); b2->data.resize(10); for (int i=0; i<10; i++) b1->data[i] = b2->data[i] = i; b2->data[2] += 1e-7; spectrum2->binaryDataArrayPtrs.push_back(b1); spectrum3->binaryDataArrayPtrs.push_back(b2); DiffConfig config; config.precision = 1e-6; Diff diffWide(a, b, config); unit_assert(!diffWide); config.precision = 1e-12; Diff diffNarrow(a, b, config); if (os_) *os_ << diffNarrow << endl; unit_assert(diffNarrow); } void testChromatogramList() { if (os_) *os_ << "testChromatogramList()\n"; ChromatogramListSimple aSimple, bSimple; ChromatogramPtr chromatogram1a = ChromatogramPtr(new Chromatogram); chromatogram1a->id = "420"; ChromatogramPtr chromatogram1b = ChromatogramPtr(new Chromatogram); chromatogram1b->id = "420"; aSimple.chromatograms.push_back(chromatogram1a); bSimple.chromatograms.push_back(chromatogram1b); ChromatogramList& a = aSimple; ChromatogramList& b = bSimple; Diff diff(a, b); DiffConfig config_ignore; config_ignore.ignoreChromatograms = true; Diff diffIgnore(a, b, config_ignore); unit_assert(!diff); unit_assert(!diffIgnore); // check: dataProcessingPtr aSimple.dp = DataProcessingPtr(new DataProcessing("dp")); diff(a, b); unit_assert(diff); DiffConfig config_ignore_dp; config_ignore_dp.ignoreDataProcessing = true; Diff diff_ignore_dp(a, b, config_ignore_dp); unit_assert(!diff_ignore_dp); aSimple.dp = DataProcessingPtr(); diff(a, b); unit_assert(!diff); // check: different ChromatogramList::size() ChromatogramPtr chromatogram2 = ChromatogramPtr(new Chromatogram); chromatogram2->id = "421"; aSimple.chromatograms.push_back(chromatogram2); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.chromatograms.size() == 1); unit_assert(diff.a_b.chromatograms[0]->userParams.size() == 1); diffIgnore(a,b); if (os_) *os_ << diffIgnore << endl; unit_assert(!diffIgnore); // check: same ChromatogramList::size(), different last scan number ChromatogramPtr chromatogram3 = ChromatogramPtr(new Chromatogram); chromatogram3->id = "422"; bSimple.chromatograms.push_back(chromatogram3); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.chromatograms.size() == 1); unit_assert(diff.a_b.chromatograms[0]->id == "421"); unit_assert(diff.b_a.chromatograms.size() == 1); unit_assert(diff.b_a.chromatograms[0]->id == "422"); diffIgnore(a,b); unit_assert(!diffIgnore); // check: scan numbers match, binary data slightly different chromatogram3->id = "421"; BinaryDataArrayPtr b1(new BinaryDataArray); BinaryDataArrayPtr b2(new BinaryDataArray); b1->data.resize(10); b2->data.resize(10); for (int i=0; i<10; i++) b1->data[i] = b2->data[i] = i; b2->data[2] += 1e-7; chromatogram2->binaryDataArrayPtrs.push_back(b1); chromatogram3->binaryDataArrayPtrs.push_back(b2); DiffConfig config; config.precision = 1e-6; Diff diffWide(a, b, config); unit_assert(!diffWide); config.precision = 1e-12; Diff diffNarrow(a, b, config); if (os_) *os_ << diffNarrow << endl; unit_assert(diffNarrow); diffIgnore(a,b); unit_assert(!diffIgnore); } void testRun() { if (os_) *os_ << "testRun()\n"; Run a, b; a.id = "goober"; a.startTimeStamp = "20 April 2004 4:20pm"; b.id = "goober"; b.startTimeStamp = "20 April 2004 4:20pm"; Diff diff(a, b); unit_assert(!diff); b.id = "raisinet"; shared_ptr spectrumList1(new SpectrumListSimple); spectrumList1->spectra.push_back(SpectrumPtr(new Spectrum)); spectrumList1->spectra.back()->id = "spectrum1"; a.spectrumListPtr = spectrumList1; shared_ptr chromatogramList1(new ChromatogramListSimple); chromatogramList1->chromatograms.push_back(ChromatogramPtr(new Chromatogram)); chromatogramList1->chromatograms.back()->id = "chromatogram1"; b.chromatogramListPtr = chromatogramList1; // same ref id a.defaultInstrumentConfigurationPtr = InstrumentConfigurationPtr(new InstrumentConfiguration("instrumentConfiguration")); b.defaultInstrumentConfigurationPtr = InstrumentConfigurationPtr(new InstrumentConfiguration("instrumentConfiguration")); b.samplePtr = SamplePtr(new Sample("sample")); a.defaultSourceFilePtr = SourceFilePtr(new SourceFile("source file")); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.spectrumListPtr->size() == 1); unit_assert(diff.a_b.spectrumListPtr->spectrum(0)->userParams.size() == 1); unit_assert(diff.a_b.chromatogramListPtr.get()); unit_assert(diff.a_b.chromatogramListPtr->size() == 1); unit_assert(diff.a_b.chromatogramListPtr->chromatogram(0)->userParams.size() == 1); unit_assert(!diff.a_b.defaultInstrumentConfigurationPtr.get()); unit_assert(!diff.b_a.defaultInstrumentConfigurationPtr.get()); unit_assert(!diff.a_b.samplePtr.get()); unit_assert(!diff.b_a.samplePtr->empty()); unit_assert(diff.a_b.defaultSourceFilePtr.get()); unit_assert(!diff.b_a.defaultSourceFilePtr.get()); unit_assert(diff.a_b.startTimeStamp.empty()); unit_assert(diff.b_a.startTimeStamp.empty()); } struct MSDataWithSettableVersion : public MSData {using MSData::version; void version(const string& v) {version_ = v;}}; void testMSData() { if (os_) *os_ << "testMSData()\n"; MSDataWithSettableVersion a, b; a.id = "goober"; b.id = "goober"; Diff diff(a, b); unit_assert(!diff); a.accession = "different"; b.version("version"); a.cvs.push_back(CV()); b.fileDescription.fileContent.cvParams.push_back(MS_reflectron_on); a.paramGroupPtrs.push_back(ParamGroupPtr(new ParamGroup("pg"))); b.samplePtrs.push_back(SamplePtr(new Sample("sample"))); a.instrumentConfigurationPtrs.push_back(InstrumentConfigurationPtr(new InstrumentConfiguration("instrumentConfiguration"))); b.softwarePtrs.push_back(SoftwarePtr(new Software("software"))); a.dataProcessingPtrs.push_back(DataProcessingPtr(new DataProcessing("dataProcessing"))); b.run.id = "run"; b.scanSettingsPtrs.push_back(ScanSettingsPtr(new ScanSettings("scanSettings"))); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.accession == "different"); unit_assert(diff.b_a.accession.empty()); unit_assert(diff.a_b.id == (a.id + " (" + a.version() + ")")); unit_assert(diff.b_a.id == (b.id + " (" + b.version() + ")")); unit_assert(diff.a_b.cvs.size() == 1); unit_assert(diff.b_a.cvs.empty()); unit_assert(diff.a_b.fileDescription.empty()); unit_assert(!diff.b_a.fileDescription.empty()); unit_assert(!diff.a_b.paramGroupPtrs.empty()); unit_assert(diff.b_a.paramGroupPtrs.empty()); unit_assert(diff.a_b.samplePtrs.empty()); unit_assert(!diff.b_a.samplePtrs.empty()); unit_assert(!diff.a_b.instrumentConfigurationPtrs.empty()); unit_assert(diff.b_a.instrumentConfigurationPtrs.empty()); unit_assert(diff.a_b.softwarePtrs.empty()); unit_assert(!diff.b_a.softwarePtrs.empty()); unit_assert(!diff.a_b.dataProcessingPtrs.empty()); unit_assert(diff.b_a.dataProcessingPtrs.empty()); unit_assert(diff.a_b.run.empty()); unit_assert(!diff.b_a.run.empty()); unit_assert(diff.a_b.scanSettingsPtrs.empty()); unit_assert(!diff.b_a.scanSettingsPtrs.empty()); } void testBinaryDataOnly() { MSData tiny; examples::initializeTiny(tiny); MSData tinier; SpectrumListSimplePtr sl(new SpectrumListSimple); ChromatogramListSimplePtr cl(new ChromatogramListSimple); tinier.run.spectrumListPtr = sl; tinier.run.chromatogramListPtr = cl; for (unsigned int i=0; isize(); i++) { SpectrumPtr from = tiny.run.spectrumListPtr->spectrum(i, true); sl->spectra.push_back(SpectrumPtr(new Spectrum)); SpectrumPtr& to = sl->spectra.back(); for (vector::const_iterator it=from->binaryDataArrayPtrs.begin(); it!=from->binaryDataArrayPtrs.end(); ++it) { // copy BinaryDataArray::data from tiny to tinier to->binaryDataArrayPtrs.push_back(BinaryDataArrayPtr(new BinaryDataArray)); to->binaryDataArrayPtrs.back()->data = (*it)->data; } // copy "important" scan metadata to->defaultArrayLength = from->defaultArrayLength; to->scanList = from->scanList; to->precursors.resize(from->precursors.size()); for (size_t precursorIndex=0; precursorIndexprecursors.size(); ++precursorIndex) { Precursor& precursorTo = to->precursors[precursorIndex]; Precursor& precursorFrom = from->precursors[precursorIndex]; precursorTo.selectedIons = precursorFrom.selectedIons; } } for (unsigned int i=0; isize(); i++) { ChromatogramPtr from = tiny.run.chromatogramListPtr->chromatogram(i, true); cl->chromatograms.push_back(ChromatogramPtr(new Chromatogram)); ChromatogramPtr& to = cl->chromatograms.back(); for (vector::const_iterator it=from->binaryDataArrayPtrs.begin(); it!=from->binaryDataArrayPtrs.end(); ++it) { // copy BinaryDataArray::data from tiny to tinier to->binaryDataArrayPtrs.push_back(BinaryDataArrayPtr(new BinaryDataArray)); to->binaryDataArrayPtrs.back()->data = (*it)->data; } // copy "important" scan metadata to->defaultArrayLength = from->defaultArrayLength; } if (os_) { *os_ << "tinier::"; TextWriter(*os_,0)(tinier); } Diff diff_full(tiny, tinier); unit_assert(diff_full); DiffConfig config; config.ignoreMetadata = true; config.ignoreIdentity = true; Diff diff_data(tiny, tinier, config); if (os_ && diff_data) *os_ << diff_data << endl; unit_assert(!diff_data); } static const char* userParamName_MaxBinaryDataArrayDifference_ = "Maximum binary data array difference"; // gets value of MaxBinaryDataArrayDifference userParam if present, else 0 template double getMaxPrecisionDiff(const list_type& list) { if (list.dp.get() && !list.dp->processingMethods.empty() && !list.dp->processingMethods.back().userParam(userParamName_MaxBinaryDataArrayDifference_).empty()) return lexical_cast(list.dp->processingMethods.back().userParam(userParamName_MaxBinaryDataArrayDifference_).value); return 0; } void testMaxPrecisionDiff() { if (os_) { *os_ <<"testMaxPrecisionDiff()\n"; } double epsilon = numeric_limits::epsilon(); BinaryDataArrayPtr a(new BinaryDataArray); BinaryDataArrayPtr b(new BinaryDataArray); BinaryDataArrayPtr c(new BinaryDataArray); BinaryDataArrayPtr d(new BinaryDataArray); BinaryDataArrayPtr e(new BinaryDataArray); BinaryDataArrayPtr f(new BinaryDataArray); std::vector data1; std::vector data2; data1.push_back(3.0); data2.push_back(3.0000001); e->data = data1; f->data = data2; DiffConfig config; config.precision=1e-6; Diff diff_toosmall(*e,*f,config); //not diff for diff of 1e-7 unit_assert(!diff_toosmall); data1.push_back(2.0); data2.push_back(2.0001); c->data = data1; d->data = data2; data1.push_back(1.0); data2.push_back(1.001); a->data = data1; b->data = data2; Diff diff(*a,*b,config); //diff unit_assert(diff); if(os_) *os_< diff2(*c,*d,config); //diff unit_assert(diff2); if(os_) *os_<(diff.a_b.userParam("Binary data array difference").value); double maxBin_b_a=boost::lexical_cast(diff.a_b.userParam("Binary data array difference").value); unit_assert_equal(maxBin_a_b,.001,epsilon); unit_assert_equal(maxBin_b_a,.001,epsilon); Run run_a, run_b; shared_ptr sls_a(new SpectrumListSimple); shared_ptr sls_b(new SpectrumListSimple); SpectrumPtr spa(new Spectrum); SpectrumPtr spb(new Spectrum); SpectrumPtr spc(new Spectrum); SpectrumPtr spd(new Spectrum); spa->binaryDataArrayPtrs.push_back(a); spb->binaryDataArrayPtrs.push_back(b); spc->binaryDataArrayPtrs.push_back(c); spd->binaryDataArrayPtrs.push_back(d); sls_a->spectra.push_back(spa); sls_a->spectra.push_back(spc); sls_b->spectra.push_back(spb); sls_b->spectra.push_back(spc); shared_ptr cls_a(new ChromatogramListSimple); shared_ptr cls_b(new ChromatogramListSimple); ChromatogramPtr cpa(new Chromatogram); ChromatogramPtr cpb(new Chromatogram); ChromatogramPtr cpc(new Chromatogram); ChromatogramPtr cpd(new Chromatogram); cpa->binaryDataArrayPtrs.push_back(a); cpb->binaryDataArrayPtrs.push_back(b); cpc->binaryDataArrayPtrs.push_back(c); cpd->binaryDataArrayPtrs.push_back(d); cls_a->chromatograms.push_back(cpa); cls_a->chromatograms.push_back(cpc); cls_b->chromatograms.push_back(cpb); cls_b->chromatograms.push_back(cpd); run_a.spectrumListPtr = sls_a; run_b.spectrumListPtr = sls_b; run_a.chromatogramListPtr = cls_a; run_b.chromatogramListPtr = cls_b; // Run user param is written for both Spectrum and Chromatogram binary data array difference user params, if present, with the correct value (max of the Spectrum and Chromatogram user params over the SpectrumList/ ChromatogramList respectively) Diff diff_run(run_a,run_b,config); // diff unit_assert(diff_run); // Run user params are set unit_assert(!diff_run.a_b.userParams.empty()); unit_assert(!diff_run.b_a.userParams.empty()); // and correctly double maxSpecList_a_b=boost::lexical_cast(diff_run.a_b.userParam("Spectrum binary data array difference").value); double maxSpecList_b_a=boost::lexical_cast(diff_run.b_a.userParam("Spectrum binary data array difference").value); double maxChrList_a_b=boost::lexical_cast(diff_run.a_b.userParam("Chromatogram binary data array difference").value); double maxChrList_b_a=boost::lexical_cast(diff_run.b_a.userParam("Chromatogram binary data array difference").value); unit_assert_equal(maxSpecList_a_b,.001,epsilon); unit_assert_equal(maxSpecList_b_a,.001,epsilon); unit_assert_equal(maxChrList_a_b,.001,epsilon); unit_assert_equal(maxChrList_b_a,.001,epsilon); // test that Spectrum UserParam is written upon finding a binary data diff, with the correct value // user params are set unit_assert(!diff_run.a_b.spectrumListPtr->spectrum(0)->userParams.empty()); unit_assert(!diff_run.b_a.spectrumListPtr->spectrum(0)->userParams.empty()); //user params are set // and correctly double maxSpec_a_b=boost::lexical_cast(diff_run.a_b.spectrumListPtr->spectrum(0)->userParam("Binary data array difference").value); double maxSpec_b_a=boost::lexical_cast(diff_run.b_a.spectrumListPtr->spectrum(0)->userParam("Binary data array difference").value); unit_assert_equal(maxSpec_a_b,.001,epsilon); unit_assert_equal(maxSpec_b_a,.001,epsilon); // test that Chromatogram UserParam is written upon finding a binary data diff, with the correct value // user params are set unit_assert(!diff_run.a_b.chromatogramListPtr->chromatogram(0)->userParams.empty()); unit_assert(!diff_run.b_a.chromatogramListPtr->chromatogram(0)->userParams.empty()); // and correctly double maxChr_a_b=boost::lexical_cast(diff_run.a_b.chromatogramListPtr->chromatogram(0)->userParam("Binary data array difference").value); double maxChr_b_a=boost::lexical_cast(diff_run.b_a.chromatogramListPtr->chromatogram(0)->userParam("Binary data array difference").value); unit_assert_equal(maxChr_a_b,.001,epsilon); unit_assert_equal(maxChr_b_a,.001,epsilon); if(os_) *os_< sls_a_a(new SpectrumListSimple); shared_ptr sls_A_A(new SpectrumListSimple); pwiz::data::diff_impl::diff(*sls_a, *sls_a,*sls_a_a,*sls_A_A,config); double maxPrecisionNonDiffSpec = getMaxPrecisionDiff(*sls_a_a); unit_assert_equal(maxPrecisionNonDiffSpec,0,epsilon); // test that maxPrecisionDiff is being returned correctly for a non-zero diff within diff_impl::diff(SpectrumList, SpectrumList, SpectrumList, SpectrumList, DiffConfig) shared_ptr sls_a_b(new SpectrumListSimple); shared_ptr sls_b_a(new SpectrumListSimple); pwiz::data::diff_impl::diff(*sls_a, *sls_b,*sls_a_b,*sls_b_a,config); double maxPrecisionDiffSpec = getMaxPrecisionDiff(*sls_a_b); unit_assert_equal(maxPrecisionDiffSpec,.001,epsilon); // test that maxPrecisionDiff is being returned correctly for a zero diff within diff_impl::diff(ChromatogramList, ChromatogramList, ChromatogramList, ChromatogramList, DiffConfig) shared_ptr cls_a_a(new ChromatogramListSimple); shared_ptr cls_A_A(new ChromatogramListSimple); pwiz::data::diff_impl::diff(*cls_a, *cls_a,*cls_a_a,*cls_A_A,config); double maxPrecisionNonDiffChr = getMaxPrecisionDiff(*cls_a_a); unit_assert_equal(maxPrecisionNonDiffChr,0,epsilon); // test that maxPrecisionDiff is being returned correctly for a non-zero diff within diff_impl::diff(ChromatogramList, ChromatogramList, ChromatogramList, ChromatogramList, DiffConfig) shared_ptr cls_a_b(new ChromatogramListSimple); shared_ptr cls_b_a(new ChromatogramListSimple); pwiz::data::diff_impl::diff(*cls_a,*cls_b,*cls_a_b,*cls_b_a,config); double maxPrecisionDiffChr = getMaxPrecisionDiff(*cls_a_b); unit_assert_equal(maxPrecisionDiffChr,.001,epsilon); } void testMSDiffUpdate() { if(os_) *os_<<"testMSDiffUpdate()"< diff_initial(tiny1,tiny2); unit_assert(!diff_initial); //inflict metadata differences tiny1.id="ego"; tiny1.run.id="superego"; //inflict spectral differences SpectrumPtr tiny1_s0 = tiny1.run.spectrumListPtr->spectrum(0); SpectrumPtr tiny2_s1 = tiny2.run.spectrumListPtr->spectrum(1); tiny1_s0->id = "tiny1"; tiny2_s1->id = "tiny2"; //inflict chromatogram differences ChromatogramPtr tiny1_c0=tiny1.run.chromatogramListPtr->chromatogram(0); tiny1_c0->id="zumas"; //test metadata, spectral, chromatogram differences Diff diff_changed(tiny1,tiny2); unit_assert(diff_changed); if(os_) *os_< diff_changed_changed(tiny1,tiny2); unit_assert(diff_changed_changed); if(os_) *os_<1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/msdata/TextWriter.hpp0000664000175100017510000004016512664775621021566 0ustar teamcityteamcity00000000000000// // $Id: TextWriter.hpp 1880 2010-03-08 22:52:43Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _TEXTWRITER_HPP_ #define _TEXTWRITER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "MSData.hpp" #include "boost/lexical_cast.hpp" #include #include #include namespace pwiz { namespace msdata { class PWIZ_API_DECL TextWriter { public: /// constructs a TextWriter for MSData types /// @param os The ostream to write to. /// @param depth The number of indentations to prefix to each output line. /// @param arrayExampleCount The number of example values to print for arrays (i.e. m/z and intensity); -1 for unlimited TextWriter(std::ostream& os, int depth = 0, int arrayExampleCount = 3) : os_(os), depth_(depth), arrayExampleCount_(arrayExampleCount < 0 ? std::numeric_limits::max() : (size_t) arrayExampleCount), indent_(depth*2, ' ') {} TextWriter child() {return TextWriter(os_, depth_+1, arrayExampleCount_);} TextWriter& operator()(const std::string& text) { os_ << indent_ << text << std::endl; return *this; } TextWriter& operator()(const CVParam& cvParam) { os_ << indent_ << "cvParam: " << cvTermInfo(cvParam.cvid).name; if (!cvParam.value.empty()) os_ << ", " << cvParam.value; if (cvParam.units != CVID_Unknown) os_ << ", " << cvParam.unitsName(); os_ << std::endl; return *this; } TextWriter& operator()(const UserParam& userParam) { os_ << indent_ << "userParam: " << userParam.name; if (!userParam.value.empty()) os_ << ", " << userParam.value; if (!userParam.type.empty()) os_ << ", " << userParam.type; if (userParam.units != CVID_Unknown) os_ << ", " << cvTermInfo(userParam.units).name; os_ << std::endl; return *this; } template TextWriter& operator()(const std::string& label, const std::vector& v) { (*this)(label); for_each(v.begin(), v.end(), child()); return *this; } TextWriter& operator()(const MSData& msd, bool metadata_only=false) { (*this)("msdata:"); child() ("id: " + msd.id); if (!msd.accession.empty()) child()("accession: " + msd.accession); if (!msd.version().empty()) child()("version: " + msd.version()); if (!msd.cvs.empty()) child()("cvList: ", msd.cvs); if (!msd.fileDescription.empty()) child()(msd.fileDescription); if (!msd.paramGroupPtrs.empty()) child()("paramGroupList: ", msd.paramGroupPtrs); if (!msd.samplePtrs.empty()) child()("sampleList: " , msd.samplePtrs); if (!msd.softwarePtrs.empty()) child()("softwareList: ", msd.softwarePtrs); if (!msd.scanSettingsPtrs.empty()) child()("scanSettingsList: ", msd.scanSettingsPtrs); if (!msd.instrumentConfigurationPtrs.empty()) child()("instrumentConfigurationList: ", msd.instrumentConfigurationPtrs); if (!msd.dataProcessingPtrs.empty()) child()("dataProcessingList: ", msd.dataProcessingPtrs); if (!msd.run.empty()) child()(msd.run, metadata_only); return *this; } TextWriter& operator()(const CV& cv) { (*this)("cv:"); child() ("id: " + cv.id) ("fullName: " + cv.fullName) ("version: " + cv.version) ("URI: " + cv.URI); return *this; } TextWriter& operator()(const FileDescription& fd) { (*this)("fileDescription:"); child() (fd.fileContent) ("sourceFileList: ", fd.sourceFilePtrs); for_each(fd.contacts.begin(), fd.contacts.end(), child()); return *this; } TextWriter& operator()(const ParamContainer& paramContainer) { for (std::vector::const_iterator it=paramContainer.paramGroupPtrs.begin(); it!=paramContainer.paramGroupPtrs.end(); ++it) (*this)("referenceableParamGroupRef: " + (*it)->id); for_each(paramContainer.cvParams.begin(), paramContainer.cvParams.end(), *this); for_each(paramContainer.userParams.begin(), paramContainer.userParams.end(), *this); return *this; } TextWriter& operator()(const FileContent& fileContent) { (*this)("fileContent:"); child()(static_cast(fileContent)); return *this; } TextWriter& operator()(const SourceFile& sf) { (*this)("sourceFile:"); child() ("id: " + sf.id) ("name: " + sf.name) ("location: " + sf.location) (static_cast(sf)); return *this; } TextWriter& operator()(const Contact& contact) { (*this)("contact:"); child()(static_cast(contact)); return *this; } TextWriter& operator()(const ParamGroup& paramGroup) { (*this)("paramGroup:"); child() ("id: " + paramGroup.id) (static_cast(paramGroup)); return *this; } TextWriter& operator()(const Sample& sample) { (*this)("sample:"); child() ("id: " + sample.id) ("name: " + sample.name) (static_cast(sample)); return *this; } TextWriter& operator()(const InstrumentConfiguration& instrumentConfiguration) { (*this)("instrumentConfiguration:"); child() ("id: " + instrumentConfiguration.id) (static_cast(instrumentConfiguration)); if (!instrumentConfiguration.componentList.empty()) child()(instrumentConfiguration.componentList); if (instrumentConfiguration.softwarePtr.get() && !instrumentConfiguration.softwarePtr->empty()) child()("softwareRef: " + instrumentConfiguration.softwarePtr->id); return *this; } TextWriter& operator()(const ComponentList& componentList) { (*this)("componentList:"); for (size_t i=0; i < componentList.size(); ++i) child()(componentList[i]); return *this; } TextWriter& operator()(const Component& component) { switch(component.type) { case ComponentType_Source: (*this)("source: "); break; case ComponentType_Analyzer: (*this)("analyzer: "); break; case ComponentType_Detector: (*this)("detector: "); break; default: break; } child() ("order: " + boost::lexical_cast(component.order)) (static_cast(component)); return *this; } TextWriter& operator()(const Software& software) { (*this)("software:"); child() ("id: " + software.id) ("version: " + software.version) (static_cast(software)); return *this; } TextWriter& operator()(const ProcessingMethod& processingMethod) { (*this)("processingMethod:"); child() ("order: " + boost::lexical_cast(processingMethod.order)); if (processingMethod.softwarePtr.get() && !processingMethod.softwarePtr->empty()) child()("softwareRef: " + processingMethod.softwarePtr->id); child() (static_cast(processingMethod)); return *this; } TextWriter& operator()(const DataProcessing& dp) { (*this)("dataProcessing:"); child() ("id: " + dp.id); for_each(dp.processingMethods.begin(), dp.processingMethods.end(), child()); return *this; } TextWriter& operator()(const Target& target) { (*this)("target:"); child()(static_cast(target)); return *this; } TextWriter& operator()(const ScanSettings& as) { (*this)("scanSettings:"); child() ("id: " + as.id); for_each(as.targets.begin(), as.targets.end(), child()); child()("sourceFileList: ", as.sourceFilePtrs); return *this; } TextWriter& operator()(const Run& run, bool metadata_only=false) { (*this)("run:"); child()("id: " + run.id); if (run.defaultInstrumentConfigurationPtr.get()) child()("defaultInstrumentConfigurationRef: " + run.defaultInstrumentConfigurationPtr->id); if (run.samplePtr.get()) child()("sampleRef: " + run.samplePtr->id); if (!run.startTimeStamp.empty()) child()("startTimeStamp: " + run.startTimeStamp); child()(static_cast(run)); if (run.defaultSourceFilePtr.get()) child()("defaultSourceFileRef: " + run.defaultSourceFilePtr->id); if (run.spectrumListPtr.get()) child()(run.spectrumListPtr, metadata_only); if (run.chromatogramListPtr.get()) child()(run.chromatogramListPtr, metadata_only); return *this; } TextWriter& operator()(const SpectrumList& spectrumList, bool metadata_only=false) { std::string text("spectrumList (" + boost::lexical_cast(spectrumList.size()) + " spectra)"); if (!metadata_only) text += ":"; (*this)(text); if (spectrumList.dataProcessingPtr().get()) child()(*spectrumList.dataProcessingPtr()); if (!metadata_only) for (size_t index=0; index(chromatogramList.size()) + " chromatograms)"); if (!metadata_only) text += ":"; (*this)(text); if (chromatogramList.dataProcessingPtr().get()) child()(*chromatogramList.dataProcessingPtr()); if (!metadata_only) for (size_t index=0; index(spectrum.index)) ("id: " + spectrum.id); if (!spectrum.spotID.empty()) child()("spotID: " + spectrum.spotID); if (spectrum.sourceFilePtr.get()) child()(spectrum.sourceFilePtr); child() ("defaultArrayLength: " + boost::lexical_cast(spectrum.defaultArrayLength)) (spectrum.dataProcessingPtr) (static_cast(spectrum)); if (!spectrum.scanList.empty()) child()(spectrum.scanList); if (!spectrum.precursors.empty()) child()("precursorList: ", spectrum.precursors); for_each(spectrum.binaryDataArrayPtrs.begin(), spectrum.binaryDataArrayPtrs.end(), child()); return *this; } TextWriter& operator()(const Chromatogram& chromatogram) { (*this)("chromatogram:"); child() ("index: " + boost::lexical_cast(chromatogram.index)) ("id: " + chromatogram.id) ("defaultArrayLength: " + boost::lexical_cast(chromatogram.defaultArrayLength)) (chromatogram.dataProcessingPtr) (static_cast(chromatogram)); for_each(chromatogram.binaryDataArrayPtrs.begin(), chromatogram.binaryDataArrayPtrs.end(), child()); return *this; } TextWriter& operator()(const Scan& scan) { (*this)("scan:"); if (scan.instrumentConfigurationPtr.get()) child()(*scan.instrumentConfigurationPtr); child()(static_cast(scan)); if (!scan.scanWindows.empty()) child()("scanWindowList: ", scan.scanWindows); return *this; } TextWriter& operator()(const ScanWindow& window) { (*this)("scanWindow:"); for_each(window.cvParams.begin(), window.cvParams.end(), child()); return *this; } TextWriter& operator()(const BinaryDataArrayPtr& p) { if (!p.get() || p->empty()) return *this; std::stringstream oss; oss << "[" << boost::lexical_cast(p->data.size()) << "] "; oss.precision(12); for (size_t i=0; i < arrayExampleCount_ && i < p->data.size(); i++) oss << p->data[i] << " "; if (p->data.size() > arrayExampleCount_) oss << "..."; (*this)("binaryDataArray:"); child() (static_cast(*p)); if (p->dataProcessingPtr.get() && !p->dataProcessingPtr->empty()) child()(p->dataProcessingPtr); if (!p->data.empty()) child()("binary: " + oss.str()); return *this; } TextWriter& operator()(const SelectedIon& selectedIon) { (*this)("selectedIon:"); child()(static_cast(selectedIon)); return *this; } TextWriter& operator()(const Precursor& precursor) { (*this)("precursor:"); child() ("spectrumRef: " + precursor.spectrumID) (static_cast(precursor)); if (!precursor.isolationWindow.empty()) { child()("isolationWindow:"); child().child()(precursor.isolationWindow); } if (!precursor.selectedIons.empty()) { child()("selectedIons:", precursor.selectedIons); } if (!precursor.activation.empty()) { child()("activation:"); child().child()(precursor.activation); } return *this; } TextWriter& operator()(const Product& product) { (*this)("product:"); if (!product.isolationWindow.empty()) { child()("isolationWindow:"); child().child()(product.isolationWindow); } return *this; } TextWriter& operator()(const ScanList& scanList) { (*this) (static_cast(scanList)) ("scanList:", scanList.scans); return *this; } // if no other overload matches, assume the object is a shared_ptr of a valid overloaded type template TextWriter& operator()(const boost::shared_ptr& p) { return p.get() ? (*this)(*p) : *this; } private: std::ostream& os_; int depth_; size_t arrayExampleCount_; std::string indent_; }; } // namespace msdata } // namespace pwiz #endif // _TEXTWRITER_HPP_ pwiz/pwiz/data/msdata/ChromatogramListBase.hpp0000664000175100017510000000277612664775621023525 0ustar teamcityteamcity00000000000000// // $Id: ChromatogramListBase.hpp 1189 2009-08-14 17:36:06Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _CHROMATOGRAMLISTBASE_HPP_ #define _CHROMATOGRAMLISTBASE_HPP_ #include "pwiz/data/msdata/MSData.hpp" #include namespace pwiz { namespace msdata { /// common functionality for base ChromatogramList implementations class PWIZ_API_DECL ChromatogramListBase : public ChromatogramList { public: /// implementation of ChromatogramList virtual const boost::shared_ptr dataProcessingPtr() const {return dp_;} /// set DataProcessing virtual void setDataProcessingPtr(DataProcessingPtr dp) {dp_ = dp;} protected: DataProcessingPtr dp_; }; } // namespace msdata } // namespace pwiz #endif // _CHROMATOGRAMLISTBASE_HPP_ pwiz/pwiz/data/msdata/SpectrumList_mzXML_Test.cpp0000664000175100017510000002172612664775621024166 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_mzXML_Test.cpp 5759 2014-02-19 22:26:29Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "SpectrumList_mzXML.hpp" #include "Serializer_mzXML.hpp" // depends on Serializer_mzXML::write() only #include "TextWriter.hpp" #include "examples.hpp" #include "pwiz/utility/minimxml/XMLWriter.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::cv; using namespace pwiz::msdata; using namespace pwiz::util; using namespace pwiz::minimxml; ostream* os_ = 0; void test(bool indexed) { if (os_) *os_ << "test(): indexed=\"" << boolalpha << indexed << "\"\n"; MSData tiny; examples::initializeTiny(tiny); Serializer_mzXML::Config config; config.indexed = indexed; Serializer_mzXML serializer(config); ostringstream oss; serializer.write(oss, tiny); if (os_) *os_ << "oss:\n" << oss.str() << endl; shared_ptr is(new istringstream(oss.str())); // dummy would normally be read in from file MSData dummy; dummy.fileDescription.sourceFilePtrs.push_back(SourceFilePtr(new SourceFile("tiny1.yep"))); dummy.fileDescription.sourceFilePtrs.back()->set(MS_Bruker_Agilent_YEP_format); dummy.fileDescription.sourceFilePtrs.back()->set(MS_Bruker_Agilent_YEP_nativeID_format); dummy.softwarePtrs.push_back(SoftwarePtr(new Software("pwiz"))); dummy.softwarePtrs.back()->set(MS_ProteoWizard_software); dummy.instrumentConfigurationPtrs.push_back(InstrumentConfigurationPtr(new InstrumentConfiguration("1"))); dummy.instrumentConfigurationPtrs.back()->set(MS_LCQ_Deca); dummy.instrumentConfigurationPtrs.back()->userParams.push_back(UserParam("doobie", "420")); dummy.dataProcessingPtrs.push_back(DataProcessingPtr(new DataProcessing("DP1"))); dummy.dataProcessingPtrs.back()->processingMethods.push_back(ProcessingMethod()); dummy.dataProcessingPtrs.back()->processingMethods.back().set(MS_Conversion_to_mzML); dummy.dataProcessingPtrs.back()->processingMethods.back().softwarePtr = dummy.softwarePtrs.back(); // note: used to have a test here to check that an exception would be thrown on // on an unindexed input file, but index is an optional element so the right thing to // do is just create it SpectrumListPtr sl = SpectrumList_mzXML::create(is, dummy, indexed); if (os_) { TextWriter write(*os_); write(*sl); *os_ << endl; } // check easy functions unit_assert(sl.get()); unit_assert(sl->size() == 4); unit_assert(sl->find("scan=19") == 0); IndexList indexList = sl->findNameValue("scan", "19"); unit_assert(indexList.size()==1 && indexList[0]==0); unit_assert(sl->find("scan=20") == 1); indexList = sl->findNameValue("scan", "20"); unit_assert(indexList.size()==1 && indexList[0]==1); unit_assert(sl->find("scan=21") == 2); indexList = sl->findNameValue("scan", "21"); unit_assert(indexList.size()==1 && indexList[0]==2); // check scan 19 unit_assert(sl->spectrumIdentity(0).index == 0); unit_assert(sl->spectrumIdentity(0).id == "scan=19"); unit_assert(sl->spectrumIdentity(0).sourceFilePosition != -1); SpectrumPtr s = sl->spectrum(0, false); unit_assert(s.get()); unit_assert(s->id == "scan=19"); unit_assert(s->index == 0); unit_assert(s->sourceFilePosition != -1); unit_assert(s->cvParam(MS_ms_level).valueAs() == 1); unit_assert(s->hasCVParam(MS_positive_scan)); unit_assert(s->scanList.scans.size() == 1); Scan& scan = s->scanList.scans[0]; unit_assert(scan.hasCVParam(MS_scan_start_time)); //unit_assert(scan.cvParam(MS_preset_scan_configuration).valueAs() == 3); unit_assert(s->cvParam(MS_base_peak_intensity).value == "120053"); unit_assert(s->defaultArrayLength == 15); unit_assert(s->binaryDataArrayPtrs.size() == 2); unit_assert(s->binaryDataArrayPtrs[0]->hasCVParam(MS_m_z_array)); unit_assert(s->binaryDataArrayPtrs[1]->hasCVParam(MS_intensity_array)); unit_assert(s->binaryDataArrayPtrs[0]->data.empty() && s->binaryDataArrayPtrs[1]->data.empty()); s = sl->spectrum(0, true); unit_assert(s->defaultArrayLength == 15); unit_assert(s->binaryDataArrayPtrs.size() == 2); unit_assert(!s->binaryDataArrayPtrs[0]->data.empty() && !s->binaryDataArrayPtrs[1]->data.empty()); vector pairs; s->getMZIntensityPairs(pairs); if (os_) { *os_ << "scan 19:\n"; copy(pairs.begin(), pairs.end(), ostream_iterator(*os_, "\n")); *os_ << endl; } unit_assert(pairs.size() == 15); for (int i=0; i<15; i++) unit_assert(pairs[i].mz==i && pairs[i].intensity==15-i); Scan& scan19 = s->scanList.scans[0]; unit_assert(scan19.instrumentConfigurationPtr.get()); InstrumentConfiguration& instrumentConfiguration = *scan19.instrumentConfigurationPtr; unit_assert(!instrumentConfiguration.cvParams.empty()); // references resolved unit_assert(instrumentConfiguration.userParams.size() == 1 && instrumentConfiguration.userParams[0].name == "doobie"); // check scan 20 unit_assert(sl->spectrumIdentity(1).index == 1); unit_assert(sl->spectrumIdentity(1).id == "scan=20"); s = sl->spectrum(1, true); unit_assert(s.get()); unit_assert(s->id == "scan=20"); unit_assert(s->index == 1); unit_assert(s->sourceFilePosition != -1); unit_assert(s->cvParam(MS_ms_level).valueAs() == 2); unit_assert(s->scanList.scans.size() == 1); //Scan& scan20 = s->scanList.scans[0]; //unit_assert(scan20.cvParam(MS_preset_scan_configuration).valueAs() == 4); unit_assert(s->precursors.size() == 1); Precursor& precursor = s->precursors[0]; unit_assert(precursor.selectedIons.size() == 1); unit_assert(precursor.selectedIons[0].hasCVParam(MS_selected_ion_m_z)); unit_assert(precursor.selectedIons[0].hasCVParam(MS_peak_intensity)); unit_assert(precursor.selectedIons[0].hasCVParam(MS_charge_state)); unit_assert(precursor.activation.hasCVParam(MS_CID)); unit_assert(precursor.activation.hasCVParam(MS_collision_energy)); unit_assert(precursor.spectrumID == "scan=19"); // Serializer_mzXML::read() sets pairs.clear(); s->getMZIntensityPairs(pairs); if (os_) { *os_ << "scan 20:\n"; copy(pairs.begin(), pairs.end(), ostream_iterator(*os_, "\n")); *os_ << endl; } unit_assert(pairs.size() == 10); for (int i=0; i<10; i++) unit_assert(pairs[i].mz==2*i && pairs[i].intensity==(10-i)*2); // check scan 21 (for userParam <-> nameValue) unit_assert(sl->spectrumIdentity(2).index == 2); unit_assert(sl->spectrumIdentity(2).id == "scan=21"); s = sl->spectrum(2, false); unit_assert(s.get()); unit_assert(s->id == "scan=21"); UserParam exampleUserParam = s->userParam("example"); unit_assert(!exampleUserParam.empty()); unit_assert(exampleUserParam.name == "example"); unit_assert(exampleUserParam.value == "spectrum with no data"); unit_assert(exampleUserParam.type == "xsd:string"); // check scan 22 (for ETD precursor activation) unit_assert(sl->spectrumIdentity(3).index == 3); unit_assert(sl->spectrumIdentity(3).id == "scan=22"); s = sl->spectrum(3, false); unit_assert(s.get()); unit_assert(s->id == "scan=22"); unit_assert(s->precursors.size() == 1); Precursor& precursor22 = s->precursors[0]; unit_assert(precursor22.selectedIons.size() == 1); unit_assert(precursor22.selectedIons[0].hasCVParam(MS_selected_ion_m_z)); unit_assert(precursor22.selectedIons[0].hasCVParam(MS_peak_intensity)); unit_assert(precursor22.selectedIons[0].hasCVParam(MS_charge_state)); unit_assert(precursor22.activation.hasCVParam(MS_ETD)); unit_assert(precursor22.activation.hasCVParam(MS_CID)); unit_assert(precursor22.activation.hasCVParam(MS_collision_energy)); } void test() { bool indexed = true; test(indexed); indexed = false; test(indexed); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/msdata/Reader.hpp0000775000175100017510000002070512664775621020650 0ustar teamcityteamcity00000000000000// // $Id: Reader.hpp 8904 2015-09-29 19:20:14Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _READER_HPP_ #define _READER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "MSData.hpp" #include #include namespace pwiz { namespace msdata { /// interface for file readers class PWIZ_API_DECL Reader { public: /// Reader configuration struct PWIZ_API_DECL Config { /// when true, sets certain vendor readers to produce SIM/SRM transitions as spectra instead of chromatograms bool simAsSpectra; bool srmAsSpectra; /// when true, allows for skipping 0 length checks (and thus skip re-reading data for ABI) bool acceptZeroLengthSpectra; /// when true, all drift bins/scans in a frame/block are written in combined form instead of as individual spectra bool combineIonMobilitySpectra; /// when true, if a reader cannot identify an instrument, an exception will be thrown asking users to report it bool unknownInstrumentIsError; /// when true, if a reader does not know what time zone was used to record a time, it will assume the time refers to the host's local time; /// when false, the reader will treat times with unknown time zone as UTC bool adjustUnknownTimeZonesToHostTimeZone; Config(); Config(const Config& rhs); }; /// return true iff Reader recognizes the file as one it should handle /// that's not to say one it CAN handle, necessarily, as in Thermo on linux, /// see comment for identify() below bool accept(const std::string& filename, const std::string& head) const { return (identify(filename,head).length() != 0); } /// return file type iff Reader recognizes the file, else empty; /// note: for formats requiring a 3rd party DLL identify() should /// return non-empty if it recognized the format, even though reading /// may fail if the 3rd party DLL isn't actually present /// Reader may filter based on filename and/or head of the file virtual std::string identify(const std::string& filename, const std::string& head) const = 0; /// fill in the MSData structure from the first (or only) sample virtual void read(const std::string& filename, const std::string& head, MSData& result, int runIndex = 0, const Config& config = Config()) const = 0; /// fill in a vector of MSData structures; provides support for multi-run input files virtual void read(const std::string& filename, const std::string& head, std::vector& results, const Config& config = Config()) const = 0; /// fill in a vector of MSData.Id values; provides support for multi-run input files virtual void readIds(const std::string& filename, const std::string& head, std::vector& dataIds, const Config& config = Config()) const; /// returns a unique string identifying the reader type virtual const char* getType() const = 0; virtual ~Reader(){} }; class PWIZ_API_DECL ReaderFail : public std::runtime_error // reader failure exception { public: ReaderFail(const std::string& error) : std::runtime_error(("[ReaderFail] " + error).c_str()), error_(error) {} virtual const std::string& error() const {return error_;} virtual ~ReaderFail() throw() {} private: std::string error_; }; typedef boost::shared_ptr ReaderPtr; /// /// Reader container (composite pattern). /// /// The template get() gives access to child Readers by type, to facilitate /// Reader-specific configuration at runtime. /// class PWIZ_API_DECL ReaderList : public Reader, public std::vector { public: /// returns child name iff some child identifies, else empty string virtual std::string identify(const std::string& filename) const; /// returns child name iff some child identifies, else empty string virtual std::string identify(const std::string& filename, const std::string& head) const; /// delegates to first child that identifies virtual void read(const std::string& filename, MSData& result, int runIndex = 0, const Config& config = Config()) const; /// delegates to first child that identifies virtual void read(const std::string& filename, const std::string& head, MSData& result, int runIndex = 0, const Config& config = Config()) const; /// delegates to first child that identifies; /// provides support for multi-run input files virtual void read(const std::string& filename, std::vector& results, const Config& config = Config()) const; /// delegates to first child that identifies; /// provides support for multi-run input files virtual void read(const std::string& filename, const std::string& head, std::vector& results, const Config& config = Config()) const; /// delegates to first child that identifies; /// provides support for multi-run input files virtual void readIds(const std::string& filename, std::vector& results, const Config& config = Config()) const; /// delegates to first child that identifies; /// provides support for multi-run input files virtual void readIds(const std::string& filename, const std::string& head, std::vector& results, const Config& config = Config()) const; /// appends all of the rhs operand's Readers to the list ReaderList& operator +=(const ReaderList& rhs); /// appends the rhs Reader to the list ReaderList& operator +=(const ReaderPtr& rhs); /// returns a concatenated list of all the Readers from the lhs and rhs operands ReaderList operator +(const ReaderList& rhs) const; /// returns a concatenated list of all the Readers from the lhs and rhs operands ReaderList operator +(const ReaderPtr& rhs) const; /// returns pointer to Reader of the specified type template reader_type* get() { for (iterator it=begin(); it!=end(); ++it) { reader_type* p = dynamic_cast(it->get()); if (p) return p; } return 0; } /// returns const pointer to Reader of the specified type template const reader_type* get() const { return const_cast(this)->get(); } virtual const char* getType() const {return "ReaderList";} // satisfy inheritance }; /// returns a list containing the lhs and rhs as readers PWIZ_API_DECL ReaderList operator +(const ReaderPtr& lhs, const ReaderPtr& rhs); /// tries to identify a filepath using the provided Reader or ReaderList; /// returns the CVID file format of the specified filepath, /// or CVID_Unknown if the file format has no CV term or the filepath doesn't exist PWIZ_API_DECL CVID identifyFileFormat(const ReaderPtr& reader, const std::string& filepath); } // namespace msdata } // namespace pwiz #endif // _READER_HPP_ pwiz/pwiz/data/msdata/Serializer_mzML_Test.cpp0000664000175100017510000000724612664775621023512 0ustar teamcityteamcity00000000000000// // $Id: Serializer_mzML_Test.cpp 5084 2013-10-28 23:32:24Z pcbrefugee $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "Serializer_mzML.hpp" #include "Diff.hpp" #include "References.hpp" #include "examples.hpp" #include "pwiz/utility/misc/unit.hpp" #include "boost/iostreams/positioning.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::msdata; ostream* os_ = 0; void testWriteRead(const MSData& msd, const Serializer_mzML::Config& config, const DiffConfig &diffcfg) { if (os_) *os_ << "testWriteRead() " << config << endl; Serializer_mzML mzmlSerializer(config); ostringstream oss; mzmlSerializer.write(oss, msd); if (os_) *os_ << "oss:\n" << oss.str() << endl; shared_ptr iss(new istringstream(oss.str())); MSData msd2; mzmlSerializer.read(iss, msd2); References::resolve(msd2); Diff diff(msd, msd2, diffcfg); if (os_ && diff) *os_ << diff << endl; unit_assert(!diff); } void testWriteRead() { MSData msd; examples::initializeTiny(msd); for (int zloop=2;zloop--;) // run through once without zlib, then with { DiffConfig diffcfg; Serializer_mzML::Config config; if (!zloop) // retest with compression config.binaryDataEncoderConfig.compression = BinaryDataEncoder::Compression_Zlib; unit_assert(config.binaryDataEncoderConfig.precision == BinaryDataEncoder::Precision_64); testWriteRead(msd, config, diffcfg); config.binaryDataEncoderConfig.precision = BinaryDataEncoder::Precision_32; testWriteRead(msd, config, diffcfg); config.indexed = false; testWriteRead(msd, config, diffcfg); // lossy compression, increase allowable mismatch diffcfg.precision = 0.01; config.binaryDataEncoderConfig.numpress = BinaryDataEncoder::Numpress_Linear; testWriteRead(msd, config, diffcfg); config.binaryDataEncoderConfig.numpress = BinaryDataEncoder::Numpress_Pic; testWriteRead(msd, config, diffcfg); config.binaryDataEncoderConfig.numpress = BinaryDataEncoder::Numpress_None; config.binaryDataEncoderConfig.numpressOverrides[MS_intensity_array] = BinaryDataEncoder::Numpress_Slof; testWriteRead(msd, config, diffcfg); if (!zloop) // provoke numpress temp. disable { config.binaryDataEncoderConfig.numpressLinearErrorTolerance = .000000001; config.binaryDataEncoderConfig.numpressSlofErrorTolerance = .000000001; testWriteRead(msd, config, diffcfg); } } } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; testWriteRead(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/msdata/SpectrumInfoTest.cpp0000664000175100017510000000620612664775620022713 0ustar teamcityteamcity00000000000000// // $Id: SpectrumInfoTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "SpectrumInfo.hpp" #include "pwiz/data/msdata/examples.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::msdata; ostream* os_ = 0; const double epsilon_ = 1e-6; void test() { if (os_) *os_ << "test()\n"; MSData tiny; examples::initializeTiny(tiny); SpectrumInfo info; info.update(*tiny.run.spectrumListPtr->spectrum(0)); unit_assert(info.index == 0); unit_assert(info.id == "scan=19"); unit_assert(info.scanNumber == 19); unit_assert(info.massAnalyzerType == MS_QIT); unit_assert(info.msLevel == 1); unit_assert_equal(info.retentionTime, 353.43, epsilon_); unit_assert_equal(info.mzLow, 400.39, epsilon_); unit_assert_equal(info.mzHigh, 1795.56, epsilon_); unit_assert(info.precursors.empty()); info.update(*tiny.run.spectrumListPtr->spectrum(0), true); unit_assert(info.data.size() == 15); info.update(*tiny.run.spectrumListPtr->spectrum(0), false); unit_assert(info.data.size() == 0); unit_assert(info.data.capacity() == 0); info.update(*tiny.run.spectrumListPtr->spectrum(1), true); unit_assert(info.index == 1); unit_assert(info.id == "scan=20"); unit_assert(info.scanNumber == 20); unit_assert(info.massAnalyzerType == MS_QIT); unit_assert(info.msLevel == 2); unit_assert_equal(info.retentionTime, 359.43, epsilon_); unit_assert_equal(info.mzLow, 320.39, epsilon_); unit_assert_equal(info.mzHigh, 1003.56, epsilon_); unit_assert(info.precursors.size() == 1); unit_assert(info.precursors[0].index == 0); unit_assert_equal(info.precursors[0].mz, 445.34, epsilon_); unit_assert_equal(info.precursors[0].intensity, 120053, epsilon_); unit_assert(info.precursors[0].charge == 2); unit_assert(info.data.size() == 10); info.clearBinaryData(); unit_assert(info.data.size() == 0); unit_assert(info.data.capacity() == 0); if (os_) *os_ << "ok\n"; } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/msdata/SpectrumListCache.cpp0000664000175100017510000001437412664775621023025 0ustar teamcityteamcity00000000000000// // $Id: SpectrumListCache.cpp 6945 2014-11-26 18:58:33Z chambm $ // // // Original author: Matt Chambers // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumListCache.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace msdata { PWIZ_API_DECL SpectrumListCache::SpectrumListCache(const SpectrumListPtr& inner, MemoryMRUCacheMode cacheMode, size_t cacheSize) : SpectrumListWrapper(inner), spectrumCache_(cacheMode, cacheSize) { } namespace { void clearSpectrumMetadata(Spectrum& spectrum) { Spectrum fresh; fresh.id = spectrum.id; fresh.index = spectrum.index; fresh.spotID = spectrum.spotID; fresh.defaultArrayLength = spectrum.defaultArrayLength; swap(spectrum, fresh); swap(spectrum.binaryDataArrayPtrs, fresh.binaryDataArrayPtrs); } struct modifyCachedSpectrumPtr { modifyCachedSpectrumPtr(const SpectrumPtr& newSpectrumPtr) : newSpectrumPtr_(newSpectrumPtr) {} void operator() (SpectrumListCache::CacheType::value_type& indexSpectrumPtrPair) { indexSpectrumPtrPair.spectrum = newSpectrumPtr_; } private: SpectrumPtr newSpectrumPtr_; }; } // namespace // There are two kinds of spectrum requests: metadata and metadata+binary; // the cache's behavior changes depending on the cache mode and the request. // // For metadata requests: // - If cache off: return spectrum directly // - If cache metadata: if spectrum not cached, cache it; return cached spectrum // - If cache binary data: return spectrum directly // - If cache all: return spectrum directly // // For metadata+binary requests: // - If cache off: return spectrum directly // - If cache metadata: get spectrum, make a copy, remove binary data, then cache the copy and return original // - If cache binary data: if spectrum cached, get spectrum without binary data, add cached binary data to it and return it; otherwise get full spectrum, make a copy, remove metadata, cache it, then return original spectrum // - If cache all: if spectrum not cached, cache it; return cached spectrum PWIZ_API_DECL SpectrumPtr SpectrumListCache::spectrum(size_t index, bool getBinaryData) const { SpectrumPtr original, copy; if (getBinaryData) { switch (spectrumCache_.mode()) { default: case MemoryMRUCacheMode_Off: return inner_->spectrum(index, true); case MemoryMRUCacheMode_MetaDataAndBinaryData: // if insert returns true, spectrum was not in cache if (spectrumCache_.insert(CacheEntry(index, SpectrumPtr()))) spectrumCache_.modify(spectrumCache_.begin(), modifyCachedSpectrumPtr(inner_->spectrum(index, true))); return spectrumCache_.mru().spectrum; case MemoryMRUCacheMode_MetaDataOnly: // if insert returns true, spectrum was not in cache if (spectrumCache_.insert(CacheEntry(index, SpectrumPtr()))) { original = inner_->spectrum(index, true); copy.reset(new Spectrum(*original)); copy->binaryDataArrayPtrs.clear(); spectrumCache_.modify(spectrumCache_.begin(), modifyCachedSpectrumPtr(copy)); } else { // we have cached metadata, hopefully this format knows how // to jump to binary data without rescanning metadata original = inner_->spectrum(spectrumCache_.mru().spectrum, true); // copy and add binary data } return original; case MemoryMRUCacheMode_BinaryDataOnly: // if insert returns true, spectrum was not in cache if (spectrumCache_.insert(CacheEntry(index, SpectrumPtr()))) { original = inner_->spectrum(index, true); copy.reset(new Spectrum(*original)); clearSpectrumMetadata(*copy); spectrumCache_.modify(spectrumCache_.begin(), modifyCachedSpectrumPtr(copy)); return original; } else { // get spectrum metadata, add cached binary data to it original = inner_->spectrum(index, false); original->binaryDataArrayPtrs = spectrumCache_.mru().spectrum->binaryDataArrayPtrs; return original; } } } else // !getBinaryData { switch (spectrumCache_.mode()) { default: case MemoryMRUCacheMode_Off: case MemoryMRUCacheMode_BinaryDataOnly: case MemoryMRUCacheMode_MetaDataAndBinaryData: return inner_->spectrum(index, false); case MemoryMRUCacheMode_MetaDataOnly: // if insert returns true, spectrum was not in cache if (spectrumCache_.insert(CacheEntry(index, SpectrumPtr()))) spectrumCache_.modify(spectrumCache_.begin(), modifyCachedSpectrumPtr(inner_->spectrum(index, false))); return spectrumCache_.mru().spectrum; } } } PWIZ_API_DECL SpectrumListCache::CacheType& SpectrumListCache::spectrumCache() { return spectrumCache_; } PWIZ_API_DECL const SpectrumListCache::CacheType& SpectrumListCache::spectrumCache() const { return spectrumCache_; } } // namespace msdata } // namespace pwiz pwiz/pwiz/data/msdata/SpectrumList_BTDX.cpp0000664000175100017510000002670412664775620022721 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_BTDX.cpp 6585 2014-08-07 22:49:28Z chambm $ // // // Original author: Matt Chambers // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_BTDX.hpp" #include "References.hpp" #include "pwiz/utility/minimxml/SAXParser.hpp" #include "pwiz/utility/misc/Std.hpp" #include namespace pwiz { namespace msdata { using namespace pwiz::minimxml; using boost::iostreams::stream_offset; using boost::iostreams::offset_to_position; namespace { class SpectrumList_BTDXImpl : public SpectrumList_BTDX { public: SpectrumList_BTDXImpl(shared_ptr is, const MSData& msd); // SpectrumList implementation virtual size_t size() const {return index_.size();} virtual const SpectrumIdentity& spectrumIdentity(size_t index) const; virtual size_t find(const string& id) const; virtual size_t findNative(const string& nativeID) const; virtual SpectrumPtr spectrum(size_t index, bool getBinaryData) const; private: shared_ptr is_; const MSData& msd_; vector index_; map idToIndex_; mutable vector spectrumCache_; mutable boost::mutex readMutex; void createIndex(); void createMaps(); }; SpectrumList_BTDXImpl::SpectrumList_BTDXImpl(shared_ptr is, const MSData& msd) : is_(is), msd_(msd) { createIndex(); createMaps(); spectrumCache_.resize(index_.size()); } const SpectrumIdentity& SpectrumList_BTDXImpl::spectrumIdentity(size_t index) const { if (index > index_.size()) throw runtime_error("[SpectrumList_BTDX::spectrumIdentity()] Index out of bounds."); return index_[index]; } size_t SpectrumList_BTDXImpl::find(const string& id) const { map::const_iterator it=idToIndex_.find(id); return it!=idToIndex_.end() ? it->second : size(); } size_t SpectrumList_BTDXImpl::findNative(const string& nativeID) const { return find(nativeID); } class HandlerPeaks : public SAXParser::Handler { public: HandlerPeaks(Spectrum& spectrum, bool getBinaryData, vector& mzArray, vector& iArray) : spectrum_(spectrum), mzArray_(mzArray), iArray_(iArray), totalIntensity_(0), basePeakIntensity_(0), getBinaryData_(getBinaryData) { spectrum_.defaultArrayLength = 0; } virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "pk") { string mz, i, sn, z; getAttribute(attributes, "mz", mz); getAttribute(attributes, "i", i); //getAttribute(attributes, "sn", sn); //getAttribute(attributes, "z", z); double mzValue = lexical_cast(mz); double iValue = lexical_cast(i); //double snValue = lexical_cast(sn); //int zValue = lexical_cast(z); if (getBinaryData_) { mzArray_.push_back(mzValue); iArray_.push_back(iValue); } ++spectrum_.defaultArrayLength; totalIntensity_ += iValue; if (iValue > basePeakIntensity_) { basePeakMz_ = mzValue; basePeakIntensity_ = iValue; } return Status::Ok; } else if (name == "ms_peaks") { return Status::Ok; } throw runtime_error(("[SpectrumList_BTDX::HandlerPeaks] Unexpected element name: " + name).c_str()); } virtual Status endElement(const string& name, stream_offset position) { if (name == "ms_peaks") { spectrum_.set(MS_TIC, totalIntensity_); spectrum_.set(MS_base_peak_m_z, basePeakMz_); spectrum_.set(MS_base_peak_intensity, basePeakIntensity_); return Status::Done; } return Status::Ok; } private: Spectrum& spectrum_; vector& mzArray_; vector& iArray_; double totalIntensity_; double basePeakMz_; double basePeakIntensity_; bool getBinaryData_; }; class HandlerCompound : public SAXParser::Handler { public: HandlerCompound(const MSData& msd, Spectrum& spectrum, bool getBinaryData) : msd_(msd), spectrum_(spectrum), getBinaryData_(getBinaryData) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "cmpd") { string cmpdnr, rt, rt_unit; getAttribute(attributes, "cmpdnr", cmpdnr); getAttribute(attributes, "rt", rt); getAttribute(attributes, "rt_unit", rt_unit); spectrum_.id = cmpdnr; spectrum_.sourceFilePosition = position; if (!rt.empty()) { CVID rtUnits = CVID_Unknown; if (rt_unit == "s") rtUnits = UO_second; else if (rt_unit == "m") rtUnits = UO_minute; else if (rt_unit == "h") rtUnits = UO_hour; spectrum_.scanList.scans.push_back(Scan()); spectrum_.scanList.scans.back().set(MS_scan_start_time, rt, rtUnits); } return Status::Ok; } else if (name == "title") { // WTF is this? return Status::Ok; } else if (name == "precursor") { string mz, i, sn, z, targetPosition, chipPosition; getAttribute(attributes, "mz", mz); getAttribute(attributes, "i", i); //getAttribute(attributes, "sn", sn); getAttribute(attributes, "z", z); getAttribute(attributes, "TargetPosition", targetPosition); getAttribute(attributes, "ChipPosition", chipPosition); if (!targetPosition.empty() && !chipPosition.empty()) spectrum_.spotID = targetPosition + "," + chipPosition; double mzValue = lexical_cast(mz); double iValue = lexical_cast(i); //double snValue = lexical_cast(sn); int zValue = lexical_cast(z); spectrum_.precursors.push_back( Precursor(mzValue, iValue, zValue, MS_number_of_detector_counts)); // TODO: support sn: spectrum_.precursors.back().set(MS_signal_to_noise, sn); return Status::Ok; } else if (name == "ms_spectrum") { string msms_stage; getAttribute(attributes, "msms_stage", msms_stage); if (msms_stage.empty()) spectrum_.set(MS_ms_level, "1"); else spectrum_.set(MS_ms_level, msms_stage); return Status::Ok; } else if (name == "ms_peaks") { spectrum_.setMZIntensityArrays(vector(), vector(), MS_number_of_detector_counts); handlerPeaks_ = shared_ptr( new HandlerPeaks(spectrum_, getBinaryData_, spectrum_.getMZArray()->data, spectrum_.getIntensityArray()->data)); return Status(Status::Delegate, &*handlerPeaks_); } throw runtime_error(("[SpectrumList_BTDX::HandlerCompound] Unexpected element name: " + name).c_str()); } private: const MSData& msd_; Spectrum& spectrum_; bool getBinaryData_; shared_ptr handlerPeaks_; }; SpectrumPtr SpectrumList_BTDXImpl::spectrum(size_t index, bool getBinaryData) const { boost::lock_guard lock(readMutex); // lock_guard will unlock mutex when out of scope or when exception thrown (during destruction) if (index > index_.size()) throw runtime_error("[SpectrumList_BTDX::spectrum()] Index out of bounds."); // returned cached Spectrum if possible if (!getBinaryData && spectrumCache_[index].get()) return spectrumCache_[index]; // allocate Spectrum object and read it in SpectrumPtr result(new Spectrum); if (!result.get()) throw runtime_error("[SpectrumList_BTDX::spectrum()] Out of memory."); result->index = index; result->set(MS_MSn_spectrum); result->set(MS_centroid_spectrum); result->scanList.set(MS_no_combination); result->scanList.scans.push_back(Scan()); //Scan& scan = result->scanList.scans[0]; is_->seekg(offset_to_position(index_[index].sourceFilePosition)); if (!*is_) throw runtime_error("[SpectrumList_BTDX::spectrum()] Error seeking to ."); HandlerCompound handler(msd_, *result, getBinaryData); SAXParser::parse(*is_, handler); // save to cache if no binary data if (!getBinaryData && !spectrumCache_[index].get()) spectrumCache_[index] = result; // resolve any references into the MSData object References::resolve(*result, msd_); return result; } class HandlerIndexCreator : public SAXParser::Handler { public: HandlerIndexCreator(vector& index) : index_(index) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "cmpd") { string cmpdNumber; getAttribute(attributes, "cmpdnr", cmpdNumber); SpectrumIdentity si; si.index = index_.size(); si.id = cmpdNumber; si.sourceFilePosition = position; index_.push_back(si); } return Status::Ok; } virtual Status endElement(const string& name, stream_offset position) { if (name == "compounds") return Status::Done; return Status::Ok; } private: vector& index_; }; void SpectrumList_BTDXImpl::createIndex() { is_->seekg(0); HandlerIndexCreator handler(index_); SAXParser::parse(*is_, handler); } void SpectrumList_BTDXImpl::createMaps() { vector::const_iterator it=index_.begin(); for (unsigned int i=0; i!=index_.size(); ++i, ++it) idToIndex_[it->id] = i; } } // namespace SpectrumListPtr SpectrumList_BTDX::create(boost::shared_ptr is, const MSData& msd) { return SpectrumListPtr(new SpectrumList_BTDXImpl(is, msd)); } } // namespace msdata } // namespace pwiz pwiz/pwiz/data/msdata/MemoryMRUCache.hpp0000664000175100017510000000405312664775620022220 0ustar teamcityteamcity00000000000000// // $Id: MemoryMRUCache.hpp 2595 2011-03-28 14:40:59Z chambm $ // // // Original author: Matt Chambers // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _MEMORYMRUCACHE_HPP_ #define _MEMORYMRUCACHE_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/utility/misc/mru_list.hpp" namespace pwiz { namespace msdata { enum PWIZ_API_DECL MemoryMRUCacheMode { MemoryMRUCacheMode_Off, MemoryMRUCacheMode_MetaDataOnly, MemoryMRUCacheMode_BinaryDataOnly, MemoryMRUCacheMode_MetaDataAndBinaryData }; /// an MRU cache for SpectrumPtrs or ChromatogramPtrs template > class MemoryMRUCache : public pwiz::util::mru_list { public: MemoryMRUCache(MemoryMRUCacheMode mode, size_t size) : pwiz::util::mru_list(size), mode_(mode) {} /// set the caching mode /// note: if the new mode is different than the current mode, the cache will be cleared void setMode(MemoryMRUCacheMode mode) { if (mode != mode_) pwiz::util::mru_list::clear(); mode_ = mode; } /// get the current caching mode MemoryMRUCacheMode mode() const {return mode_;} private: MemoryMRUCacheMode mode_; }; } // namespace msdata } // namespace pwiz #endif // _MEMORYMRUCACHE_HPP_ pwiz/pwiz/data/msdata/SpectrumIterator.hpp0000664000175100017510000001010712664775621022752 0ustar teamcityteamcity00000000000000// // $Id: SpectrumIterator.hpp 1189 2009-08-14 17:36:06Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMITERATOR_HPP_ #define _SPECTRUMITERATOR_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "MSData.hpp" #include "pwiz/utility/misc/IntegerSet.hpp" namespace pwiz { namespace msdata { using pwiz::util::IntegerSet; /// /// SpectrumIterator provides convenient iteration through a set of scans in a SpectrumList. /// /// Its behavior is similar to istream_iterator. In particular: /// - the default constructed SpectrumIterator() is a past-the-end marker /// - references to the current Spectrum are invalidated by preincrement /// /// Because SpectrumIterator holds a copy of the current Spectrum internally, /// copy assignment and postincrement have been disabled. /// /// Iteration may be customized in a number of ways: /// - clients may specify an IntegerSet of scan numbers through which to iterate. /// - clients may specify a Sieve to filter based on Spectrum fields. /// - clients may specify whether binary data is retrieved in the Spectrum object (default==true) /// /// For usage examples, see SpectrumIteratorTest.cpp /// class PWIZ_API_DECL SpectrumIterator { public: /// interface for filtering based on ScanInfo class PWIZ_API_DECL Sieve { public: virtual bool accept(const Spectrum& spectrum) const {return true;} virtual ~Sieve(){} }; /// SpectrumIterator configuration -- note that constructors allow automatic /// conversion from IntegerSet or Sieve to Config struct PWIZ_API_DECL Config { const IntegerSet* scanNumbers; const Sieve* sieve; bool getBinaryData; Config() : scanNumbers(0), sieve(0), getBinaryData(true) {} Config(const IntegerSet& _scanNumbers, bool _getBinaryData = true) : scanNumbers(&_scanNumbers), sieve(0), getBinaryData(_getBinaryData) {} Config(const Sieve& _sieve, bool _getBinaryData = true) : scanNumbers(0), sieve(&_sieve), getBinaryData(_getBinaryData) {} }; /// special default object for marking past-the-end SpectrumIterator(); /// constructor for normal initialization of the iterator SpectrumIterator(const SpectrumList& spectrumList, const Config& config = Config()); /// constructor using MSData object SpectrumIterator(const MSData& msd, const Config& config = Config()); /// copy constructor SpectrumIterator(const SpectrumIterator&); /// \name input iterator interface //@{ SpectrumIterator& operator++(); const Spectrum& operator*() const; const Spectrum* operator->() const; bool operator==(const SpectrumIterator& that) const; bool operator!=(const SpectrumIterator& that) const; //@} /// \name standard iterator typedefs //@{ typedef std::input_iterator_tag iterator_category; typedef Spectrum value_type; typedef int difference_type; typedef value_type* pointer; typedef value_type& reference; //@} private: class Impl; boost::shared_ptr impl_; /// no copying SpectrumIterator& operator=(const SpectrumIterator&); /// don't do this -- avoid temporary copy SpectrumIterator operator++(int); }; } // namespace msdata } // namespace pwiz #endif // _SPECTRUMITERATOR_HPP_ pwiz/pwiz/data/msdata/Diff.hpp0000664000175100017510000001331412664775621020311 0ustar teamcityteamcity00000000000000// // $Id: Diff.hpp 1766 2010-01-29 21:42:48Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _DIFF_HPP_ #define _DIFF_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "MSData.hpp" namespace pwiz { namespace msdata { struct DiffConfig; } } namespace pwiz { namespace data { namespace diff_impl { using namespace msdata; PWIZ_API_DECL void diff(const SourceFile& a, const SourceFile& b, SourceFile& a_b, SourceFile& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const FileDescription& a, const FileDescription& b, FileDescription& a_b, FileDescription& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Sample& a, const Sample& b, Sample& a_b, Sample& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Component& a, const Component& b, Component& a_b, Component& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const ComponentList& a, const ComponentList& b, ComponentList& a_b, ComponentList& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Software& a, const Software& b, Software& a_b, Software& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const InstrumentConfiguration& a, const InstrumentConfiguration& b, InstrumentConfiguration& a_b, InstrumentConfiguration& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const ProcessingMethod& a, const ProcessingMethod& b, ProcessingMethod& a_b, ProcessingMethod& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const DataProcessing& a, const DataProcessing& b, DataProcessing& a_b, DataProcessing& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const ScanSettings& a, const ScanSettings& b, ScanSettings& a_b, ScanSettings& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Precursor& a, const Precursor& b, Precursor& a_b, Precursor& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Product& a, const Product& b, Product& a_b, Product& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Scan& a, const Scan& b, Scan& a_b, Scan& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const ScanList& a, const ScanList& b, ScanList& a_b, ScanList& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const BinaryDataArray& a, const BinaryDataArray& b, BinaryDataArray& a_b, BinaryDataArray& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Spectrum& a, const Spectrum& b, Spectrum& a_b, Spectrum& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Chromatogram& a, const Chromatogram& b, Chromatogram& a_b, Chromatogram& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const SpectrumList& a, const SpectrumList& b, SpectrumListSimple& a_b, SpectrumListSimple& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const ChromatogramList& a, const ChromatogramList& b, ChromatogramListSimple& a_b, ChromatogramListSimple& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const Run& a, const Run& b, Run& a_b, Run& b_a, const DiffConfig& config); PWIZ_API_DECL void diff(const MSData& a, const MSData& b, MSData& a_b, MSData& b_a, const DiffConfig& config); } // namespace diff_impl } // namespace data } // namespace pwiz // this include must come after the above declarations or GCC won't see them #include "pwiz/data/common/diff_std.hpp" namespace pwiz { namespace msdata { /// configuration struct for diffing MSData types struct PWIZ_API_DECL DiffConfig : public pwiz::data::BaseDiffConfig { /// ignore members of SpectrumIdentity and ChromatogramIdentity bool ignoreIdentity; /// ignore all file level metadata, and most scan level metadata, /// i.e. verify scan binary data, plus important scan metadata: /// - msLevel /// - precursor.ionSelection bool ignoreMetadata; bool ignoreSpectra; bool ignoreChromatograms; bool ignoreDataProcessing; DiffConfig() : pwiz::data::BaseDiffConfig(), ignoreIdentity(false), ignoreMetadata(false), ignoreSpectra(false), ignoreChromatograms(false), ignoreDataProcessing(false) {} }; PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const pwiz::data::Diff& diff); } // namespace msdata } // namespace pwiz #endif // _DIFF_HPP_ pwiz/pwiz/data/msdata/MSDataTest.cpp0000664000175100017510000002535512664775621021415 0ustar teamcityteamcity00000000000000// // $Id: MSDataTest.cpp 6385 2014-06-12 22:56:04Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "MSData.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::data; using namespace pwiz::msdata; void testSpectrumListSimple() { // fill in SpectrumListSimple shared_ptr spectrumListSimple(new SpectrumListSimple); unit_assert(spectrumListSimple->empty()); spectrumListSimple->dp = DataProcessingPtr(new DataProcessing("dp")); unit_assert(!spectrumListSimple->empty()); SpectrumPtr spectrum0(new Spectrum); spectrum0->index = 0; spectrum0->id = "sample=1 period=1 cycle=123 experiment=2"; // add m/z values 0,...,9 BinaryDataArrayPtr bd_mz(new BinaryDataArray); for (unsigned int i=0; i<10; i++) bd_mz->data.push_back(i); bd_mz->cvParams.push_back(MS_m_z_array); double* buffer = &bd_mz->data[0]; // add intensity values 10,...,1 BinaryDataArrayPtr bd_intensity(new BinaryDataArray); for (unsigned int i=0; i<10; i++) bd_intensity->data.push_back(10-i); bd_intensity->cvParams.push_back(MS_intensity_array); spectrum0->binaryDataArrayPtrs.push_back(bd_mz); spectrum0->binaryDataArrayPtrs.push_back(bd_intensity); spectrum0->defaultArrayLength = 10; SpectrumPtr spectrum1(new Spectrum); spectrum1->index = 1; spectrum1->id = "sample=1 period=1 cycle=345 experiment=2"; spectrum1->cvParams.push_back(MS_MSn_spectrum); spectrum1->cvParams.push_back(CVParam(MS_ionization_type, 420)); spectrumListSimple->spectra.push_back(spectrum0); spectrumListSimple->spectra.push_back(spectrum1); // let an MSData object hold onto it as a SpectrumListPtr MSData data; data.run.spectrumListPtr = spectrumListSimple; // test SpectrumList interface // verify index() const SpectrumList& spectrumList = *data.run.spectrumListPtr; unit_assert_operator_equal(2, spectrumList.size()); unit_assert_operator_equal(0, spectrumList.find("sample=1 period=1 cycle=123 experiment=2")); unit_assert_operator_equal(1, spectrumList.find("sample=1 period=1 cycle=345 experiment=2")); // verify findAbbreviated() unit_assert_operator_equal(0, spectrumList.findAbbreviated("1.1.123.2")); unit_assert_operator_equal(1, spectrumList.findAbbreviated("1.1.345.2")); // verify findNameValue IndexList result = spectrumList.findNameValue("cycle", "123"); unit_assert(result.size()==1 && result[0]==0); result = spectrumList.findNameValue("cycle", "345"); unit_assert(result.size()==1 && result[0]==1); // verify spectrumIdentity() const SpectrumIdentity& identity0 = spectrumList.spectrumIdentity(0); unit_assert(identity0.index == spectrum0->index); unit_assert(identity0.id == spectrum0->id); const SpectrumIdentity& identity1 = spectrumList.spectrumIdentity(1); unit_assert(identity1.index == spectrum1->index); unit_assert(identity1.id == spectrum1->id); // verify spectrum 0 SpectrumPtr spectrum = spectrumList.spectrum(0); unit_assert(spectrum->index == spectrum0->index); unit_assert(spectrum->id == spectrum0->id); // verify no extra copying of binary data arrays unit_assert(spectrum->binaryDataArrayPtrs.size() == 2); unit_assert(&(spectrum->binaryDataArrayPtrs[0]->data[0]) == buffer); // verify getMZIntensityPairs() unit_assert(spectrum->binaryDataArrayPtrs[0]->hasCVParam(MS_m_z_array) == true); unit_assert(spectrum->binaryDataArrayPtrs[1]->hasCVParam(MS_intensity_array) == true); vector mziPairs; spectrum->getMZIntensityPairs(mziPairs); unit_assert(mziPairs.size() == 10); vector doubleArray; unit_assert(spectrum->defaultArrayLength == 10); doubleArray.resize(spectrum->defaultArrayLength*2); spectrum->getMZIntensityPairs(reinterpret_cast(&doubleArray[0]), spectrum->defaultArrayLength); for (unsigned int i=0; i<10; i++) { const MZIntensityPair& p = mziPairs[i]; unit_assert(p.mz == i); unit_assert(p.intensity == 10-i); unit_assert(doubleArray[2*i] == i); unit_assert(doubleArray[2*i+1] == 10-i); } // verify setMZIntensityPairs() spectrum->binaryDataArrayPtrs.clear(); unit_assert(spectrum->binaryDataArrayPtrs.empty()); vector mziPairs2; for (unsigned int i=0; i<10; i++) mziPairs2.push_back(MZIntensityPair(2*i, 3*i)); spectrum->setMZIntensityPairs(mziPairs2, MS_number_of_detector_counts); unit_assert(spectrum->binaryDataArrayPtrs.size() == 2); unit_assert(spectrum->binaryDataArrayPtrs[0]->hasCVParam(MS_m_z_array) == true); unit_assert(spectrum->binaryDataArrayPtrs[1]->hasCVParam(MS_intensity_array) == true); unit_assert(spectrum->binaryDataArrayPtrs[1]->cvParam(MS_intensity_array).units == MS_number_of_detector_counts); unit_assert(spectrum->binaryDataArrayPtrs[0]->data.size() == 10); unit_assert(spectrum->binaryDataArrayPtrs[1]->data.size() == 10); for (unsigned int i=0; i<10; i++) unit_assert(spectrum->binaryDataArrayPtrs[0]->data[i] == 2*i && spectrum->binaryDataArrayPtrs[1]->data[i] == 3*i); // verify spectrum 1 spectrum = spectrumList.spectrum(1); unit_assert(spectrum->index == spectrum1->index); unit_assert(spectrum->id == spectrum1->id); // verify DataProcessingPtr unit_assert(spectrumList.dataProcessingPtr().get() && spectrumList.dataProcessingPtr()->id == "dp"); } void testChromatograms() { ChromatogramListSimple cls; for (int i=0; i<3; i++) { vector pairs; for (int j=0; j<10; j++) pairs.push_back(TimeIntensityPair(j, 10*i+j)); cls.chromatograms.push_back(ChromatogramPtr(new Chromatogram)); cls.chromatograms.back()->setTimeIntensityPairs(pairs, UO_second, MS_number_of_detector_counts); } DataProcessingPtr dp(new DataProcessing("dp")); cls.dp = dp; ChromatogramList& cl = cls; unit_assert(cl.size() == 3); for (size_t i=0; i<3; i++) { vector result; cl.chromatogram(i)->getTimeIntensityPairs(result); unit_assert(result.size() == 10); for (size_t j=0; j<10; j++) unit_assert(result[j].time==j && result[j].intensity==10*i+j); } unit_assert(cl.dataProcessingPtr().get() && cl.dataProcessingPtr()->id == "dp"); } void testIDParsing() { string id = "hair=blue favorite=420 age=36.175 upsideDown=1"; map parsedID = id::parse(id); unit_assert(parsedID.size() == 4); unit_assert(id::value(id, "hair") == "blue"); unit_assert(id::valueAs(id, "favorite") == 420); unit_assert_equal(id::valueAs(id, "age"), 36.175, 1e-6); unit_assert(id::valueAs(id, "upsideDown") == true); unit_assert(id::abbreviate(id) == "blue.420.36.175.1"); unit_assert(id::abbreviate(id, ',') == "blue,420,36.175,1"); id = "controllerType=0 controllerNumber=1 scan=123"; unit_assert(id::translateNativeIDToScanNumber(MS_Thermo_nativeID_format, id) == "123"); unit_assert(id::translateNativeIDToScanNumber(MS_no_nativeID_format, id) == ""); unit_assert(id::translateNativeIDToScanNumber(MS_scan_number_only_nativeID_format, id) == "123"); unit_assert(id::translateScanNumberToNativeID(MS_Thermo_nativeID_format, "123") == id); unit_assert(id::abbreviate(id) == "0.1.123"); unit_assert(id::abbreviate(id, ',') == "0,1,123"); unit_assert(id::translateScanNumberToNativeID(MS_multiple_peak_list_nativeID_format, "123") == "index=123"); id = "spectrum=123"; unit_assert(id::translateNativeIDToScanNumber(MS_spectrum_identifier_nativeID_format, id) == "123"); unit_assert(id::translateScanNumberToNativeID(MS_spectrum_identifier_nativeID_format, "123") == id); unit_assert(id::translateNativeIDToScanNumber(MS_Thermo_nativeID_format, id) == ""); id = "scan=123"; unit_assert(id::translateNativeIDToScanNumber(MS_scan_number_only_nativeID_format, id) == "123"); unit_assert(id::translateNativeIDToScanNumber(CVID_Unknown, id) == "123"); unit_assert(id::translateScanNumberToNativeID(MS_scan_number_only_nativeID_format, "123") == id); unit_assert(id::translateScanNumberToNativeID(MS_Bruker_Agilent_YEP_nativeID_format, "123") == id); unit_assert(id::translateScanNumberToNativeID(MS_Bruker_BAF_nativeID_format, "123") == id); unit_assert(id::translateNativeIDToScanNumber(MS_Thermo_nativeID_format, id) == ""); unit_assert(id::translateNativeIDToScanNumber(MS_spectrum_identifier_nativeID_format, id) == ""); unit_assert(id::translateNativeIDToScanNumber(MS_multiple_peak_list_nativeID_format, id) == ""); unit_assert(id::abbreviate(id) == "123"); unit_assert(id::abbreviate(id, ',') == "123"); id = "sample=1 period=2 cycle=123 experiment=3"; unit_assert(id::translateNativeIDToScanNumber(MS_WIFF_nativeID_format, id) == ""); unit_assert(id::translateScanNumberToNativeID(MS_WIFF_nativeID_format, "123") == ""); unit_assert(id::abbreviate(id) == "1.2.123.3"); unit_assert(id::abbreviate(id, ',') == "1,2,123,3"); } void testAllDataProcessing() { MSData msd; SpectrumListSimplePtr sl(new SpectrumListSimple); msd.run.spectrumListPtr = sl; DataProcessingPtr realDeal(new DataProcessing("dp")); DataProcessingPtr poser(new DataProcessing("dp")); msd.dataProcessingPtrs.push_back(realDeal); sl->dp = poser; // test allDataProcessingPtrs() vector all = msd.allDataProcessingPtrs(); unit_assert_operator_equal(1, all.size()); unit_assert_operator_equal(realDeal, all[0]); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { testSpectrumListSimple(); testChromatograms(); testIDParsing(); testAllDataProcessing(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/msdata/MSDataMerger.hpp0000664000175100017510000000222412664775621021712 0ustar teamcityteamcity00000000000000// // $Id: MSDataMerger.hpp 1814 2010-02-16 22:52:44Z chambm $ // // // Original author: Matt Chambers // // Copyright 2010 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _MSDATAMERGER_HPP_ #define _MSDATAMERGER_HPP_ #include "MSData.hpp" namespace pwiz { namespace msdata { struct PWIZ_API_DECL MSDataMerger : public MSData { MSDataMerger(const std::vector& inputs); private: std::vector inputMSDataPtrs_; }; } // namespace pwiz } // namespace msdata #endif // _MSDATAMERGER_HPP_ pwiz/pwiz/data/msdata/SpectrumListWrapper.hpp0000664000175100017510000000520012664775621023433 0ustar teamcityteamcity00000000000000// // $Id: SpectrumListWrapper.hpp 6585 2014-08-07 22:49:28Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLISTWRAPPER_HPP_ #define _SPECTRUMLISTWRAPPER_HPP_ #include "pwiz/data/msdata/MSData.hpp" #include namespace pwiz { namespace msdata { /// Inheritable pass-through implementation for wrapping a SpectrumList class PWIZ_API_DECL SpectrumListWrapper : public SpectrumList { public: SpectrumListWrapper(const SpectrumListPtr& inner) : inner_(inner), dp_(inner->dataProcessingPtr().get() ? new DataProcessing(*inner->dataProcessingPtr()) : new DataProcessing("pwiz_Spectrum_Processing")) { if (!inner.get()) throw std::runtime_error("[SpectrumListWrapper] Null SpectrumListPtr."); } virtual size_t size() const {return inner_->size();} virtual bool empty() const {return size() == 0;} virtual const SpectrumIdentity& spectrumIdentity(size_t index) const {return inner_->spectrumIdentity(index);} // no default implementation, because otherwise subclasses could override the DetailLevel overload and the getBinaryData overload would be inconsistent virtual SpectrumPtr spectrum(size_t index, bool getBinaryData = false) const = 0; virtual SpectrumPtr spectrum(size_t index, DetailLevel detailLevel) const {return spectrum(index, detailLevel == DetailLevel_FullData);} virtual const boost::shared_ptr dataProcessingPtr() const {return dp_;} SpectrumListPtr inner() const {return inner_;} SpectrumListPtr innermost() const { if(dynamic_cast(&*inner_)) return dynamic_cast(&*inner_)->innermost(); else return inner(); } protected: SpectrumListPtr inner_; DataProcessingPtr dp_; }; } // namespace msdata } // namespace pwiz #endif // _SPECTRUMLISTWRAPPER_HPP_ pwiz/pwiz/data/msdata/SpectrumWorkerThreads.hpp0000664000175100017510000000246612664775621023756 0ustar teamcityteamcity00000000000000// // $Id: SpectrumWorkerThreads.hpp 6585 2014-08-07 22:49:28Z chambm $ // // // Original author: William French // // Copyright 2014 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMWORKERTHREADS_HPP_ #define _SPECTRUMWORKERTHREADS_HPP_ #include "pwiz/data/msdata/MSData.hpp" #include namespace pwiz { namespace msdata { class SpectrumWorkerThreads { public: SpectrumWorkerThreads(const SpectrumList& sl); ~SpectrumWorkerThreads(); SpectrumPtr processBatch(size_t index, bool getBinaryData = true); private: class Impl; boost::scoped_ptr impl_; }; } // namespace msdata } // namespace pwiz #endif // _SPECTRUMWORKERTHREADS_HPP_ pwiz/pwiz/data/msdata/MSDataFile.hpp0000664000175100017510000000731312664775621021354 0ustar teamcityteamcity00000000000000// // $Id: MSDataFile.hpp 4009 2012-10-17 18:40:44Z kaipot $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _MSDATAFILE_HPP_ #define _MSDATAFILE_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "MSData.hpp" #include "Reader.hpp" #include "BinaryDataEncoder.hpp" #include "pwiz/utility/misc/IterationListener.hpp" namespace pwiz { namespace msdata { /// MSData object plus file I/O struct PWIZ_API_DECL MSDataFile : public MSData { /// constructs MSData object backed by file; /// reader==0 -> use DefaultReaderList MSDataFile(const std::string& filename, const Reader* reader = 0, bool calculateSourceFileChecksum = false); /// data format for write() enum PWIZ_API_DECL Format {Format_Text, Format_mzML, Format_mzXML, Format_MGF, Format_MS1, Format_CMS1, Format_MS2, Format_CMS2, Format_MZ5}; /// configuration for write() struct PWIZ_API_DECL WriteConfig { Format format; BinaryDataEncoder::Config binaryDataEncoderConfig; bool indexed; bool gzipped; // if true, file is written as .gz WriteConfig(Format _format = Format_mzML,bool _gzipped = false) : format(_format), indexed(true), gzipped(_gzipped) {} }; /// static write function for any MSData object; /// iterationListenerRegistry may be used for progress updates static void write(const MSData& msd, const std::string& filename, const WriteConfig& config = WriteConfig(), const pwiz::util::IterationListenerRegistry* iterationListenerRegistry = 0); /// member write function void write(const std::string& filename, const WriteConfig& config = WriteConfig(), const pwiz::util::IterationListenerRegistry* iterationListenerRegistry = 0); /// static write function for any MSData object; /// iterationListenerRegistry may be used for progress updates static void write(const MSData& msd, std::ostream& os, const WriteConfig& config = WriteConfig(), const pwiz::util::IterationListenerRegistry* iterationListenerRegistry = 0); /// member write function void write(std::ostream& os, const WriteConfig& config = WriteConfig(), const pwiz::util::IterationListenerRegistry* iterationListenerRegistry = 0); }; /// calculates and adds a CV term for the SHA1 checksum of a source file element PWIZ_API_DECL void calculateSourceFileSHA1(SourceFile& sourceFile); /// Iterate and calculate SHA-1 for all source files PWIZ_API_DECL void calculateSHA1Checksums(const MSData& msd); PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, MSDataFile::Format format); PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const MSDataFile::WriteConfig& config); } // namespace msdata } // namespace pwiz #endif // _MSDATAFILE_HPP_ pwiz/pwiz/data/msdata/Reader.cpp0000775000175100017510000001467212664775620020650 0ustar teamcityteamcity00000000000000// // $Id: Reader.cpp 9283 2016-01-11 21:31:03Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Reader.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace msdata { using namespace pwiz::util; Reader::Config::Config() : simAsSpectra(false) , srmAsSpectra(false) , acceptZeroLengthSpectra(false) , combineIonMobilitySpectra(false) , unknownInstrumentIsError(false) , adjustUnknownTimeZonesToHostTimeZone(true) { } /// copy constructor Reader::Config::Config(const Config& rhs) { simAsSpectra = rhs.simAsSpectra; srmAsSpectra = rhs.srmAsSpectra; acceptZeroLengthSpectra = rhs.acceptZeroLengthSpectra; combineIonMobilitySpectra = rhs.combineIonMobilitySpectra; unknownInstrumentIsError = rhs.unknownInstrumentIsError; adjustUnknownTimeZonesToHostTimeZone = rhs.adjustUnknownTimeZonesToHostTimeZone; } // default implementation; most Readers don't need to worry about multi-run input files PWIZ_API_DECL void Reader::readIds(const string& filename, const string& head, vector& results, const Config& config) const { MSData data; read(filename, head, data); results.push_back(data.id); } PWIZ_API_DECL std::string ReaderList::identify(const string& filename) const { return identify(filename, read_file_header(filename, 512)); } PWIZ_API_DECL std::string ReaderList::identify(const string& filename, const string& head) const { std::string result; for (const_iterator it=begin(); it!=end(); ++it) { result = (*it)->identify(filename, head); if (result.length()) { break; } } return result; } PWIZ_API_DECL void ReaderList::read(const string& filename, MSData& result, int sampleIndex /* = 0 */, const Config& config) const { read(filename, read_file_header(filename, 512), result, sampleIndex, config); } PWIZ_API_DECL void ReaderList::read(const string& filename, const string& head, MSData& result, int sampleIndex /* = 0 */, const Config& config) const { for (const_iterator it=begin(); it!=end(); ++it) if ((*it)->accept(filename, head)) { (*it)->read(filename, head, result, sampleIndex, config); return; } throw ReaderFail((" don't know how to read " + filename).c_str()); } PWIZ_API_DECL void ReaderList::read(const string& filename, vector& results, const Config& config) const { read(filename, read_file_header(filename, 512), results, config); } PWIZ_API_DECL void ReaderList::read(const string& filename, const string& head, vector& results, const Config& config) const { for (const_iterator it=begin(); it!=end(); ++it) if ((*it)->accept(filename, head)) { (*it)->read(filename, head, results, config); return; } throw ReaderFail((" don't know how to read " + filename).c_str()); } PWIZ_API_DECL void ReaderList::readIds(const string& filename, vector& results, const Config& config) const { readIds(filename, read_file_header(filename, 512), results, config); } PWIZ_API_DECL void ReaderList::readIds(const string& filename, const string& head, vector& results, const Config& config) const { for (const_iterator it=begin(); it!=end(); ++it) if ((*it)->accept(filename, head)) { (*it)->readIds(filename, head, results, config); return; } throw ReaderFail((" don't know how to read " + filename).c_str()); } PWIZ_API_DECL ReaderList& ReaderList::operator +=(const ReaderList& rhs) { insert(end(), rhs.begin(), rhs.end()); return *this; } PWIZ_API_DECL ReaderList& ReaderList::operator +=(const ReaderPtr& rhs) { push_back(rhs); return *this; } PWIZ_API_DECL ReaderList ReaderList::operator +(const ReaderList& rhs) const { ReaderList readerList(*this); readerList += rhs; return readerList; } PWIZ_API_DECL ReaderList ReaderList::operator +(const ReaderPtr& rhs) const { ReaderList readerList(*this); readerList += rhs; return readerList; } PWIZ_API_DECL ReaderList operator +(const ReaderPtr& lhs, const ReaderPtr& rhs) { ReaderList readerList; readerList.push_back(lhs); readerList.push_back(rhs); return readerList; } PWIZ_API_DECL CVID identifyFileFormat(const ReaderPtr& reader, const std::string& filepath) { try { string head = read_file_header(filepath, 512); string type = reader->identify(filepath, head); if (type == "mzML") return MS_mzML_format; else if (type == "mzXML") return MS_ISB_mzXML_format; else if (type == "MZ5") return MS_mz5_format; else if (type == "Mascot Generic") return MS_Mascot_MGF_format; else if (type == "MSn") return MS_MS2_format; else if (type == "ABSciex WIFF") return MS_ABI_WIFF_format; else if (type == "ABSciex T2D") return MS_SCIEX_TOF_TOF_T2D_format; else if (type == "Agilent MassHunter") return MS_Agilent_MassHunter_format; else if (type == "Thermo RAW") return MS_Thermo_RAW_format; else if (type == "Waters RAW") return MS_Waters_raw_format; else if (type == "Bruker FID") return MS_Bruker_FID_format; else if (type == "Bruker YEP") return MS_Bruker_Agilent_YEP_format; else if (type == "Bruker BAF") return MS_Bruker_BAF_format; } catch (exception&) { // the filepath is missing or inaccessible } return CVID_Unknown; } } // namespace msdata } // namespace pwiz pwiz/pwiz/data/msdata/BinaryDataEncoderTest.cpp0000664000175100017510000003754712664775621023630 0ustar teamcityteamcity00000000000000// // $Id: BinaryDataEncoderTest.cpp 5084 2013-10-28 23:32:24Z pcbrefugee $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "BinaryDataEncoder.hpp" #include "pwiz/utility/misc/unit.hpp" #include "boost/filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::msdata; namespace bfs = boost::filesystem; ostream* os_ = 0; double sampleData_[] = { 200.00018816645022000000, 0.00000000000000000000, 200.00043034083151000000, 0.00000000000000000000, 200.00067251579924000000, 0.00000000000000000000, 200.00091469135347000000, 0.00000000000000000000, 201.10647068550810000000, 0.00000000000000000000, 201.10671554643099000000, 0.00000000000000000000, 201.10696040795017000000, 0.00000000000000000000, 201.10720527006566000000, 0.00000000000000000000, 201.10745013277739000000, 908.68475341796875000000, 201.10769499608537000000, 1266.26928710937500000000, 201.10793985998967000000, 1258.11450195312500000000, 201.10818472449023000000, 848.79339599609375000000, 201.10842958958708000000, 0.00000000000000000000, 201.10867445528024000000, 0.00000000000000000000, 201.10891932156963000000, 0.0000000000000000000, 200, 0, 300, 1, 400, 10, 500, 100, 600, 1000, }; const int sampleDataSize_ = sizeof(sampleData_)/sizeof(double); // regression test strings const char* sampleEncoded32Big_ = "Q0gADAAAAABDSAAcAAAAAENIACwAAAAAQ0gAPAAAAABDSRtCAAAAAENJG1IAAAAAQ0kbYgAAAABDSRtyAAAAAENJG4JEYyvTQ0kbkkSeSJ5DSRuiRJ1DqkNJG7JEVDLHQ0kbwgAAAABDSRvSAAAAAENJG+IAAAAAQ0gAAAAAAABDlgAAP4AAAEPIAABBIAAAQ/oAAELIAABEFgAARHoAAA=="; const char* sampleEncoded32Little_ = "DABIQwAAAAAcAEhDAAAAACwASEMAAAAAPABIQwAAAABCG0lDAAAAAFIbSUMAAAAAYhtJQwAAAAByG0lDAAAAAIIbSUPTK2NEkhtJQ55InkSiG0lDqkOdRLIbSUPHMlREwhtJQwAAAADSG0lDAAAAAOIbSUMAAAAAAABIQwAAAAAAAJZDAACAPwAAyEMAACBBAAD6QwAAyEIAABZEAAB6RA=="; const char* sampleEncoded64Little_ = "/xedigEAaUAAAAAAAAAAAIV5fYYDAGlAAAAAAAAAAACkK16CBQBpQAAAAAAAAAAAXy4/fgcAaUAAAAAAAAAAAK4HNjVoI2lAAAAAAAAAAACrvLg2aiNpQAAAAAAAAAAAnMM7OGwjaUAAAAAAAAAAAIIcvzluI2lAAAAAAAAAAABax0I7cCNpQAAAAGB6ZYxAJcTGPHIjaUAAAADAE8mTQOUSSz50I2lAAAAAQHWok0CYs88/diNpQAAAAOBYhopAP6ZUQXgjaUAAAAAAAAAAANvq2UJ6I2lAAAAAAAAAAABpgV9EfCNpQAAAAAAAAAAAAAAAAAAAaUAAAAAAAAAAAAAAAAAAwHJAAAAAAAAA8D8AAAAAAAB5QAAAAAAAACRAAAAAAABAf0AAAAAAAABZQAAAAAAAwIJAAAAAAABAj0A="; const char* sampleEncoded64Big_ = "QGkAAYqdF/8AAAAAAAAAAEBpAAOGfXmFAAAAAAAAAABAaQAFgl4rpAAAAAAAAAAAQGkAB34/Ll8AAAAAAAAAAEBpI2g1NgeuAAAAAAAAAABAaSNqNri8qwAAAAAAAAAAQGkjbDg7w5wAAAAAAAAAAEBpI245vxyCAAAAAAAAAABAaSNwO0LHWkCMZXpgAAAAQGkjcjzGxCVAk8kTwAAAAEBpI3Q+SxLlQJOodUAAAABAaSN2P8+zmECKhljgAAAAQGkjeEFUpj8AAAAAAAAAAEBpI3pC2erbAAAAAAAAAABAaSN8RF+BaQAAAAAAAAAAQGkAAAAAAAAAAAAAAAAAAEBywAAAAAAAP/AAAAAAAABAeQAAAAAAAEAkAAAAAAAAQH9AAAAAAABAWQAAAAAAAECCwAAAAAAAQI9AAAAAAAA="; const char* sampleEncoded32LittleZlib_ = "eJzjYfBwZgACGSitA6VtoLSTtCeYDoLSSVC6CEo3AenL2skuk4D0PI95LouA9CrnuS6bgPRxoxCXQ1B1l6D0IyjNADWfgWEakG6wZ2A4AaQVHBkYfgHpE04MDGIuDAxVLgB7LB3q"; const char* sampleEncoded32BigZlib_ = "eJxz9mDgYQACZw8GGSitA6VtwLSntBOUDoLSSVC6CEo3uSRrXwbSk1zmecwD0otc5jqvAtKbXEKMjgPpQ1B1l6D0I6j5YOA8jYHBvgFIn2BgcFQA0r8YGJyAbBcxIK5iYAAAfLkd6g=="; const char* sampleEncoded64LittleZlib_ = "eJz7Lz63i5Eh04EBClora9uYkfhLtOOaWJH48Xr2dexI/HXsZqYZygj+6j07zLKQ+HMOW1vkIPGbZPZb5iHxo447WRdA+AlVqT0OqkeO2RRB+AeET052eCrkbVcC4TuUrpjsMGPzefsyCP9BRFuXg/2yEMcKJPNuv7rpVIXEz2yMd6lB4kNFUfkHiqD8D/YQuhLKV4HQDvVQfiSEPtAEFe93AACmsz1+"; const char* sampleEncoded64BigZlib_ = "eJxzyGRg7Jor/p8BChwyGZjbaitbkfisTXHaS5D47HX2evEIvnKGqRn7OiR+ltmOPauR+DkW1ofnIPHzLPfLNCHxC6ydjkc59KRWJUD4RTbHjqg6TD4pfADCL7HzFnrqMHlFqQOEX2Z/fvMMh662iAcQfoVjyDJ7JPOqnG6+uo3Er3GJb8xEcj8KcCg6AKbtP0D5lVBaBUrXO0DoSCi/CaLeoR8iDgC0Qj1+"; const char* sampleEncodedNumpressLinear_ = "QS69PAAAAAAu7AEMAAAAAA9J0wgQ61LPfgY70wgQbTLPfg4d0wgQ7hLPfgMM1BgQwGKtfgvq1SgQ4UKtfgjc1SgQIyKtfgXO1SgQRAKtfgKw5SgQ78OG4QNVqQugf3Tmpg+6yRCARe2G9wiYdBGAecaFZgs+qjKwizv8oQVa5SgQS0GtfgJM5SgQjCGtfgwC5BgQApLPfgicxA4Q5MmQzQzK9+kgoDYaDQAvNdQwS+AZrAhzqAY5hKD/kA=="; const char* sampleEncodedNumpressLinearZlib_ = "eJxz1NtrwwAEem8YeUA0v+dlDoHXQefr2KyBjFyj83V8skDGO6Hzdcw8VyQEDiStreN+dVVD4KHT2jqOO0CGstLaOtZzQIYL09o6pg1PNQTeH257yBy6kntBfcmzZfy7Tgo0uL5t+84xo0SwofJYaxq33SqjDd3WfxayRgEVezsCdfkAGT2Ka+t4mJ5ICDBNOl/HMecIn8CTkxPO8pz6/lJhgZkUL4O+6RUD7weSaziKV7BZtiz4PwEAkp1KXg=="; const char* sampleEncodedNumpressSlof_ = "QMHqAAAAAAACvgAAAr4AAAK+AAACvgAANL4AADS+AAA0vgAANL4AADS+GvQ0vvr/NL6//zS+qfE0vgAANL4AADS+AAACvgAAeszWGMHW6VW73lqlQOWH9w=="; const char* sampleEncodedNumpressSlofZlib_ = "eJxzOPiKAQSY9qFiEwws9cVk36//Jvv2A/HKj8hyIPVVZ65JHLz2MnT3vailDk/bvwMAn1ogtQ=="; const char* sampleEncodedNumpressPic_ = "aMhoyGjIaMhpyGnIachpyGnF2DacUvRpxa5GnFFTachpyGnIaMhcIXFQkXpU8WRlhSWOMA=="; const char* sampleEncodedNumpressPicZlib_ = "eJzLOJEBhpkwePSG2ZygL5lH17nNCQyGiGWciFEsDJhYFfIxJbVVtc8AAAjsG4c="; const char* sampleEncodedModified64BigZlib_ = "eJxzyGRg7Jor/r/+/X8wcMhkYG6rrWz9j+CzNsVpL6m/D+ez19nrxf+H85UzTM3Y1zFAAZCfZbZjz2okfo6F9eE5SPw8y/0yTUj8Amun41EOPalVCRB+kc2xI6oOk08KH4DwS+y8hZ46TF5R6gDhl9mf3zzDoast4gGEX+EYssweybwqp5uvbiPxa1ziGzMRfAYU4FB0AEzbf4DyK6G0CpSud4DQkVB+E0S9Qz9EHACREFv+"; const char* regressionTest(const BinaryDataEncoder::Config& config,bool expectNumpressIgnored) { if (expectNumpressIgnored) // when set, expecting numpress not to be used even though it was requested { return sampleEncodedModified64BigZlib_; } else { if (config.numpress == BinaryDataEncoder::Numpress_Linear) return (BinaryDataEncoder::Compression_Zlib==config.compression)?sampleEncodedNumpressLinearZlib_:sampleEncodedNumpressLinear_; if (config.numpress == BinaryDataEncoder::Numpress_Pic) return (BinaryDataEncoder::Compression_Zlib==config.compression)?sampleEncodedNumpressPicZlib_:sampleEncodedNumpressPic_; if (config.numpress == BinaryDataEncoder::Numpress_Slof) return (BinaryDataEncoder::Compression_Zlib==config.compression)?sampleEncodedNumpressSlofZlib_:sampleEncodedNumpressSlof_; } if (config.precision == BinaryDataEncoder::Precision_32 && config.byteOrder == BinaryDataEncoder::ByteOrder_LittleEndian && config.compression == BinaryDataEncoder::Compression_None) return sampleEncoded32Little_; if (config.precision == BinaryDataEncoder::Precision_32 && config.byteOrder == BinaryDataEncoder::ByteOrder_BigEndian && config.compression == BinaryDataEncoder::Compression_None) return sampleEncoded32Big_; if (config.precision == BinaryDataEncoder::Precision_64 && config.byteOrder == BinaryDataEncoder::ByteOrder_LittleEndian && config.compression == BinaryDataEncoder::Compression_None) return sampleEncoded64Little_; if (config.precision == BinaryDataEncoder::Precision_64 && config.byteOrder == BinaryDataEncoder::ByteOrder_BigEndian && config.compression == BinaryDataEncoder::Compression_None) return sampleEncoded64Big_; if (config.precision == BinaryDataEncoder::Precision_32 && config.byteOrder == BinaryDataEncoder::ByteOrder_LittleEndian && config.compression == BinaryDataEncoder::Compression_Zlib) return sampleEncoded32LittleZlib_; if (config.precision == BinaryDataEncoder::Precision_32 && config.byteOrder == BinaryDataEncoder::ByteOrder_BigEndian && config.compression == BinaryDataEncoder::Compression_Zlib) return sampleEncoded32BigZlib_; if (config.precision == BinaryDataEncoder::Precision_64 && config.byteOrder == BinaryDataEncoder::ByteOrder_LittleEndian && config.compression == BinaryDataEncoder::Compression_Zlib) return sampleEncoded64LittleZlib_; if (config.precision == BinaryDataEncoder::Precision_64 && config.byteOrder == BinaryDataEncoder::ByteOrder_BigEndian && config.compression == BinaryDataEncoder::Compression_Zlib) return sampleEncoded64BigZlib_; throw runtime_error("[BinaryDataEncoderTest::regressionTest()] Untested configuration."); } void testConfiguration(const BinaryDataEncoder::Config& config_in) { BinaryDataEncoder::Config config(config_in); if (os_) *os_ << "testConfiguration: " << config << endl; // initialize scan data vector binary(sampleDataSize_); copy(sampleData_, sampleData_+sampleDataSize_, binary.begin()); bool checkNumpressMaxErrorSupression = (BinaryDataEncoder::Numpress_None != config.numpress)&&(config.numpressLinearErrorTolerance>0); if (checkNumpressMaxErrorSupression) { binary[1] = numeric_limits::max( )-.1; // attempt to blow out the numpress lossiness limiter binary[3] = -binary[1]; // attempt to blow out the numpress lossiness limiter binary[5] = .5*binary[1]; // attempt to blow out the numpress lossiness limiter binary[7] = .5*binary[3]; // attempt to blow out the numpress lossiness limiter } if (os_) { *os_ << "original: " << binary.size() << endl; *os_ << setprecision(20) << fixed; copy(binary.begin(), binary.end(), ostream_iterator(*os_, "\n")); } // instantiate encoder BinaryDataEncoder encoder(config); // encode string encoded; encoder.encode(binary, encoded); if (os_) *os_ << "encoded: " << encoded.size() << endl << encoded << endl; // regression testing for encoding unit_assert(encoded == regressionTest(config,checkNumpressMaxErrorSupression)); // decode vector decoded; encoder.decode(encoded, decoded); if (os_) { *os_ << "decoded: " << decoded.size() << endl; copy(decoded.begin(), decoded.end(), ostream_iterator(*os_, "\n")); } // validate by comparing scan data before/after encode/decode unit_assert(binary.size() == decoded.size()); const double epsilon = config.precision == BinaryDataEncoder::Precision_64 ? 1e-14 : 1e-5 ; switch (config.numpress) { case BinaryDataEncoder::Numpress_Linear: case BinaryDataEncoder::Numpress_Slof: case BinaryDataEncoder::Numpress_Pic: // lossy compression for (vector::const_iterator it=binary.begin(), jt=decoded.begin(); it!=binary.end(); ++it, ++jt) { if (0==*it || 0==*jt) unit_assert_equal(*it, *jt, 0.1); else if (*it > *jt) unit_assert((*jt)/(*it) > .999 ); else unit_assert((*it)/(*jt) > .999 ); } break; default: for (vector::const_iterator it=binary.begin(), jt=decoded.begin(); it!=binary.end(); ++it, ++jt) { unit_assert_equal(*it, *jt, epsilon); } break; } if (os_) *os_ << "validated with epsilon: " << fixed << setprecision(1) << scientific << epsilon << "\n\n"; } void test() { BinaryDataEncoder::Config config; config.precision = BinaryDataEncoder::Precision_32; config.byteOrder = BinaryDataEncoder::ByteOrder_LittleEndian; testConfiguration(config); config.precision = BinaryDataEncoder::Precision_32; config.byteOrder = BinaryDataEncoder::ByteOrder_BigEndian; testConfiguration(config); config.precision = BinaryDataEncoder::Precision_64; config.byteOrder = BinaryDataEncoder::ByteOrder_LittleEndian; testConfiguration(config); config.precision = BinaryDataEncoder::Precision_64; config.byteOrder = BinaryDataEncoder::ByteOrder_BigEndian; testConfiguration(config); config.precision = BinaryDataEncoder::Precision_32; config.byteOrder = BinaryDataEncoder::ByteOrder_LittleEndian; config.compression = BinaryDataEncoder::Compression_Zlib; testConfiguration(config); config.precision = BinaryDataEncoder::Precision_32; config.byteOrder = BinaryDataEncoder::ByteOrder_BigEndian; config.compression = BinaryDataEncoder::Compression_Zlib; testConfiguration(config); config.precision = BinaryDataEncoder::Precision_64; config.byteOrder = BinaryDataEncoder::ByteOrder_LittleEndian; config.compression = BinaryDataEncoder::Compression_Zlib; testConfiguration(config); config.precision = BinaryDataEncoder::Precision_64; config.byteOrder = BinaryDataEncoder::ByteOrder_BigEndian; config.compression = BinaryDataEncoder::Compression_Zlib; testConfiguration(config); // test the numpress stuff with and without zlib, and to see if it honors error limits config.compression = BinaryDataEncoder::Compression_None; config.numpressLinearErrorTolerance = 0; // means don't do tolerance checks config.numpressSlofErrorTolerance = 0; // means don't do tolerance checks for (int zloop=3;zloop--;) { config.numpress = BinaryDataEncoder::Numpress_Linear; testConfiguration(config); config.numpress = BinaryDataEncoder::Numpress_Slof; testConfiguration(config); config.numpress = BinaryDataEncoder::Numpress_Pic; testConfiguration(config); config.compression = BinaryDataEncoder::Compression_Zlib; // and again with zlib if (1==zloop) // and finally test numpress excessive error avoidance { config.numpressLinearErrorTolerance = .01; config.numpressSlofErrorTolerance = .01; } } } void testBadFile(const string& filename) { if (os_) *os_ << "testBadFile: " << filename << flush; size_t filesize = 0; try { filesize = (size_t) bfs::file_size(filename); } catch (exception&) { cerr << "\nUnable to find file " << filename << endl; return; } if (os_) *os_ << " (" << filesize << " bytes)\n"; unit_assert(filesize%sizeof(double) == 0); // read data from file into memory vector data(filesize/sizeof(double)); ifstream is(filename.c_str(), ios::binary); is.read((char*)&data[0], filesize); // set configuration to produce the error BinaryDataEncoder::Config config; if (filename.find("BinaryDataEncoderTest.bad.bin")!=string::npos) { // zlib compression encoding error with this configuration config.precision = BinaryDataEncoder::Precision_32; config.byteOrder = BinaryDataEncoder::ByteOrder_LittleEndian; config.compression = BinaryDataEncoder::Compression_Zlib; } // encode and decode BinaryDataEncoder encoder(config); string encoded; encoder.encode(data, encoded); vector decoded; encoder.decode(encoded, decoded); // verify unit_assert(decoded.size() == data.size()); for (size_t i=0; i filenames; for (int i=1; i // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_MSn.hpp" #include "References.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/chemistry/Chemistry.hpp" #include "zlib.h" #include namespace pwiz { namespace msdata { using boost::iostreams::stream_offset; using boost::iostreams::offset_to_position; using namespace pwiz::chemistry; namespace { // these are the fixed sizes used to write .bms1, .cms1, .bms2, and .cms2 files // use these to read from files rather than sizeof() const int sizeIntMSn = 4; const int sizeFloatMSn = 4; const int sizeDoubleMSn = 8; const int sizeChargeMSn = 12; // struct Charge{ int z; double mass; } const int sizeEzMSn = 20; // struct EZState{ int z; double mass; float rTime; float area; } const int sizePeakMSn = 12; // struct Peak{ double mz; float intensity; } struct MSnScanInfo { int scanNumber; double mz; float rTime; float basePeakIntensity; double basePeakMz; double conversionFactorA; double conversionFactorB; double TIC; float ionInjectionTime; int numPeaks; int numChargeStates; int numEzStates; MSnScanInfo(): scanNumber(-1), mz(-1), rTime(-1), basePeakIntensity(-1), basePeakMz(-1), conversionFactorA(-1), conversionFactorB(-1), TIC(-1), ionInjectionTime(-1), numPeaks(-1), numChargeStates(-1), numEzStates(0) {} void readSpectrumHeader(boost::shared_ptr is, int version) { (*is).read(reinterpret_cast(&scanNumber), sizeIntMSn); (*is).read(reinterpret_cast(&scanNumber), sizeIntMSn); // yes, there are two (*is).read(reinterpret_cast(&mz), sizeDoubleMSn); (*is).read(reinterpret_cast(&rTime), sizeFloatMSn); if( version >= 2 ) { (*is).read(reinterpret_cast(&basePeakIntensity), sizeFloatMSn); (*is).read(reinterpret_cast(&basePeakMz), sizeDoubleMSn); (*is).read(reinterpret_cast(&conversionFactorA), sizeDoubleMSn); (*is).read(reinterpret_cast(&conversionFactorB), sizeDoubleMSn); (*is).read(reinterpret_cast(&TIC), sizeDoubleMSn); (*is).read(reinterpret_cast(&ionInjectionTime), sizeFloatMSn); } (*is).read(reinterpret_cast(&numChargeStates), sizeIntMSn); if( version == 3 ) { (*is).read(reinterpret_cast(&numEzStates), sizeIntMSn); } (*is).read(reinterpret_cast(&numPeaks), sizeIntMSn); }; }; class SpectrumList_MSnImpl : public SpectrumList_MSn { public: SpectrumList_MSnImpl(shared_ptr is, const MSData& msd, MSn_Type filetype) : is_(is), msd_(msd), version_(0), filetype_(filetype) { switch( filetype_){ case MSn_Type_MS1: case MSn_Type_MS2: createIndexText(); break; case MSn_Type_BMS1: case MSn_Type_CMS1: case MSn_Type_BMS2: case MSn_Type_CMS2: createIndexBinary(); break; case MSn_Type_UNKNOWN: throw runtime_error("[SpectrumList_MSn::constructor] Cannot create index for unknown MSn file type."); } } size_t size() const {return index_.size();} const SpectrumIdentity& spectrumIdentity(size_t index) const { return index_[index]; } size_t find(const string& id) const { map::const_iterator it = idToIndex_.find(id); return it != idToIndex_.end() ? it->second : size(); } size_t findNative(const string& nativeID) const { size_t index; try { index = lexical_cast(nativeID); } catch (boost::bad_lexical_cast&) { throw runtime_error("[SpectrumList_MSn::findNative] invalid nativeID format (expected a positive integer)"); } if (index < size()) return index; else return size(); } SpectrumPtr spectrum(size_t index, bool getBinaryData) const { boost::lock_guard lock(readMutex); // lock_guard will unlock mutex when out of scope or when exception thrown (during destruction) if (index > index_.size()) throw runtime_error("[SpectrumList_MSn::spectrum] Index out of bounds"); // allocate Spectrum object and read it in SpectrumPtr result(new Spectrum); if (!result.get()) throw runtime_error("[SpectrumList_MSn::spectrum] Out of memory"); result->index = index; result->sourceFilePosition = index_[index].sourceFilePosition; is_->seekg(bio::offset_to_position(result->sourceFilePosition)); if (!*is_) throw runtime_error("[SpectrumList_MSn::spectrum] Error seeking to spectrum index " + lexical_cast(index)); if( filetype_ == MSn_Type_MS1 || filetype_ == MSn_Type_MS2 ){ parseSpectrumText(*result, getBinaryData); }else{ parseSpectrumBinary(*result, getBinaryData); } // resolve any references into the MSData object References::resolve(*result, msd_); return result; } private: shared_ptr is_; const MSData& msd_; vector index_; map idToIndex_; int version_; // read from fileheader for bms1, cms1, bms2, and cms2 filetypes MSn_Type filetype_; mutable boost::mutex readMutex; void parseSpectrumText(Spectrum& spectrum, bool getBinaryData) const { // Every MS1/MS2 spectrum is assumed to be: // * MSn spectrum // * MS level // * a peak list (centroided) // * not deisotoped (even though it may actually be, there's no way to tell) bool ms1File = MSn_Type_MS1 == filetype_ || MSn_Type_BMS1 == filetype_ || MSn_Type_CMS1 == filetype_; spectrum.set(MS_MSn_spectrum); spectrum.set(MS_ms_level, (ms1File ? 1 : 2)); spectrum.set(MS_centroid_spectrum); if (!ms1File) { spectrum.precursors.push_back(Precursor()); Precursor& precursor = spectrum.precursors.back(); precursor.selectedIons.push_back(SelectedIon()); } string lineStr; bool inPeakList = false; double lowMZ = std::numeric_limits::max(); double highMZ = 0; double tic = 0; double basePeakMZ = 0; double basePeakIntensity = 0; spectrum.defaultArrayLength = 0; spectrum.setMZIntensityArrays(vector(), vector(), MS_number_of_detector_counts); vector& mzArray = spectrum.getMZArray()->data; vector& intensityArray = spectrum.getIntensityArray()->data; double precursor_mz = 0; // start reading the file if( getline(*is_, lineStr) ) // not end of file { // confirm that the first line is an S line if (lineStr.find("S") != 0) { throw runtime_error(("[SpectrumList_MSn::parseSpectrum] S line found mixed " "with other S/Z/I/D lines at offset " + lexical_cast(size_t(is_->tellg())-lineStr.length()-1) + "\n")); } // read in the scan number size_t first_num_pos = lineStr.find_first_of("123456789"); size_t second_space_pos = lineStr.find_first_of(" \t", first_num_pos); int scanNum = lexical_cast(lineStr.substr(first_num_pos, second_space_pos-first_num_pos)); spectrum.id = "scan=" + lexical_cast(scanNum); // read in the precursor mz if (!ms1File) { size_t last_num_pos = lineStr.find_last_of("0123456789"); size_t last_space_pos = lineStr.find_last_of(" \t", last_num_pos); precursor_mz = lexical_cast(lineStr.substr(last_space_pos+1, last_num_pos-last_space_pos)); // store precursor in the first selected ion if we do not have accurate mass data (below) Precursor& precursor = spectrum.precursors.back(); precursor.isolationWindow.set(MS_isolation_window_target_m_z, precursor_mz, MS_m_z); } } else // eof, exit { // clean up? return; } // We may have multiple charges, so build a list vector charges; // and we may have multiple charges with accurate mass vector< pair > chargeMassPairs; // read in remainder of spectrum while (getline(*is_, lineStr)) { if (lineStr.find("S") == 0) // we are at the next spectrum { // if (!inPeakList) // the spec had no peaks, clean up? break; // stop reading file } else if (lineStr.find("Z") == 0) { if (ms1File) { throw runtime_error(("[SpectrumList_MSn::parseSpectrum] Z line found in MS1 file at offset " + lexical_cast(size_t(is_->tellg())-lineStr.length()-1) + "\n")); } if (inPeakList) { throw runtime_error(("[SpectrumList_MSn::parseSpectrum] Z line found without S line at offset " + lexical_cast(size_t(is_->tellg())-lineStr.length()-1) + "\n")); } // This is where we would get the charge state, but unless the file // has been processed for charge state determination (e.g. Hardklor), // it's not really known. Thus, we need to use "possible charges". size_t first_space_pos = lineStr.find_first_of(" \t"); size_t first_num_pos = lineStr.find_first_of("0123456789", first_space_pos); size_t next_space_pos = lineStr.find_first_of(" \t", first_num_pos); int charge = lexical_cast(lineStr.substr(first_num_pos, next_space_pos-first_num_pos)); charges.push_back(charge); size_t last_num_pos = lineStr.find_last_of("0123456789"); size_t last_space_pos = lineStr.find_last_of(" \t", last_num_pos); double z_precursor_mz = calculateMassOverCharge( lexical_cast(lineStr.substr(last_space_pos+1, last_num_pos-last_space_pos)), charge, 1); stringstream ss; ss << charge << ' ' << z_precursor_mz; // Store Z line information in UserParams, in the format " " spectrum.userParams.push_back(UserParam("ms2 file charge state", ss.str())); } else if (lineStr.find("I") == 0) { if (inPeakList) { throw runtime_error(("[SpectrumList_MSn::parseSpectrum] I line found without S line at offset " + lexical_cast(size_t(is_->tellg())-lineStr.length()-1) + "\n")); } // else if(lineStr.find("RTime") != string::npos) { // get the retention time size_t last_num_pos = lineStr.find_last_of("0123456789"); size_t last_space_pos = lineStr.find_last_of(" \t", last_num_pos); size_t len = last_num_pos - last_space_pos; double rt = lexical_cast(lineStr.substr(last_space_pos + 1, len)); spectrum.scanList.scans.push_back(Scan()); spectrum.scanList.scans.back().set(MS_scan_start_time, rt*60, UO_second); } else if (lineStr.find("EZ") != string::npos) { // get the charge and mass pair size_t num_start_pos = lineStr.find_first_of("123456789"); size_t next_space_pos = lineStr.find_first_of(" \t", num_start_pos); size_t len = next_space_pos - num_start_pos; int charge = lexical_cast(lineStr.substr(num_start_pos, len)); num_start_pos = lineStr.find_first_of("0123456789", next_space_pos); next_space_pos = lineStr.find_first_of(" \t", num_start_pos); len = next_space_pos - num_start_pos; double mass = lexical_cast(lineStr.substr(num_start_pos, len)); chargeMassPairs.push_back(pair(charge, mass)); } } else if (lineStr.find("D") == 0) { // ignore D lines for now if (inPeakList) { throw runtime_error(("[SpectrumList_MSn::parseSpectrum] D line found without S line at offset " + lexical_cast(size_t(is_->tellg())-lineStr.length()-1) + "\n")); } } else { inPeakList = true; // always parse the peaks (intensity must be summed to build TIC) size_t delim = lineStr.find_first_of(" \t"); if(delim == string::npos) { continue; } size_t delim2 = lineStr.find_first_not_of(" \t", delim+1); if(delim2 == string::npos) { continue; } size_t delim3 = lineStr.find_first_of(" \t\r\n", delim2); if(delim3 == string::npos) { delim3 = lineStr.length(); } double mz = lexical_cast(lineStr.substr(0, delim)); double inten = lexical_cast(lineStr.substr(delim2, delim3-delim2)); tic += inten; if (inten > basePeakIntensity) { basePeakMZ = mz; basePeakIntensity = inten; } lowMZ = std::min(lowMZ, mz); highMZ = std::max(highMZ, mz); ++spectrum.defaultArrayLength; if (getBinaryData) { mzArray.push_back(mz); intensityArray.push_back(inten); } }// header vs peaks }// read next line // if we got to the end of the file, clear the eof bit and return to beginning of file if( is_->eof() ){ is_->clear(); is_->seekg(0); } if (!ms1File) { Precursor& precursor = spectrum.precursors.back(); // if no accurate masses, set charge as possible if (chargeMassPairs.empty()) { size_t numCharges = charges.size(); for (size_t i = 0; i < numCharges; i++) { precursor.selectedIons.back().cvParams.push_back(CVParam(MS_possible_charge_state, charges[i])); } precursor.selectedIons.back().set(MS_selected_ion_m_z, precursor_mz, MS_m_z); } else // create a new selected ion for each charge,mass pair { for(size_t i=0; i < chargeMassPairs.size(); i++) { const pair& chargeMass = chargeMassPairs.at(i); precursor.selectedIons.back().cvParams.push_back(CVParam(MS_charge_state, chargeMass.first)); precursor.selectedIons.back().cvParams.push_back(CVParam(MS_accurate_mass_OBSOLETE, chargeMass.second)); precursor.selectedIons.back().set(MS_selected_ion_m_z, calculateMassOverCharge(chargeMass.second, chargeMass.first, 1), // this is a singly charged mass MS_m_z); precursor.selectedIons.push_back(SelectedIon()); } // last ion added has no data precursor.selectedIons.pop_back(); } } spectrum.set(MS_lowest_observed_m_z, lowMZ); spectrum.set(MS_highest_observed_m_z, highMZ); spectrum.set(MS_total_ion_current, tic); spectrum.set(MS_base_peak_m_z, basePeakMZ); spectrum.set(MS_base_peak_intensity, basePeakIntensity); } // Calcualte m/z given mass (neutral or charged) and charge double calculateMassOverCharge(double mass, int charge, int charges_on_mass /* = 0 for neutral mass */) const { double neutralMass = mass - (charges_on_mass * Proton); double mz = (neutralMass + (charge * Proton)) / charge; return mz; } void parseSpectrumBinary(Spectrum& spectrum, bool getBinaryData) const { // Every MSn spectrum is assumed to be: // * MSn spectrum // * MS level // * a peak list (centroided) // * not deisotoped (even though it may actually be, there's no way to tell) bool ms1File = MSn_Type_MS1 == filetype_ || MSn_Type_BMS1 == filetype_ || MSn_Type_CMS1 == filetype_; spectrum.set(MS_MSn_spectrum); spectrum.set(MS_ms_level, (ms1File ? 1 : 2)); spectrum.set(MS_centroid_spectrum); MSnScanInfo scanInfo; scanInfo.readSpectrumHeader(is_, version_); if (!ms1File) { spectrum.precursors.push_back(Precursor()); Precursor& precursor = spectrum.precursors.back(); precursor.selectedIons.push_back(SelectedIon()); precursor.isolationWindow.set(MS_isolation_window_target_m_z, scanInfo.mz, MS_m_z); } spectrum.id = "scan=" + lexical_cast(scanInfo.scanNumber); // read in all the charge state information before adding it to the spectrum // get charge states from equivalent of Z lines int charge = 0; vector charges; double mass = 0; if (!ms1File) { Precursor& precursor = spectrum.precursors.back(); for(int i=0; i(&charge), sizeIntMSn); charges.push_back(charge); (*is_).read(reinterpret_cast(&mass), sizeDoubleMSn); } // if there is no extended charge information, add the (possible) charges if( scanInfo.numEzStates == 0 ) { for(int i=0; i(&eCharge), sizeIntMSn); (*is_).read(reinterpret_cast(&eMass), sizeDoubleMSn); (*is_).read(reinterpret_cast(&pRTime), sizeFloatMSn); (*is_).read(reinterpret_cast(&pArea), sizeFloatMSn); // store each charge and accurate mass as a separate selected ion precursor.selectedIons.back().cvParams.push_back(CVParam(MS_charge_state, eCharge)); precursor.selectedIons.back().cvParams.push_back(CVParam(MS_accurate_mass_OBSOLETE, eMass)); precursor.selectedIons.back().set(MS_selected_ion_m_z, calculateMassOverCharge(eMass, eCharge, 1), MS_m_z); precursor.selectedIons.push_back(SelectedIon()); } // last ion added was not populated precursor.selectedIons.pop_back(); } } // get retention time spectrum.scanList.scans.push_back(Scan()); spectrum.scanList.scans.back().set(MS_scan_start_time, scanInfo.rTime*60, UO_second); double* mzs = NULL; float* intensities = NULL; if( filetype_ == MSn_Type_CMS1 || filetype_ == MSn_Type_CMS2 )// get compression info { int iTemp; // get length of compressed array of m/z (*is_).read(reinterpret_cast(&iTemp), sizeIntMSn); uLong mzLen = (unsigned long)iTemp; // get length of compressed array of intensities (*is_).read(reinterpret_cast(&iTemp), sizeIntMSn); uLong intensityLen = (unsigned long)iTemp; // allocate a buffer for storing the compressed data from file Byte* compressedData = new Byte[mzLen]; // allocate a buffer for the uncompressed version mzs = new double[scanInfo.numPeaks]; uLong uncompressedLen = scanInfo.numPeaks * sizeDoubleMSn; (*is_).read(reinterpret_cast(compressedData), mzLen); int success = uncompress((Bytef*)mzs, &uncompressedLen, compressedData, mzLen); if( success != Z_OK ) throw runtime_error("[SpectrumList_MSn::parseSpectrum] Error uncompressing peaks."); // repeat for intensities delete [] compressedData; compressedData = new Byte[intensityLen]; intensities = new float[scanInfo.numPeaks]; uncompressedLen = scanInfo.numPeaks * sizeFloatMSn; (*is_).read(reinterpret_cast(compressedData), intensityLen); success = uncompress((Bytef*)intensities, &uncompressedLen, compressedData, intensityLen); if( success != Z_OK ) throw runtime_error("[SpectrumList_MSn::parseSpectrum] Error uncompressing peaks."); delete [] compressedData; } // always get the peaks to find lowMZ, highMZ double lowMZ = std::numeric_limits::max(); double highMZ = 0; double tic = 0; double basePeakMZ = 0; // we may already have these but we have to read the peaks anyway... double basePeakIntensity = 0; spectrum.defaultArrayLength = 0; spectrum.setMZIntensityArrays(vector(), vector(), MS_number_of_detector_counts); vector& mzArray = spectrum.getMZArray()->data; vector& intensityArray = spectrum.getIntensityArray()->data; double mz = 0; float intensity = 0; for(int i=0; i(&mz), sizeDoubleMSn); (*is_).read(reinterpret_cast(&intensity), sizeFloatMSn); } tic += intensity; if( intensity > basePeakIntensity) { basePeakMZ = mz; basePeakIntensity = intensity; } lowMZ = std::min(lowMZ, mz); highMZ = std::max(highMZ, mz); ++spectrum.defaultArrayLength; if (getBinaryData) { mzArray.push_back(mz); intensityArray.push_back(intensity); } }// next peak // done reading the file delete [] intensities; delete [] mzs; spectrum.set(MS_lowest_observed_m_z, lowMZ); spectrum.set(MS_highest_observed_m_z, highMZ); spectrum.set(MS_total_ion_current, tic); spectrum.set(MS_base_peak_m_z, basePeakMZ); spectrum.set(MS_base_peak_intensity, basePeakIntensity); } void createIndexText() { string lineStr; size_t lineCount = 0; map::iterator curIdToIndexItr; while (getline(*is_, lineStr)) { ++lineCount; if (lineStr.find("S") == 0) { // beginning of spectrum, get the scan number // format: 'S ' int scanNum = 0; if( sscanf(lineStr.c_str(), "S %d", &scanNum) != 1 ){ throw runtime_error(("[SpectrumList_MSn::createIndex] Did not find scan number at offset " + lexical_cast(size_t(is_->tellg())-lineStr.length()-1) + ": " + lineStr + "\n")); } // create a new SpectrumIdentity and put it on the list index_.push_back(SpectrumIdentity()); // get a pointer to the current identity SpectrumIdentity& curIdentity = index_.back(); curIdentity.index = index_.size()-1; curIdentity.id = "scan=" + lexical_cast(scanNum); curIdentity.sourceFilePosition = size_t(is_->tellg())-lineStr.length()-1; curIdToIndexItr = idToIndex_.insert(pair(curIdentity.id, index_.size()-1)).first; } }// next line is_->clear(); is_->seekg(0); } void createIndexBinary() { map::iterator curIdToIndexItr; // header information int intFileType = 0; MSnHeader header; (*is_).read(reinterpret_cast(&intFileType), sizeIntMSn); (*is_).read(reinterpret_cast(&version_), sizeIntMSn); (*is_).read(reinterpret_cast(&header), sizeof(MSnHeader)); if( version_ > 3 ){ throw runtime_error(("[SpectrumList_MSn::createIndexBinary] The version of this file is " + lexical_cast(version_) + " but the latest version handled is 3")); } // temp varabiles for each scan MSnScanInfo scanInfo; // until we get to the end of the file... while( true ) { // keep track of where we are at the beginning of spectrum streampos specBegin = is_->tellg(); scanInfo.readSpectrumHeader(is_, version_); if( !*is_ ){ break; } // create a new SpectrumIdentity and put it on the list index_.push_back(SpectrumIdentity()); // get a pointer to the current identity SpectrumIdentity& curIdentity = index_.back(); curIdentity.index = index_.size()-1; curIdentity.id = "scan=" + lexical_cast(scanInfo.scanNumber); curIdentity.sourceFilePosition = size_t(specBegin); curIdToIndexItr = idToIndex_.insert(pair(curIdentity.id, index_.size()-1)).first; // skip to next spec if( filetype_ == MSn_Type_CMS1 || filetype_ == MSn_Type_CMS2 ){ // skip the charge states (*is_).seekg(scanInfo.numChargeStates * sizeChargeMSn, std::ios_base::cur); // skip the EZ states (*is_).seekg(scanInfo.numEzStates * sizeEzMSn, std::ios_base::cur); // skip the peaks, first find out how far int iTemp; unsigned long mzLen, intensityLen; (*is_).read(reinterpret_cast(&iTemp), sizeIntMSn); mzLen = (unsigned long)iTemp; (*is_).read(reinterpret_cast(&iTemp), sizeIntMSn); intensityLen = (unsigned long)iTemp; (*is_).seekg(mzLen + intensityLen, std::ios_base::cur); }else if( filetype_ == MSn_Type_BMS1 || filetype_ == MSn_Type_BMS2 ){ // skip the charge states (*is_).seekg(scanInfo.numChargeStates * sizeChargeMSn, std::ios_base::cur); // skip the peaks (*is_).seekg(scanInfo.numPeaks * sizePeakMSn, std::ios_base::cur); } }// next spectrum is_->clear(); is_->seekg(0); } }; } // namespace SpectrumListPtr SpectrumList_MSn::create(boost::shared_ptr is, const MSData& msd, MSn_Type filetype) { return SpectrumListPtr(new SpectrumList_MSnImpl(is, msd, filetype)); } } // namespace msdata } // namespace pwiz pwiz/pwiz/data/msdata/SpectrumList_mzML.hpp0000664000175100017510000000267412664775621023045 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_mzML.hpp 2898 2011-08-01 17:55:13Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_MZML_HPP_ #define _SPECTRUMLIST_MZML_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "SpectrumListBase.hpp" #include "Index_mzML.hpp" #include namespace pwiz { namespace msdata { /// implementation of SpectrumList, backed by an mzML file class PWIZ_API_DECL SpectrumList_mzML : public SpectrumListBase { public: static SpectrumListPtr create(boost::shared_ptr is, const MSData& msd, const Index_mzML_Ptr& indexPtr); }; } // namespace msdata } // namespace pwiz #endif // _SPECTRUMLIST_MZML_HPP_ pwiz/pwiz/data/msdata/Serializer_mzXML.cpp0000664000175100017510000014502412664775620022637 0ustar teamcityteamcity00000000000000// // $Id: Serializer_mzXML.cpp 9172 2015-11-25 19:46:23Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Serializer_mzXML.hpp" #include "SpectrumList_mzXML.hpp" #include "Diff.hpp" #include "SHA1OutputObserver.hpp" #include "LegacyAdapter.hpp" #include "pwiz/data/common/CVTranslator.hpp" #include "pwiz/utility/minimxml/XMLWriter.hpp" #include "pwiz/utility/minimxml/SAXParser.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include "SpectrumWorkerThreads.hpp" namespace pwiz { namespace msdata { using minimxml::XMLWriter; using boost::iostreams::stream_offset; using namespace pwiz::util; using namespace pwiz::minimxml; using namespace pwiz::data; class Serializer_mzXML::Impl { public: Impl(const Config& config) : config_(config) {} void write(ostream& os, const MSData& msd, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry) const; void read(shared_ptr is, MSData& msd) const; private: Config config_; CVTranslator cvTranslator_; }; // // write() implementation // namespace { void start_mzXML(XMLWriter& xmlWriter) { XMLWriter::Attributes attributes; attributes.add("xmlns", "http://sashimi.sourceforge.net/schema_revision/mzXML_3.2"); attributes.add("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); attributes.add("xsi:schemaLocation", "http://sashimi.sourceforge.net/schema_revision/mzXML_3.2 http://sashimi.sourceforge.net/schema_revision/mzXML_3.2/mzXML_idx_3.2.xsd"); xmlWriter.pushStyle(XMLWriter::StyleFlag_AttributesOnMultipleLines); xmlWriter.startElement("mzXML", attributes); xmlWriter.popStyle(); } string getRetentionTime(const Scan& scan) { ostringstream oss; oss << "PT" << scan.cvParam(MS_scan_start_time).timeInSeconds() << "S"; return oss.str(); } void start_msRun(XMLWriter& xmlWriter, const MSData& msd) { string scanCount, startTime, endTime; if (msd.run.spectrumListPtr.get()) { const SpectrumList& sl = *msd.run.spectrumListPtr; scanCount = lexical_cast(sl.size()); if (sl.size() > 0) { SpectrumPtr spectrum = sl.spectrum(0); if (!spectrum->scanList.scans.empty()) startTime = getRetentionTime(spectrum->scanList.scans[0]); spectrum = sl.spectrum(sl.size()-1); if (!spectrum->scanList.scans.empty()) endTime = getRetentionTime(spectrum->scanList.scans[0]); } } XMLWriter::Attributes attributes; attributes.add("scanCount", scanCount); attributes.add("startTime", startTime); attributes.add("endTime", endTime); xmlWriter.startElement("msRun", attributes); } string translate_SourceFileTypeToRunID(const SourceFile& sf, CVID sourceFileType) { string nameExtension = bal::to_lower_copy(bfs::extension(sf.name)); string locationExtension = bal::to_lower_copy(bfs::extension(sf.location)); switch (sourceFileType) { // location="file://path/to" name="source.RAW" case MS_Thermo_RAW_format: if (nameExtension == ".raw") return bfs::basename(sf.name); return ""; // sane: location="file://path/to/source.raw" name="_FUNC001.DAT" // insane: location="file://path/to" name="source.raw" case MS_Waters_raw_format: if (nameExtension == ".dat" && locationExtension == ".raw") return bfs::basename(bfs::path(sf.location).leaf()); else if (nameExtension == ".raw") return bfs::basename(sf.name); return ""; // location="file://path/to/source.d" name="Analysis.yep" case MS_Bruker_Agilent_YEP_format: if (nameExtension == ".yep" && locationExtension == ".d") return bfs::basename(bfs::path(sf.location).leaf()); return ""; // location="file://path/to/source.d" name="Analysis.baf" case MS_Bruker_BAF_format: if (nameExtension == ".baf" && locationExtension == ".d") return bfs::basename(bfs::path(sf.location).leaf()); return ""; // location="file://path/to/source.d/AcqData" name="msprofile.bin" case MS_Agilent_MassHunter_format: if (bfs::path(sf.location).leaf() == "AcqData" && (bal::iends_with(sf.name, "msprofile.bin") || bal::iends_with(sf.name, "mspeak.bin") || bal::iends_with(sf.name, "msscan.bin"))) return bfs::basename(bfs::path(sf.location).parent_path().leaf()); return ""; // location="file://path/to" name="source.mzXML" // location="file://path/to" name="source.mz.xml" // location="file://path/to" name="source.d" (ambiguous) case MS_ISB_mzXML_format: if (nameExtension == ".mzxml" || nameExtension == ".d") return bfs::basename(sf.name); else if (bal::iends_with(sf.name, ".mz.xml")) return sf.name.substr(0, sf.name.length()-7); return ""; // location="file://path/to" name="source.mzData" // location="file://path/to" name="source.mz.data" ??? case MS_PSI_mzData_format: if (nameExtension == ".mzdata") return bfs::basename(sf.name); return ""; // location="file://path/to" name="source.mgf" case MS_Mascot_MGF_format: if (nameExtension == ".mgf") return bfs::basename(sf.name); return ""; // location="file://path/to" name="source.wiff" case MS_ABI_WIFF_format: if (nameExtension == ".wiff") return bfs::basename(sf.name); return ""; // location="file://path/to/source/maldi-spot/1/1SRef" name="fid" // location="file://path/to/source/1/1SRef" name="fid" case MS_Bruker_FID_format: // need the full list of FIDs to create a run ID (from the common prefix) return bfs::path(sf.location).parent_path().parent_path().string(); // location="file://path/to/source" name="spectrum-id.t2d" // location="file://path/to/source/MS" name="spectrum-id.t2d" // location="file://path/to/source/MSMS" name="spectrum-id.t2d" case MS_SCIEX_TOF_TOF_T2D_format: // need the full list of T2Ds to create a run ID (from the common prefix) return sf.location; default: return ""; } } void write_parentFile(XMLWriter& xmlWriter, const MSData& msd) { BOOST_FOREACH(const SourceFilePtr& sourceFilePtr, msd.fileDescription.sourceFilePtrs) { const SourceFile& sf = *sourceFilePtr; // skip files with unknown source file type CVID sourceFileType = sf.cvParamChild(MS_mass_spectrometer_file_format).cvid; if (sourceFileType == CVID_Unknown) continue; // skip files with no nativeID format (like acquisition settings) CVID nativeIdFormat = sf.cvParamChild(MS_nativeID_format).cvid; if (nativeIdFormat == MS_no_nativeID_format) continue; // if we can't translate the file to a run ID, skip it as a parentFile string runID = translate_SourceFileTypeToRunID(sf, sourceFileType); if (runID.empty()) continue; string fileName, fileType, fileSha1; fileName = sf.location + "/" + sf.name; switch (nativeIdFormat) { // nativeID formats from processed data file types case MS_scan_number_only_nativeID_format: case MS_spectrum_identifier_nativeID_format: case MS_multiple_peak_list_nativeID_format: case MS_single_peak_list_nativeID_format: fileType = "processedData"; break; // consider other formats to be raw default: fileType = "RAWData"; break; } fileSha1 = sf.cvParam(MS_SHA_1).value; XMLWriter::Attributes attributes; attributes.add("fileName", fileName); attributes.add("fileType", fileType); attributes.add("fileSha1", fileSha1); xmlWriter.pushStyle(XMLWriter::StyleFlag_AttributesOnMultipleLines); xmlWriter.startElement("parentFile", attributes, XMLWriter::EmptyElement); xmlWriter.popStyle(); } } void writeCategoryValue(XMLWriter& xmlWriter, const string& category, const string& value) { XMLWriter::Attributes attributes; attributes.add("category", category); attributes.add("value", value); xmlWriter.startElement(category, attributes, XMLWriter::EmptyElement); } void writeSoftware(XMLWriter& xmlWriter, SoftwarePtr software, const MSData& msd, const CVTranslator& cvTranslator, const string& type = "") { LegacyAdapter_Software adapter(software, const_cast(msd), cvTranslator); XMLWriter::Attributes attributes; attributes.add("type", type.empty() ? adapter.type() : type); attributes.add("name", adapter.name()); attributes.add("version", adapter.version()); xmlWriter.startElement("software", attributes, XMLWriter::EmptyElement); } void write_msInstrument(XMLWriter& xmlWriter, const InstrumentConfigurationPtr& instrumentConfiguration, const MSData& msd, const CVTranslator& cvTranslator, map& instrumentIndexByPtr) { const LegacyAdapter_Instrument adapter( const_cast(*instrumentConfiguration), cvTranslator); int index = (int) instrumentIndexByPtr.size() + 1; instrumentIndexByPtr[instrumentConfiguration] = index; XMLWriter::Attributes attributes; attributes.add("msInstrumentID", index); xmlWriter.startElement("msInstrument", attributes); writeCategoryValue(xmlWriter, "msManufacturer", adapter.manufacturer()); writeCategoryValue(xmlWriter, "msModel", adapter.model()); try { writeCategoryValue(xmlWriter, "msIonisation", adapter.ionisation()); } catch (std::out_of_range&) {} try { writeCategoryValue(xmlWriter, "msMassAnalyzer", adapter.analyzer()); } catch (std::out_of_range&) {} try { writeCategoryValue(xmlWriter, "msDetector", adapter.detector()); } catch (std::out_of_range&) {} if (instrumentConfiguration->softwarePtr.get()) writeSoftware(xmlWriter, instrumentConfiguration->softwarePtr, msd, cvTranslator, "acquisition"); xmlWriter.endElement(); // msInstrument } void write_msInstruments(XMLWriter& xmlWriter, const MSData& msd, const CVTranslator& cvTranslator, map& instrumentIndexByPtr) { BOOST_FOREACH(const InstrumentConfigurationPtr& icPtr, msd.instrumentConfigurationPtrs) if (icPtr.get()) write_msInstrument(xmlWriter, icPtr, msd, cvTranslator, instrumentIndexByPtr); } void write_processingOperation(XMLWriter& xmlWriter, const ProcessingMethod& pm, CVID action) { CVParam actionParam = pm.cvParamChild(action); if (!actionParam.empty() && actionParam != action) { XMLWriter::Attributes attributes; attributes.add("name", actionParam.name()); xmlWriter.startElement("processingOperation", attributes, XMLWriter::EmptyElement); } } void write_dataProcessing(XMLWriter& xmlWriter, const MSData& msd, const CVTranslator& cvTranslator) { BOOST_FOREACH(const DataProcessingPtr& dpPtr, msd.allDataProcessingPtrs()) { if (!dpPtr.get() || dpPtr->processingMethods.empty()) continue; XMLWriter::Attributes attributes; BOOST_FOREACH(const ProcessingMethod& pm, dpPtr->processingMethods) { if (pm.hasCVParamChild(MS_peak_picking)) attributes.add("centroided", "1"); if (pm.hasCVParamChild(MS_deisotoping)) attributes.add("deisotoped", "1"); if (pm.hasCVParamChild(MS_charge_deconvolution)) attributes.add("chargeDeconvoluted", "1"); if (pm.hasCVParamChild(MS_thresholding)) { CVParam threshold = pm.cvParam(MS_low_intensity_threshold); if (!threshold.empty()) attributes.add("intensityCutoff", threshold.value); } } xmlWriter.startElement("dataProcessing", attributes); BOOST_FOREACH(const ProcessingMethod& pm, dpPtr->processingMethods) { CVParam fileFormatConversion = pm.cvParamChild(MS_file_format_conversion); string softwareType = fileFormatConversion.empty() ? "processing" : "conversion"; if (pm.softwarePtr.get()) writeSoftware(xmlWriter, pm.softwarePtr, msd, cvTranslator, softwareType); write_processingOperation(xmlWriter, pm, MS_file_format_conversion); write_processingOperation(xmlWriter, pm, MS_peak_picking); write_processingOperation(xmlWriter, pm, MS_deisotoping); write_processingOperation(xmlWriter, pm, MS_charge_deconvolution); write_processingOperation(xmlWriter, pm, MS_thresholding); xmlWriter.pushStyle(XMLWriter::StyleFlag_InlineInner); BOOST_FOREACH(const UserParam& param, pm.userParams) { xmlWriter.startElement("comment"); xmlWriter.characters(param.name + (param.value.empty() ? string() : ": " + param.value)); xmlWriter.endElement(); // comment } xmlWriter.popStyle(); } xmlWriter.endElement(); // dataProcessing } } struct IndexEntry { int scanNumber; stream_offset offset; }; string getPolarity(const Spectrum& spectrum) { string result = ""; CVParam paramPolarity = spectrum.cvParamChild(MS_scan_polarity); if (paramPolarity.empty()) paramPolarity = spectrum.cvParamChild(MS_polarity_OBSOLETE); if (paramPolarity.cvid == MS_positive_scan) result = "+"; if (paramPolarity.cvid == MS_negative_scan) result = "-"; return result; } struct PrecursorInfo { string scanNum; string mz; string intensity; string charge; string collisionEnergy; string activation; double windowWideness; bool empty() const { return scanNum.empty() && mz.empty() && intensity.empty() && charge.empty() && collisionEnergy.empty() && activation.empty() && windowWideness == 0; } }; vector getPrecursorInfo(const Spectrum& spectrum, const SpectrumListPtr spectrumListPtr, CVID nativeIdFormat) { vector result; for (vector::const_iterator it=spectrum.precursors.begin(); it!=spectrum.precursors.end(); ++it) { PrecursorInfo info; if (!it->spectrumID.empty()) { // mzXML scanNumber takes a different form depending on the source's nativeID format info.scanNum = id::translateNativeIDToScanNumber(nativeIdFormat, it->spectrumID); } if (!it->selectedIons.empty()) { info.mz = it->selectedIons[0].cvParam(MS_selected_ion_m_z).value; info.intensity = it->selectedIons[0].cvParam(MS_peak_intensity).value; info.charge = it->selectedIons[0].cvParam(MS_charge_state).value; } if (!it->activation.empty()) { if (it->activation.hasCVParam(MS_ETD)) { info.activation = "ETD"; if (it->activation.hasCVParam(MS_CID)) info.activation += "+SA"; } else if (it->activation.hasCVParam(MS_ECD)) { info.activation = "ECD"; } else if (it->activation.hasCVParam(MS_CID)) { info.activation = "CID"; } else if (it->activation.hasCVParam(MS_HCD)) { info.activation = "HCD"; } if (it->activation.hasCVParam(MS_CID) || it->activation.hasCVParam(MS_HCD)) info.collisionEnergy = it->activation.cvParam(MS_collision_energy).value; } info.windowWideness = 0; if (!it->isolationWindow.empty()) { CVParam isolationWindowLowerOffset = it->isolationWindow.cvParam(MS_isolation_window_lower_offset); CVParam isolationWindowUpperOffset = it->isolationWindow.cvParam(MS_isolation_window_upper_offset); if (!isolationWindowLowerOffset.empty() && !isolationWindowUpperOffset.empty()) info.windowWideness = fabs(isolationWindowLowerOffset.valueAs()) + isolationWindowUpperOffset.valueAs(); } if (!info.empty()) result.push_back(info); } return result; } void write_precursors(XMLWriter& xmlWriter, const vector& precursorInfo) { xmlWriter.pushStyle(XMLWriter::StyleFlag_InlineInner); for (vector::const_iterator it=precursorInfo.begin(); it!=precursorInfo.end(); ++it) { XMLWriter::Attributes attributes; if (!it->scanNum.empty()) attributes.add("precursorScanNum", it->scanNum); if (it->intensity.empty()) attributes.add("precursorIntensity", "0"); // required attribute else attributes.add("precursorIntensity", it->intensity); if (!it->charge.empty()) attributes.add("precursorCharge", it->charge); if (!it->activation.empty()) attributes.add("activationMethod", it->activation); if (it->windowWideness != 0) attributes.add("windowWideness", it->windowWideness); xmlWriter.startElement("precursorMz", attributes); xmlWriter.characters(it->mz, false); xmlWriter.endElement(); } xmlWriter.popStyle(); } void write_peaks(XMLWriter& xmlWriter, const vector& mzIntensityPairs, const Serializer_mzXML::Config& config) { BinaryDataEncoder::Config bdeConfig = config.binaryDataEncoderConfig; bdeConfig.byteOrder = BinaryDataEncoder::ByteOrder_BigEndian; // mzXML always big endian BinaryDataEncoder encoder(bdeConfig); string encoded; size_t binaryByteCount; // size before base64 encoding XMLWriter::Attributes attributes; if (!mzIntensityPairs.empty()) encoder.encode(reinterpret_cast(&mzIntensityPairs[0]), mzIntensityPairs.size()*2, encoded, &binaryByteCount); else { binaryByteCount = 0; attributes.add("xsi:nil", "true"); } string precision = bdeConfig.precision == BinaryDataEncoder::Precision_32 ? "32" : "64"; if (bdeConfig.compression == BinaryDataEncoder::Compression_Zlib) { attributes.add("compressionType", "zlib"); attributes.add("compressedLen", binaryByteCount); } else { attributes.add("compressionType", "none"); attributes.add("compressedLen", "0"); } attributes.add("precision", precision); attributes.add("byteOrder", "network"); attributes.add("contentType", "m/z-int"); xmlWriter.pushStyle(XMLWriter::StyleFlag_InlineInner | XMLWriter::StyleFlag_AttributesOnMultipleLines); xmlWriter.startElement("peaks", attributes); xmlWriter.characters(encoded, false); xmlWriter.endElement(); xmlWriter.popStyle(); } IndexEntry write_scan(XMLWriter& xmlWriter, CVID nativeIdFormat, const Spectrum& spectrum, const SpectrumListPtr spectrumListPtr, const Serializer_mzXML::Config& config, map& instrumentIndexByPtr) { IndexEntry result; result.offset = xmlWriter.positionNext(); // mzXML scanNumber takes a different form depending on the source's nativeID format if (MS_multiple_peak_list_nativeID_format == nativeIdFormat) // 0-based { result.scanNumber = spectrum.index+1; // mzXML is 1-based } else { string scanNumberStr = id::translateNativeIDToScanNumber(nativeIdFormat, spectrum.id); if (scanNumberStr.empty()) result.scanNumber = spectrum.index+1; // scanNumber is a 1-based index for some nativeID formats else result.scanNumber = lexical_cast(scanNumberStr); } // get info Scan dummy; const Scan& scan = spectrum.scanList.scans.empty() ? dummy : spectrum.scanList.scans[0]; CVParam spectrumTypeParam = spectrum.cvParamChild(MS_spectrum_type); string scanType; switch (spectrumTypeParam.cvid) { case MS_MSn_spectrum: case MS_MS1_spectrum: scanType = "Full"; break; case MS_CRM_spectrum: scanType = "CRM"; break; case MS_SIM_spectrum: scanType = "SIM"; break; case MS_SRM_spectrum: scanType = "SRM"; break; case MS_precursor_ion_spectrum: scanType = "Q1"; break; case MS_constant_neutral_gain_spectrum: case MS_constant_neutral_loss_spectrum: scanType = "Q3"; break; default: break; } //string scanEvent = scan.cvParam(MS_preset_scan_configuration).value; string msLevel = spectrum.cvParam(MS_ms_level).value; string polarity = getPolarity(spectrum); string retentionTime = getRetentionTime(scan); string lowMz = spectrum.cvParam(MS_lowest_observed_m_z).value; string highMz = spectrum.cvParam(MS_highest_observed_m_z).value; string basePeakMz = spectrum.cvParam(MS_base_peak_m_z).value; string basePeakIntensity = spectrum.cvParam(MS_base_peak_intensity).value; string totIonCurrent = spectrum.cvParam(MS_total_ion_current).value; string filterLine = spectrum.cvParam(MS_filter_string).value; string compensationVoltage; if (spectrum.hasCVParam(MS_FAIMS_compensation_voltage)) compensationVoltage = spectrum.cvParam(MS_FAIMS_compensation_voltage).value; bool isCentroided = spectrum.hasCVParam(MS_centroid_spectrum); vector precursorInfo = getPrecursorInfo(spectrum, spectrumListPtr, nativeIdFormat); vector mzIntensityPairs; spectrum.getMZIntensityPairs(mzIntensityPairs); // write out xml XMLWriter::Attributes attributes; attributes.add("num", result.scanNumber); //if (!scanEvent.empty()) // attributes.add("scanEvent", scanEvent); if (!scanType.empty()) attributes.add("scanType", scanType); if (!filterLine.empty()) attributes.add("filterLine", filterLine); // TODO: write this attribute only when SpectrumList_PeakPicker has processed the spectrum attributes.add("centroided", isCentroided ? "1" : "0"); attributes.add("msLevel", msLevel); attributes.add("peaksCount", mzIntensityPairs.size()); if (!polarity.empty()) attributes.add("polarity", polarity); attributes.add("retentionTime", retentionTime); if (!precursorInfo.empty()) { if(!precursorInfo[0].collisionEnergy.empty()) attributes.add("collisionEnergy", precursorInfo[0].collisionEnergy); } if (!lowMz.empty()) attributes.add("lowMz", lowMz); if (!highMz.empty()) attributes.add("highMz", highMz); if (!basePeakMz.empty()) attributes.add("basePeakMz", basePeakMz); if (!basePeakIntensity.empty()) attributes.add("basePeakIntensity", basePeakIntensity); if (!totIonCurrent.empty()) attributes.add("totIonCurrent", totIonCurrent); if (!compensationVoltage.empty()) attributes.add("compensationVoltage", compensationVoltage); if (scan.instrumentConfigurationPtr.get()) attributes.add("msInstrumentID", instrumentIndexByPtr[scan.instrumentConfigurationPtr]); xmlWriter.pushStyle(XMLWriter::StyleFlag_AttributesOnMultipleLines); xmlWriter.startElement("scan", attributes); xmlWriter.popStyle(); write_precursors(xmlWriter, precursorInfo); write_peaks(xmlWriter, mzIntensityPairs, config); // write userParams as arbitrary nameValue elements BOOST_FOREACH(const UserParam& userParam, spectrum.userParams) { attributes.clear(); attributes.add("name", userParam.name); attributes.add("value", userParam.value); xmlWriter.startElement("nameValue", attributes, XMLWriter::EmptyElement); } xmlWriter.endElement(); // scan return result; } void write_scans(XMLWriter& xmlWriter, const MSData& msd, const Serializer_mzXML::Config& config, vector& index, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry, map& instrumentIndexByPtr) { SpectrumListPtr sl = msd.run.spectrumListPtr; if (!sl.get()) return; CVID defaultNativeIdFormat = id::getDefaultNativeIDFormat(msd); SpectrumWorkerThreads spectrumWorkers(*sl); for (size_t i=0; isize(); i++) { // send progress updates, handling cancel IterationListener::Status status = IterationListener::Status_Ok; if (iterationListenerRegistry) status = iterationListenerRegistry->broadcastUpdateMessage( IterationListener::UpdateMessage(i, sl->size())); if (status == IterationListener::Status_Cancel) break; //SpectrumPtr spectrum = sl->spectrum(i, true); SpectrumPtr spectrum = spectrumWorkers.processBatch(i); // Thermo spectra not from "controllerType=0 controllerNumber=1" are ignored if (defaultNativeIdFormat == MS_Thermo_nativeID_format && spectrum->id.find("controllerType=0 controllerNumber=1") != 0) continue; // scans from a source file other than the default are ignored; // note: multiple parentFile elements in mzXML are intended to represent // the data processing history of a single source file if (spectrum->sourceFilePtr.get() && spectrum->sourceFilePtr != msd.run.defaultSourceFilePtr) continue; // write the spectrum index.push_back(write_scan(xmlWriter, defaultNativeIdFormat, *spectrum, msd.run.spectrumListPtr, config, instrumentIndexByPtr)); } } void write_index(XMLWriter& xmlWriter, const vector& index) { XMLWriter::Attributes attributes; attributes.add("name", "scan"); xmlWriter.startElement("index", attributes); xmlWriter.pushStyle(XMLWriter::StyleFlag_InlineInner); for (vector::const_iterator it=index.begin(); it!=index.end(); ++it) { attributes.clear(); attributes.add("id", it->scanNumber); xmlWriter.startElement("offset", attributes); xmlWriter.characters(lexical_cast(it->offset), false); xmlWriter.endElement(); // offset } xmlWriter.popStyle(); xmlWriter.endElement(); // index } } // namespace void Serializer_mzXML::Impl::write(ostream& os, const MSData& msd, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry) const { SHA1OutputObserver sha1OutputObserver; XMLWriter::Config config; config.outputObserver = &sha1OutputObserver; XMLWriter xmlWriter(os, config); string xmlData = "version=\"1.0\" encoding=\"ISO-8859-1\""; // TODO: UTF-8 ? xmlWriter.processingInstruction("xml", xmlData); start_mzXML(xmlWriter); map instrumentIndexByPtr; start_msRun(xmlWriter, msd); write_parentFile(xmlWriter, msd); write_msInstruments(xmlWriter, msd, cvTranslator_, instrumentIndexByPtr); write_dataProcessing(xmlWriter, msd, cvTranslator_); vector index; write_scans(xmlWriter, msd, config_, index, iterationListenerRegistry, instrumentIndexByPtr); xmlWriter.endElement(); // msRun stream_offset indexOffset = xmlWriter.positionNext(); if (config_.indexed && msd.run.spectrumListPtr && msd.run.spectrumListPtr->size() > 0) { write_index(xmlWriter, index); xmlWriter.pushStyle(XMLWriter::StyleFlag_InlineInner); xmlWriter.startElement("indexOffset"); xmlWriter.characters(lexical_cast(indexOffset), false); xmlWriter.endElement(); xmlWriter.popStyle(); } xmlWriter.pushStyle(XMLWriter::StyleFlag_InlineInner); xmlWriter.startElement("sha1"); xmlWriter.characters(sha1OutputObserver.hash(), false); xmlWriter.endElement(); xmlWriter.popStyle(); xmlWriter.endElement(); // mzXML } // // read() implementation // namespace { void splitFilename(const string& fullpath, string& path, string& basename) { string::size_type lastSlash = fullpath.find_last_of("/\\"); if (lastSlash==string::npos || lastSlash==fullpath.size()-1) { path.clear(); basename = fullpath; return; } path = fullpath.substr(0, lastSlash); basename = fullpath.substr(lastSlash+1); } CVID translate_parentFilenameToSourceFileType(const string& name) { string fileExtension = bal::to_lower_copy(bfs::extension(name)); // check for known vendor formats if (fileExtension == ".raw") { // (Mass)Wolf-MRM or other non-compliant Waters converters might // conflict with this case, i.e. the extension could be from a Waters .raw directory // instead of a Thermo RAW file; these aberrant cases will be fixed globally by fillInMetadata() return MS_Thermo_RAW_format; } else if (fileExtension == ".dat") return MS_Waters_raw_format; else if (fileExtension == ".wiff") return MS_ABI_WIFF_format; else if (fileExtension == ".yep") return MS_Bruker_Agilent_YEP_format; else if (fileExtension == ".baf") return MS_Bruker_BAF_format; else if (name == "fid") return MS_Bruker_FID_format; else if (bal::iequals(name, "msprofile.bin")) return MS_Agilent_MassHunter_format; else if (bal::iequals(name, "mspeak.bin")) return MS_Agilent_MassHunter_format; else if (bal::iequals(name, "msscan.bin")) return MS_Agilent_MassHunter_format; else if (fileExtension == ".t2d") return MS_SCIEX_TOF_TOF_T2D_format; // check for known open formats else if (fileExtension == ".mzdata") return MS_PSI_mzData_format; else if (fileExtension == ".mgf") return MS_Mascot_MGF_format; else if (fileExtension == ".dta") return MS_DTA_format; else if (fileExtension == ".pkl") return MS_Micromass_PKL_format; else if (fileExtension == ".mzxml") return MS_ISB_mzXML_format; else if (bal::iends_with(name, ".mz.xml")) return MS_ISB_mzXML_format; else if (fileExtension == ".mzml") return MS_mzML_format; // This case is nasty for several reasons: // 1) a .d suffix almost certainly indicates a directory, not a file (so no SHA-1) // 2) the same suffix is used by multiple different formats (Agilent/Bruker YEP, Bruker BAF, Agilent ms*.bin) // 3) all the formats use the same nativeID style ("scan=123") so just treat it like an mzXML source // Therefore this "file" extension is quite useless. else if (fileExtension == ".d") return MS_ISB_mzXML_format; else return CVID_Unknown; } CVID translateSourceFileTypeToNativeIdFormat(CVID sourceFileType) { switch (sourceFileType) { // for these sources we treat the scan number as the nativeID case MS_Thermo_RAW_format: return MS_Thermo_nativeID_format; case MS_Bruker_Agilent_YEP_format: return MS_Bruker_Agilent_YEP_nativeID_format; case MS_Bruker_BAF_format: return MS_Bruker_BAF_nativeID_format; case MS_ISB_mzXML_format: return MS_scan_number_only_nativeID_format; case MS_PSI_mzData_format: return MS_spectrum_identifier_nativeID_format; case MS_Mascot_MGF_format: return MS_multiple_peak_list_nativeID_format; case MS_DTA_format: return MS_scan_number_only_nativeID_format; case MS_Agilent_MassHunter_format: return MS_Agilent_MassHunter_nativeID_format; // for these sources we must assume the scan number came from the index case MS_ABI_WIFF_format: case MS_Bruker_FID_format: case MS_SCIEX_TOF_TOF_T2D_format: case MS_Waters_raw_format: case MS_Micromass_PKL_format: return MS_scan_number_only_nativeID_format; // in other cases, assume the source file doesn't contain instrument data case CVID_Unknown: return MS_no_nativeID_format; default: throw runtime_error("[Serializer_mzXML::translateSourceFileTypeToNativeIdFormat] unknown file type"); } } void process_parentFile(const string& fileName, const string& fileType, const string& fileSha1, MSData& msd) { string name, location; splitFilename(fileName, location, name); msd.fileDescription.sourceFilePtrs.push_back(SourceFilePtr(new SourceFile)); SourceFile& sf = *msd.fileDescription.sourceFilePtrs.back(); sf.id = name; sf.name = name; sf.location = location; if (fileType != "RAWData" && fileType != "processedData") throw runtime_error("[Serializer_mzXML::process_parentFile] invalid value for fileType attribute"); // TODO: if fileSha1 is empty or invalid, log a warning sf.set(MS_SHA_1, fileSha1); } SoftwarePtr registerSoftware(MSData& msd, const string& type, const string& name, const string& version, const CVTranslator& cvTranslator) { SoftwarePtr result; // see if we already registered this Software for (vector::const_iterator it=msd.softwarePtrs.begin(); it!=msd.softwarePtrs.end(); ++it) { CVParam softwareParam = (*it)->cvParamChild(MS_software); if (softwareParam.cvid == cvTranslator.translate(name) && (*it)->version == version) result = *it; } // create a new entry if (!result.get()) { result = SoftwarePtr(new Software); msd.softwarePtrs.push_back(result); } result->id = name + " software"; LegacyAdapter_Software adapter(result, msd, cvTranslator); adapter.name(name); adapter.version(version); adapter.type(type); return result; } class HandlerScanFileContent : public SAXParser::Handler { MSData& msd_; bool hasCentroidDataProcessing; bool hasCentroidScan; bool hasProfileScan; public: HandlerScanFileContent(MSData& msd, bool hasCentroidDataProcessing) : msd_(msd), hasCentroidDataProcessing(hasCentroidDataProcessing), hasCentroidScan(false), hasProfileScan(false) { } virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name != "scan") throw runtime_error("[Serializer_mzXML::HandlerScanFileContent] Index offset does not point at element."); string msLevel, centroided, scanType; getAttribute(attributes, "msLevel", msLevel); getAttribute(attributes, "scanType", scanType); getAttribute(attributes, "centroided", centroided); //TODO: use this: getAttribute(attributes, "deisotoped", deisotoped); //TODO: use this: getAttribute(attributes, "chargeDeconvoluted", chargeDeconvoluted); // set spectrum type by scanType attribute (assume MSn/Full if absent) boost::to_lower(scanType); boost::trim(msLevel); if (scanType.empty() || scanType == "full" || scanType == "zoom") msd_.fileDescription.fileContent.set(msLevel == "1" ? MS_MS1_spectrum : MS_MSn_spectrum); else if (scanType == "q1") msd_.fileDescription.fileContent.set(MS_precursor_ion_spectrum); else if (scanType == "q3") msd_.fileDescription.fileContent.set(MS_product_ion_spectrum); else if (scanType == "sim" || scanType == "srm" || scanType == "mrm" || // HACK: mzWiff (ABI) and wolf-mrm (Waters) use this value scanType == "multiplereaction" || // HACK: Trapper (Agilent) uses this value scanType == "crm") { // SIM/SRM spectra are accessed as chromatograms } if (!hasCentroidScan || !hasProfileScan) { // if the global data processing says spectra were centroided, the default // spectrum representation is centroid, otherwise profile if (centroided.empty()) { if (!hasCentroidScan && hasCentroidDataProcessing) { hasCentroidScan = true; msd_.fileDescription.fileContent.set(MS_centroid_spectrum); } else if (!hasProfileScan && !hasCentroidDataProcessing) { hasProfileScan = true; msd_.fileDescription.fileContent.set(MS_profile_spectrum); } } // non-empty centroided attribute overrides the default spectrum representation else if (!hasCentroidScan && centroided == "1") { hasCentroidScan = true; msd_.fileDescription.fileContent.set(MS_centroid_spectrum); } else if (!hasProfileScan && centroided == "0") { hasProfileScan = true; msd_.fileDescription.fileContent.set(MS_profile_spectrum); } } return Status::Done; } }; void fillInMetadata(MSData& msd) { // check for (Mass)Wolf-MRM metadata: multiple parentFiles with the same .raw URI set uniqueURIs; BOOST_FOREACH(SourceFilePtr& sf, msd.fileDescription.sourceFilePtrs) { pair::iterator, bool> ir = uniqueURIs.insert((sf->location.empty() ? "" : sf->location + '/') + sf->name); if (!ir.second) { // found duplicate URI: remove all the .raw sourceFiles (leave only the mzXML) SourceFilePtr firstSourceFile = msd.fileDescription.sourceFilePtrs[0]; msd.fileDescription.sourceFilePtrs.assign(1, firstSourceFile); break; } } // add nativeID type and source file type to the remaining source files set uniqueIDs; BOOST_FOREACH(SourceFilePtr& sf, msd.fileDescription.sourceFilePtrs) { CVID sourceFileType = translate_parentFilenameToSourceFileType(sf->name); // TODO: if sourceFileType is CVID_Unknown, log a warning sf->set(sourceFileType); sf->set(translateSourceFileTypeToNativeIdFormat(sourceFileType)); if (sourceFileType == MS_Bruker_FID_format || sourceFileType == MS_SCIEX_TOF_TOF_T2D_format) { // each source file is translated to a run ID and added to a set of potential ids; // if they all have a common prefix, that is used as the id, otherwise it stays empty string runId = translate_SourceFileTypeToRunID(*sf, sourceFileType); if (!runId.empty()) uniqueIDs.insert(runId); } else { if (msd.id.empty()) msd.id = msd.run.id = translate_SourceFileTypeToRunID(*sf, sourceFileType); } } string lcp = longestCommonPrefix(uniqueIDs); if (!lcp.empty()) { // part of the prefix after the source name might need to be trimmed off, e.g.: // path/to/source/1A/1/1SRef/fid, path/to/source/1B/1/1SRef/fid, lcp: path/to/source/1, run id: source (not "1") // path/to/source/1A/1/1SRef/fid, path/to/source/2A/1/1SRef/fid, lcp: path/to/source/, run id: source if (*lcp.rbegin() == '/') msd.id = msd.run.id = BFS_STRING(bfs::path(lcp).leaf()); else msd.id = msd.run.id = BFS_STRING(bfs::path(lcp).parent_path().leaf()); } } struct Handler_msInstrument : public SAXParser::Handler { InstrumentConfiguration* instrumentConfiguration; Handler_msInstrument(MSData& msd, const CVTranslator& cvTranslator) : instrumentConfiguration(0), msd_(msd), cvTranslator_(cvTranslator) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!instrumentConfiguration) throw runtime_error("[Serializer_mzXML::Handler_msInstrument] Null instrumentConfiguration."); string value; getAttribute(attributes, "value", value); if (name=="msInstrument") { manufacturer_ = model_ = ionisation_ = analyzer_ = detector_ = ""; return Status::Ok; } else if (name == "instrument") // older mzXML { manufacturer_ = model_ = ionisation_ = analyzer_ = detector_ = ""; getAttribute(attributes, "manufacturer", manufacturer_); getAttribute(attributes, "model", model_); getAttribute(attributes, "ionisation", ionisation_); getAttribute(attributes, "msType", analyzer_); return Status::Ok; } else if (name == "msManufacturer") { manufacturer_ = value; return Status::Ok; } else if (name == "msModel") { model_ = value; return Status::Ok; } else if (name == "msIonisation") { ionisation_ = value; return Status::Ok; } else if (name == "msMassAnalyzer") { analyzer_ = value; return Status::Ok; } else if (name == "msDetector") { detector_ = value; return Status::Ok; } else if (name == "msResolution") { // TODO: use this to set instrument resolution? return Status::Ok; } else if (name == "software") { string type, name, version; getAttribute(attributes, "type", type); getAttribute(attributes, "name", name); getAttribute(attributes, "version", version); instrumentConfiguration->softwarePtr = registerSoftware(msd_, type, name, version, cvTranslator_); return Status::Ok; } else if (name == "operator") { // TODO: use this to make a Contact return Status::Ok; } else if (name == "nameValue") { // TODO: use this? return Status::Ok; } else if (name == "comment") { // TODO: use this? return Status::Ok; } throw runtime_error(("[SpectrumList_mzXML::Handler_msInstrument] Unexpected element name: " + name).c_str()); } virtual Status endElement(const string& name, stream_offset position) { if (name=="msInstrument" || name=="instrument") { if (!instrumentConfiguration) throw runtime_error("[Serializer_mzXML::Handler_msInstrument] Null instrumentConfiguration."); instrumentConfiguration->componentList.push_back(Component(ComponentType_Source, 1)); instrumentConfiguration->componentList.push_back(Component(ComponentType_Analyzer, 1)); instrumentConfiguration->componentList.push_back(Component(ComponentType_Detector, 1)); LegacyAdapter_Instrument adapter(*instrumentConfiguration, cvTranslator_); adapter.manufacturerAndModel(manufacturer_, model_); if(adapter.model() == "LTQ Orbitrap XL" && analyzer_ == "FTMS") analyzer_ = "orbitrap"; // hack to set analyzer_ correctly for LTQ ORBI adapter.ionisation(ionisation_); adapter.analyzer(analyzer_); adapter.detector(detector_); } return Status::Ok; } private: MSData& msd_; const CVTranslator& cvTranslator_; string manufacturer_; string model_; string ionisation_; string analyzer_; string detector_; }; struct Handler_dataProcessing : public SAXParser::Handler { bool hasCentroidDataProcessing; Handler_dataProcessing(MSData& msd, const CVTranslator& cvTranslator) : hasCentroidDataProcessing(false), msd_(msd), cvTranslator_(cvTranslator) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "dataProcessing") { string centroided, deisotoped; getAttribute(attributes, "centroided", centroided); getAttribute(attributes, "deisotoped", deisotoped); hasCentroidDataProcessing = centroided == "1"; // TODO: term for charge-deconvolution? if (hasCentroidDataProcessing || deisotoped == "1") { DataProcessingPtr dpPtr(new DataProcessing("dataProcessing")); msd_.dataProcessingPtrs.push_back(dpPtr); ProcessingMethod method; method.order = 0; if (hasCentroidDataProcessing) method.set(MS_peak_picking); if (deisotoped == "1") method.set(MS_deisotoping); dpPtr->processingMethods.push_back(method); } return Status::Ok; } else if (name == "software") { string type, name, version; getAttribute(attributes, "type", type); getAttribute(attributes, "name", name); getAttribute(attributes, "version", version); registerSoftware(msd_, type, name, version, cvTranslator_); return Status::Ok; } else if (name == "processingOperation") { // ignore its only attribute, which is "comment" return Status::Ok; } else if (name == "comment") { // just ignore return Status::Ok; } throw runtime_error(("[Serializer_mzXML::Handler_dataProcessing] Unexpected element name: " + name).c_str()); } private: MSData& msd_; const CVTranslator& cvTranslator_; }; class Handler_mzXML : public SAXParser::Handler { public: bool hasCentroidDataProcessing; Handler_mzXML(MSData& msd, const CVTranslator& cvTranslator) : msd_(msd), handler_msInstrument_(msd, cvTranslator), handler_dataProcessing_(msd, cvTranslator) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "mzXML" || name == "msRun") { return Status::Ok; } else if (name == "parentFile") { string fileName, fileType, fileSha1; getAttribute(attributes, "fileName", fileName); getAttribute(attributes, "fileType", fileType); getAttribute(attributes, "fileSha1", fileSha1); process_parentFile(fileName, fileType, fileSha1, msd_); return Status::Ok; } else if (name=="msInstrument" || name=="instrument") { string id; getAttribute(attributes, "msInstrumentID", id); if (id.empty()) getAttribute(attributes, "id", id); if (id.empty()) getAttribute(attributes, "ID", id); // hack: id or ID if (id.empty()) id = "IC1"; // xml:ID cannot be empty msd_.instrumentConfigurationPtrs.push_back(InstrumentConfigurationPtr(new InstrumentConfiguration(id))); handler_msInstrument_.instrumentConfiguration = msd_.instrumentConfigurationPtrs.back().get(); return Status(Status::Delegate, &handler_msInstrument_); } else if (name == "dataProcessing") { return Status(Status::Delegate, &handler_dataProcessing_); } else if (name == "scan" || name == "index" || name == "sha1") { // all file-level metadata has been parsed, but there are some gaps to fill fillInMetadata(msd_); hasCentroidDataProcessing = handler_dataProcessing_.hasCentroidDataProcessing; return Status::Done; } throw runtime_error(("[Serializer_mzXML::Handler_mzXML] Unexpected element name: " + name).c_str()); } private: MSData& msd_; Handler_msInstrument handler_msInstrument_; Handler_dataProcessing handler_dataProcessing_; }; } // namespace void Serializer_mzXML::Impl::read(shared_ptr is, MSData& msd) const { if (!is.get() || !*is) throw runtime_error("[Serializer_mzXML::read()] Bad istream."); is->seekg(0); Handler_mzXML handler(msd, cvTranslator_); SAXParser::parse(*is, handler); msd.run.spectrumListPtr = SpectrumList_mzXML::create(is, msd, config_.indexed); HandlerScanFileContent handlerScanFileContent(msd, handler.hasCentroidDataProcessing); for (size_t i=0; i < msd.run.spectrumListPtr->size(); ++i) { bio::stream_offset offset = msd.run.spectrumListPtr->spectrumIdentity(i).sourceFilePosition; is->seekg(bio::offset_to_position(offset)); SAXParser::parse(*is, handlerScanFileContent); } } // // Serializer_mzXML // PWIZ_API_DECL Serializer_mzXML::Serializer_mzXML(const Config& config) : impl_(new Impl(config)) {} PWIZ_API_DECL void Serializer_mzXML::write(ostream& os, const MSData& msd, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry) const { return impl_->write(os, msd, iterationListenerRegistry); } PWIZ_API_DECL void Serializer_mzXML::read(shared_ptr is, MSData& msd) const { return impl_->read(is, msd); } PWIZ_API_DECL ostream& operator<<(ostream& os, const Serializer_mzXML::Config& config) { os << config.binaryDataEncoderConfig << " indexed=\"" << boolalpha << config.indexed << "\""; return os; } } // namespace msdata } // namespace pwiz pwiz/pwiz/data/msdata/IO.cpp0000664000175100017510000026307312664775621017754 0ustar teamcityteamcity00000000000000// // $Id: IO.cpp 8934 2015-10-06 22:03:06Z pcbrefugee $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "IO.hpp" #include "References.hpp" #include "pwiz/utility/minimxml/SAXParser.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include "SpectrumWorkerThreads.hpp" namespace pwiz { namespace msdata { namespace IO { using namespace minimxml; using namespace minimxml::SAXParser; using namespace util; // // CV // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const CV& cv) { XMLWriter::Attributes attributes; attributes.add("id", encode_xml_id_copy(cv.id)); attributes.add("fullName", cv.fullName); attributes.add("version", cv.version); attributes.add("URI", cv.URI); writer.startElement("cv", attributes, XMLWriter::EmptyElement); } struct HandlerCV : public SAXParser::Handler { CV* cv; HandlerCV(CV* _cv = 0) : cv(_cv) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name != "cv") throw runtime_error(("[IO::HandlerCV] Unexpected element name: " + name).c_str()); decode_xml_id(getAttribute(attributes, "id", cv->id)); getAttribute(attributes, "fullName", cv->fullName); getAttribute(attributes, "version", cv->version); getAttribute(attributes, "URI", cv->URI); return Status::Ok; } }; PWIZ_API_DECL void read(std::istream& is, CV& cv) { HandlerCV handler(&cv); SAXParser::parse(is, handler); } // // UserParam // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const UserParam& userParam) { XMLWriter::Attributes attributes; attributes.add("name", userParam.name); if (!userParam.value.empty()) attributes.add("value", userParam.value); if (!userParam.type.empty()) attributes.add("type", userParam.type); if (userParam.units != CVID_Unknown) { attributes.add("unitAccession", cvTermInfo(userParam.units).id); attributes.add("unitName", cvTermInfo(userParam.units).name); } writer.startElement("userParam", attributes, XMLWriter::EmptyElement); } struct HandlerUserParam : public SAXParser::Handler { UserParam* userParam; HandlerUserParam(UserParam* _userParam = 0) : userParam(_userParam) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name != "userParam") throw runtime_error(("[IO::HandlerUserParam] Unexpected element name: " + name).c_str()); if (!userParam) throw runtime_error("[IO::HandlerUserParam] Null userParam."); getAttribute(attributes, "name", userParam->name); getAttribute(attributes, "value", userParam->value); getAttribute(attributes, "type", userParam->type); string unitAccession; getAttribute(attributes, "unitAccession", unitAccession); if (!unitAccession.empty()) userParam->units = cvTermInfo(unitAccession).cvid; return Status::Ok; } }; PWIZ_API_DECL void read(std::istream& is, UserParam& userParam) { HandlerUserParam handler(&userParam); SAXParser::parse(is, handler); } // // CVParam // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const CVParam& cvParam) { XMLWriter::Attributes attributes; attributes.add("cvRef", cvTermInfo(cvParam.cvid).prefix()); attributes.add("accession", cvTermInfo(cvParam.cvid).id); attributes.add("name", cvTermInfo(cvParam.cvid).name); attributes.add("value", cvParam.value); if (cvParam.units != CVID_Unknown) { attributes.add("unitCvRef", cvTermInfo(cvParam.units).prefix()); attributes.add("unitAccession", cvTermInfo(cvParam.units).id); attributes.add("unitName", cvTermInfo(cvParam.units).name); } writer.startElement("cvParam", attributes, XMLWriter::EmptyElement); } struct HandlerCVParam : public SAXParser::Handler { CVParam* cvParam; HandlerCVParam(CVParam* _cvParam = 0) : cvParam(_cvParam) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name != "cvParam") throw runtime_error(("[IO::HandlerCVParam] Unexpected element name: " + name).c_str()); if (!cvParam) throw runtime_error("[IO::HandlerCVParam] Null cvParam."); const char *accession = getAttribute(attributes, "accession", NoXMLUnescape); if (accession) cvParam->cvid = cvTermInfo(accession).cvid; getAttribute(attributes, "value", cvParam->value); const char *unitAccession = getAttribute(attributes, "unitAccession", NoXMLUnescape); if (unitAccession) cvParam->units = cvTermInfo(unitAccession).cvid; return Status::Ok; } }; PWIZ_API_DECL void read(std::istream& is, CVParam& cvParam) { HandlerCVParam handler(&cvParam); SAXParser::parse(is, handler); } // // ParamContainer // // // note: These are auxilliary functions to be called by ParamContainer subclasses // PWIZ_API_DECL void writeParamGroupRef(minimxml::XMLWriter& writer, const ParamGroup& paramGroup) { XMLWriter::Attributes attributes; attributes.add("ref", paramGroup.id); writer.startElement("referenceableParamGroupRef", attributes, XMLWriter::EmptyElement); } PWIZ_API_DECL void writeParamContainer(minimxml::XMLWriter& writer, const ParamContainer& pc) { for (vector::const_iterator it=pc.paramGroupPtrs.begin(); it!=pc.paramGroupPtrs.end(); ++it) writeParamGroupRef(writer, **it); for (vector::const_iterator it=pc.cvParams.begin(); it!=pc.cvParams.end(); ++it) write(writer, *it); for (vector::const_iterator it=pc.userParams.begin(); it!=pc.userParams.end(); ++it) write(writer, *it); } struct HandlerParamContainer : public SAXParser::Handler { ParamContainer* paramContainer; HandlerParamContainer(ParamContainer* _paramContainer = 0) : paramContainer(_paramContainer) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!paramContainer) throw runtime_error("[IO::HandlerParamContainer] Null paramContainer."); if (name == "cvParam") { paramContainer->cvParams.push_back(CVParam()); handlerCVParam_.cvParam = ¶mContainer->cvParams.back(); return Status(Status::Delegate, &handlerCVParam_); } else if (name == "userParam") { paramContainer->userParams.push_back(UserParam()); handlerUserParam_.userParam = ¶mContainer->userParams.back(); return Status(Status::Delegate, &handlerUserParam_); } else if (name == "referenceableParamGroupRef") { // note: placeholder string id; decode_xml_id(getAttribute(attributes, "ref", id)); if (!id.empty()) paramContainer->paramGroupPtrs.push_back(ParamGroupPtr(new ParamGroup(id))); return Status::Ok; } throw runtime_error(("[IO::HandlerParamContainer] Unknown element " + name).c_str()); } private: HandlerCVParam handlerCVParam_; HandlerUserParam handlerUserParam_; }; struct HandlerNamedParamContainer : public HandlerParamContainer { const string name_; HandlerNamedParamContainer(const string& name, ParamContainer* paramContainer = 0) : HandlerParamContainer(paramContainer), name_(name) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == name_) return Status::Ok; return HandlerParamContainer::startElement(name, attributes, position); } }; // // ParamGroup // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const ParamGroup& paramGroup) { XMLWriter::Attributes attributes; attributes.add("id", encode_xml_id_copy(paramGroup.id)); writer.startElement("referenceableParamGroup", attributes); writeParamContainer(writer, paramGroup); writer.endElement(); } struct HandlerParamGroup : public HandlerParamContainer { ParamGroup* paramGroup; HandlerParamGroup(ParamGroup* _paramGroup = 0) : paramGroup(_paramGroup) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!paramGroup) throw runtime_error("[IO::HandlerParamGroup] Null paramGroup."); if (name == "referenceableParamGroup") { decode_xml_id(getAttribute(attributes, "id", paramGroup->id)); return Status::Ok; } HandlerParamContainer::paramContainer = paramGroup; return HandlerParamContainer::startElement(name, attributes, position); } }; PWIZ_API_DECL void read(std::istream& is, ParamGroup& paramGroup) { HandlerParamGroup handler(¶mGroup); SAXParser::parse(is, handler); } // // FileContent // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const FileContent& fc) { writer.startElement("fileContent"); writeParamContainer(writer, fc); writer.endElement(); } PWIZ_API_DECL void read(std::istream& is, FileContent& fc) { HandlerNamedParamContainer handler("fileContent", &fc); SAXParser::parse(is, handler); } // // SourceFile // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const SourceFile& sf) { XMLWriter::Attributes attributes; attributes.add("id", encode_xml_id_copy(sf.id)); attributes.add("name", sf.name); attributes.add("location", sf.location); writer.startElement("sourceFile", attributes); writeParamContainer(writer, sf); writer.endElement(); } void writeSourceFileRef(minimxml::XMLWriter& writer, const SourceFile& sourceFile) { XMLWriter::Attributes attributes; attributes.add("ref", encode_xml_id_copy(sourceFile.id)); writer.startElement("sourceFileRef", attributes, XMLWriter::EmptyElement); } struct HandlerSourceFile : public HandlerParamContainer { SourceFile* sourceFile; HandlerSourceFile(SourceFile* _sourceFile = 0) : sourceFile(_sourceFile) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!sourceFile) throw runtime_error("[IO::HandlerSourceFile] Null sourceFile."); if (name == "sourceFile") { decode_xml_id(getAttribute(attributes, "id", sourceFile->id)); getAttribute(attributes, "name", sourceFile->name); getAttribute(attributes, "location", sourceFile->location); return Status::Ok; } HandlerParamContainer::paramContainer = sourceFile; return HandlerParamContainer::startElement(name, attributes, position); } }; PWIZ_API_DECL void read(std::istream& is, SourceFile& sf) { HandlerSourceFile handler(&sf); SAXParser::parse(is, handler); } // // Contact // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Contact& c) { writer.startElement("contact"); writeParamContainer(writer, c); writer.endElement(); } PWIZ_API_DECL void read(std::istream& is, Contact& c) { HandlerNamedParamContainer handler("contact", &c); SAXParser::parse(is, handler); } // // FileDescription // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const FileDescription& fd) { writer.startElement("fileDescription"); write(writer, fd.fileContent); XMLWriter::Attributes attributes; attributes.add("count", fd.sourceFilePtrs.size()); writer.startElement("sourceFileList", attributes); for (vector::const_iterator it=fd.sourceFilePtrs.begin(); it!=fd.sourceFilePtrs.end(); ++it) write(writer, **it); writer.endElement(); for (vector::const_iterator it=fd.contacts.begin(); it!=fd.contacts.end(); ++it) write(writer, *it); writer.endElement(); } struct HandlerFileDescription : public SAXParser::Handler { FileDescription* fileDescription; HandlerFileDescription(FileDescription* _fileDescription = 0) : fileDescription(_fileDescription), handlerFileContent_("fileContent"), handlerContact_("contact") {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!fileDescription) throw runtime_error("[IO::HandlerFileDescription] Null fileDescription."); if (name == "fileDescription") { return Status::Ok; } else if (name == "fileContent") { handlerFileContent_.paramContainer = &fileDescription->fileContent; return Status(Status::Delegate, &handlerFileContent_); } else if (name == "sourceFileList") { return Status::Ok; } else if (name == "sourceFile") { fileDescription->sourceFilePtrs.push_back(SourceFilePtr(new SourceFile)); handlerSourceFile_.sourceFile = fileDescription->sourceFilePtrs.back().get(); return Status(Status::Delegate, &handlerSourceFile_); } else if (name == "contact") { fileDescription->contacts.push_back(Contact()); handlerContact_.paramContainer = &fileDescription->contacts.back(); return Status(Status::Delegate, &handlerContact_); } throw runtime_error(("[IO::HandlerFileDescription] Unknown element " + name).c_str()); } private: HandlerNamedParamContainer handlerFileContent_; HandlerSourceFile handlerSourceFile_; HandlerNamedParamContainer handlerContact_; }; PWIZ_API_DECL void read(std::istream& is, FileDescription& fd) { HandlerFileDescription handler(&fd); SAXParser::parse(is, handler); } // // Sample // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Sample& sample) { XMLWriter::Attributes attributes; attributes.add("id", encode_xml_id_copy(sample.id)); attributes.add("name", sample.name); writer.startElement("sample", attributes); writeParamContainer(writer, sample); writer.endElement(); } struct HandlerSample : public HandlerParamContainer { Sample* sample; HandlerSample(Sample* _sample = 0) : sample(_sample) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!sample) throw runtime_error("[IO::HandlerSample] Null sample."); if (name == "sample") { decode_xml_id(getAttribute(attributes, "id", sample->id)); getAttribute(attributes, "name", sample->name); return Status::Ok; } HandlerParamContainer::paramContainer = sample; return HandlerParamContainer::startElement(name, attributes, position); } }; PWIZ_API_DECL void read(std::istream& is, Sample& sample) { HandlerSample handler(&sample); SAXParser::parse(is, handler); } // // Component (Source, Analyzer, Detector) // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Component& component) { XMLWriter::Attributes attributes; attributes.add("order", component.order); switch (component.type) { case ComponentType_Source: writer.startElement("source", attributes); break; case ComponentType_Analyzer: writer.startElement("analyzer", attributes); break; case ComponentType_Detector: writer.startElement("detector", attributes); break; case ComponentType_Unknown: throw runtime_error("[IO::write] Unknown component type."); } writeParamContainer(writer, component); writer.endElement(); } struct HandlerComponent : public HandlerParamContainer { Component* component; HandlerComponent(Component* _component = 0) : component(_component) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!component) throw runtime_error("[IO::HandlerComponent] Null component."); if (name=="source" || name=="analyzer" || name=="detector") { getAttribute(attributes, "order", component->order); return Status::Ok; } HandlerParamContainer::paramContainer = component; return HandlerParamContainer::startElement(name, attributes, position); } }; PWIZ_API_DECL void read(std::istream& is, Component& component) { HandlerComponent handler(&component); SAXParser::parse(is, handler); } // // ComponentList // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const ComponentList& componentList) { int count = (int) componentList.size(); XMLWriter::Attributes attributes; attributes.add("count", count); writer.startElement("componentList", attributes); for (size_t i=0; i < componentList.size(); ++i) write(writer, componentList[i]); writer.endElement(); } struct HandlerComponentList : public SAXParser::Handler { ComponentList* componentList; HandlerComponentList(ComponentList* _componentList = 0) : componentList(_componentList) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!componentList) throw runtime_error("[IO::HandlerComponentList] Null componentList."); if (name == "componentList") { return Status::Ok; } else if (name == "source") { componentList->push_back(Component(ComponentType_Source, 1)); handlerComponent_.component = &componentList->back(); return Status(Status::Delegate, &handlerComponent_); } else if (name == "analyzer") { componentList->push_back(Component(ComponentType_Analyzer, 1)); handlerComponent_.component = &componentList->back(); return Status(Status::Delegate, &handlerComponent_); } else if (name == "detector") { componentList->push_back(Component(ComponentType_Detector, 1)); handlerComponent_.component = &componentList->back(); return Status(Status::Delegate, &handlerComponent_); } throw runtime_error(("[IO::HandlerComponentList] Unexpected element name: " + name).c_str()); } private: HandlerComponent handlerComponent_; }; PWIZ_API_DECL void read(std::istream& is, ComponentList& componentList) { HandlerComponentList handler(&componentList); SAXParser::parse(is, handler); } // // Software // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Software& software) { XMLWriter::Attributes attributes; attributes.add("id", encode_xml_id_copy(software.id)); attributes.add("version", software.version); writer.startElement("software", attributes); writeParamContainer(writer, software); writer.endElement(); } struct HandlerSoftware : public HandlerParamContainer { Software* software; HandlerSoftware(Software* _software = 0) : software(_software) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!software) throw runtime_error("[IO::HandlerSoftware] Null software."); if (name == "software") { decode_xml_id(getAttribute(attributes, "id", software->id)); getAttribute(attributes, "version", software->version); return Status::Ok; } // mzML 1.0 else if (version == 1 && name == "softwareParam") { string accession; getAttribute(attributes, "accession", accession); if (!accession.empty()) software->set(cvTermInfo(accession).cvid); getAttribute(attributes, "version", software->version); return Status::Ok; } HandlerParamContainer::paramContainer = software; return HandlerParamContainer::startElement(name, attributes, position); } }; PWIZ_API_DECL void read(std::istream& is, Software& software) { HandlerSoftware handler(&software); SAXParser::parse(is, handler); } // // InstrumentConfiguration // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const InstrumentConfiguration& instrumentConfiguration) { XMLWriter::Attributes attributes; attributes.add("id", encode_xml_id_copy(instrumentConfiguration.id)); writer.startElement("instrumentConfiguration", attributes); writeParamContainer(writer, instrumentConfiguration); if (!instrumentConfiguration.componentList.empty()) // optional element write(writer, instrumentConfiguration.componentList); if (instrumentConfiguration.softwarePtr.get()) { attributes.clear(); attributes.add("ref", encode_xml_id_copy(instrumentConfiguration.softwarePtr->id)); writer.startElement("softwareRef", attributes, XMLWriter::EmptyElement); } writer.endElement(); } struct HandlerInstrumentConfiguration : public HandlerParamContainer { InstrumentConfiguration* instrumentConfiguration; HandlerInstrumentConfiguration(InstrumentConfiguration* _instrumentConfiguration = 0) : instrumentConfiguration(_instrumentConfiguration) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!instrumentConfiguration) throw runtime_error("[IO::HandlerInstrumentConfiguration] Null instrumentConfiguration."); if (name == "instrumentConfiguration") { decode_xml_id(getAttribute(attributes, "id", instrumentConfiguration->id)); return Status::Ok; } else if (name == "componentList") { handlerComponentList_.componentList = &instrumentConfiguration->componentList; return Status(Status::Delegate, &handlerComponentList_); } else if (name == "softwareRef") { // note: placeholder string ref; decode_xml_id(getAttribute(attributes, "ref", ref)); if (!ref.empty()) instrumentConfiguration->softwarePtr = SoftwarePtr(new Software(ref)); return Status::Ok; } HandlerParamContainer::paramContainer = instrumentConfiguration; return HandlerParamContainer::startElement(name, attributes, position); } private: HandlerComponentList handlerComponentList_; }; PWIZ_API_DECL void read(std::istream& is, InstrumentConfiguration& instrumentConfiguration) { HandlerInstrumentConfiguration handler(&instrumentConfiguration); SAXParser::parse(is, handler); } // // ProcessingMethod // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const ProcessingMethod& processingMethod) { XMLWriter::Attributes attributes; attributes.add("order", processingMethod.order); if (processingMethod.softwarePtr.get()) attributes.add("softwareRef", encode_xml_id_copy(processingMethod.softwarePtr->id)); writer.startElement("processingMethod", attributes); writeParamContainer(writer, processingMethod); writer.endElement(); } struct HandlerProcessingMethod : public HandlerParamContainer { ProcessingMethod* processingMethod; string defaultSoftwareRef; HandlerProcessingMethod(ProcessingMethod* _processingMethod = 0) : processingMethod(_processingMethod) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!processingMethod) throw runtime_error("[IO::HandlerProcessingMethod] Null processingMethod."); if (name == "processingMethod") { getAttribute(attributes, "order", processingMethod->order); // note: placeholder string softwareRef; decode_xml_id(getAttribute(attributes, "softwareRef", softwareRef)); if (!softwareRef.empty()) processingMethod->softwarePtr = SoftwarePtr(new Software(softwareRef)); else if (!defaultSoftwareRef.empty()) processingMethod->softwarePtr = SoftwarePtr(new Software(defaultSoftwareRef)); return Status::Ok; } HandlerParamContainer::paramContainer = processingMethod; return HandlerParamContainer::startElement(name, attributes, position); } }; PWIZ_API_DECL void read(std::istream& is, ProcessingMethod& processingMethod) { HandlerProcessingMethod handler(&processingMethod); SAXParser::parse(is, handler); } // // DataProcessing // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const DataProcessing& dataProcessing) { XMLWriter::Attributes attributes; attributes.add("id", encode_xml_id_copy(dataProcessing.id)); writer.startElement("dataProcessing", attributes); for (vector::const_iterator it=dataProcessing.processingMethods.begin(); it!=dataProcessing.processingMethods.end(); ++it) write(writer, *it); writer.endElement(); } struct HandlerDataProcessing : public HandlerParamContainer { DataProcessing* dataProcessing; HandlerDataProcessing(DataProcessing* _dataProcessing = 0) : dataProcessing(_dataProcessing) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!dataProcessing) throw runtime_error("[IO::HandlerDataProcessing] Null dataProcessing."); if (name == "dataProcessing") { decode_xml_id(getAttribute(attributes, "id", dataProcessing->id)); // mzML 1.0 if (version == 1) { string softwareRef; getAttribute(attributes, "softwareRef", softwareRef); if (!softwareRef.empty()) handlerProcessingMethod_.defaultSoftwareRef = softwareRef; } return Status::Ok; } else if (name == "processingMethod") { dataProcessing->processingMethods.push_back(ProcessingMethod()); handlerProcessingMethod_.processingMethod = &dataProcessing->processingMethods.back(); return Status(Status::Delegate, &handlerProcessingMethod_); } throw runtime_error(("[IO::HandlerDataProcessing] Unexpected element name: " + name).c_str()); } private: HandlerProcessingMethod handlerProcessingMethod_; }; PWIZ_API_DECL void read(std::istream& is, DataProcessing& dataProcessing) { HandlerDataProcessing handler(&dataProcessing); SAXParser::parse(is, handler); } // // Target // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Target& t) { writer.startElement("target"); writeParamContainer(writer, t); writer.endElement(); } PWIZ_API_DECL void read(std::istream& is, Target& t) { HandlerNamedParamContainer handler("target", &t); SAXParser::parse(is, handler); } // // ScanSettings // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const ScanSettings& scanSettings) { XMLWriter::Attributes attributes; attributes.add("id", encode_xml_id_copy(scanSettings.id)); writer.startElement("scanSettings", attributes); if (!scanSettings.sourceFilePtrs.empty()) { attributes.clear(); attributes.add("count", scanSettings.sourceFilePtrs.size()); writer.startElement("sourceFileRefList", attributes); for (vector::const_iterator it=scanSettings.sourceFilePtrs.begin(); it!=scanSettings.sourceFilePtrs.end(); ++it) writeSourceFileRef(writer, **it); writer.endElement(); // sourceFileRefList } if (!scanSettings.targets.empty()) { XMLWriter::Attributes attributes; attributes.add("count", scanSettings.targets.size()); writer.startElement("targetList", attributes); for (vector::const_iterator it=scanSettings.targets.begin(); it!=scanSettings.targets.end(); ++it) write(writer, *it); writer.endElement(); // targetList } writer.endElement(); } struct HandlerScanSettings : public HandlerParamContainer { ScanSettings* scanSettings; HandlerScanSettings(ScanSettings* _scanSettings = 0) : scanSettings(_scanSettings), handlerTarget_("target") {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!scanSettings) throw runtime_error("[IO::HandlerScanSettings] Null scanSettings."); if ((version == 1 && name == "acquisitionSettings") /* mzML 1.0 */ || name == "scanSettings") { decode_xml_id(getAttribute(attributes, "id", scanSettings->id)); return Status::Ok; } else if (name=="sourceFileRefList" || name=="targetList") { return Status::Ok; } else if (name=="sourceFileRef") { // note: placeholder string sourceFileRef; decode_xml_id(getAttribute(attributes, "ref", sourceFileRef)); if (!sourceFileRef.empty()) scanSettings->sourceFilePtrs.push_back(SourceFilePtr(new SourceFile(sourceFileRef))); return Status::Ok; } else if (name=="target") { scanSettings->targets.push_back(Target()); handlerTarget_.paramContainer = &scanSettings->targets.back(); return Status(Status::Delegate, &handlerTarget_); } throw runtime_error(("[IO::HandlerScanSettings] Unexpected element name: " + name).c_str()); } private: HandlerNamedParamContainer handlerTarget_; }; PWIZ_API_DECL void read(std::istream& is, ScanSettings& scanSettings) { HandlerScanSettings handler(&scanSettings); SAXParser::parse(is, handler); } // // IsolationWindow // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const IsolationWindow& isolationWindow) { writer.startElement("isolationWindow"); writeParamContainer(writer, isolationWindow); writer.endElement(); } PWIZ_API_DECL void read(std::istream& is, IsolationWindow& isolationWindow) { HandlerNamedParamContainer handler("isolationWindow", &isolationWindow); SAXParser::parse(is, handler); } // // SelectedIon // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const SelectedIon& selectedIon) { writer.startElement("selectedIon"); writeParamContainer(writer, selectedIon); writer.endElement(); } PWIZ_API_DECL void read(std::istream& is, SelectedIon& selectedIon) { HandlerNamedParamContainer handler("selectedIon", &selectedIon); SAXParser::parse(is, handler); } // // Activation // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Activation& activation) { writer.startElement("activation"); writeParamContainer(writer, activation); writer.endElement(); } PWIZ_API_DECL void read(std::istream& is, Activation& activation) { HandlerNamedParamContainer handler("activation", &activation); SAXParser::parse(is, handler); } // // Precursor // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Precursor& precursor) { XMLWriter::Attributes attributes; if (precursor.spectrumID.empty()) { if (!precursor.externalSpectrumID.empty()) { if (!precursor.sourceFilePtr.get()) throw runtime_error("[IO::write] External spectrum references must refer to a source file"); attributes.add("sourceFileRef", encode_xml_id_copy(precursor.sourceFilePtr->id)); attributes.add("externalSpectrumID", precursor.externalSpectrumID); } } else attributes.add("spectrumRef", precursor.spectrumID); // not an XML:IDREF writer.startElement("precursor", attributes); writeParamContainer(writer, precursor); if (!precursor.isolationWindow.empty()) { writer.startElement("isolationWindow"); writeParamContainer(writer, precursor.isolationWindow); writer.endElement(); // isolationWindow } if (!precursor.selectedIons.empty()) { attributes.clear(); attributes.add("count", precursor.selectedIons.size()); writer.startElement("selectedIonList", attributes); for (vector::const_iterator it=precursor.selectedIons.begin(); it!=precursor.selectedIons.end(); ++it) { writer.startElement("selectedIon"); writeParamContainer(writer, *it); writer.endElement(); // selectedIon } writer.endElement(); // selectedIonList } writer.startElement("activation"); writeParamContainer(writer, precursor.activation); writer.endElement(); // activation writer.endElement(); } struct HandlerPrecursor : public HandlerParamContainer { Precursor* precursor; const map* legacyIdRefToNativeId; HandlerPrecursor(Precursor* _precursor = 0, const map* legacyIdRefToNativeId = 0) : precursor(_precursor), legacyIdRefToNativeId(legacyIdRefToNativeId), handlerIsolationWindow_("isolationWindow"), handlerSelectedIon_("selectedIon"), handlerActivation_("activation") {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!precursor) throw runtime_error("[IO::HandlerPrecursor] Null precursor."); if (name == "precursor") { getAttribute(attributes, "spectrumRef", precursor->spectrumID); // not an XML:IDREF getAttribute(attributes, "externalSpectrumID", precursor->externalSpectrumID); // mzML 1.0 if (version == 1 && legacyIdRefToNativeId && !precursor->spectrumID.empty()) { map::const_iterator itr = legacyIdRefToNativeId->find(precursor->spectrumID); if (itr != legacyIdRefToNativeId->end()) precursor->spectrumID = itr->second; } // note: placeholder string sourceFileRef; decode_xml_id(getAttribute(attributes, "sourceFileRef", sourceFileRef)); if (!sourceFileRef.empty()) precursor->sourceFilePtr = SourceFilePtr(new SourceFile(sourceFileRef)); return Status::Ok; } else if (name == "isolationWindow") { handlerIsolationWindow_.paramContainer = &precursor->isolationWindow; return Status(Status::Delegate, &handlerIsolationWindow_); } else if (name == "selectedIon") { precursor->selectedIons.push_back(SelectedIon()); handlerSelectedIon_.paramContainer = &precursor->selectedIons.back(); return Status(Status::Delegate, &handlerSelectedIon_); } else if (name == "activation") { handlerActivation_.paramContainer = &precursor->activation; return Status(Status::Delegate, &handlerActivation_); } else if (name == "selectedIonList") { return Status::Ok; } HandlerParamContainer::paramContainer = precursor; return HandlerParamContainer::startElement(name, attributes, position); } private: HandlerNamedParamContainer handlerIsolationWindow_; HandlerNamedParamContainer handlerSelectedIon_; HandlerNamedParamContainer handlerActivation_; }; PWIZ_API_DECL void read(std::istream& is, Precursor& precursor, const map* legacyIdRefToNativeId) { HandlerPrecursor handler(&precursor, legacyIdRefToNativeId); SAXParser::parse(is, handler); } // // Product // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Product& product) { XMLWriter::Attributes attributes; writer.startElement("product", attributes); if (!product.isolationWindow.empty()) { writer.startElement("isolationWindow"); writeParamContainer(writer, product.isolationWindow); writer.endElement(); // isolationWindow } writer.endElement(); } struct HandlerProduct : public SAXParser::Handler { Product* product; HandlerProduct(Product* _product = 0) : product(_product), handlerIsolationWindow_("isolationWindow") {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!product) throw runtime_error("[IO::HandlerProduct] Null product."); if (name == "product") { return Status::Ok; } else if (name == "isolationWindow") { handlerIsolationWindow_.paramContainer = &product->isolationWindow; return Status(Status::Delegate, &handlerIsolationWindow_); } throw runtime_error(("[IO::HandlerProduct] Unknown element " + name).c_str()); } private: HandlerNamedParamContainer handlerIsolationWindow_; }; PWIZ_API_DECL void read(std::istream& is, Product& product) { HandlerProduct handler(&product); SAXParser::parse(is, handler); } // // ScanWindow // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const ScanWindow& scanWindow) { writer.startElement("scanWindow"); writeParamContainer(writer, scanWindow); writer.endElement(); } PWIZ_API_DECL void read(std::istream& is, ScanWindow& scanWindow) { HandlerNamedParamContainer handler("scanWindow", &scanWindow); SAXParser::parse(is, handler); } // // Scan // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Scan& scan, const MSData& msd) { XMLWriter::Attributes attributes; if (scan.spectrumID.empty()) { if (!scan.externalSpectrumID.empty()) { if (!scan.sourceFilePtr.get()) throw runtime_error("[IO::write] External spectrum references must refer to a source file"); attributes.add("sourceFileRef", encode_xml_id_copy(scan.sourceFilePtr->id)); attributes.add("externalSpectrumID", scan.externalSpectrumID); } } else attributes.add("spectrumRef", scan.spectrumID); // not an XML:IDREF // don't write the instrumentConfigurationRef if it's set to the default const InstrumentConfigurationPtr& defaultIC = msd.run.defaultInstrumentConfigurationPtr; if (scan.instrumentConfigurationPtr.get() && (!defaultIC.get() || scan.instrumentConfigurationPtr != defaultIC)) attributes.add("instrumentConfigurationRef", encode_xml_id_copy(scan.instrumentConfigurationPtr->id)); writer.startElement("scan", attributes); writeParamContainer(writer, scan); if (!scan.scanWindows.empty()) { attributes.clear(); attributes.add("count", scan.scanWindows.size()); writer.startElement("scanWindowList", attributes); for (vector::const_iterator it=scan.scanWindows.begin(); it!=scan.scanWindows.end(); ++it) write(writer, *it); writer.endElement(); } writer.endElement(); } struct HandlerScan : public HandlerParamContainer { Scan* scan; HandlerScan(Scan* _scan = 0) : scan(_scan), handlerScanWindow_("scanWindow") {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!scan) throw runtime_error("[IO::HandlerScan] Null scan."); if (name != "cvParam") { // most common, but not handled here if (name == "scan") { getAttribute(attributes, "spectrumRef", scan->spectrumID); // not an XML:IDREF getAttribute(attributes, "externalSpectrumID", scan->externalSpectrumID); // note: placeholder string sourceFileRef; decode_xml_id(getAttribute(attributes, "sourceFileRef", sourceFileRef)); if (!sourceFileRef.empty()) scan->sourceFilePtr = SourceFilePtr(new SourceFile(sourceFileRef)); // note: placeholder string instrumentConfigurationRef; decode_xml_id(getAttribute(attributes, "instrumentConfigurationRef", instrumentConfigurationRef)); if (!instrumentConfigurationRef.empty()) scan->instrumentConfigurationPtr = InstrumentConfigurationPtr(new InstrumentConfiguration(instrumentConfigurationRef)); return Status::Ok; } else if (version == 1 && name == "acquisition") { // note: spectrumRef, externalNativeID, and externalSpectrumID are mutually exclusive getAttribute(attributes, "spectrumRef", scan->spectrumID); // not an XML:IDREF if (scan->spectrumID.empty()) { string externalNativeID; getAttribute(attributes, "externalNativeID", externalNativeID); if (externalNativeID.empty()) getAttribute(attributes, "externalSpectrumID", scan->externalSpectrumID); else try { lexical_cast(externalNativeID); //cerr << "[IO::HandlerScan] Warning - mzML 1.0: ::externalNativeID\n"; scan->externalSpectrumID = "scan=" + externalNativeID; } catch(exception&) { //cerr << "[IO::HandlerScan] Warning - mzML 1.0: non-integral ::externalNativeID; externalSpectrumID format unknown\n"; scan->externalSpectrumID = externalNativeID; } } // note: placeholder string sourceFileRef; decode_xml_id(getAttribute(attributes, "sourceFileRef", sourceFileRef)); if (!sourceFileRef.empty()) scan->sourceFilePtr = SourceFilePtr(new SourceFile(sourceFileRef)); return Status::Ok; } else if (name == "scanWindowList") { return Status::Ok; } else if (name == "scanWindow") { scan->scanWindows.push_back(ScanWindow()); handlerScanWindow_.paramContainer = &scan->scanWindows.back(); return Status(Status::Delegate, &handlerScanWindow_); } } // end if not cvParam HandlerParamContainer::paramContainer = scan; return HandlerParamContainer::startElement(name, attributes, position); } private: HandlerNamedParamContainer handlerScanWindow_; }; PWIZ_API_DECL void read(std::istream& is, Scan& scan) { HandlerScan handler(&scan); SAXParser::parse(is, handler); } // // ScanList // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const ScanList& scanList, const MSData& msd) { XMLWriter::Attributes attributes; attributes.add("count", scanList.scans.size()); writer.startElement("scanList", attributes); writeParamContainer(writer, scanList); for (vector::const_iterator it=scanList.scans.begin(); it!=scanList.scans.end(); ++it) write(writer, *it, msd); writer.endElement(); } struct HandlerScanList : public HandlerParamContainer { ScanList* scanList; HandlerScanList(ScanList* _scanList = 0) : scanList(_scanList) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!scanList) throw runtime_error("[IO::HandlerScanList] Null scanList."); if (name == "scanList" || name == "acquisitionList") { return Status::Ok; } else if (name == "scan" || name == "acquisition") { scanList->scans.push_back(Scan()); handlerScan_.version = version; handlerScan_.scan = &scanList->scans.back(); return Status(Status::Delegate, &handlerScan_); } HandlerParamContainer::paramContainer = scanList; return HandlerParamContainer::startElement(name, attributes, position); } private: HandlerScan handlerScan_; }; PWIZ_API_DECL void read(std::istream& is, ScanList& scanList) { HandlerScanList handler(&scanList); SAXParser::parse(is, handler); } // // BinaryData // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const BinaryDataArray& binaryDataArray, const BinaryDataEncoder::Config& config) { BinaryDataEncoder::Config usedConfig = config; map::const_iterator overrideItr = config.precisionOverrides.find(binaryDataArray.cvParamChild(MS_binary_data_array).cvid); if (overrideItr != config.precisionOverrides.end()) usedConfig.precision = overrideItr->second; map::const_iterator n_overrideItr = config.numpressOverrides.find(binaryDataArray.cvParamChild(MS_binary_data_array).cvid); if (n_overrideItr != config.numpressOverrides.end()) usedConfig.numpress = n_overrideItr->second; BinaryDataEncoder encoder(usedConfig); string encoded; encoder.encode(binaryDataArray.data, encoded); usedConfig = encoder.getConfig(); // config may have changed if numpress error was excessive XMLWriter::Attributes attributes; // primary array types can never override the default array length if (!binaryDataArray.hasCVParam(MS_m_z_array) && !binaryDataArray.hasCVParam(MS_time_array) && !binaryDataArray.hasCVParam(MS_intensity_array)) { attributes.add("arrayLength", binaryDataArray.data.size()); } attributes.add("encodedLength", encoded.size()); if (binaryDataArray.dataProcessingPtr.get()) attributes.add("dataProcessingRef", encode_xml_id_copy(binaryDataArray.dataProcessingPtr->id)); writer.startElement("binaryDataArray", attributes); if (BinaryDataEncoder::Numpress_None == usedConfig.numpress) { if (usedConfig.precision == BinaryDataEncoder::Precision_32) write(writer, MS_32_bit_float); else write(writer, MS_64_bit_float); } if (usedConfig.byteOrder == BinaryDataEncoder::ByteOrder_BigEndian) throw runtime_error("[IO::write()] mzML: must use little endian encoding."); switch (usedConfig.compression) { case BinaryDataEncoder::Compression_None: if (BinaryDataEncoder::Numpress_None == usedConfig.numpress) write(writer, MS_no_compression); break; case BinaryDataEncoder::Compression_Zlib: write(writer, MS_zlib_compression); break; default: throw runtime_error("[IO::write()] Unsupported compression method."); break; } switch (usedConfig.numpress) { case BinaryDataEncoder::Numpress_Linear: write(writer, MS_32_bit_float); // This should actually be ignored by any reader since numpress defines word size and format, but it makes output standards-compliant and is pretty close to true anyway write(writer, MS_MS_Numpress_linear_prediction_compression); break; case BinaryDataEncoder::Numpress_Pic: write(writer, MS_32_bit_integer); // This should actually be ignored by any reader since numpress defines word size and format, but it makes output standards-compliant and is pretty close to true anyway write(writer, MS_MS_Numpress_positive_integer_compression); break; case BinaryDataEncoder::Numpress_Slof: write(writer, MS_32_bit_float); // This should actually be ignored by any reader since numpress defines word size and format, but it makes output standards-compliant and is pretty close to true anyway write(writer, MS_MS_Numpress_short_logged_float_compression); break; case BinaryDataEncoder::Numpress_None: break; default: throw runtime_error("[IO::write()] Unsupported numpress method."); break; } writeParamContainer(writer, binaryDataArray); writer.pushStyle(XMLWriter::StyleFlag_InlineInner); writer.startElement("binary"); writer.characters(encoded, false); // base64 doesn't use any reserved characters writer.endElement(); writer.popStyle(); writer.endElement(); } struct HandlerBinaryDataArray : public HandlerParamContainer { BinaryDataArray* binaryDataArray; const MSData* msd; size_t defaultArrayLength; BinaryDataEncoder::Config config; HandlerBinaryDataArray(BinaryDataArray* _binaryDataArray = 0, const MSData* _msd = 0) : binaryDataArray(_binaryDataArray), msd(_msd), defaultArrayLength(0), arrayLength_(0), encodedLength_(0) { parseCharacters = true; autoUnescapeCharacters = false; } virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!binaryDataArray) throw runtime_error("[IO::HandlerBinaryDataArray] Null binaryDataArray."); if (name != "cvParam") // most common, but not handled here { if (name == "binaryDataArray") { // note: placeholder string dataProcessingRef; decode_xml_id(getAttribute(attributes, "dataProcessingRef", dataProcessingRef)); if (!dataProcessingRef.empty()) binaryDataArray->dataProcessingPtr = DataProcessingPtr(new DataProcessing(dataProcessingRef)); getAttribute(attributes, "encodedLength", encodedLength_, NoXMLUnescape); getAttribute(attributes, "arrayLength", arrayLength_, NoXMLUnescape, defaultArrayLength); return Status::Ok; } else if (name == "binary") { if (msd) References::resolve(*binaryDataArray, *msd); config = getConfig(); return Status::Ok; } } // end if not cvParam HandlerParamContainer::paramContainer = binaryDataArray; return HandlerParamContainer::startElement(name, attributes, position); } virtual Status characters(const SAXParser::saxstring& text, stream_offset position) { if (!binaryDataArray) throw runtime_error("[IO::HandlerBinaryDataArray] Null binaryDataArray."); BinaryDataEncoder encoder(config); encoder.decode(text.c_str(), text.length(), binaryDataArray->data); if (binaryDataArray->data.size() != arrayLength_) throw runtime_error((format("[IO::HandlerBinaryDataArray] At position %d: expected array of size %d, but decoded array is actually size %d.") % position % arrayLength_ % binaryDataArray->data.size()).str()); if (text.length() != encodedLength_) throw runtime_error("[IO::HandlerBinaryDataArray] At position " + lexical_cast(position) + ": encoded lengths differ."); return Status::Ok; } private: size_t arrayLength_; size_t encodedLength_; CVID extractCVParam(ParamContainer& container, CVID cvid) { vector& params = container.cvParams; vector::iterator it = find_if(params.begin(), params.end(), CVParamIsChildOf(cvid)); CVID result = CVID_Unknown; if (it != params.end()) { // found the cvid in container -- erase the CVParam result = it->cvid; params.erase(it); } else { // didn't find it -- search recursively, but don't erase anything CVParam temp = container.cvParamChild(cvid); result = temp.cvid; } return result; } void extractCVParams(ParamContainer& container, CVID cvid, vector &results) { vector& params = container.cvParams; vector::iterator it; while ((it = find_if(params.begin(), params.end(),CVParamIsChildOf(cvid))) != params.end()) { // found the cvid in container -- erase the CVParam results.push_back(it->cvid); params.erase(it); } // also search recursively, but don't erase anything vector CVParams = container.cvParamChildren(cvid); BOOST_FOREACH(const CVParam& cvParam, CVParams) results.push_back(cvParam.cvid); } BinaryDataEncoder::Config getConfig() { if (!binaryDataArray) throw runtime_error("[IO::HandlerBinaryDataArray] Null binaryDataArray."); BinaryDataEncoder::Config config; // // Note: these CVParams are really info about the encoding, and not // part of the BinaryDataArray. We look at them to see how to decode the data, // and remove them from the BinaryDataArray struct (extractCVParam does the removal). // CVID cvidBinaryDataType = extractCVParam(*binaryDataArray, MS_binary_data_type); // handle mix of zlib and numpress compression CVID cvidCompressionType; config.compression = BinaryDataEncoder::Compression_None; config.numpress = BinaryDataEncoder::Numpress_None; vector children; extractCVParams(*binaryDataArray, MS_binary_data_compression_type, children); BOOST_FOREACH(cvidCompressionType,children) { switch (cvidCompressionType) { case MS_no_compression: config.compression = BinaryDataEncoder::Compression_None; break; case MS_zlib_compression: config.compression = BinaryDataEncoder::Compression_Zlib; break; case MS_MS_Numpress_linear_prediction_compression: config.numpress = BinaryDataEncoder::Numpress_Linear; break; case MS_MS_Numpress_positive_integer_compression: config.numpress = BinaryDataEncoder::Numpress_Pic; break; case MS_MS_Numpress_short_logged_float_compression: config.numpress = BinaryDataEncoder::Numpress_Slof; break; default: throw runtime_error("[IO::HandlerBinaryDataArray] Unknown compression type."); } } switch (cvidBinaryDataType) { case MS_32_bit_float: if (BinaryDataEncoder::Numpress_None == config.numpress) config.precision = BinaryDataEncoder::Precision_32; break; case MS_64_bit_float: config.precision = BinaryDataEncoder::Precision_64; break; case MS_32_bit_integer: case CVID_Unknown: if (BinaryDataEncoder::Numpress_None == config.numpress) // 32 vs 64 bit is meaningless in numpress throw runtime_error("[IO::HandlerBinaryDataArray] Missing binary data type."); break; default: throw runtime_error("[IO::HandlerBinaryDataArray] Unknown binary data type."); } return config; } }; PWIZ_API_DECL void read(std::istream& is, BinaryDataArray& binaryDataArray, const MSData* msd) { HandlerBinaryDataArray handler(&binaryDataArray, msd); SAXParser::parse(is, handler); } // // Spectrum // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Spectrum& spectrum, const MSData& msd, const BinaryDataEncoder::Config& config) { XMLWriter::Attributes attributes; attributes.add("index", spectrum.index); attributes.add("id", spectrum.id); // not an XML:ID if (!spectrum.spotID.empty()) attributes.add("spotID", spectrum.spotID); attributes.add("defaultArrayLength", spectrum.defaultArrayLength); if (spectrum.dataProcessingPtr.get()) attributes.add("dataProcessingRef", encode_xml_id_copy(spectrum.dataProcessingPtr->id)); if (spectrum.sourceFilePtr.get()) attributes.add("sourceFileRef", encode_xml_id_copy(spectrum.sourceFilePtr->id)); writer.startElement("spectrum", attributes); writeParamContainer(writer, spectrum); write(writer, spectrum.scanList, msd); if (!spectrum.precursors.empty()) { XMLWriter::Attributes attributes; attributes.add("count", spectrum.precursors.size()); writer.startElement("precursorList", attributes); for (vector::const_iterator it=spectrum.precursors.begin(); it!=spectrum.precursors.end(); ++it) write(writer, *it); writer.endElement(); } if (!spectrum.products.empty()) { XMLWriter::Attributes attributes; attributes.add("count", spectrum.products.size()); writer.startElement("productList", attributes); for (vector::const_iterator it=spectrum.products.begin(); it!=spectrum.products.end(); ++it) write(writer, *it); writer.endElement(); } if (!spectrum.binaryDataArrayPtrs.empty()) { attributes.clear(); attributes.add("count", spectrum.binaryDataArrayPtrs.size()); writer.startElement("binaryDataArrayList", attributes); for (vector::const_iterator it=spectrum.binaryDataArrayPtrs.begin(); it!=spectrum.binaryDataArrayPtrs.end(); ++it) write(writer, **it, config); writer.endElement(); // binaryDataArrayList } writer.endElement(); // spectrum } struct HandlerSpectrum : public HandlerParamContainer { BinaryDataFlag binaryDataFlag; Spectrum* spectrum; const SpectrumIdentityFromXML *spectrumID; const map* legacyIdRefToNativeId; const MSData* msd; HandlerSpectrum(BinaryDataFlag _binaryDataFlag, Spectrum* _spectrum = 0, const map* legacyIdRefToNativeId = 0, const MSData* _msd = 0, const SpectrumIdentityFromXML *_spectrumID = 0) : binaryDataFlag(_binaryDataFlag), spectrum(_spectrum), spectrumID(_spectrumID), legacyIdRefToNativeId(legacyIdRefToNativeId), msd(_msd), handlerPrecursor_(0, legacyIdRefToNativeId) { } virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!spectrum) throw runtime_error("[IO::HandlerSpectrum] Null spectrum."); if (name != "cvParam") // the most common, but not handled here { if (name == "spectrum") { spectrum->sourceFilePosition = position; getAttribute(attributes, "index", spectrum->index); getAttribute(attributes, "spotID", spectrum->spotID); getAttribute(attributes, "defaultArrayLength", spectrum->defaultArrayLength); getAttribute(attributes, "id", spectrum->id); // not an XML:ID // mzML 1.0 if (version == 1 && legacyIdRefToNativeId) { map::const_iterator itr = legacyIdRefToNativeId->find(spectrum->id); if (itr != legacyIdRefToNativeId->end()) spectrum->id = itr->second; } // note: placeholder string dataProcessingRef; decode_xml_id(getAttribute(attributes, "dataProcessingRef", dataProcessingRef)); if (!dataProcessingRef.empty()) spectrum->dataProcessingPtr = DataProcessingPtr(new DataProcessing(dataProcessingRef)); // note: placeholder string sourceFileRef; decode_xml_id(getAttribute(attributes, "sourceFileRef", sourceFileRef)); if (!sourceFileRef.empty()) spectrum->sourceFilePtr = SourceFilePtr(new SourceFile(sourceFileRef)); return Status::Ok; } else if (version == 1 && name == "acquisitionList" /* mzML 1.0 */ || name == "scanList") { handlerScanList_.scanList = &spectrum->scanList; handlerScanList_.version = version; return Status(Status::Delegate, &handlerScanList_); } else if (name == "precursorList" || name == "productList") { return Status::Ok; } else if (name == "precursor") { spectrum->precursors.push_back(Precursor()); handlerPrecursor_.precursor = &spectrum->precursors.back(); handlerPrecursor_.version = version; return Status(Status::Delegate, &handlerPrecursor_); } else if (name == "product") { spectrum->products.push_back(Product()); handlerProduct_.product = &spectrum->products.back(); return Status(Status::Delegate, &handlerProduct_); } else if (name == "binaryDataArray") { if (binaryDataFlag == IgnoreBinaryData) return Status::Done; spectrum->binaryDataArrayPtrs.push_back(BinaryDataArrayPtr(new BinaryDataArray())); handlerBinaryDataArray_.binaryDataArray = spectrum->binaryDataArrayPtrs.back().get(); handlerBinaryDataArray_.defaultArrayLength = spectrum->defaultArrayLength; handlerBinaryDataArray_.msd = msd; return Status(Status::Delegate, &handlerBinaryDataArray_); } else if (name == "binaryDataArrayList") { // pretty likely to come right back here and read the // binary data once the header info has been inspected, // so note position if (spectrumID) { spectrumID->sourceFilePositionForBinarySpectrumData = position; } return Status::Ok; } else if (version == 1 && name == "spectrumDescription") // mzML 1.0 { // read cvParams, userParams, and referenceableParamGroups in into return Status::Ok; } else if (version == 1 && name == "scan") // mzML 1.0 { spectrum->scanList.scans.push_back(Scan()); handlerScan_.version = version; handlerScan_.scan = &spectrum->scanList.scans.back(); return Status(Status::Delegate, &handlerScan_); } } // end if name != cvParam HandlerParamContainer::paramContainer = spectrum; return HandlerParamContainer::startElement(name, attributes, position); } private: HandlerScanList handlerScanList_; HandlerPrecursor handlerPrecursor_; HandlerProduct handlerProduct_; HandlerBinaryDataArray handlerBinaryDataArray_; HandlerScan handlerScan_; }; PWIZ_API_DECL void read(std::istream& is, Spectrum& spectrum, BinaryDataFlag binaryDataFlag, int version, const map* legacyIdRefToNativeId, const MSData* msd, const SpectrumIdentityFromXML *id) { HandlerSpectrum handler(binaryDataFlag, &spectrum, legacyIdRefToNativeId, msd, id); handler.version = version; SAXParser::parse(is, handler); } // // Chromatogram // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Chromatogram& chromatogram, const BinaryDataEncoder::Config& config) { XMLWriter::Attributes attributes; attributes.add("index", chromatogram.index); attributes.add("id", chromatogram.id); // not an XML:ID attributes.add("defaultArrayLength", chromatogram.defaultArrayLength); if (chromatogram.dataProcessingPtr.get()) attributes.add("dataProcessingRef", encode_xml_id_copy(chromatogram.dataProcessingPtr->id)); writer.startElement("chromatogram", attributes); writeParamContainer(writer, chromatogram); if (!chromatogram.precursor.empty()) write(writer, chromatogram.precursor); if (!chromatogram.product.empty()) write(writer, chromatogram.product); if (!chromatogram.binaryDataArrayPtrs.empty()) { attributes.clear(); attributes.add("count", chromatogram.binaryDataArrayPtrs.size()); writer.startElement("binaryDataArrayList", attributes); for (vector::const_iterator it=chromatogram.binaryDataArrayPtrs.begin(); it!=chromatogram.binaryDataArrayPtrs.end(); ++it) write(writer, **it, config); writer.endElement(); // binaryDataArrayList } writer.endElement(); // spectrum } struct HandlerChromatogram : public HandlerParamContainer { BinaryDataFlag binaryDataFlag; Chromatogram* chromatogram; HandlerChromatogram(BinaryDataFlag _binaryDataFlag, Chromatogram* _chromatogram = 0) : binaryDataFlag(_binaryDataFlag), chromatogram(_chromatogram) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!chromatogram) throw runtime_error("[IO::HandlerChromatogram] Null chromatogram."); if (name == "chromatogram") { chromatogram->sourceFilePosition = position; getAttribute(attributes, "id", chromatogram->id); // not an XML:ID getAttribute(attributes, "index", chromatogram->index); getAttribute(attributes, "defaultArrayLength", chromatogram->defaultArrayLength); // note: placeholder string dataProcessingRef; decode_xml_id(getAttribute(attributes, "dataProcessingRef", dataProcessingRef)); if (!dataProcessingRef.empty()) chromatogram->dataProcessingPtr = DataProcessingPtr(new DataProcessing(dataProcessingRef)); return Status::Ok; } else if (name == "precursor") { handlerPrecursor_.precursor = &chromatogram->precursor; return Status(Status::Delegate, &handlerPrecursor_); } else if (name == "product") { handlerProduct_.product = &chromatogram->product; return Status(Status::Delegate, &handlerProduct_); } else if (name == "binaryDataArray") { if (binaryDataFlag == IgnoreBinaryData) return Status::Done; chromatogram->binaryDataArrayPtrs.push_back(BinaryDataArrayPtr(new BinaryDataArray())); handlerBinaryDataArray_.binaryDataArray = chromatogram->binaryDataArrayPtrs.back().get(); handlerBinaryDataArray_.defaultArrayLength = chromatogram->defaultArrayLength; return Status(Status::Delegate, &handlerBinaryDataArray_); } else if (name == "binaryDataArrayList") { return Status::Ok; } HandlerParamContainer::paramContainer = chromatogram; return HandlerParamContainer::startElement(name, attributes, position); } private: HandlerPrecursor handlerPrecursor_; HandlerProduct handlerProduct_; HandlerBinaryDataArray handlerBinaryDataArray_; }; PWIZ_API_DECL void read(std::istream& is, Chromatogram& chromatogram, BinaryDataFlag binaryDataFlag) { HandlerChromatogram handler(binaryDataFlag, &chromatogram); SAXParser::parse(is, handler); } // // SpectrumList // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const SpectrumList& spectrumList, const MSData& msd, const BinaryDataEncoder::Config& config, vector* spectrumPositions, const IterationListenerRegistry* iterationListenerRegistry) { XMLWriter::Attributes attributes; attributes.add("count", spectrumList.size()); if (spectrumList.dataProcessingPtr().get()) attributes.push_back(make_pair("defaultDataProcessingRef", spectrumList.dataProcessingPtr()->id)); writer.startElement("spectrumList", attributes); SpectrumWorkerThreads spectrumWorkers(spectrumList); for (size_t i=0; ibroadcastUpdateMessage( IterationListener::UpdateMessage(i, spectrumList.size())); if (status == IterationListener::Status_Cancel) break; // save write position if (spectrumPositions) spectrumPositions->push_back(writer.positionNext()); // write the spectrum //SpectrumPtr spectrum = spectrumList.spectrum(i, true); SpectrumPtr spectrum = spectrumWorkers.processBatch(i); BOOST_ASSERT(spectrum->binaryDataArrayPtrs.empty() || spectrum->defaultArrayLength == spectrum->getMZArray()->data.size()); if (spectrum->index != i) throw runtime_error("[IO::write(SpectrumList)] Bad index."); write(writer, *spectrum, msd, config); } writer.endElement(); } struct HandlerSpectrumListSimple : public HandlerParamContainer { SpectrumListSimple* spectrumListSimple; HandlerSpectrumListSimple(SpectrumListSimple* _spectrumListSimple = 0) : spectrumListSimple(_spectrumListSimple), handlerSpectrum_(ReadBinaryData) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!spectrumListSimple) throw runtime_error("[IO::HandlerSpectrumListSimple] Null spectrumListSimple."); if (name == "spectrumList") { // note: placeholder string defaultDataProcessingRef; decode_xml_id(getAttribute(attributes, "defaultDataProcessingRef", defaultDataProcessingRef)); if (!defaultDataProcessingRef.empty()) spectrumListSimple->dp = DataProcessingPtr(new DataProcessing(defaultDataProcessingRef)); return Status::Ok; } else if (name == "spectrum") { spectrumListSimple->spectra.push_back(SpectrumPtr(new Spectrum)); handlerSpectrum_.version = version; handlerSpectrum_.spectrum = spectrumListSimple->spectra.back().get(); return Status(Status::Delegate, &handlerSpectrum_); } throw runtime_error(("[IO::HandlerSpectrumListSimple] Unexpected element name: " + name).c_str()); } private: HandlerSpectrum handlerSpectrum_; }; PWIZ_API_DECL void read(std::istream& is, SpectrumListSimple& spectrumListSimple) { HandlerSpectrumListSimple handler(&spectrumListSimple); SAXParser::parse(is, handler); } // // ChromatogramList // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const ChromatogramList& chromatogramList, const BinaryDataEncoder::Config& config, vector* chromatogramPositions, const IterationListenerRegistry* iterationListenerRegistry) { XMLWriter::Attributes attributes; attributes.add("count", chromatogramList.size()); if (chromatogramList.dataProcessingPtr().get()) attributes.push_back(make_pair("defaultDataProcessingRef", chromatogramList.dataProcessingPtr()->id)); writer.startElement("chromatogramList", attributes); for (size_t i=0; ibroadcastUpdateMessage( IterationListener::UpdateMessage(i, chromatogramList.size())); if (status == IterationListener::Status_Cancel) break; // save write position if (chromatogramPositions) chromatogramPositions->push_back(writer.positionNext()); // write the chromatogram ChromatogramPtr chromatogram = chromatogramList.chromatogram(i, true); if (chromatogram->index != i) throw runtime_error("[IO::write(ChromatogramList)] Bad index."); write(writer, *chromatogram, config); } writer.endElement(); } struct HandlerChromatogramListSimple : public HandlerParamContainer { ChromatogramListSimple* chromatogramListSimple; HandlerChromatogramListSimple(ChromatogramListSimple* _chromatogramListSimple = 0) : chromatogramListSimple(_chromatogramListSimple), handlerChromatogram_(ReadBinaryData) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!chromatogramListSimple) throw runtime_error("[IO::HandlerChromatogramListSimple] Null chromatogramListSimple."); if (name == "chromatogramList") { // note: placeholder string defaultDataProcessingRef; decode_xml_id(getAttribute(attributes, "defaultDataProcessingRef", defaultDataProcessingRef)); if (!defaultDataProcessingRef.empty()) chromatogramListSimple->dp = DataProcessingPtr(new DataProcessing(defaultDataProcessingRef)); return Status::Ok; } else if (name == "chromatogram") { chromatogramListSimple->chromatograms.push_back(ChromatogramPtr(new Chromatogram)); handlerChromatogram_.chromatogram = chromatogramListSimple->chromatograms.back().get(); return Status(Status::Delegate, &handlerChromatogram_); } throw runtime_error(("[IO::HandlerChromatogramListSimple] Unexpected element name: " + name).c_str()); } private: HandlerChromatogram handlerChromatogram_; }; PWIZ_API_DECL void read(std::istream& is, ChromatogramListSimple& chromatogramListSimple) { HandlerChromatogramListSimple handler(&chromatogramListSimple); SAXParser::parse(is, handler); } // // Run // PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Run& run, const MSData& msd, const BinaryDataEncoder::Config& config, vector* spectrumPositions, vector* chromatogramPositions, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry) { XMLWriter::Attributes attributes; attributes.add("id", encode_xml_id_copy(run.id)); // defaultInstrumentConfigurationPtr is mandatory for schematic validity; // at least one (possibly unknown) instrument configuration is mandatory for schematic validity; // therefore we set this attribute to a reasonable default if the client didn't set it if (run.defaultInstrumentConfigurationPtr.get()) attributes.add("defaultInstrumentConfigurationRef", encode_xml_id_copy(run.defaultInstrumentConfigurationPtr->id)); else if (!msd.instrumentConfigurationPtrs.empty()) attributes.add("defaultInstrumentConfigurationRef", encode_xml_id_copy(msd.instrumentConfigurationPtrs.front()->id)); else attributes.add("defaultInstrumentConfigurationRef", "IC"); if (run.samplePtr.get()) attributes.add("sampleRef", encode_xml_id_copy(run.samplePtr->id)); if (!run.startTimeStamp.empty()) attributes.add("startTimeStamp", run.startTimeStamp); if (run.defaultSourceFilePtr.get()) attributes.add("defaultSourceFileRef", encode_xml_id_copy(run.defaultSourceFilePtr->id)); writer.startElement("run", attributes); writeParamContainer(writer, run); bool hasSpectrumList = run.spectrumListPtr.get() && run.spectrumListPtr->size() > 0; bool hasChromatogramList = run.chromatogramListPtr.get() && run.chromatogramListPtr->size() > 0; if (hasSpectrumList) write(writer, *run.spectrumListPtr, msd, config, spectrumPositions, iterationListenerRegistry); if (hasChromatogramList) write(writer, *run.chromatogramListPtr, config, chromatogramPositions, iterationListenerRegistry); writer.endElement(); } struct HandlerRun : public HandlerParamContainer { SpectrumListFlag spectrumListFlag; Run* run; HandlerRun(SpectrumListFlag _spectrumListFlag, Run* _run = 0) : spectrumListFlag(_spectrumListFlag), run(_run) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!run) throw runtime_error("[IO::HandlerRun] Null run."); if (name == "run") { decode_xml_id(getAttribute(attributes, "id", run->id)); getAttribute(attributes, "startTimeStamp", run->startTimeStamp); // note: placeholder string defaultInstrumentConfigurationRef; decode_xml_id(getAttribute(attributes, "defaultInstrumentConfigurationRef", defaultInstrumentConfigurationRef)); if (!defaultInstrumentConfigurationRef.empty()) run->defaultInstrumentConfigurationPtr = InstrumentConfigurationPtr(new InstrumentConfiguration(defaultInstrumentConfigurationRef)); // note: placeholder string sampleRef; decode_xml_id(getAttribute(attributes, "sampleRef", sampleRef)); if (!sampleRef.empty()) run->samplePtr = SamplePtr(new Sample(sampleRef)); // note: placeholder string defaultSourceFileRef; decode_xml_id(getAttribute(attributes, "defaultSourceFileRef", defaultSourceFileRef)); if (!defaultSourceFileRef.empty()) run->defaultSourceFilePtr = SourceFilePtr(new SourceFile(defaultSourceFileRef)); return Status::Ok; } else if (name == "spectrumList") { if (spectrumListFlag == IgnoreSpectrumList) return Status::Done; shared_ptr temp(new SpectrumListSimple); handlerSpectrumListSimple_.spectrumListSimple = temp.get(); run->spectrumListPtr = temp; return Status(Status::Delegate, &handlerSpectrumListSimple_); } else if (name == "chromatogramList") { shared_ptr temp(new ChromatogramListSimple); handlerChromatogramListSimple_.chromatogramListSimple = temp.get(); run->chromatogramListPtr = temp; return Status(Status::Delegate, &handlerChromatogramListSimple_); } else if (version == 1 && name == "sourceFileRefList") { return Status::Ok; } else if (version == 1 && name == "sourceFileRef") { // note: placeholder string sourceFileRef; decode_xml_id(getAttribute(attributes, "ref", sourceFileRef)); if (!sourceFileRef.empty()) run->defaultSourceFilePtr = SourceFilePtr(new SourceFile(sourceFileRef)); return Status::Ok; } HandlerParamContainer::paramContainer = run; return HandlerParamContainer::startElement(name, attributes, position); } private: HandlerSpectrumListSimple handlerSpectrumListSimple_; HandlerChromatogramListSimple handlerChromatogramListSimple_; }; PWIZ_API_DECL void read(std::istream& is, Run& run, SpectrumListFlag spectrumListFlag) { HandlerRun handler(spectrumListFlag, &run); SAXParser::parse(is, handler); } // // MSData // template void writeList(minimxml::XMLWriter& writer, const vector& objectPtrs, const string& label) { if (!objectPtrs.empty()) { XMLWriter::Attributes attributes; attributes.add("count", objectPtrs.size()); writer.startElement(label, attributes); for (typename vector::const_iterator it=objectPtrs.begin(); it!=objectPtrs.end(); ++it) write(writer, **it); writer.endElement(); } } PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const MSData& msd, const BinaryDataEncoder::Config& config, vector* spectrumPositions, vector* chromatogramPositions, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry) { XMLWriter::Attributes attributes; attributes.add("xmlns", "http://psi.hupo.org/ms/mzml"); attributes.add("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); attributes.add("xsi:schemaLocation", "http://psi.hupo.org/ms/mzml http://psidev.info/files/ms/mzML/xsd/mzML" + msd.version() + ".xsd"); if (!msd.accession.empty()) attributes.add("accession", msd.accession); attributes.add("id", msd.id); // not an XML:ID attributes.add("version", msd.version()); writer.startElement("mzML", attributes); if (!msd.cvs.empty()) { attributes.clear(); attributes.add("count", msd.cvs.size()); writer.startElement("cvList", attributes); for (vector::const_iterator it=msd.cvs.begin(); it!=msd.cvs.end(); ++it) write(writer, *it); writer.endElement(); } write(writer, msd.fileDescription); writeList(writer, msd.paramGroupPtrs, "referenceableParamGroupList"); writeList(writer, msd.samplePtrs, "sampleList"); writeList(writer, msd.softwarePtrs, "softwareList"); writeList(writer, msd.scanSettingsPtrs, "scanSettingsList"); // instrumentConfigurationList and at least one instrumentConfiguration is mandatory for schematic validity if (msd.instrumentConfigurationPtrs.empty()) { // the base term "instrument model" indicates the instrument is unknown vector list(1, InstrumentConfigurationPtr(new InstrumentConfiguration("IC"))); list.back()->set(MS_instrument_model); writeList(writer, list, "instrumentConfigurationList"); } else writeList(writer, msd.instrumentConfigurationPtrs, "instrumentConfigurationList"); writeList(writer, msd.allDataProcessingPtrs(), "dataProcessingList"); write(writer, msd.run, msd, config, spectrumPositions, chromatogramPositions, iterationListenerRegistry); writer.endElement(); } struct HandlerMSData : public SAXParser::Handler { MSData* msd; HandlerMSData(SpectrumListFlag spectrumListFlag, MSData* _msd = 0) : msd(_msd), handlerRun_(spectrumListFlag) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (!msd) throw runtime_error("[IO::HandlerMSData] Null msd."); if (name == "mzML") { getAttribute(attributes, "accession", msd->accession); getAttribute(attributes, "id", msd->id); // not an XML:ID // "http://psi.hupo.org/ms/mzml http://psidev.info/files/ms/mzML/xsd/mzML.xsd" string schemaLocation; getAttribute(attributes, "xsi:schemaLocation", schemaLocation); if (schemaLocation.empty()) getAttribute(attributes, "version", msd->version_); // deprecated? else { schemaLocation = schemaLocation.substr(schemaLocation.find(' ')+1); string xsdName = BFS_STRING(bfs::path(schemaLocation).filename()); msd->version_ = xsdName.substr(4, xsdName.length()-8); // read between "mzML" and ".xsd" } if (msd->version_.find("1.0") == 0) version = 1; return Status::Ok; } else if (name == "cvList" || name == "referenceableParamGroupList" || name == "sampleList" || name == "instrumentConfigurationList" || name == "softwareList" || name == "dataProcessingList" || (version == 1 && name == "acquisitionSettingsList") /* mzML 1.0 */ || name == "scanSettingsList") { // ignore these, unless we want to validate the count attribute return Status::Ok; } else if (name == "cv") { msd->cvs.push_back(CV()); handlerCV_.cv = &msd->cvs.back(); return Status(Status::Delegate, &handlerCV_); } else if (name == "fileDescription") { handlerFileDescription_.fileDescription = &msd->fileDescription; return Status(Status::Delegate, &handlerFileDescription_); } else if (name == "referenceableParamGroup") { msd->paramGroupPtrs.push_back(ParamGroupPtr(new ParamGroup)); handlerParamGroup_.paramGroup = msd->paramGroupPtrs.back().get(); return Status(Status::Delegate, &handlerParamGroup_); } else if (name == "sample") { msd->samplePtrs.push_back(SamplePtr(new Sample)); handlerSample_.sample = msd->samplePtrs.back().get(); return Status(Status::Delegate, &handlerSample_); } else if (name == "instrumentConfiguration") { msd->instrumentConfigurationPtrs.push_back(InstrumentConfigurationPtr(new InstrumentConfiguration)); handlerInstrumentConfiguration_.instrumentConfiguration = msd->instrumentConfigurationPtrs.back().get(); return Status(Status::Delegate, &handlerInstrumentConfiguration_); } else if (name == "software") { msd->softwarePtrs.push_back(SoftwarePtr(new Software)); handlerSoftware_.version = version; handlerSoftware_.software = msd->softwarePtrs.back().get(); return Status(Status::Delegate, &handlerSoftware_); } else if (name == "dataProcessing") { msd->dataProcessingPtrs.push_back(DataProcessingPtr(new DataProcessing)); handlerDataProcessing_.version = version; handlerDataProcessing_.dataProcessing = msd->dataProcessingPtrs.back().get(); return Status(Status::Delegate, &handlerDataProcessing_); } else if (version == 1 && name == "acquisitionSettings" /* mzML 1.0 */ || name == "scanSettings") { msd->scanSettingsPtrs.push_back(ScanSettingsPtr(new ScanSettings)); handlerScanSettings_.version = version; handlerScanSettings_.scanSettings = msd->scanSettingsPtrs.back().get(); return Status(Status::Delegate, &handlerScanSettings_); } else if (name == "run") { handlerRun_.version = version; handlerRun_.run = &msd->run; return Status(Status::Delegate, &handlerRun_); } throw runtime_error(("[IO::HandlerMSData] Unexpected element name: " + name).c_str()); } private: HandlerCV handlerCV_; HandlerFileDescription handlerFileDescription_; HandlerParamGroup handlerParamGroup_; HandlerSample handlerSample_; HandlerInstrumentConfiguration handlerInstrumentConfiguration_; HandlerSoftware handlerSoftware_; HandlerDataProcessing handlerDataProcessing_; HandlerScanSettings handlerScanSettings_; HandlerRun handlerRun_; }; PWIZ_API_DECL void read(std::istream& is, MSData& msd, SpectrumListFlag spectrumListFlag) { HandlerMSData handler(spectrumListFlag, &msd); SAXParser::parse(is, handler); References::resolve(msd); } } // namespace IO } // namespace msdata } // namespace pwiz pwiz/pwiz/data/msdata/SpectrumInfo.hpp0000664000175100017510000000422312664775620022055 0ustar teamcityteamcity00000000000000// // $Id: SpectrumInfo.hpp 2842 2011-07-07 22:11:07Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMINFO_HPP_ #define _SPECTRUMINFO_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "MSData.hpp" namespace pwiz { namespace msdata { /// simple structure for holding Spectrum info struct PWIZ_API_DECL SpectrumInfo { /// structure for Precursor info struct PWIZ_API_DECL PrecursorInfo { size_t index; double mz; double intensity; double charge; PrecursorInfo() : index((size_t)-1), mz(0), intensity(0), charge(0) {} }; size_t index; std::string id; int scanNumber; CVID massAnalyzerType; int scanEvent; int msLevel; bool isZoomScan; double retentionTime; // seconds std::string filterString; double mzLow; double mzHigh; double basePeakMZ; double basePeakIntensity; double totalIonCurrent; double thermoMonoisotopicMZ; double ionInjectionTime; std::vector precursors; size_t dataSize; std::vector data; SpectrumInfo(); SpectrumInfo(const Spectrum& spectrum); void update(const Spectrum& spectrum, bool getBinaryData = false); void clearBinaryData(); // some helper functions std::string massAnalyzerTypeAbbreviation() const; double mzFromFilterString() const; }; } // namespace msdata } // namespace pwiz #endif // _SPECTRUMINFO_HPP_ pwiz/pwiz/data/msdata/MSData.cpp0000664000175100017510000010106612664775621020547 0ustar teamcityteamcity00000000000000// // $Id: MSData.cpp 6452 2014-07-03 19:01:15Z pcbrefugee $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "MSData.hpp" #include "pwiz/utility/misc/Std.hpp" #include #include "Diff.hpp" namespace pwiz { namespace msdata { using namespace pwiz::cv; using namespace pwiz::data; PWIZ_API_DECL vector defaultCVList() { vector result; result.resize(2); result[0] = cv::cv("MS"); result[1] = cv::cv("UO"); return result; } // // SourceFile // PWIZ_API_DECL SourceFile::SourceFile(const string _id, const string _name, const string _location) : id(_id), name(_name), location(_location) {} PWIZ_API_DECL bool SourceFile::empty() const { return id.empty() && name.empty() && location.empty() && ParamContainer::empty(); } // // FileDescription // PWIZ_API_DECL bool FileDescription::empty() const { return fileContent.empty() && sourceFilePtrs.empty() && contacts.empty(); } // // Sample // PWIZ_API_DECL Sample::Sample(const string _id, const string _name) : id(_id), name(_name) {} PWIZ_API_DECL bool Sample::empty() const { return id.empty() && name.empty() && ParamContainer::empty(); } // // Component // PWIZ_API_DECL void Component::define(CVID cvid, int order) { cvParams.clear(); cvParams.push_back(cvid); this->order = order; if (cvIsA(cvid, MS_ionization_type)) type = ComponentType_Source; else if (cvIsA(cvid, MS_mass_analyzer_type)) type = ComponentType_Analyzer; else if (cvIsA(cvid, MS_detector_type)) type = ComponentType_Detector; else throw runtime_error(("[Component::define] Error determining component type for term \"" + cvTermInfo(cvid).name + "\"")); } PWIZ_API_DECL bool Component::empty() const { return order==0 && ParamContainer::empty(); } // // ComponentList // PWIZ_API_DECL Component& ComponentList::source(size_t index) { size_t count = 0; for (size_t i=0; i < size(); ++i) { Component& c = at(i); if (c.type == ComponentType_Source) { if (count == index) return c; ++count; } } throw out_of_range((boost::format("[ComponentList::source] Source %d is out of range; only found %d sources") % index % count).str()); } PWIZ_API_DECL Component& ComponentList::analyzer(size_t index) { size_t count = 0; for (size_t i=0; i < size(); ++i) { Component& c = at(i); if (c.type == ComponentType_Analyzer) { if (count == index) return c; ++count; } } throw out_of_range((boost::format("[ComponentList::analyzer] Analyzer %d is out of range; only found %d analyzers") % index % count).str()); } PWIZ_API_DECL Component& ComponentList::detector(size_t index) { size_t count = 0; for (size_t i=0; i < size(); ++i) { Component& c = at(i); if (c.type == ComponentType_Detector) { if (count == index) return c; ++count; } } throw out_of_range((boost::format("[ComponentList::detector] Detector %d is out of range; only found %d detectors") % index % count).str()); } PWIZ_API_DECL const Component& ComponentList::source(size_t index) const { return const_cast(this)->source(index); } PWIZ_API_DECL const Component& ComponentList::analyzer(size_t index) const { return const_cast(this)->analyzer(index); } PWIZ_API_DECL const Component& ComponentList::detector(size_t index) const { return const_cast(this)->detector(index); } // // Software // PWIZ_API_DECL bool Software::empty() const { return id.empty() && version.empty() && ParamContainer::empty(); } // // This constructor is a workaround for an MSVC internal compiler error. // For some reason MSVC doesn't like this default argument, but won't say why: // const CVParam& _cvParam = CVParam(), // PWIZ_API_DECL Software::Software(const string& _id) : id(_id) {} PWIZ_API_DECL Software::Software(const string& _id, const CVParam& _param, const string& _version) : id(_id), version(_version) { cvParams.push_back(_param); } // // InstrumentConfiguration // PWIZ_API_DECL InstrumentConfiguration::InstrumentConfiguration(const string& _id) : id(_id) {} PWIZ_API_DECL bool InstrumentConfiguration::empty() const { return id.empty() && componentList.empty() && (!softwarePtr.get() || softwarePtr->empty()) && ParamContainer::empty(); } // // ProcessingMethod // PWIZ_API_DECL bool ProcessingMethod::empty() const { return order==0 && (!softwarePtr.get() || softwarePtr->empty()) && ParamContainer::empty(); } // // DataProcessing // PWIZ_API_DECL DataProcessing::DataProcessing(const string& _id) : id(_id) {} PWIZ_API_DECL bool DataProcessing::empty() const { return id.empty() && processingMethods.empty(); } // // ScanSettings // PWIZ_API_DECL ScanSettings::ScanSettings(const string& _id) : id(_id) {} PWIZ_API_DECL bool ScanSettings::empty() const { return id.empty() && sourceFilePtrs.empty() && targets.empty(); } // // SelectedIon // PWIZ_API_DECL SelectedIon::SelectedIon(double mz) { set(MS_selected_ion_m_z, mz, MS_m_z); } PWIZ_API_DECL SelectedIon::SelectedIon(double mz, double intensity, CVID intensityUnit) { set(MS_selected_ion_m_z, mz, MS_m_z); set(MS_peak_intensity, intensity, intensityUnit); } PWIZ_API_DECL SelectedIon::SelectedIon(double mz, int chargeState) { set(MS_selected_ion_m_z, mz, MS_m_z); set(MS_charge_state, boost::lexical_cast(chargeState)); } PWIZ_API_DECL SelectedIon::SelectedIon(double mz, double intensity, int chargeState, CVID intensityUnit) { set(MS_selected_ion_m_z, mz, MS_m_z); set(MS_peak_intensity, intensity, intensityUnit); set(MS_charge_state, boost::lexical_cast(chargeState)); } // // Precursor // PWIZ_API_DECL Precursor::Precursor(double mz) { selectedIons.push_back(SelectedIon(mz)); } PWIZ_API_DECL Precursor::Precursor(double mz, double intensity, CVID intensityUnit) { selectedIons.push_back(SelectedIon(mz, intensity, intensityUnit)); } PWIZ_API_DECL Precursor::Precursor(double mz, int chargeState) { selectedIons.push_back(SelectedIon(mz, chargeState)); } PWIZ_API_DECL Precursor::Precursor(double mz, double intensity, int chargeState, CVID intensityUnit) { selectedIons.push_back(SelectedIon(mz, intensity, chargeState, intensityUnit)); } PWIZ_API_DECL bool Precursor::empty() const { return (!sourceFilePtr.get() || sourceFilePtr->empty()) && spectrumID.empty() && isolationWindow.empty() && selectedIons.empty() && activation.empty() && ParamContainer::empty(); } // // Product // PWIZ_API_DECL bool Product::empty() const { return (isolationWindow.empty()); } PWIZ_API_DECL bool Product::operator==(const Product& that) const { return isolationWindow == that.isolationWindow; } // // ScanWindow // PWIZ_API_DECL ScanWindow::ScanWindow(double low, double high, CVID unit) { set(MS_scan_window_lower_limit, low, unit); set(MS_scan_window_upper_limit, high, unit); } // // Scan // PWIZ_API_DECL bool Scan::empty() const { return (!instrumentConfigurationPtr.get() || instrumentConfigurationPtr->empty()) && scanWindows.empty() && ParamContainer::empty(); } // // ScanList // PWIZ_API_DECL bool ScanList::empty() const { return scans.empty() && ParamContainer::empty(); } // // BinaryDataArray // PWIZ_API_DECL bool BinaryDataArray::empty() const { return (!dataProcessingPtr.get() || dataProcessingPtr->empty()) && data.empty() && ParamContainer::empty(); } // // MZIntensityPair // PWIZ_API_DECL ostream& operator<<(ostream& os, const MZIntensityPair& mzi) { os << "(" << mzi.mz << "," << mzi.intensity << ")"; return os; } PWIZ_API_DECL bool MZIntensityPair::operator==(const MZIntensityPair& that) const { return mz == that.mz && intensity == that.intensity; } // // TimeIntensityPair // PWIZ_API_DECL ostream& operator<<(ostream& os, const TimeIntensityPair& ti) { os << "(" << ti.time << "," << ti.intensity << ")"; return os; } PWIZ_API_DECL bool TimeIntensityPair::operator==(const TimeIntensityPair& that) const { return time == that.time && intensity == that.intensity; } // // id // namespace id { pair stringToPair(const string& nameValuePair) { string::size_type indexEquals = nameValuePair.find('='); if (indexEquals==string::npos || indexEquals+1>=nameValuePair.size()) throw runtime_error(("[MSData::stringToPair] Bad format: " + nameValuePair).c_str()); return make_pair(nameValuePair.substr(0,indexEquals), nameValuePair.substr(indexEquals+1)); } PWIZ_API_DECL map parse(const string& id) { vector pairs; boost::split(pairs, id, boost::is_any_of(" \t\n\r")); map result; transform(pairs.begin(), pairs.end(), inserter(result, result.end()), stringToPair); return result; } PWIZ_API_DECL string value(const string& id, const string& name) { map temp = parse(id); return temp[name]; } PWIZ_API_DECL CVID getDefaultNativeIDFormat(const MSData& msd) { CVID result = CVID_Unknown; if (msd.run.defaultSourceFilePtr.get()) result = msd.run.defaultSourceFilePtr->cvParamChild(MS_nativeID_format).cvid; else if (!msd.fileDescription.sourceFilePtrs.empty()) result = msd.fileDescription.sourceFilePtrs[0]->cvParamChild(MS_nativeID_format).cvid; if (( CVID_Unknown == result ) && (msd.version().find("1.0") == 0)) result = MS_scan_number_only_nativeID_format; return result; } PWIZ_API_DECL string translateScanNumberToNativeID(CVID nativeIdFormat, const string& scanNumber) { switch (nativeIdFormat) { case MS_Thermo_nativeID_format: return "controllerType=0 controllerNumber=1 scan=" + scanNumber; case MS_spectrum_identifier_nativeID_format: return "spectrum=" + scanNumber; case MS_multiple_peak_list_nativeID_format: return "index=" + scanNumber; case MS_Agilent_MassHunter_nativeID_format: return "scanId=" + scanNumber; case MS_Bruker_Agilent_YEP_nativeID_format: case MS_Bruker_BAF_nativeID_format: case MS_scan_number_only_nativeID_format: return "scan=" + scanNumber; default: return ""; } } PWIZ_API_DECL string translateNativeIDToScanNumber(CVID nativeIdFormat, const string& id) { switch (nativeIdFormat) { case MS_spectrum_identifier_nativeID_format: // mzData return value(id, "spectrum"); case MS_multiple_peak_list_nativeID_format: // MGF return value(id, "index"); case MS_Agilent_MassHunter_nativeID_format: return value(id, "scanId"); case MS_Thermo_nativeID_format: // conversion from Thermo nativeIDs assumes default controller information if (id.find("controllerType=0 controllerNumber=1") != 0) return ""; // fall through to get scan case MS_Bruker_Agilent_YEP_nativeID_format: case MS_Bruker_BAF_nativeID_format: case MS_scan_number_only_nativeID_format: return value(id, "scan"); default: if (bal::starts_with(id, "scan=")) return value(id, "scan"); else if (bal::starts_with(id, "index=")) return value(id, "index"); return ""; } } string abbreviate(const string& id, char delimiter /*= '.'*/) { string result; size_t indexEquals, indexSpace = 0; do { if (!result.empty()) result += delimiter; indexEquals = id.find('=', indexSpace); if (indexEquals == string::npos) throw runtime_error("[MSData::id::abbreviate] Bad format: " + id); indexSpace = id.find(' ', indexEquals+1); if (indexSpace == string::npos) result += id.substr(indexEquals+1); else result += id.substr(indexEquals+1, indexSpace-indexEquals-1); } while (indexSpace != string::npos); return result; } } // namespace id // // Spectrum // PWIZ_API_DECL bool Spectrum::empty() const { return index==IDENTITY_INDEX_NONE && id.empty() && defaultArrayLength==0 && (!dataProcessingPtr.get() || dataProcessingPtr->empty()) && (!sourceFilePtr.get() || sourceFilePtr->empty()) && scanList.empty() && precursors.empty() && products.empty() && binaryDataArrayPtrs.empty() && ParamContainer::empty(); } namespace { pair getMZIntensityArrays(const vector& ptrs) { BinaryDataArrayPtr mzArray; BinaryDataArrayPtr intensityArray; for (vector::const_iterator it=ptrs.begin(); it!=ptrs.end(); ++it) { if (((*it)->hasCVParam(MS_m_z_array) || (*it)->hasCVParam(MS_wavelength_array)) && !mzArray.get()) mzArray = *it; if ((*it)->hasCVParam(MS_intensity_array) && !intensityArray.get()) intensityArray = *it; } return make_pair(mzArray, intensityArray); } } // namespace PWIZ_API_DECL void Spectrum::getMZIntensityPairs(vector& output) const { // retrieve and validate m/z and intensity arrays pair arrays = getMZIntensityArrays(binaryDataArrayPtrs); if (!arrays.first.get() || !arrays.second.get()) return; if (arrays.first->data.size() != arrays.second->data.size()) throw runtime_error("[MSData::Spectrum::getMZIntensityPairs()] Sizes do not match."); output.clear(); output.resize(arrays.first->data.size()); if (!output.empty()) { double* mz = &arrays.first->data[0]; double* intensity = &arrays.second->data[0]; MZIntensityPair* start = &output[0]; for (MZIntensityPair* p = start; p != start + output.size(); ++p) { p->mz = *mz++; p->intensity = *intensity++; } } } PWIZ_API_DECL void Spectrum::getMZIntensityPairs(MZIntensityPair* output, size_t expectedSize) const { // retrieve and validate m/z and intensity arrays pair arrays = getMZIntensityArrays(binaryDataArrayPtrs); // if either array is absent, do not modify the output if (!arrays.first.get() || !arrays.second.get()) return; if (arrays.first->data.size() != expectedSize) throw runtime_error("[MSData::Spectrum::getMZIntensityPairs()] m/z array invalid size."); if (arrays.second->data.size() != expectedSize) throw runtime_error("[MSData::Spectrum::getMZIntensityPairs()] Intensity array invalid size."); if (!output) throw runtime_error("[MSData::Spectrum::getMZIntensityPairs()] Null output buffer."); // copy data into return buffer double* mz = &arrays.first->data[0]; double* intensity = &arrays.second->data[0]; for (MZIntensityPair* p=output; p!=output+expectedSize; ++p) { p->mz = *mz++; p->intensity = *intensity++; } } PWIZ_API_DECL BinaryDataArrayPtr Spectrum::getMZArray() const { for (vector::const_iterator it = binaryDataArrayPtrs.begin(); it != binaryDataArrayPtrs.end(); ++it) { if ((*it)->hasCVParam(MS_m_z_array) || (*it)->hasCVParam(MS_wavelength_array)) return *it; } return BinaryDataArrayPtr(); } PWIZ_API_DECL BinaryDataArrayPtr Spectrum::getIntensityArray() const { for (vector::const_iterator it = binaryDataArrayPtrs.begin(); it != binaryDataArrayPtrs.end(); ++it) { if ((*it)->hasCVParam(MS_intensity_array)) return *it; } return BinaryDataArrayPtr(); } PWIZ_API_DECL void Spectrum::setMZIntensityPairs(const vector& input, CVID intensityUnits) { if (!input.empty()) setMZIntensityPairs(&input[0], input.size(), intensityUnits); else setMZIntensityArrays(vector(), vector(), intensityUnits); } PWIZ_API_DECL void Spectrum::setMZIntensityPairs(const MZIntensityPair* input, size_t size, CVID intensityUnits) { pair arrays = getMZIntensityArrays(binaryDataArrayPtrs); BinaryDataArrayPtr& bd_mz = arrays.first; BinaryDataArrayPtr& bd_intensity = arrays.second; if (!bd_mz.get()) { bd_mz = BinaryDataArrayPtr(new BinaryDataArray); CVParam arrayType(MS_m_z_array); arrayType.units = MS_m_z; bd_mz->cvParams.push_back(arrayType); binaryDataArrayPtrs.push_back(bd_mz); } if (!bd_intensity.get()) { bd_intensity = BinaryDataArrayPtr(new BinaryDataArray); CVParam arrayType(MS_intensity_array); arrayType.units = intensityUnits; bd_intensity->cvParams.push_back(arrayType); binaryDataArrayPtrs.push_back(bd_intensity); } bd_mz->data.clear(); bd_intensity->data.clear(); bd_mz->data.resize(size); bd_intensity->data.resize(size); defaultArrayLength = size; if (size == 0) return; double* mz = &bd_mz->data[0]; double* intensity = &bd_intensity->data[0]; for (const MZIntensityPair* p=input; p!=input+size; ++p) { *mz++ = p->mz; *intensity++ = p->intensity; } } /// set m/z and intensity arrays separately (they must be the same size) by swapping the vector contents /// this allows for a more nearly zero copy setup. Contents of mzArray and intensityArray are undefined after calling. PWIZ_API_DECL void Spectrum::swapMZIntensityArrays(std::vector& mzArray, std::vector& intensityArray, CVID intensityUnits) { if (mzArray.size() != intensityArray.size()) throw runtime_error("[MSData::Spectrum::swapMZIntensityArrays()] Sizes do not match."); pair arrays = getMZIntensityArrays(binaryDataArrayPtrs); BinaryDataArrayPtr& bd_mz = arrays.first; BinaryDataArrayPtr& bd_intensity = arrays.second; if (!bd_mz.get()) { bd_mz = BinaryDataArrayPtr(new BinaryDataArray); CVParam arrayType(MS_m_z_array); arrayType.units = MS_m_z; bd_mz->cvParams.push_back(arrayType); binaryDataArrayPtrs.push_back(bd_mz); } if (!bd_intensity.get()) { bd_intensity = BinaryDataArrayPtr(new BinaryDataArray); CVParam arrayType(MS_intensity_array); arrayType.units = intensityUnits; bd_intensity->cvParams.push_back(arrayType); binaryDataArrayPtrs.push_back(bd_intensity); } defaultArrayLength = mzArray.size(); bd_mz->data.swap(mzArray); bd_intensity->data.swap(intensityArray); } PWIZ_API_DECL void Spectrum::setMZIntensityArrays(const std::vector& mzArray, const std::vector& intensityArray, CVID intensityUnits) { if (mzArray.size() != intensityArray.size()) throw runtime_error("[MSData::Spectrum::setMZIntensityArrays()] Sizes do not match."); pair arrays = getMZIntensityArrays(binaryDataArrayPtrs); BinaryDataArrayPtr& bd_mz = arrays.first; BinaryDataArrayPtr& bd_intensity = arrays.second; if (!bd_mz.get()) { bd_mz = BinaryDataArrayPtr(new BinaryDataArray); CVParam arrayType(MS_m_z_array); arrayType.units = MS_m_z; bd_mz->cvParams.push_back(arrayType); binaryDataArrayPtrs.push_back(bd_mz); } if (!bd_intensity.get()) { bd_intensity = BinaryDataArrayPtr(new BinaryDataArray); CVParam arrayType(MS_intensity_array); arrayType.units = intensityUnits; bd_intensity->cvParams.push_back(arrayType); binaryDataArrayPtrs.push_back(bd_intensity); } defaultArrayLength = mzArray.size(); bd_mz->data.clear(); bd_intensity->data.clear(); bd_mz->data.insert(bd_mz->data.end(), mzArray.begin(), mzArray.end()); bd_intensity->data.insert(bd_intensity->data.end(), intensityArray.begin(), intensityArray.end()); } // // Chromatogram // PWIZ_API_DECL bool Chromatogram::empty() const { return index==IDENTITY_INDEX_NONE && id.empty() && defaultArrayLength==0 && (!dataProcessingPtr.get() || dataProcessingPtr->empty()) && precursor.empty() && product.empty() && binaryDataArrayPtrs.empty() && ParamContainer::empty(); } namespace { pair getTimeIntensityArrays(const vector& ptrs) { BinaryDataArrayPtr timeArray; BinaryDataArrayPtr intensityArray; for (vector::const_iterator it=ptrs.begin(); it!=ptrs.end(); ++it) { if ((*it)->hasCVParam(MS_time_array) && !timeArray.get()) timeArray = *it; if ((*it)->hasCVParam(MS_intensity_array) && !intensityArray.get()) intensityArray = *it; } return make_pair(timeArray, intensityArray); } } // namespace PWIZ_API_DECL void Chromatogram::getTimeIntensityPairs(vector& output) const { output.clear(); output.resize(defaultArrayLength); if (!output.empty()) getTimeIntensityPairs(&output[0], output.size()); } PWIZ_API_DECL void Chromatogram::getTimeIntensityPairs(TimeIntensityPair* output, size_t expectedSize) const { // retrieve and validate time and intensity arrays if (expectedSize == 0) return; pair arrays = getTimeIntensityArrays(binaryDataArrayPtrs); if (!output) throw runtime_error("[MSData::Chromatogram::getTimeIntensityPairs()] Null output buffer."); // copy data into return buffer double* time = &arrays.first->data[0]; double* intensity = &arrays.second->data[0]; for (TimeIntensityPair* p=output; p!=output+expectedSize; ++p) { p->time = *time++; p->intensity = *intensity++; } } PWIZ_API_DECL BinaryDataArrayPtr Chromatogram::getTimeArray() const { for (vector::const_iterator it = binaryDataArrayPtrs.begin(); it != binaryDataArrayPtrs.end(); ++it) { if ((*it)->hasCVParam(MS_time_array)) return *it; } return BinaryDataArrayPtr(); } PWIZ_API_DECL BinaryDataArrayPtr Chromatogram::getIntensityArray() const { for (vector::const_iterator it = binaryDataArrayPtrs.begin(); it != binaryDataArrayPtrs.end(); ++it) { if ((*it)->hasCVParam(MS_intensity_array)) return *it; } return BinaryDataArrayPtr(); } PWIZ_API_DECL void Chromatogram::setTimeIntensityPairs(const vector& input, CVID timeUnits, CVID intensityUnits) { if (!input.empty()) setTimeIntensityPairs(&input[0], input.size(), timeUnits, intensityUnits); } PWIZ_API_DECL void Chromatogram::setTimeIntensityPairs(const TimeIntensityPair* input, size_t size, CVID timeUnits, CVID intensityUnits) { BinaryDataArrayPtr bd_time(new BinaryDataArray); BinaryDataArrayPtr bd_intensity(new BinaryDataArray); binaryDataArrayPtrs.clear(); binaryDataArrayPtrs.push_back(bd_time); binaryDataArrayPtrs.push_back(bd_intensity); bd_time->cvParams.push_back(CVParam(MS_time_array, "", timeUnits)); bd_intensity->cvParams.push_back(CVParam(MS_intensity_array, "", intensityUnits)); bd_time->data.resize(size); bd_intensity->data.resize(size); defaultArrayLength = size; if (size == 0) return; double* time = &bd_time->data[0]; double* intensity = &bd_intensity->data[0]; for (const TimeIntensityPair* p=input; p!=input+size; ++p) { *time++ = p->time; *intensity++ = p->intensity; } } PWIZ_API_DECL void Chromatogram::setTimeIntensityArrays(const std::vector& timeArray, const std::vector& intensityArray, CVID timeUnits, CVID intensityUnits) { if (timeArray.size() != intensityArray.size()) throw runtime_error("[MSData::Chromatogram::setTimeIntensityArrays()] Sizes do not match."); pair arrays = getTimeIntensityArrays(binaryDataArrayPtrs); BinaryDataArrayPtr& bd_time = arrays.first; BinaryDataArrayPtr& bd_intensity = arrays.second; if (!bd_time.get()) { bd_time = BinaryDataArrayPtr(new BinaryDataArray); CVParam arrayType(MS_time_array); arrayType.units = timeUnits; bd_time->cvParams.push_back(arrayType); binaryDataArrayPtrs.push_back(bd_time); } if (!bd_intensity.get()) { bd_intensity = BinaryDataArrayPtr(new BinaryDataArray); CVParam arrayType(MS_intensity_array); arrayType.units = intensityUnits; bd_intensity->cvParams.push_back(arrayType); binaryDataArrayPtrs.push_back(bd_intensity); } defaultArrayLength = timeArray.size(); bd_time->data.assign(timeArray.begin(), timeArray.end()); bd_intensity->data.assign(intensityArray.begin(), intensityArray.end()); } // // SpectrumList (default implementations) // PWIZ_API_DECL bool SpectrumList::empty() const { return size()==0 && !dataProcessingPtr().get(); } PWIZ_API_DECL size_t SpectrumList::find(const string& id) const { for (size_t index=0; index abbreviatedTokens, actualTokens; // "1.1.123.2" splits to { 1, 1, 123, 2 } bal::split(abbreviatedTokens, abbreviatedId, bal::is_any_of(string(1, delimiter))); if (empty()) return 0; // "sample=1 period=1 cycle=123 experiment=2" splits to { sample, 1, period, 1, cycle, 123, experiment, 2 } string firstId = spectrumIdentity(0).id; bal::split(actualTokens, firstId, bal::is_any_of(" =")); string fullId(actualTokens[0] + "=" + abbreviatedTokens[0]); for (size_t i = 1; i < abbreviatedTokens.size(); ++i) fullId += " " + actualTokens[2*i] + "=" + abbreviatedTokens[i]; return find(fullId); } PWIZ_API_DECL IndexList SpectrumList::findNameValue(const string& name, const string& value) const { IndexList result; for (size_t index=0; index SpectrumList::dataProcessingPtr() const { return shared_ptr(); } PWIZ_API_DECL SpectrumPtr SpectrumList::spectrum(const SpectrumPtr& seed, bool getBinaryData) const { return spectrum(seed->index, getBinaryData); }; PWIZ_API_DECL SpectrumPtr SpectrumList::spectrum(size_t index, DetailLevel detailLevel) const { // By default faster metadeta access is not implemented if (detailLevel == DetailLevel_FastMetadata || detailLevel == DetailLevel_InstantMetadata) return SpectrumPtr(new Spectrum); return spectrum(index, detailLevel == DetailLevel_FullData); } PWIZ_API_DECL void SpectrumList::warn_once(const char *msg) const { } // // SpectrumListSimple // PWIZ_API_DECL const SpectrumIdentity& SpectrumListSimple::spectrumIdentity(size_t index) const { return *spectrum(index, false); } PWIZ_API_DECL SpectrumPtr SpectrumListSimple::spectrum(size_t index, bool getBinaryData) const { // validate index if (index >= size()) throw runtime_error("[MSData::SpectrumListSimple::spectrum()] Invalid index."); // validate Spectrum* if (!spectra[index].get()) throw runtime_error("[MSData::SpectrumListSimple::spectrum()] Null SpectrumPtr."); return spectra[index]; } PWIZ_API_DECL const shared_ptr SpectrumListSimple::dataProcessingPtr() const { return dp; } // // ChromatogramList (default implementations) // PWIZ_API_DECL bool ChromatogramList::empty() const { return size()==0 && !dataProcessingPtr().get(); } PWIZ_API_DECL size_t ChromatogramList::find(const string& id) const { for (size_t index=0; index ChromatogramList::dataProcessingPtr() const { return shared_ptr(); } // // ChromatogramListSimple // PWIZ_API_DECL const ChromatogramIdentity& ChromatogramListSimple::chromatogramIdentity(size_t index) const { return *chromatogram(index, false); } PWIZ_API_DECL ChromatogramPtr ChromatogramListSimple::chromatogram(size_t index, bool getBinaryData) const { // validate index if (index >= size()) throw runtime_error("[MSData::ChromatogramListSimple::chromatogram()] Invalid index."); // validate Chromatogram* if (!chromatograms[index].get()) throw runtime_error("[MSData::ChromatogramListSimple::chromatogram()] Null ChromatogramPtr."); return chromatograms[index]; } PWIZ_API_DECL const shared_ptr ChromatogramListSimple::dataProcessingPtr() const { return dp; } // // Run // PWIZ_API_DECL bool Run::empty() const { return id.empty() && (!defaultInstrumentConfigurationPtr.get() || defaultInstrumentConfigurationPtr->empty()) && (!samplePtr.get() || samplePtr->empty()) && startTimeStamp.empty() && (!defaultSourceFilePtr.get() || defaultSourceFilePtr->empty()) && (!spectrumListPtr.get() || spectrumListPtr->empty()) && (!chromatogramListPtr.get() || chromatogramListPtr->empty()) && ParamContainer::empty(); } // // MSData // PWIZ_API_DECL MSData::MSData() : version_("1.1.0"),nFiltersApplied_(0) {} PWIZ_API_DECL MSData::~MSData() {} PWIZ_API_DECL bool MSData::empty() const { return accession.empty() && id.empty() && cvs.empty() && fileDescription.empty() && paramGroupPtrs.empty() && samplePtrs.empty() && softwarePtrs.empty() && scanSettingsPtrs.empty() && instrumentConfigurationPtrs.empty() && dataProcessingPtrs.empty() && run.empty(); } PWIZ_API_DECL const string& MSData::version() const {return version_;} namespace { template struct HasID { const string& id_; HasID(const string& id) : id_(id) {} bool operator()(const shared_ptr& objectPtr) { return objectPtr.get() && objectPtr->id == id_; } }; } // namespace PWIZ_API_DECL vector MSData::allDataProcessingPtrs() const { vector result(dataProcessingPtrs); if (run.spectrumListPtr.get()) { // if SpectrumList::dataProcessingPtr() is not in MSData::dataProcessingPtrs, add it const shared_ptr sldp = run.spectrumListPtr->dataProcessingPtr(); if (sldp.get() && std::find_if(result.begin(), result.end(), HasID(sldp->id)) == result.end()) result.push_back(boost::const_pointer_cast(sldp)); } if (run.chromatogramListPtr.get()) { // if ChromatogramList::dataProcessingPtr() is not in MSData::dataProcessingPtrs, add it const shared_ptr cldp = run.chromatogramListPtr->dataProcessingPtr(); if (cldp.get() && std::find_if(result.begin(), result.end(), HasID(cldp->id)) == result.end()) result.push_back(boost::const_pointer_cast(cldp)); } return result; } } // namespace msdata } // namespace pwiz pwiz/pwiz/data/msdata/SpectrumListCacheTest.cpp0000664000175100017510000003743112664775621023664 0ustar teamcityteamcity00000000000000// // $Id: SpectrumListCacheTest.cpp 6948 2014-11-26 20:47:23Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/unit.hpp" #include "MSDataFile.hpp" #include "MemoryMRUCache.hpp" #include "SpectrumListCache.hpp" #include "pwiz/utility/misc/Std.hpp" #include "Serializer_MGF.hpp" using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::msdata; //using namespace pwiz::analysis; ostream* os_ = 0; namespace std { ostream& operator<< (ostream& os, SpectrumListCache::CacheType& cache) { os << "Spectrum cache indices (from MRU to LRU):"; for (SpectrumListCache::CacheType::iterator itr = cache.begin(); itr != cache.end(); ++itr) os << " " << itr->spectrum->index; return os; } } // namespace std void testMemoryMRUCache() { SpectrumListCache::CacheType cache(MemoryMRUCacheMode_Off, 2); unit_assert_operator_equal(2, cache.max_size()); unit_assert(cache.empty()); unit_assert_operator_equal(0, cache.size()); cache.insert(SpectrumListCache::CacheEntry(0, SpectrumPtr())); unit_assert(!cache.empty()); unit_assert_operator_equal(1, cache.size()); cache.insert(SpectrumListCache::CacheEntry(1, SpectrumPtr())); unit_assert_operator_equal(2, cache.size()); unit_assert_operator_equal(1, cache.mru().index); unit_assert_operator_equal(0, cache.lru().index); cache.insert(SpectrumListCache::CacheEntry(0, SpectrumPtr())); unit_assert_operator_equal(2, cache.size()); unit_assert_operator_equal(0, cache.mru().index); unit_assert_operator_equal(1, cache.lru().index); cache.insert(SpectrumListCache::CacheEntry(2, SpectrumPtr())); unit_assert_operator_equal(2, cache.size()); unit_assert_operator_equal(2, cache.mru().index); unit_assert_operator_equal(0, cache.lru().index); } SpectrumPtr makeSpectrumPtr(size_t index, const string& id) { SpectrumPtr spectrum(new Spectrum); spectrum->id = id; spectrum->index = index; spectrum->set(MS_MSn_spectrum); spectrum->set(MS_ms_level, 2); spectrum->precursors.push_back(Precursor(123.4)); spectrum->setMZIntensityArrays(vector(), vector(), MS_number_of_detector_counts); BinaryDataArray& mzArray = *spectrum->getMZArray(); BinaryDataArray& intensityArray = *spectrum->getIntensityArray(); for (size_t i=0; i < (index+1)*10; ++i) { mzArray.data.push_back(i); intensityArray.data.push_back(i*100); } spectrum->defaultArrayLength = mzArray.data.size(); return spectrum; } bool spectrumHasMetadata(const Spectrum& s) { return s.dataProcessingPtr.get() || s.sourceFilePtr.get() || !s.scanList.empty() || !s.precursors.empty() || !s.paramGroupPtrs.empty() || !s.cvParams.empty() || !s.userParams.empty(); } bool spectrumHasBinaryData(const Spectrum& s) { return s.hasBinaryData(); } void testModeOff() { // initialize list shared_ptr sl(new SpectrumListSimple); sl->spectra.push_back(makeSpectrumPtr(0, "S1")); sl->spectra.push_back(makeSpectrumPtr(1, "S2")); sl->spectra.push_back(makeSpectrumPtr(2, "S3")); sl->spectra.push_back(makeSpectrumPtr(3, "S4")); // access a series of spectra and make sure the cache behaves appropriately: // in off mode, the cache should always be empty SpectrumPtr s; SpectrumListCache slc(sl, MemoryMRUCacheMode_Off, 2); SpectrumListCache::CacheType& cache = slc.spectrumCache(); unit_assert(cache.empty()); s = slc.spectrum(0, false); s = slc.spectrum(1, true); s = slc.spectrum(2, false); s = slc.spectrum(3, true); if (os_) *os_ << cache << endl; unit_assert(cache.empty()); } void testModeMetaDataOnly() { // initialize list MSData msd; shared_ptr sl(new SpectrumListSimple); sl->spectra.push_back(makeSpectrumPtr(0, "S1")); sl->spectra.push_back(makeSpectrumPtr(1, "S2")); sl->spectra.push_back(makeSpectrumPtr(2, "S3")); sl->spectra.push_back(makeSpectrumPtr(3, "S4")); msd.run.spectrumListPtr = sl; // SpectrumListSimple returns the same shared_ptrs regardless of caching; // serializing to MGF and back will produce different shared_ptrs boost::shared_ptr ss(new stringstream); Serializer_MGF serializer; serializer.write(*ss, msd, 0); serializer.read(ss, msd); // access a series of spectra and make sure the cache behaves appropriately: // in metadata-only mode, entries in the cache should: // - always have metadata // - never have binary data SpectrumPtr s; SpectrumListCache slc(msd.run.spectrumListPtr, MemoryMRUCacheMode_MetaDataOnly, 2); SpectrumListCache::CacheType& cache = slc.spectrumCache(); unit_assert(cache.empty()); unit_assert_operator_equal(2, cache.max_size()); s = slc.spectrum(0, false); // pointers should be equal unit_assert_operator_equal(slc.spectrum(0, false), s); if (os_) *os_ << cache << endl; unit_assert(!cache.empty()); unit_assert_operator_equal(1, cache.size()); unit_assert_operator_equal(0, cache.mru().spectrum->index); // with-binary-data access should return the binary data, but only cache the metadata s = slc.spectrum(1, true); if (os_) *os_ << cache << endl; unit_assert_operator_equal(2, cache.size()); unit_assert_operator_equal(1, cache.mru().spectrum->index); unit_assert(spectrumHasMetadata(*cache.mru().spectrum)); unit_assert(!spectrumHasBinaryData(*cache.mru().spectrum)); unit_assert(spectrumHasMetadata(*cache.lru().spectrum)); unit_assert_operator_equal(0, cache.lru().spectrum->index); s = slc.spectrum(2, false); // pointers should be equal unit_assert_operator_equal(slc.spectrum(2, false), s); if (os_) *os_ << cache << endl; unit_assert_operator_equal(2, cache.size()); unit_assert_operator_equal(2, cache.mru().spectrum->index); unit_assert(spectrumHasMetadata(*cache.mru().spectrum)); unit_assert(!spectrumHasBinaryData(*cache.mru().spectrum)); unit_assert_operator_equal(1, cache.lru().spectrum->index); s = slc.spectrum(3, true); if (os_) *os_ << cache << endl; unit_assert_operator_equal(2, cache.size()); unit_assert_operator_equal(3, cache.mru().spectrum->index); unit_assert(spectrumHasMetadata(*cache.mru().spectrum)); unit_assert(!spectrumHasBinaryData(*cache.mru().spectrum)); unit_assert_operator_equal(2, cache.lru().spectrum->index); unit_assert(spectrumHasMetadata(*cache.lru().spectrum)); s = slc.spectrum(2, true); if (os_) *os_ << cache << endl; unit_assert_operator_equal(2, cache.size()); unit_assert_operator_equal(2, cache.mru().spectrum->index); unit_assert(spectrumHasMetadata(*cache.mru().spectrum)); unit_assert(!spectrumHasBinaryData(*cache.mru().spectrum)); unit_assert_operator_equal(3, cache.lru().spectrum->index); unit_assert(spectrumHasMetadata(*cache.lru().spectrum)); } void testModeBinaryDataOnly() { // initialize list MSData msd; shared_ptr sl(new SpectrumListSimple); sl->spectra.push_back(makeSpectrumPtr(0, "S1")); sl->spectra.push_back(makeSpectrumPtr(1, "S2")); sl->spectra.push_back(makeSpectrumPtr(2, "S3")); sl->spectra.push_back(makeSpectrumPtr(3, "S4")); msd.run.spectrumListPtr = sl; // SpectrumListSimple returns the same shared_ptrs regardless of caching; // serializing to MGF and back will produce different shared_ptrs boost::shared_ptr ss(new stringstream); Serializer_MGF serializer; serializer.write(*ss, msd, 0); serializer.read(ss, msd); // access a series of spectra and make sure the cache behaves appropriately: // in binary-data-only mode, entries in the cache should: // - never have metadata // - always have binary data SpectrumPtr s; SpectrumListCache slc(msd.run.spectrumListPtr, MemoryMRUCacheMode_BinaryDataOnly, 2); SpectrumListCache::CacheType& cache = slc.spectrumCache(); unit_assert(cache.empty()); unit_assert_operator_equal(2, cache.max_size()); // metadata-only access should not affect the cache s = slc.spectrum(0, false); if (os_) *os_ << cache << endl; unit_assert(cache.empty()); unit_assert_operator_equal(0, cache.size()); // with-binary-data access should be cached without the metadata s = slc.spectrum(1, true); if (os_) *os_ << cache << endl; unit_assert_operator_equal(1, cache.size()); unit_assert_operator_equal(1, cache.mru().spectrum->index); unit_assert(!spectrumHasMetadata(*cache.mru().spectrum)); unit_assert(spectrumHasBinaryData(*cache.mru().spectrum)); s = slc.spectrum(2, false); if (os_) *os_ << cache << endl; unit_assert_operator_equal(1, cache.size()); unit_assert_operator_equal(1, cache.mru().spectrum->index); unit_assert(!spectrumHasMetadata(*cache.mru().spectrum)); unit_assert(spectrumHasBinaryData(*cache.mru().spectrum)); s = slc.spectrum(3, true); if (os_) *os_ << cache << endl; unit_assert_operator_equal(2, cache.size()); unit_assert_operator_equal(3, cache.mru().spectrum->index); unit_assert(!spectrumHasMetadata(*cache.mru().spectrum)); unit_assert(spectrumHasBinaryData(*cache.mru().spectrum)); unit_assert_operator_equal(1, cache.lru().spectrum->index); unit_assert(!spectrumHasMetadata(*cache.lru().spectrum)); unit_assert(spectrumHasBinaryData(*cache.lru().spectrum)); s = slc.spectrum(1, true); if (os_) *os_ << cache << endl; unit_assert_operator_equal(2, cache.size()); unit_assert_operator_equal(1, cache.mru().spectrum->index); unit_assert(!spectrumHasMetadata(*cache.mru().spectrum)); unit_assert(spectrumHasBinaryData(*cache.mru().spectrum)); unit_assert_operator_equal(3, cache.lru().spectrum->index); unit_assert(!spectrumHasMetadata(*cache.lru().spectrum)); unit_assert(spectrumHasBinaryData(*cache.lru().spectrum)); } void testModeMetaDataAndBinaryData() { // initialize list MSData msd; shared_ptr sl(new SpectrumListSimple); sl->spectra.push_back(makeSpectrumPtr(0, "S1")); sl->spectra.push_back(makeSpectrumPtr(1, "S2")); sl->spectra.push_back(makeSpectrumPtr(2, "S3")); sl->spectra.push_back(makeSpectrumPtr(3, "S4")); msd.run.spectrumListPtr = sl; // SpectrumListSimple returns the same shared_ptrs regardless of caching; // serializing to MGF and back will produce different shared_ptrs boost::shared_ptr ss(new stringstream); Serializer_MGF serializer; serializer.write(*ss, msd, 0); serializer.read(ss, msd); // access a series of spectra and make sure the cache behaves appropriately: // in metadata-and-binary-data mode, entries in the cache should: // - always have metadata // - always have binary data SpectrumPtr s; SpectrumListCache slc(msd.run.spectrumListPtr, MemoryMRUCacheMode_MetaDataAndBinaryData, 2); SpectrumListCache::CacheType& cache = slc.spectrumCache(); unit_assert(cache.empty()); unit_assert_operator_equal(2, cache.max_size()); // metadata-only access should not affect the cache s = slc.spectrum(0, false); if (os_) *os_ << cache << endl; unit_assert(cache.empty()); unit_assert_operator_equal(0, cache.size()); s = slc.spectrum(1, true); // pointers should be equal unit_assert_operator_equal(slc.spectrum(1, true), s); if (os_) *os_ << cache << endl; unit_assert_operator_equal(1, cache.size()); unit_assert_operator_equal(1, cache.mru().spectrum->index); unit_assert(spectrumHasMetadata(*cache.mru().spectrum)); unit_assert(spectrumHasBinaryData(*cache.mru().spectrum)); s = slc.spectrum(2, false); if (os_) *os_ << cache << endl; unit_assert_operator_equal(1, cache.size()); unit_assert_operator_equal(1, cache.mru().spectrum->index); unit_assert(spectrumHasMetadata(*cache.mru().spectrum)); unit_assert(spectrumHasBinaryData(*cache.mru().spectrum)); s = slc.spectrum(3, true); // pointers should be equal unit_assert_operator_equal(slc.spectrum(3, true), s); if (os_) *os_ << cache << endl; unit_assert_operator_equal(2, cache.size()); unit_assert_operator_equal(3, cache.mru().spectrum->index); unit_assert(spectrumHasMetadata(*cache.mru().spectrum)); unit_assert(spectrumHasBinaryData(*cache.mru().spectrum)); unit_assert_operator_equal(1, cache.lru().spectrum->index); unit_assert(spectrumHasMetadata(*cache.lru().spectrum)); unit_assert(spectrumHasBinaryData(*cache.lru().spectrum)); s = slc.spectrum(2, true); if (os_) *os_ << cache << endl; unit_assert_operator_equal(2, cache.size()); unit_assert_operator_equal(2, cache.mru().spectrum->index); unit_assert(spectrumHasMetadata(*cache.mru().spectrum)); unit_assert(spectrumHasBinaryData(*cache.mru().spectrum)); unit_assert_operator_equal(3, cache.lru().spectrum->index); unit_assert(spectrumHasMetadata(*cache.lru().spectrum)); unit_assert(spectrumHasBinaryData(*cache.lru().spectrum)); } void testFileReads(const char *filename) { std::string srcparent(__FILE__); // locate test data relative to this source file // something like \ProteoWizard\pwiz\pwiz\data\msdata\SpectrumListCacheTest.cpp size_t pos = srcparent.rfind("pwiz"); srcparent.resize(pos); std::string example_data_dir = srcparent + "example_data/"; pwiz::msdata::MSDataFile msd1(example_data_dir + filename); SpectrumListCache cache(msd1.run.spectrumListPtr, MemoryMRUCacheMode_MetaDataOnly, 2); pwiz::msdata::MSDataFile msd2(example_data_dir + filename); // test logic for efficient delayed read of binary data - // we try to avoid reparsing the header since we have that cached // mzML and mzXML readers can do this, others could probably be made to int index = 3; SpectrumPtr s=msd2.run.spectrumListPtr->spectrum(index, false); SpectrumPtr c=cache.spectrum(index, false); unit_assert(*s==*c); unit_assert(!s->hasBinaryData()); unit_assert(!c->hasBinaryData()); s=msd2.run.spectrumListPtr->spectrum(index, true); c=cache.spectrum(index, true); unit_assert(*s==*c); unit_assert(s->hasBinaryData()); unit_assert(c->hasBinaryData()); unit_assert(s->binaryDataArrayPtrs[0]->data[0]== c->binaryDataArrayPtrs[0]->data[0]); unit_assert(!s->binaryDataArrayPtrs[1]->data.empty()); unit_assert(!c->binaryDataArrayPtrs[1]->data.empty()); unit_assert(s->binaryDataArrayPtrs[1]->data[0]== c->binaryDataArrayPtrs[1]->data[0]); } void test() { testMemoryMRUCache(); testModeOff(); testModeMetaDataOnly(); testModeBinaryDataOnly(); testModeMetaDataAndBinaryData(); // check the delayed-binary-read // logic for mzML and mzXML readers testFileReads("tiny.pwiz.mzXML"); testFileReads("tiny.pwiz.1.0.mzML"); testFileReads("tiny.pwiz.1.1.mzML"); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/msdata/References.hpp0000664000175100017510000000522412664775621021523 0ustar teamcityteamcity00000000000000// // $Id: References.hpp 1189 2009-08-14 17:36:06Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _REFERENCES_HPP_ #define _REFERENCES_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "MSData.hpp" namespace pwiz { namespace msdata { /// functions for resolving references from objects into the internal MSData lists namespace References { PWIZ_API_DECL void resolve(ParamContainer& paramContainer, const MSData& msd); PWIZ_API_DECL void resolve(FileDescription& fileDescription, const MSData& msd); PWIZ_API_DECL void resolve(ComponentList& componentList, const MSData& msd); PWIZ_API_DECL void resolve(InstrumentConfiguration& instrumentConfiguration, const MSData& msd); PWIZ_API_DECL void resolve(ProcessingMethod& processingMethod, const MSData& msd); PWIZ_API_DECL void resolve(DataProcessing& dataProcesssing, const MSData& msd); PWIZ_API_DECL void resolve(ScanSettings& dataProcesssing, const MSData& msd); PWIZ_API_DECL void resolve(Precursor& precursor, const MSData& msd); PWIZ_API_DECL void resolve(Product& product, const MSData& msd); PWIZ_API_DECL void resolve(Scan& scan, const MSData& msd); PWIZ_API_DECL void resolve(ScanList& List, const MSData& msd); PWIZ_API_DECL void resolve(BinaryDataArray& binaryDataArray, const MSData& msd); PWIZ_API_DECL void resolve(Spectrum& spectrum, const MSData& msd); PWIZ_API_DECL void resolve(Chromatogram& chromatogram, const MSData& msd); PWIZ_API_DECL void resolve(Run& run, const MSData& msd); /// /// Resolve internal references in an MSData object. /// /// For an MSData object using a SpectrumListSimple to hold Spectrum objects in memory, /// these references will be resolved as well. /// /// File-backed SpectrumList implementations using lazy evaluation of a Spectrum need /// to call resolve(spectrum, msd) before returning it to the client. /// PWIZ_API_DECL void resolve(MSData& msd); } // namespace References } // namespace msdata } // namespace pwiz #endif // _REFERENCES_HPP_ pwiz/pwiz/data/msdata/examples.hpp0000664000175100017510000000225712664775621021263 0ustar teamcityteamcity00000000000000// // $Id: examples.hpp 1189 2009-08-14 17:36:06Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _EXAMPLES_HPP_ #define _EXAMPLES_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "MSData.hpp" namespace pwiz { namespace msdata { namespace examples { PWIZ_API_DECL void initializeTiny(MSData& msd); PWIZ_API_DECL void addMIAPEExampleMetadata(MSData& msd); } // namespace examples } // namespace msdata } // namespace pwiz #endif // _EXAMPLES_HPP_ pwiz/pwiz/data/msdata/Serializer_MGF.cpp0000664000175100017510000001631112664775620022235 0ustar teamcityteamcity00000000000000// // $Id: Serializer_MGF.cpp 6585 2014-08-07 22:49:28Z chambm $ // // // Original author: Matt Chambers // // Copyright 2011 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Serializer_MGF.hpp" #include "SpectrumList_MGF.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include #include "SpectrumWorkerThreads.hpp" namespace pwiz { namespace msdata { using boost::iostreams::stream_offset; using namespace pwiz::util; class Serializer_MGF::Impl { public: Impl() {} void write(ostream& os, const MSData& msd, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry) const; void read(shared_ptr is, MSData& msd) const; }; template struct nosci10_policy : boost::spirit::karma::real_policies { // we want to generate up to 10 fractional digits static unsigned int precision(T) { return 10; } // we want the numbers always to be in fixed format static int floatfield(T) { return boost::spirit::karma::real_policies::fmtflags::fixed; } }; void Serializer_MGF::Impl::write(ostream& os, const MSData& msd, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry) const { bool titleIsThermoDTA = false; if (msd.fileDescription.sourceFilePtrs.size() >= 1) titleIsThermoDTA = msd.fileDescription.sourceFilePtrs[0]->hasCVParam(MS_Thermo_nativeID_format); const string& thermoFilename = titleIsThermoDTA ? msd.fileDescription.sourceFilePtrs[0]->name : ""; string thermoBasename = titleIsThermoDTA ? bfs::basename(thermoFilename) : ""; os << std::setprecision(10); // 1234.567890 SpectrumList& sl = *msd.run.spectrumListPtr; SpectrumWorkerThreads spectrumWorkers(sl); for (size_t i=0, end=sl.size(); i < end; ++i) { //SpectrumPtr s = sl.spectrum(i, true); SpectrumPtr s = spectrumWorkers.processBatch(i); Scan* scan = !s->scanList.empty() ? &s->scanList.scans[0] : 0; if (s->cvParam(MS_ms_level).valueAs() > 1 && !s->precursors.empty() && !s->precursors[0].selectedIons.empty()) { os << "BEGIN IONS\n"; const SelectedIon& si = s->precursors[0].selectedIons[0]; CVParam scanTimeParam = scan ? scan->cvParam(MS_scan_start_time) : CVParam(); CVParam chargeParam = si.cvParam(MS_charge_state); CVParam spectrumTitle = s->cvParam(MS_spectrum_title); if (!spectrumTitle.empty()) os << "TITLE=" << spectrumTitle.value << '\n'; else if (titleIsThermoDTA) { string scan = id::value(s->id, "scan"); os << "TITLE=" << thermoBasename << '.' << scan << '.' << scan << '.' << chargeParam.value << '\n'; } else os << "TITLE=" << s->id << '\n'; if (!scanTimeParam.empty()) os << "RTINSECONDS=" << scanTimeParam.timeInSeconds() << '\n'; // many MGF parsers can't handle scientific notation (!) so explicitly use fixed os << "PEPMASS=" << si.cvParam(MS_selected_ion_m_z).valueFixedNotation(); bool negativePolarity = s->hasCVParam(MS_negative_scan) ? true : false; CVParam intensityParam = si.cvParam(MS_peak_intensity); if (!intensityParam.empty()) os << " " << intensityParam.valueFixedNotation(); os << '\n'; if (chargeParam.empty()) { vector charges; BOOST_FOREACH(const CVParam& param, si.cvParams) { if (param.cvid == MS_possible_charge_state) charges.push_back(param.value + (negativePolarity ? '-' : '+')); } if (!charges.empty()) os << "CHARGE=" << bal::join(charges, " and ") << '\n'; } else os << "CHARGE=" << chargeParam.value << (negativePolarity ? '-' : '+') << '\n'; const BinaryDataArray& mzArray = *s->getMZArray(); const BinaryDataArray& intensityArray = *s->getIntensityArray(); using namespace boost::spirit::karma; typedef real_generator > nosci10_type; static const nosci10_type nosci10 = nosci10_type(); char buffer[256]; for (size_t p=0; p < s->defaultArrayLength; ++p) { char* b = buffer; generate(b, nosci10, intensityArray.data[p]); *b = 0; os << mzArray.data[p] << ' ' << buffer << '\n'; } os << "END IONS\n"; } // update any listeners and handle cancellation IterationListener::Status status = IterationListener::Status_Ok; if (iterationListenerRegistry) status = iterationListenerRegistry->broadcastUpdateMessage( IterationListener::UpdateMessage(i, end)); if (status == IterationListener::Status_Cancel) break; } } void Serializer_MGF::Impl::read(shared_ptr is, MSData& msd) const { if (!is.get() || !*is) throw runtime_error("[Serializer_MGF::read()] Bad istream."); is->seekg(0); // read mzML file-level metadata stored in comment tags by the MGF writer like: // # fileContent CVParam MS:12345678 (term name) // # sourceFile id=foo name=bar location=file:///foo/bar /*string lineStr; while (is->peek() != (int) 'B') { getline(*is_, lineStr); if (lineStr[0] == '#') { vector tokens; bal::split(tokens, lineStr, bal::is_space()); if (tokens[1] == "fileContent") addParamToContainer(msd.fileDescription.fileContent, */ // we treat all MGF data is MSn (PMF MGFs not currently supported) msd.fileDescription.fileContent.set(MS_MSn_spectrum); msd.fileDescription.fileContent.set(MS_centroid_spectrum); msd.run.spectrumListPtr = SpectrumList_MGF::create(is, msd); msd.run.chromatogramListPtr.reset(new ChromatogramListSimple); } // // Serializer_MGF // PWIZ_API_DECL Serializer_MGF::Serializer_MGF() : impl_(new Impl()) {} PWIZ_API_DECL void Serializer_MGF::write(ostream& os, const MSData& msd, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry) const { return impl_->write(os, msd, iterationListenerRegistry); } PWIZ_API_DECL void Serializer_MGF::read(shared_ptr is, MSData& msd) const { return impl_->read(is, msd); } } // namespace msdata } // namespace pwiz pwiz/pwiz/data/msdata/LegacyAdapter.hpp0000664000175100017510000000744112664775621022152 0ustar teamcityteamcity00000000000000// // $Id: LegacyAdapter.hpp 1656 2009-12-30 20:54:17Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // #ifndef _LEGACYADAPTER_HPP_ #define _LEGACYADAPTER_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "MSData.hpp" #include "boost/shared_ptr.hpp" namespace pwiz { namespace data { class CVTranslator; } } namespace pwiz { namespace msdata { using pwiz::data::CVTranslator; /// /// interface for legacy access to Instrument /// /// mzXML/RAMP encode instrument information as 5 strings: /// manufacturer, model, ionisation, analyzer, detector /// /// In mzML, the equivalent information is encoded as cvParams in /// various locations in the element. One important /// difference is that the manufacturer information is implicit in /// the CV term used to encode the model. /// /// The "set" methods use CVTranslator to translate the string(s) to an /// appropriate cvParam. If no CV term can be found, the information is /// encoded as a userParam. /// /// The "get" methods look for the cvParam first, then the userParam. /// class PWIZ_API_DECL LegacyAdapter_Instrument { public: LegacyAdapter_Instrument(InstrumentConfiguration& instrumentConfiguration, const CVTranslator& cvTranslator); std::string manufacturer() const; std::string model() const; void manufacturerAndModel(const std::string& valueManufacturer, const std::string& valueModel); std::string ionisation() const; void ionisation(const std::string& value); std::string analyzer() const; void analyzer(const std::string& value); std::string detector() const; void detector(const std::string& value); private: struct Impl; boost::shared_ptr impl_; LegacyAdapter_Instrument(LegacyAdapter_Instrument&); LegacyAdapter_Instrument& operator=(LegacyAdapter_Instrument&); }; /// /// interface for legacy access to Software /// /// mzXML: /// /// /// MSData: /// name: Software::cvParams(0) /// version: Software::version /// type: DataProcessing::processingMethods[?].userParams[?] /// /// Note: setting 'type' may create a DataProcessing object, which needs an id. /// Since the id is generated from 'name', it is an error to set 'type' before /// setting 'name'. /// class PWIZ_API_DECL LegacyAdapter_Software { public: LegacyAdapter_Software(SoftwarePtr software, MSData& msd, const CVTranslator& cvTranslator); std::string name() const; void name(const std::string& value); std::string version() const; void version(const std::string& value); std::string type() const; void type(const std::string& value); private: struct Impl; boost::shared_ptr impl_; LegacyAdapter_Software(LegacyAdapter_Software&); LegacyAdapter_Software& operator=(LegacyAdapter_Software&); }; } // namespace msdata } // namespace pwiz #endif // _LEGACYADAPTER_HPP_ pwiz/pwiz/data/msdata/MSDataFileTest.cpp0000664000175100017510000003077312664775621022215 0ustar teamcityteamcity00000000000000// // $Id: MSDataFileTest.cpp 6141 2014-05-05 21:03:47Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "MSDataFile.hpp" #include "Diff.hpp" #include "IO.hpp" #include "SpectrumListBase.hpp" #include "ChromatogramListBase.hpp" #include "examples.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include #include #include #include using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::data; using namespace pwiz::msdata; ostream* os_ = 0; string filenameBase_ = "temp.MSDataFileTest"; void hackInMemoryMSData(MSData& msd) { // remove metadata ptrs appended on read vector& sfs = msd.fileDescription.sourceFilePtrs; if (!sfs.empty()) sfs.erase(sfs.end()-1); vector& sws = msd.softwarePtrs; if (!sws.empty()) sws.erase(sws.end()-1); // remove current DataProcessing created on read SpectrumListBase* sl = dynamic_cast(msd.run.spectrumListPtr.get()); ChromatogramListBase* cl = dynamic_cast(msd.run.chromatogramListPtr.get()); if (sl) sl->setDataProcessingPtr(DataProcessingPtr()); if (cl) cl->setDataProcessingPtr(DataProcessingPtr()); } void validateMmgfMzxmlRoundTrip() { string filename1 = filenameBase_ + ".mgf"; string filename2 = filenameBase_ + ".mzXML"; ofstream ofs(filename1.c_str()); string mgf = "CHARGE=2+ and 3+\nBEGIN IONS\nPEPMASS=952.924194 145032.0000\nCHARGE=2+\nRTINSECONDS=301.48\n271.0874 2\n298.1747 4\nEND IONS\nBEGIN IONS\nPEPMASS=503.800000 67522.2000\nCHARGE=2+\nRTINSECONDS=302.51\n147.1840 3\n154.3668 3\n162.2118 2\n162.9007 1\n167.3297 1\n175.2387 2\n184.9460 3\nEND IONS\n"; ofs.write(mgf.c_str(), mgf.length()); ofs.close(); // make sure that round trip doesn't systematically increase converted scan numbers for (int loop = 3; loop--; ) { MSDataFile msd1(filename1); // read back the MGF const SpectrumList& sl = *msd1.run.spectrumListPtr; SpectrumPtr spectrum = sl.spectrum(0); unit_assert(spectrum->id == "index=0"); MSDataFile::WriteConfig writeConfig; writeConfig.format = MSDataFile::Format_mzXML; MSDataFile::write(msd1, filename2, writeConfig); // write as mzXML MSDataFile msd2(filename2); // read back the mzXML const SpectrumList& sl2= *msd2.run.spectrumListPtr; SpectrumPtr spectrum2 = sl2.spectrum(0); unit_assert(spectrum2->id == "index=1"); // mzXML is 1-based MSDataFile::WriteConfig writeConfig2; writeConfig2.format = MSDataFile::Format_MGF; MSDataFile::write(msd2, filename1, writeConfig2); // write as mgf } // remove temp files boost::filesystem::remove(filename1); boost::filesystem::remove(filename2); } void validateWriteRead(const MSDataFile::WriteConfig& writeConfig, const DiffConfig diffConfig) { if (os_) *os_ << "validateWriteRead()\n " << writeConfig << endl; string filename1 = filenameBase_ + ".1"; string filename2 = filenameBase_ + ".2"; string filename3 = filenameBase_ + ".3"; string filename4 = filenameBase_ + ".\xE4\xB8\x80\xE4\xB8\xAA\xE8\xAF\x95.4"; // FIXME: 4-byte UTF-8 not working: string filename5 = filenameBase_ + ".\x01\x04\xA4\x01\x04\xA2.5"; { // create MSData object in memory MSData tiny; examples::initializeTiny(tiny); if (writeConfig.format == MSDataFile::Format_mzXML) { // remove s22 since it is not written to mzXML static_cast(*tiny.run.spectrumListPtr).spectra.pop_back(); } // write to file #1 (static) MSDataFile::write(tiny, filename1, writeConfig); // simulate CLI garbage collect behavior, wherein delayed deletes stress // memory and file handle usage { std::vector< boost::shared_ptr< MSDataFile > > msds; for (int i=0;i<100;i++) { boost::shared_ptr msd1(new MSDataFile(filename1)); msds.push_back(msd1); hackInMemoryMSData(*msd1); Diff diff(tiny, *msd1, diffConfig); } } // read back into an MSDataFile object MSDataFile msd1(filename1); hackInMemoryMSData(msd1); // compare Diff diff(tiny, msd1, diffConfig); if (diff && os_) *os_ << diff << endl; unit_assert(!diff); // write to file #2 (member) msd1.write(filename2, writeConfig); // read back into another MSDataFile object MSDataFile msd2(filename2); hackInMemoryMSData(msd2); // compare diff(tiny, msd2); if (diff && os_) *os_ << diff << endl; unit_assert(!diff); // now give the gzip read a workout bio::filtering_istream tinyGZ(bio::gzip_compressor() | bio::file_descriptor_source(filename1)); bio::copy(tinyGZ, bio::file_descriptor_sink(filename1+".gz", ios::out|ios::binary)); MSDataFile msd3(filename1+".gz"); hackInMemoryMSData(msd3); // compare diff(tiny, msd3); if (diff && os_) *os_ << diff << endl; unit_assert(!diff); // test writing to a stream ostringstream oss; msd1.write(oss, writeConfig); string ossStr = oss.str(); ofstream ofs(filename3.c_str()); ofs.write(ossStr.c_str(), ossStr.length()); ofs.close(); // read back into another MSDataFile object MSDataFile msd4(filename3); hackInMemoryMSData(msd4); // compare diff(tiny, msd4); if (diff && os_) *os_ << diff << endl; unit_assert(!diff); // write to file #4 (testing two byte UTF-8 code points) msd1.write(filename4, writeConfig); // read back into another MSDataFile object MSDataFile msd5(filename4); hackInMemoryMSData(msd5); // compare diff(tiny, msd5); if (diff && os_) *os_ << diff << endl; unit_assert(!diff); // write to file #5 (testing four byte UTF-8 code points) /*msd1.write(filename5, writeConfig); // read back into another MSDataFile object MSDataFile msd6(filename5); hackInMemoryMSData(msd6); // compare diff(tiny, msd6); if (diff && os_) *os_ << diff << endl; unit_assert(!diff);*/ } // remove temp files boost::filesystem::remove(filename1); boost::filesystem::remove(filename2); boost::filesystem::remove(filename1 + ".gz"); boost::filesystem::remove(filename3); boost::filesystem::remove(filename4); //boost::filesystem::remove(filename5); } void test() { MSDataFile::WriteConfig writeConfig; DiffConfig diffConfig; validateMmgfMzxmlRoundTrip(); // mzML 64-bit, full diff validateWriteRead(writeConfig, diffConfig); writeConfig.indexed = false; validateWriteRead(writeConfig, diffConfig); // no index writeConfig.indexed = true; // mzML 32-bit, full diff writeConfig.binaryDataEncoderConfig.precision = BinaryDataEncoder::Precision_32; validateWriteRead(writeConfig, diffConfig); // mzXML 32-bit, diff ignoring metadata and chromatograms writeConfig.format = MSDataFile::Format_mzXML; diffConfig.ignoreMetadata = true; diffConfig.ignoreChromatograms = true; validateWriteRead(writeConfig, diffConfig); // mzXML 64-bit, diff ignoring metadata and chromatograms writeConfig.binaryDataEncoderConfig.precision = BinaryDataEncoder::Precision_64; validateWriteRead(writeConfig, diffConfig); writeConfig.indexed = false; validateWriteRead(writeConfig, diffConfig); // no index writeConfig.indexed = true; } void demo() { MSData tiny; examples::initializeTiny(tiny); MSDataFile::WriteConfig config; MSDataFile::write(tiny, filenameBase_ + ".64.mzML", config); config.binaryDataEncoderConfig.precision = BinaryDataEncoder::Precision_32; MSDataFile::write(tiny, filenameBase_ + ".32.mzML", config); config.format = MSDataFile::Format_Text; MSDataFile::write(tiny, filenameBase_ + ".txt", config); config.format = MSDataFile::Format_mzXML; MSDataFile::write(tiny, filenameBase_ + ".32.mzXML", config); config.binaryDataEncoderConfig.precision = BinaryDataEncoder::Precision_64; MSDataFile::write(tiny, filenameBase_ + ".64.mzXML", config); } const char rawHeader_[] = {'\x01', '\xA1', 'F', '\0', 'i', '\0', 'n', '\0', 'n', '\0', 'i', '\0', 'g', '\0', 'a', '\0', 'n', '\0'}; class TestReader : public Reader { public: TestReader() : count(0) {} virtual std::string identify(const std::string& filename, const std::string& head) const { if (filename.size()<=4 || filename.substr(filename.size()-4)!=".RAW") return std::string(""); for (size_t i=0; i& results, const Config& config = Config()) const { results.push_back(MSDataPtr(new MSData)); read(filename, head, *results.back(), 0, config); } const char *getType() const {return "testReader";} // satisfy inheritance mutable int count; }; void testReader() { // create a file string filename = filenameBase_ + ".RAW"; ofstream os(filename.c_str()); os.write(rawHeader_, 18); os.close(); // open the file with our Reader TestReader reader; MSDataFile msd(filename, &reader); // verify that our reader got called properly unit_assert(reader.count == 2); // remove temp file boost::filesystem::remove(filename); if (os_) *os_ << endl; } void testSHA1() { if (os_) *os_ << "testSHA1()\n"; // write out a test file string filename = filenameBase_ + ".SHA1Test"; MSData tiny; examples::initializeTiny(tiny); MSDataFile::write(tiny, filename); { // read in without SHA-1 calculation MSDataFile msd(filename); if (os_) { *os_ << "no SHA-1:\n"; pwiz::minimxml::XMLWriter writer(*os_); IO::write(writer, *msd.fileDescription.sourceFilePtrs.back()); } unit_assert(!msd.fileDescription.sourceFilePtrs.empty()); unit_assert(!msd.fileDescription.sourceFilePtrs.back()->hasCVParam(MS_SHA_1)); // read in with SHA-1 calculation MSDataFile msd_sha1(filename, 0, true); if (os_) { *os_ << "with SHA-1:\n"; pwiz::minimxml::XMLWriter writer(*os_); IO::write(writer, *msd_sha1.fileDescription.sourceFilePtrs.back()); } unit_assert(!msd_sha1.fileDescription.sourceFilePtrs.empty()); unit_assert(msd_sha1.fileDescription.sourceFilePtrs.back()->hasCVParam(MS_SHA_1)); } // clean up boost::filesystem::remove(filename); if (os_) *os_ << endl; } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); //demo(); testReader(); testSHA1(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/msdata/Serializer_mzML.cpp0000664000175100017510000001774412664775621022517 0ustar teamcityteamcity00000000000000// // $Id: Serializer_mzML.cpp 6141 2014-05-05 21:03:47Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Serializer_mzML.hpp" #include "IO.hpp" #include "SpectrumList_mzML.hpp" #include "ChromatogramList_mzML.hpp" #include "SHA1OutputObserver.hpp" #include "pwiz/utility/minimxml/XMLWriter.hpp" #include "pwiz/utility/minimxml/SAXParser.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace msdata { using minimxml::XMLWriter; using boost::iostreams::stream_offset; using namespace pwiz::util; using namespace pwiz::minimxml; class Serializer_mzML::Impl { public: Impl(const Config& config) : config_(config) {} void write(ostream& os, const MSData& msd, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry) const; void read(shared_ptr is, MSData& msd) const; private: Config config_; }; namespace { void writeSpectrumIndex(XMLWriter& xmlWriter, const SpectrumListPtr& spectrumListPtr, const vector& positions) { XMLWriter::Attributes indexAttributes; indexAttributes.push_back(make_pair("name", "spectrum")); xmlWriter.startElement("index", indexAttributes); xmlWriter.pushStyle(XMLWriter::StyleFlag_InlineInner); if (spectrumListPtr.get() && spectrumListPtr->size() > 0) { if (spectrumListPtr->size() != positions.size()) throw runtime_error("[Serializer_mzML::writeSpectrumIndex()] Sizes differ."); for (unsigned int i=0; ispectrumIdentity(i); XMLWriter::Attributes attributes; attributes.push_back(make_pair("idRef", spectrum.id)); if (!spectrum.spotID.empty()) attributes.push_back(make_pair("spotID", spectrum.spotID)); xmlWriter.startElement("offset", attributes); xmlWriter.characters(lexical_cast(positions[i])); xmlWriter.endElement(); } } xmlWriter.popStyle(); xmlWriter.endElement(); } void writeChromatogramIndex(XMLWriter& xmlWriter, const ChromatogramListPtr& chromatogramListPtr, const vector& positions) { XMLWriter::Attributes indexAttributes; indexAttributes.push_back(make_pair("name", "chromatogram")); xmlWriter.startElement("index", indexAttributes); xmlWriter.pushStyle(XMLWriter::StyleFlag_InlineInner); if (chromatogramListPtr.get() && chromatogramListPtr->size() > 0) { if (chromatogramListPtr->size() != positions.size()) throw runtime_error("[Serializer_mzML::WriteChromatogramIndex()] sizes differ."); for (unsigned int i=0; ichromatogramIdentity(i); XMLWriter::Attributes Attributes; Attributes.push_back(make_pair("idRef", chromatogram.id)); xmlWriter.startElement("offset", Attributes); xmlWriter.characters(lexical_cast(positions[i])); xmlWriter.endElement(); } } xmlWriter.popStyle(); xmlWriter.endElement(); } } // namespace void Serializer_mzML::Impl::write(ostream& os, const MSData& msd, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry) const { // instantiate XMLWriter SHA1OutputObserver sha1OutputObserver; XMLWriter::Config xmlConfig; xmlConfig.outputObserver = &sha1OutputObserver; XMLWriter xmlWriter(os, xmlConfig); string xmlData = "version=\"1.0\" encoding=\"utf-8\""; xmlWriter.processingInstruction("xml", xmlData); // start if (config_.indexed) { XMLWriter::Attributes attributes; attributes.push_back(make_pair("xmlns", "http://psi.hupo.org/ms/mzml")); attributes.push_back(make_pair("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")); attributes.push_back(make_pair("xsi:schemaLocation", "http://psi.hupo.org/ms/mzml http://psidev.info/files/ms/mzML/xsd/mzML1.1.2_idx.xsd")); xmlWriter.startElement("indexedmzML", attributes); attributes.clear(); } // vector spectrumPositions; vector chromatogramPositions; BinaryDataEncoder::Config bdeConfig = config_.binaryDataEncoderConfig; bdeConfig.byteOrder = BinaryDataEncoder::ByteOrder_LittleEndian; // mzML always little endian IO::write(xmlWriter, msd, bdeConfig, &spectrumPositions, &chromatogramPositions, iterationListenerRegistry); // end if (config_.indexed) { stream_offset indexListOffset = xmlWriter.positionNext(); XMLWriter::Attributes attributes; attributes.push_back(make_pair("count", "2")); xmlWriter.startElement("indexList", attributes); writeSpectrumIndex(xmlWriter, msd.run.spectrumListPtr, spectrumPositions); writeChromatogramIndex(xmlWriter, msd.run.chromatogramListPtr, chromatogramPositions); xmlWriter.endElement(); // indexList xmlWriter.pushStyle(XMLWriter::StyleFlag_InlineInner); xmlWriter.startElement("indexListOffset"); xmlWriter.characters(lexical_cast(indexListOffset)); xmlWriter.endElement(); xmlWriter.startElement("fileChecksum"); xmlWriter.characters(sha1OutputObserver.hash()); xmlWriter.endElement(); xmlWriter.popStyle(); xmlWriter.endElement(); // indexedmzML } } struct HandlerIndexedMZML : public SAXParser::Handler { virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "indexedmzML") return Status::Done; throw runtime_error(("[SpectrumList_mzML::HandlerIndexedMZML] Unexpected element name: " + name).c_str()); } }; void Serializer_mzML::Impl::read(shared_ptr is, MSData& msd) const { if (!is.get() || !*is) throw runtime_error("[Serializer_mzML::read()] Bad istream."); is->seekg(0); if (config_.indexed) { HandlerIndexedMZML handler; SAXParser::parse(*is, handler); } IO::read(*is, msd, IO::IgnoreSpectrumList); Index_mzML_Ptr indexPtr(new Index_mzML(is, msd)); msd.run.spectrumListPtr = SpectrumList_mzML::create(is, msd, indexPtr); msd.run.chromatogramListPtr = ChromatogramList_mzML::create(is, msd, indexPtr); } // // Serializer_mzML // PWIZ_API_DECL Serializer_mzML::Serializer_mzML(const Config& config) : impl_(new Impl(config)) {} PWIZ_API_DECL void Serializer_mzML::write(ostream& os, const MSData& msd, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry) const { return impl_->write(os, msd, iterationListenerRegistry); } PWIZ_API_DECL void Serializer_mzML::read(shared_ptr is, MSData& msd) const { return impl_->read(is, msd); } PWIZ_API_DECL ostream& operator<<(ostream& os, const Serializer_mzML::Config& config) { os << config.binaryDataEncoderConfig << " indexed=\"" << boolalpha << config.indexed << "\""; return os; } } // namespace msdata } // namespace pwiz pwiz/pwiz/data/msdata/SpectrumListBaseTest.cpp0000664000175100017510000000365212664775621023531 0ustar teamcityteamcity00000000000000// // $Id: SpectrumListBaseTest.cpp 6141 2014-05-05 21:03:47Z chambm $ // // // Original author: Darren Kessner // // Copyright 2009 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "SpectrumListBase.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::msdata; using namespace pwiz::util; class MyBase : public SpectrumListBase { public: virtual size_t size() const {return 0;} virtual const SpectrumIdentity& spectrumIdentity(size_t index) const {throw runtime_error("heh");} virtual SpectrumPtr spectrum(size_t index, bool getBinaryData = false) const {return SpectrumPtr();} // make sure we still compile -- error if setDataProcessingPtr() renamed to dataProcessingPtr() virtual const boost::shared_ptr dataProcessingPtr() const {return dp_;} }; void test() { MyBase base; DataProcessingPtr dp(new DataProcessing("dp")); base.setDataProcessingPtr(dp); unit_assert(base.dataProcessingPtr().get() == dp.get()); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/msdata/Serializer_MSn.cpp0000664000175100017510000004576512664775621022341 0ustar teamcityteamcity00000000000000// // $Id: Serializer_MSn.cpp 8888 2015-09-24 20:16:23Z kaipot $ // // // Original author: Barbara Frewen // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Serializer_MSn.hpp" #include "SpectrumList_MSn.hpp" #include "SpectrumInfo.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/chemistry/Chemistry.hpp" #include "zlib.h" #include #include "SpectrumWorkerThreads.hpp" namespace pwiz { namespace msdata { // these are the fixed sizes used to read/write .bms2 and .cms2 files // use these to write to files rather than sizeof() const int sizeIntMSn = 4; const int sizeFloatMSn = 4; const int sizeDoubleMSn = 8; const int sizeChargeMSn = 12; // struct Charge{ int z; double mass; } const int sizePeakMSn = 12; // struct Peak{ double mz; float intensity; } using namespace std; using boost::shared_ptr; using boost::iostreams::stream_offset; using namespace pwiz::util; using namespace pwiz::chemistry; class Serializer_MSn::Impl { public: Impl(MSn_Type filetype) : _filetype(filetype) {} void write(ostream& os, const MSData& msd, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry) const; void read(shared_ptr is, MSData& msd) const; private: MSn_Type _filetype; // .ms1, .cms1, .bms1, .ms2, .cms2, .bms2 }; namespace { void writeBinaryFileHeader(MSn_Type filetype, int version, const MSData& msd, ostream& os) { time_t rawtime; time (&rawtime); os.write(reinterpret_cast(&filetype), sizeIntMSn); os.write(reinterpret_cast(&version), sizeIntMSn); MSnHeader header; sprintf(header.header[0], "CreationDate %s", ctime(&rawtime)); sprintf(header.header[1], "Extractor\tProteoWizard\n"); sprintf(header.header[2], "Extractor version\t%s\n", (msd.softwarePtrs.empty() ? "unknown" : msd.softwarePtrs.at(0)->id.c_str())); sprintf(header.header[3], "Source file\t%s\n", (msd.fileDescription.sourceFilePtrs.empty() ? "unknown" : msd.fileDescription.sourceFilePtrs.at(0)->name.c_str())); os.write(reinterpret_cast(&header), sizeof(MSnHeader)); } void writeTextFileHeader(const MSData& msd, ostream& os) { time_t rawtime; time (&rawtime); os << "H\tCreationDate " << ctime(&rawtime) << flush; os << "H\tExtractor\tProteoWizard" << endl; os << "H\tExtractor version\t" << ( msd.softwarePtrs.empty() ? "unknown" : msd.softwarePtrs.at(0)->id ) << endl; os << "H\tSource file\t" << ( (msd.fileDescription.sourceFilePtrs.empty()) ? "unknown" : msd.fileDescription.sourceFilePtrs.at(0)->name ) << endl; } // Could be one charge state, with or without accurate mass // or could be multiple possible charge states without accurate mass // if no accurate mass, compute it from mz and charge double calculateMass(double mz, int charge) { return (mz * charge) - ((charge - 1) * Proton); } size_t getChargeStates(const SelectedIon& si, vector& charges, vector& masses) { int startingChargesCount = charges.size(); CVParam chargeParam = si.cvParam(MS_charge_state); CVParam massParam = si.cvParam(MS_accurate_mass_OBSOLETE); double mz = si.cvParam(MS_selected_ion_m_z).valueAs(); if (!chargeParam.empty()) { charges.push_back(chargeParam.valueAs()); if (!massParam.empty()) { masses.push_back(massParam.valueAs()); } else { masses.push_back(calculateMass(mz, charges.back())); } } else { BOOST_FOREACH(const CVParam& param, si.cvParams) { if (param.cvid == MS_possible_charge_state) { charges.push_back(param.valueAs()); masses.push_back(calculateMass(mz, charges.back())); } } } return (int)(charges.size() - startingChargesCount); } int getScanNumber(SpectrumPtr s) { string scanNumber = id::translateNativeIDToScanNumber(MS_scan_number_only_nativeID_format, s->id); int scanNum = 0; if (!scanNumber.empty()) { scanNum = lexical_cast(scanNumber); } return scanNum; } void writeSpectrumText(SpectrumPtr s, ostream& os) { os << std::setprecision(7); // 123.4567 bool ms1File = s->cvParam(MS_ms_level).valueAs() == 1; // Write the scan numbers os << "S\t"; int scanNum = getScanNumber(s); os << scanNum << "\t" << scanNum; if (!ms1File) { // Write the precursor mz Precursor& precur = s->precursors[0]; double mz = precur.isolationWindow.cvParam(MS_isolation_window_target_m_z).valueAs(); os << "\t" << mz; } os << "\n"; // Write the scan time, if available if( !(s->scanList.empty()) && s->scanList.scans[0].cvParam(MS_scan_start_time).timeInSeconds() ) os << "I\tRTime\t" << s->scanList.scans[0].cvParam(MS_scan_start_time).timeInSeconds()/60 << "\n"; if (s->defaultArrayLength > 0) { // Write the base peak intensity and base peak m/z if (s->hasCVParam(MS_base_peak_intensity)) { double bpi = s->cvParam(MS_base_peak_intensity).valueAs(); os << "I\tBPI\t" << bpi << "\n"; } if (s->hasCVParam(MS_base_peak_m_z)) { double bpm = s->cvParam(MS_base_peak_m_z).valueAs(); os << "I\tBPM\t" << bpm << "\n"; } // Write the total ion current if (s->hasCVParam(MS_total_ion_current)) { double tic = s->cvParam(MS_total_ion_current).valueAs(); os << "I\tTIC\t" << tic << "\n"; } } //TODO // Write ConvA/ConvB information // Write the ion injection time //os << "I\tIIT\t" << s->scanList.scans[0].cvParam(MS_ion_injection_time).timeInSeconds()/60 << "\n"; if (!ms1File) { Precursor& precur = s->precursors[0]; SelectedIon& si = precur.selectedIons[0]; // Collect charge and mass info vector charges; vector masses; int numChargeStates = 0; // for each selected ion BOOST_FOREACH(const SelectedIon& curIon, precur.selectedIons){ numChargeStates += getChargeStates(curIon, charges, masses); } // Write EZ lines if accurate masses are available CVParam massParam = si.cvParam(MS_accurate_mass_OBSOLETE); if( !massParam.empty() ){ for(int i=0; i < numChargeStates; i++){ os << "I\tEZ\t" << charges[i] << "\t" << masses[i] << "\t0\t0" << endl; // pad last two fields with 0 } } // For each charge, write the charge and mass for(int i = 0; i < numChargeStates; i++) { os << "Z\t" << charges[i] << "\t" << masses[i] << "\n"; } } // Write each mz, intensity pair const BinaryDataArray& mzArray = *s->getMZArray(); const BinaryDataArray& intensityArray = *s->getIntensityArray(); for (size_t p=0; p < s->defaultArrayLength; ++p) { os << mzArray.data[p] << " " << intensityArray.data[p] << "\n"; } } void writeCompressedPeaks(SpectrumPtr s, ostream& os) { // Build arrays to hold peaks prior to compression int numPeaks = (int) s->defaultArrayLength; double *pD = new double[numPeaks]; float *pF = new float[numPeaks]; const BinaryDataArray& mzArray = *s->getMZArray(); const BinaryDataArray& intensityArray = *s->getIntensityArray(); for(int j = 0; j < numPeaks; j++) { pD[j] = mzArray.data[j]; pF[j] = (float) intensityArray.data[j]; } // compress mz uLong sizeM = (uLong) (numPeaks * sizeDoubleMSn); uLong comprLenM = compressBound(sizeM); Byte *comprM = (Byte*)calloc((uInt)comprLenM, 1); int retM = compress(comprM, &comprLenM, (const Bytef*)pD, sizeM); // compress intensity uLong sizeI = (uLong) (numPeaks * sizeFloatMSn); uLong comprLenI = compressBound(sizeI); Byte *comprI = (Byte*)calloc((uInt)comprLenI, 1); int retI = compress(comprI, &comprLenI, (const Bytef*)pF, sizeI); // Write the compressed peaks if all is well if ((Z_OK == retM) && (Z_OK == retI)) { // write length of compressed array of m/z os.write(reinterpret_cast(&comprLenM), sizeIntMSn); // write length of compressed array of intensities os.write(reinterpret_cast(&comprLenI), sizeIntMSn); // write compressed array of m/z os.write(reinterpret_cast(comprM), comprLenM); // write compressed array of intensities os.write(reinterpret_cast(comprI), comprLenI); } // Clean up memory free(comprM); free(comprI); delete [] pD; delete [] pF; // In case of error, throw exception AFTER cleaning up memory if (Z_OK != retM || Z_OK != retI) { throw runtime_error("[Serializer_MSn::writeCompressedPeaks] Error compressing peaks."); } } void writeSpectrumBinary(SpectrumPtr s, int version, bool compress, ostream& os) { bool ms1File = s->cvParam(MS_ms_level).valueAs() == 1; int scanNum = getScanNumber(s); os.write(reinterpret_cast(&scanNum), sizeIntMSn); os.write(reinterpret_cast(&scanNum), sizeIntMSn); // Yes, there are two Precursor precur; SelectedIon si; if (!ms1File) { precur = s->precursors[0]; si = precur.selectedIons[0]; double mz = precur.isolationWindow.cvParam(MS_isolation_window_target_m_z).valueAs(); os.write(reinterpret_cast(&mz), sizeDoubleMSn); } else { double mz = 0; os.write(reinterpret_cast(&mz), sizeDoubleMSn); } float rt = 0.0; if( !(s->scanList.empty()) && s->scanList.scans[0].cvParam(MS_scan_start_time).timeInSeconds() ) { rt = (float) s->scanList.scans[0].cvParam(MS_scan_start_time).timeInSeconds()/60; } os.write(reinterpret_cast(&rt), sizeFloatMSn); if (version >= 2) { float basePeakIntensity = s->cvParam(MS_base_peak_intensity).valueAs(); os.write(reinterpret_cast(&basePeakIntensity), sizeFloatMSn); double basePeakMZ = s->cvParam(MS_base_peak_m_z).valueAs(); os.write(reinterpret_cast(&basePeakMZ), sizeDoubleMSn); // We don't have this information, but we need to write something, // so pad with 0's. (version 2 specific data) double conversionFactorA = (double)0; os.write(reinterpret_cast(&conversionFactorA), sizeDoubleMSn); double conversionFactorB = (double)0; os.write(reinterpret_cast(&conversionFactorB), sizeDoubleMSn); double tic = s->cvParam(MS_total_ion_current).valueAs(); os.write(reinterpret_cast(&tic), sizeDoubleMSn); // TODO float ionInjectionTime = (float)0; os.write(reinterpret_cast(&ionInjectionTime), sizeFloatMSn); } vector charges; vector masses; int numChargeStates = 0; if (!ms1File) { BOOST_FOREACH(const SelectedIon& curIon, precur.selectedIons) { numChargeStates += getChargeStates(curIon, charges, masses); } } os.write(reinterpret_cast(&numChargeStates), sizeIntMSn); bool hasAccurateMass = false; if (version == 3) { int numEzStates = 0; CVParam massParam = si.cvParam(MS_accurate_mass_OBSOLETE); if (!massParam.empty()) { numEzStates = numChargeStates; hasAccurateMass = true; } os.write(reinterpret_cast(&numEzStates), sizeIntMSn); } int numPeaks = (int) s->defaultArrayLength; os.write(reinterpret_cast(&numPeaks), sizeIntMSn); // end spectrum header info // Write out each charge state and corresponding mass for(int i = 0; i < numChargeStates; i++) { os.write(reinterpret_cast(&(charges[i])), sizeIntMSn); os.write(reinterpret_cast(&(masses[i])), sizeDoubleMSn); } // if there are accurate masses, write out EZ entries if( hasAccurateMass ){ float blank = 0; // we don't have rTime or area, pad with zeros for(int i=0; i < numChargeStates; i++){ os.write(reinterpret_cast(&charges[i]), sizeIntMSn); os.write(reinterpret_cast(&masses[i]), sizeDoubleMSn); os.write(reinterpret_cast(&blank), sizeFloatMSn); os.write(reinterpret_cast(&blank), sizeFloatMSn); } } // Do we need to write compressed m/z, intensity arrays? if (compress) { writeCompressedPeaks(s, os); } else { // No need to compress, just write out the arrays const BinaryDataArray& mzArray = *s->getMZArray(); const BinaryDataArray& intensityArray = *s->getIntensityArray(); for(int i = 0; i < numPeaks; i++) { double mzPeak = mzArray.data[i]; os.write(reinterpret_cast(&mzPeak), sizeDoubleMSn); float intensityPeak = (float) intensityArray.data[i]; os.write(reinterpret_cast(&intensityPeak), sizeFloatMSn); } } } } // namespace void Serializer_MSn::Impl::write(ostream& os, const MSData& msd, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry) const { // Write the header if ((MSn_Type_BMS1 == _filetype) || (MSn_Type_CMS1 == _filetype) || (MSn_Type_BMS2 == _filetype) || (MSn_Type_CMS2 == _filetype)) { writeBinaryFileHeader(_filetype, 3 /* version */, msd, os); } else if ((MSn_Type_MS1 == _filetype) || (MSn_Type_MS2 == _filetype)) { writeTextFileHeader(msd, os); } // Go through the spectrum list and write each spectrum bool ms1File = MSn_Type_MS1 == _filetype || MSn_Type_BMS1 == _filetype || MSn_Type_CMS1 == _filetype; SpectrumList& sl = *msd.run.spectrumListPtr; SpectrumWorkerThreads spectrumWorkers(sl); for (size_t i=0, end=sl.size(); i < end; ++i) { //SpectrumPtr s = sl.spectrum(i, true); SpectrumPtr s = spectrumWorkers.processBatch(i); int msLevel = s->cvParam(MS_ms_level).valueAs(); if ((ms1File && msLevel == 1) || (!ms1File && msLevel == 2 && !s->precursors.empty() && !s->precursors[0].selectedIons.empty())) { switch (_filetype) { case MSn_Type_MS1: writeSpectrumText(s, os); break; case MSn_Type_CMS1: writeSpectrumBinary(s, 3 /* version */, true, os); break; case MSn_Type_BMS1: writeSpectrumBinary(s, 3 /* version */, false, os); break; case MSn_Type_MS2: writeSpectrumText(s, os); break; case MSn_Type_CMS2: writeSpectrumBinary(s, 3 /* version */, true, os); break; case MSn_Type_BMS2: writeSpectrumBinary(s, 3 /* version */, false, os); break; case MSn_Type_UNKNOWN: throw runtime_error("[SpectrumList_MSn::Impl::write] Cannot create unknown MSn file type."); } } // update any listeners and handle cancellation IterationListener::Status status = IterationListener::Status_Ok; if (iterationListenerRegistry) { status = iterationListenerRegistry->broadcastUpdateMessage( IterationListener::UpdateMessage(i, end)); } if (status == IterationListener::Status_Cancel) { break; } } } void Serializer_MSn::Impl::read(shared_ptr is, MSData& msd) const { if (!is.get() || !*is) throw runtime_error("[Serializer_MSn::read()] Bad istream."); is->seekg(0); msd.fileDescription.fileContent.set(MS_MSn_spectrum); msd.fileDescription.fileContent.set(MS_centroid_spectrum); msd.fileDescription.fileContent.set(MS_scan_number_only_nativeID_format); msd.run.spectrumListPtr = SpectrumList_MSn::create(is, msd, _filetype); msd.run.chromatogramListPtr.reset(new ChromatogramListSimple); } // // Serializer_MSn // PWIZ_API_DECL Serializer_MSn::Serializer_MSn(MSn_Type filetype) : impl_(new Impl(filetype)) {} PWIZ_API_DECL void Serializer_MSn::write(ostream& os, const MSData& msd, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry) const { return impl_->write(os, msd, iterationListenerRegistry); } PWIZ_API_DECL void Serializer_MSn::read(shared_ptr is, MSData& msd) const { return impl_->read(is, msd); } } // namespace msdata } // namespace pwiz pwiz/pwiz/data/msdata/IOTest.cpp0000664000175100017510000011350312664775621020604 0ustar teamcityteamcity00000000000000// // $Id: IOTest.cpp 6478 2014-07-08 20:01:38Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "IO.hpp" #include "Diff.hpp" #include "References.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::minimxml; using namespace pwiz::cv; using namespace pwiz::data; using namespace pwiz::msdata; using boost::iostreams::stream_offset; ostream* os_ = 0; template void testObject(const object_type& a) { if (os_) *os_ << "testObject(): " << typeid(a).name() << endl; // write 'a' out to a stream ostringstream oss; XMLWriter writer(oss); IO::write(writer, a); if (os_) *os_ << oss.str() << endl; // read 'b' in from stream object_type b; istringstream iss(oss.str()); IO::read(iss, b); // compare 'a' and 'b' Diff diff(a,b); if (diff && os_) *os_ << "diff:\n" << diff << endl; unit_assert(!diff); } template void testObjectWithMSData(const object_type& a, const MSData& msd) { if (os_) *os_ << "testObject(): " << typeid(a).name() << endl; // write 'a' out to a stream ostringstream oss; XMLWriter writer(oss); IO::write(writer, a, msd); if (os_) *os_ << oss.str() << endl; // read 'b' in from stream object_type b; istringstream iss(oss.str()); IO::read(iss, b); // compare 'a' and 'b' Diff diff(a,b); if (diff && os_) *os_ << "diff:\n" << diff << endl; unit_assert(!diff); } void testObject_SpectrumList(const SpectrumList& a) { if (os_) *os_ << "testObject_SpectrumList(): " << endl; // write 'a' out to a stream ostringstream oss; XMLWriter writer(oss); MSData dummy; IO::write(writer, a, dummy); if (os_) *os_ << oss.str() << endl; // read 'b' in from stream SpectrumListSimple b; istringstream iss(oss.str()); IO::read(iss, b); // compare 'a' and 'b' Diff diff(a,b); if (diff && os_) *os_ << "diff:\n" << diff << endl; unit_assert(!diff); } void testObject_ChromatogramList(const ChromatogramList& a) { if (os_) *os_ << "testObject_ChromatogramList(): " << endl; // write 'a' out to a stream ostringstream oss; XMLWriter writer(oss); IO::write(writer, a); if (os_) *os_ << oss.str() << endl; // read 'b' in from stream ChromatogramListSimple b; istringstream iss(oss.str()); IO::read(iss, b); // compare 'a' and 'b' Diff diff(a,b); if (diff && os_) *os_ << "diff:\n" << diff << endl; unit_assert(!diff); } void testCV() { CV a; a.URI = "abcd"; a.id = "efgh"; a.fullName = "ijkl"; a.version = "mnop"; testObject(a); } void testUserParam() { UserParam a; a.name = "abcd"; a.value = "efgh"; a.type = "ijkl"; a.units = UO_minute; testObject(a); } void testCVParam() { CVParam a(MS_selected_ion_m_z, "810.48", MS_m_z); testObject(a); CVParam b(UO_second, "123.45"); testObject(b); } void testParamGroup() { ParamGroup a("pg"); a.userParams.push_back(UserParam("goober", "goo", "peanuts")); a.cvParams.push_back(CVParam(MS_ionization_type, "420")); a.cvParams.push_back(CVParam(MS_selected_ion_m_z, "666", MS_m_z)); a.paramGroupPtrs.push_back(ParamGroupPtr(new ParamGroup("pgp"))); testObject(a); } template void testNamedParamContainer() { object_type a; a.userParams.push_back(UserParam("goober", "goo", "peanuts")); a.cvParams.push_back(CVParam(MS_ionization_type, "420")); a.cvParams.push_back(CVParam(MS_selected_ion_m_z, "666", MS_m_z)); a.paramGroupPtrs.push_back(ParamGroupPtr(new ParamGroup("pgp"))); testObject(a); } void testSourceFile() { SourceFile a("id123", "name456", "location789"); a.userParams.push_back(UserParam("goober", "goo", "peanuts")); a.cvParams.push_back(CVParam(MS_ionization_type, "420")); a.cvParams.push_back(CVParam(MS_selected_ion_m_z, "666", MS_m_z)); a.paramGroupPtrs.push_back(ParamGroupPtr(new ParamGroup("pgp"))); testObject(a); } void testFileDescription() { FileDescription a; a.fileContent.cvParams.push_back(MS_MSn_spectrum); SourceFilePtr sf(new SourceFile("1", "tiny1.RAW", "file://F:/data/Exp01")); sf->cvParams.push_back(MS_Thermo_RAW_format); sf->cvParams.push_back(MS_SHA_1); a.sourceFilePtrs.push_back(sf); Contact contact; contact.cvParams.push_back(CVParam(MS_contact_name, "Darren")); a.contacts.push_back(contact); testObject(a); } void testSample() { Sample a("id123", "name456"); a.userParams.push_back(UserParam("goober", "goo", "peanuts")); a.cvParams.push_back(CVParam(MS_ionization_type, "420")); a.cvParams.push_back(CVParam(MS_selected_ion_m_z, "666", MS_m_z)); a.paramGroupPtrs.push_back(ParamGroupPtr(new ParamGroup("pgp"))); testObject(a); } void testComponent() { Component a(ComponentType_Source, 1); a.userParams.push_back(UserParam("goober", "goo", "peanuts")); a.cvParams.push_back(CVParam(MS_ionization_type, "420")); a.cvParams.push_back(CVParam(MS_selected_ion_m_z, "666", MS_m_z)); a.paramGroupPtrs.push_back(ParamGroupPtr(new ParamGroup("pgp"))); testObject(a); } void testComponentList() { ComponentList a; a.push_back(Component(MS_nanoelectrospray, 1)); a.push_back(Component(MS_quadrupole_ion_trap, 2)); a.push_back(Component(MS_electron_multiplier, 3)); testObject(a); } void testSoftware() { Software a; a.id = "goober"; a.set(MS_ionization_type); a.version = "4.20"; testObject(a); } void testInstrumentConfiguration() { InstrumentConfiguration a; a.id = "LCQ Deca"; a.cvParams.push_back(MS_LCQ_Deca); a.cvParams.push_back(CVParam(MS_instrument_serial_number, 23433)); a.componentList.push_back(Component(MS_nanoelectrospray, 1)); a.componentList.push_back(Component(MS_quadrupole_ion_trap, 2)); a.componentList.push_back(Component(MS_electron_multiplier, 3)); a.softwarePtr = SoftwarePtr(new Software("XCalibur")); testObject(a); } void testProcessingMethod() { ProcessingMethod a; a.order = 420; a.cvParams.push_back(CVParam(MS_deisotoping, false)); a.cvParams.push_back(CVParam(MS_charge_deconvolution, false)); a.cvParams.push_back(CVParam(MS_peak_picking, true)); a.softwarePtr = SoftwarePtr(new Software("pwiz")); testObject(a); } void testDataProcessing() { DataProcessing a; a.id = "msdata processing"; ProcessingMethod pm1, pm2; pm1.order = 420; pm1.cvParams.push_back(CVParam(MS_deisotoping, false)); pm1.cvParams.push_back(CVParam(MS_charge_deconvolution, false)); pm1.cvParams.push_back(CVParam(MS_peak_picking, true)); pm1.softwarePtr = SoftwarePtr(new Software("msdata")); pm2.order = 421; pm2.userParams.push_back(UserParam("testing")); a.processingMethods.push_back(pm1); a.processingMethods.push_back(pm2); testObject(a); } void testScanSettings() { ScanSettings a; a.id = "as1"; Target t1, t2; t1.set(MS_selected_ion_m_z, 200); t2.userParams.push_back(UserParam("testing")); a.targets.push_back(t1); a.targets.push_back(t2); a.sourceFilePtrs.push_back(SourceFilePtr(new SourceFile("sf1"))); a.sourceFilePtrs.push_back(SourceFilePtr(new SourceFile("sf2"))); testObject(a); } void testPrecursor() { Precursor a; a.spectrumID = "scan=19"; a.isolationWindow.set(MS_isolation_window_target_m_z, 123456, MS_m_z); a.isolationWindow.set(MS_isolation_window_lower_offset, 2, MS_m_z); a.isolationWindow.set(MS_isolation_window_upper_offset, 3, MS_m_z); a.selectedIons.resize(2); a.selectedIons[0].set(MS_selected_ion_m_z, 445.34, MS_m_z); a.selectedIons[1].set(MS_charge_state, 2); a.activation.set(MS_collision_induced_dissociation); a.activation.set(MS_collision_energy, 35.00); testObject(a); // TODO: fix this to test mzML 1.0 precursors; // (requires fixing the framework to support testing different schema versions) } void testProduct() { Product a; a.isolationWindow.set(MS_isolation_window_target_m_z, 123456, MS_m_z); a.isolationWindow.set(MS_isolation_window_lower_offset, 2, MS_m_z); a.isolationWindow.set(MS_isolation_window_upper_offset, 3, MS_m_z); testObject(a); } void testScan() { Scan a; a.instrumentConfigurationPtr = InstrumentConfigurationPtr(new InstrumentConfiguration("LTQ FT")); a.paramGroupPtrs.push_back(ParamGroupPtr(new ParamGroup("CommonMS1SpectrumParams"))); a.cvParams.push_back(CVParam(MS_scan_start_time, 5.890500, UO_minute)); a.cvParams.push_back(CVParam(MS_filter_string, "+ c NSI Full ms [ 400.00-1800.00]")); a.scanWindows.push_back(ScanWindow(400.0, 1800.0, MS_m_z)); MSData dummy; testObjectWithMSData(a, dummy); } void testScanList() { ScanList a; a.cvParams.push_back(MS_sum_of_spectra); Scan a1; a1.cvParams.push_back(MS_reflectron_on); Scan a2; a1.cvParams.push_back(MS_reflectron_off); a.scans.push_back(a1); a.scans.push_back(a2); MSData dummy; testObjectWithMSData(a, dummy); } void testBinaryDataArray(const BinaryDataEncoder::Config& config) { if (os_) *os_ << "testBinaryDataArray():\n"; BinaryDataArray a; for (int i=0; i<10; i++) a.data.push_back(i); a.dataProcessingPtr = DataProcessingPtr(new DataProcessing("msdata")); // write 'a' out to a stream ostringstream oss; XMLWriter writer(oss); IO::write(writer, a, config); if (os_) *os_ << oss.str() << endl; // read 'b' in from stream BinaryDataArray b; istringstream iss(oss.str()); IO::read(iss, b); // compare 'a' and 'b' Diff diff(a,b); if (diff && os_) *os_ << "diff:\n" << diff << endl; unit_assert(!diff); } void testBinaryDataArray() { BinaryDataEncoder::Config config; config.precision = BinaryDataEncoder::Precision_32; config.byteOrder = BinaryDataEncoder::ByteOrder_LittleEndian; testBinaryDataArray(config); config.precision = BinaryDataEncoder::Precision_64; config.byteOrder = BinaryDataEncoder::ByteOrder_LittleEndian; testBinaryDataArray(config); //config.precision = BinaryDataEncoder::Precision_64; //config.compression = BinaryDataEncoder::Compression_Zlib; //testBinaryDataArray(config); } const char* bdaWithExternalMetadata = "\ \ \ AAAAAAAAAAAAAAAAAADwPwAAAAAAAABAAAAAAAAACEAAAAAAAAAQQAAAAAAAABRAAAAAAAAAGEAAAAAAAAAcQAAAAAAAACBAAAAAAAAAIkAAAAAAAAAkQAAAAAAAACZAAAAAAAAAKEAAAAAAAAAqQAAAAAAAACxA \ "; void testBinaryDataArrayExternalMetadata() { // instantiate an MSData object with the binary array metadata held in a ParamGroup MSData msd; ParamGroupPtr pg(new ParamGroup); pg->id = "mz_params"; pg->cvParams.push_back(MS_m_z_array); pg->cvParams.push_back(MS_64_bit_float); pg->cvParams.push_back(MS_no_compression); msd.paramGroupPtrs.push_back(pg); istringstream is(bdaWithExternalMetadata); BinaryDataArray bda; // test read with MSData reference IO::read(is, bda, &msd); unit_assert(bda.data.size() == 15); for (size_t i=0; i<15; i++) unit_assert(bda.data[i] == i); } void testSpectrum() { if (os_) *os_ << "testSpectrum():\n"; Spectrum a; a.index = 123; a.id = "goo"; a.defaultArrayLength = 666; a.dataProcessingPtr = DataProcessingPtr(new DataProcessing("dp")); a.sourceFilePtr = SourceFilePtr(new SourceFile("sf")); a.binaryDataArrayPtrs.push_back(BinaryDataArrayPtr(new BinaryDataArray)); for (size_t i=0; idata.push_back(i); a.binaryDataArrayPtrs.back()->set(MS_m_z_array); a.binaryDataArrayPtrs.push_back(BinaryDataArrayPtr(new BinaryDataArray)); for (size_t i=0; idata.push_back(i*2); a.binaryDataArrayPtrs.back()->set(MS_intensity_array); a.cvParams.push_back(MS_reflectron_on); a.cvParams.push_back(MS_MSn_spectrum); a.precursors.push_back(Precursor()); a.precursors.back().spectrumID = "19"; a.precursors.back().selectedIons.resize(1); a.precursors.back().selectedIons[0].set(MS_selected_ion_m_z, 445.34, MS_m_z); a.precursors.back().selectedIons[0].set(MS_charge_state, 2); a.precursors.back().activation.set(MS_collision_induced_dissociation); a.precursors.back().activation.set(MS_collision_energy, 35.00, UO_electronvolt); a.products.push_back(Product()); a.products.back().isolationWindow.set(MS_ionization_type, "420"); a.scanList.scans.push_back(Scan()); Scan& scan = a.scanList.scans.back(); scan.set(MS_scan_start_time, 4.20); scan.set(MS_filter_string, "doobie"); a.scanList.scans.push_back(Scan()); Scan& scan2 = a.scanList.scans.back(); scan2.set(MS_scan_start_time, 4.21); scan2.set(MS_filter_string, "doo"); // write 'a' out to a stream ostringstream oss; XMLWriter writer(oss); MSData dummy; IO::write(writer, a, dummy); if (os_) *os_ << oss.str() << endl; // read 'b' in from stream Spectrum b; istringstream iss(oss.str()); IO::read(iss, b, IO::ReadBinaryData); unit_assert(b.sourceFilePosition == 0); // not -1 // compare 'a' and 'b' Diff diff(a,b); if (diff && os_) *os_ << "diff:\n" << diff << endl; unit_assert(!diff); // test IgnoreBinaryData Spectrum c; iss.seekg(0); IO::read(iss, c); // default = IgnoreBinaryData unit_assert(c.binaryDataArrayPtrs.empty()); unit_assert(c.sourceFilePosition == 0); // not -1 a.binaryDataArrayPtrs.clear(); diff(a, c); unit_assert(!diff); } void testChromatogram() { if (os_) *os_ << "testChromatogram():\n"; Chromatogram a; a.index = 123; a.id = "goo"; a.defaultArrayLength = 666; a.dataProcessingPtr = DataProcessingPtr(new DataProcessing("dp")); a.binaryDataArrayPtrs.push_back(BinaryDataArrayPtr(new BinaryDataArray)); for (size_t i=0; idata.push_back(i); a.binaryDataArrayPtrs.back()->set(MS_time_array); a.binaryDataArrayPtrs.push_back(BinaryDataArrayPtr(new BinaryDataArray)); for (size_t i=0; idata.push_back(i*2); a.binaryDataArrayPtrs.back()->set(MS_intensity_array); a.cvParams.push_back(MS_total_ion_current_chromatogram); // TODO: fix when CV has appropriate terms // write 'a' out to a stream ostringstream oss; XMLWriter writer(oss); IO::write(writer, a); if (os_) *os_ << oss.str() << endl; // read 'b' in from stream Chromatogram b; istringstream iss(oss.str()); IO::read(iss, b, IO::ReadBinaryData); unit_assert(b.sourceFilePosition == 0); // not -1 // compare 'a' and 'b' Diff diff(a,b); if (diff && os_) *os_ << "diff:\n" << diff << endl; unit_assert(!diff); // test IgnoreBinaryData Chromatogram c; iss.seekg(0); IO::read(iss, c); // default = IgnoreBinaryData unit_assert(c.binaryDataArrayPtrs.empty()); unit_assert(c.sourceFilePosition == 0); // not -1 a.binaryDataArrayPtrs.clear(); diff(a, c); unit_assert(!diff); } void testSpectrumList() { SpectrumListSimple a; SpectrumPtr spectrum1(new Spectrum); spectrum1->id = "goober"; spectrum1->index = 0; spectrum1->defaultArrayLength = 666; spectrum1->userParams.push_back(UserParam("description1")); SpectrumPtr spectrum2(new Spectrum); spectrum2->id = "raisinet"; spectrum2->index = 1; spectrum2->defaultArrayLength = 667; spectrum2->userParams.push_back(UserParam("description2")); a.spectra.push_back(spectrum1); a.spectra.push_back(spectrum2); a.dp = DataProcessingPtr(new DataProcessing("dp")); testObject_SpectrumList(a); } void testSpectrumListWithPositions() { if (os_) *os_ << "testSpectrumListWithPositions()\n "; SpectrumListSimple a; SpectrumPtr spectrum1(new Spectrum); spectrum1->id = "goober"; spectrum1->index = 0; spectrum1->defaultArrayLength = 666; spectrum1->userParams.push_back(UserParam("description1")); SpectrumPtr spectrum2(new Spectrum); spectrum2->id = "raisinet"; spectrum2->index = 1; spectrum2->defaultArrayLength = 667; spectrum2->userParams.push_back(UserParam("description2")); a.spectra.push_back(spectrum1); a.spectra.push_back(spectrum2); ostringstream oss; XMLWriter writer(oss); vector positions; MSData dummy; IO::write(writer, a, dummy, BinaryDataEncoder::Config(), &positions); if (os_) { copy(positions.begin(), positions.end(), ostream_iterator(*os_, " ")); *os_ << endl << oss.str() << endl; *os_ << "\n\n"; } unit_assert(positions.size() == 2); unit_assert(positions[0] == 27); unit_assert(positions[1] == 179); } class TestIterationListener : public IterationListener { public: virtual Status update(const UpdateMessage& updateMessage) { indices_.push_back(updateMessage.iterationIndex); return Status_Ok; } const vector& indices() const {return indices_;} private: vector indices_; }; class TestIterationListener_WithCancel : public IterationListener { public: virtual Status update(const UpdateMessage& updateMessage) { if (updateMessage.iterationIndex == 5) return Status_Cancel; indices_.push_back(updateMessage.iterationIndex); return Status_Ok; } const vector& indices() const {return indices_;} private: vector indices_; }; void testSpectrumListWriteProgress() { if (os_) *os_ << "testSpectrumListWriteProgress()\n "; SpectrumListSimple a; for (size_t i=0; i<11; i++) { SpectrumPtr spectrum(new Spectrum); spectrum->id = "goober_" + lexical_cast(i); spectrum->index = i; spectrum->defaultArrayLength = 666; a.spectra.push_back(spectrum); } ostringstream oss; XMLWriter writer(oss); IterationListenerPtr listenerPtr(new TestIterationListener); TestIterationListener& listener = *boost::static_pointer_cast(listenerPtr); IterationListenerRegistry registry; registry.addListener(listenerPtr, 3); // callbacks: 0,2,5,8,10 MSData dummy; IO::write(writer, a, dummy, BinaryDataEncoder::Config(), 0, ®istry); if (os_) { *os_ << "callback indices: "; copy(listener.indices().begin(), listener.indices().end(), ostream_iterator(*os_, " ")); *os_ << "\n\n"; } unit_assert(listener.indices().size() == 5); unit_assert(listener.indices()[0] == 0); unit_assert(listener.indices()[1] == 2); unit_assert(listener.indices()[2] == 5); unit_assert(listener.indices()[3] == 8); unit_assert(listener.indices()[4] == 10); // test #2, this time with cancel at index 6 IterationListenerPtr cancelListenerPtr(new TestIterationListener_WithCancel); TestIterationListener_WithCancel& cancelListener = *boost::static_pointer_cast(cancelListenerPtr); IterationListenerRegistry registry2; registry2.addListener(cancelListenerPtr, 3); // callbacks: 0,2, cancel at 5 ostringstream oss2; XMLWriter writer2(oss2); IO::write(writer2, a, dummy, BinaryDataEncoder::Config(), 0, ®istry2); if (os_) { *os_ << "callback indices: "; copy(cancelListener.indices().begin(), cancelListener.indices().end(), ostream_iterator(*os_, " ")); *os_ << "\n\n"; } unit_assert(cancelListener.indices().size() == 2); unit_assert(cancelListener.indices()[0] == 0); unit_assert(cancelListener.indices()[1] == 2); } void testChromatogramList() { ChromatogramListSimple a; ChromatogramPtr chromatogram1(new Chromatogram); chromatogram1->id = "goober"; chromatogram1->index = 0; chromatogram1->defaultArrayLength = 666; ChromatogramPtr chromatogram2(new Chromatogram); chromatogram2->id = "raisinet"; chromatogram2->index = 1; chromatogram2->defaultArrayLength = 667; a.chromatograms.push_back(chromatogram1); a.chromatograms.push_back(chromatogram2); a.dp = DataProcessingPtr(new DataProcessing("dp")); testObject_ChromatogramList(a); } void testChromatogramListWithPositions() { if (os_) *os_ << "testChromatogramListWithPositions()\n "; ChromatogramListSimple a; ChromatogramPtr chromatogram1(new Chromatogram); chromatogram1->id = "goober"; chromatogram1->index = 0; chromatogram1->defaultArrayLength = 666; ChromatogramPtr chromatogram2(new Chromatogram); chromatogram2->id = "raisinet"; chromatogram2->index = 1; chromatogram2->defaultArrayLength = 667; a.chromatograms.push_back(chromatogram1); a.chromatograms.push_back(chromatogram2); ostringstream oss; XMLWriter writer(oss); vector positions; IO::write(writer, a, BinaryDataEncoder::Config(), &positions); if (os_) { copy(positions.begin(), positions.end(), ostream_iterator(*os_, " ")); *os_ << endl << oss.str() << endl; *os_ << "\n\n"; } unit_assert(positions.size() == 2); unit_assert(positions[0] == 31); unit_assert(positions[1] == 113); } void testRun() { if (os_) *os_ << "testRun():\n"; Run a; a.id = "goober"; a.defaultInstrumentConfigurationPtr = InstrumentConfigurationPtr(new InstrumentConfiguration("instrumentConfiguration")); a.samplePtr = SamplePtr(new Sample("sample")); a.startTimeStamp = "20 April 2004 4:20pm"; a.defaultSourceFilePtr = SourceFilePtr(new SourceFile("sf1")); // spectrumList shared_ptr spectrumListSimple(new SpectrumListSimple); SpectrumPtr spectrum1(new Spectrum); spectrum1->id = "goober"; spectrum1->index = 0; spectrum1->defaultArrayLength = 666; spectrum1->userParams.push_back(UserParam("description1")); SpectrumPtr spectrum2(new Spectrum); spectrum2->id = "raisinet"; spectrum2->index = 1; spectrum2->defaultArrayLength = 667; spectrum2->userParams.push_back(UserParam("description2")); spectrumListSimple->spectra.push_back(spectrum1); spectrumListSimple->spectra.push_back(spectrum2); a.spectrumListPtr = spectrumListSimple; // chromatogramList shared_ptr chromatogramListSimple(new ChromatogramListSimple); ChromatogramPtr chromatogram1(new Chromatogram); chromatogram1->id = "goober"; chromatogram1->index = 0; chromatogram1->defaultArrayLength = 666; ChromatogramPtr chromatogram2(new Chromatogram); chromatogram2->id = "raisinet"; chromatogram2->index = 1; chromatogram2->defaultArrayLength = 667; chromatogramListSimple->chromatograms.push_back(chromatogram1); chromatogramListSimple->chromatograms.push_back(chromatogram2); a.chromatogramListPtr = chromatogramListSimple; // write 'a' out to a stream MSData dummy; ostringstream oss; XMLWriter writer(oss); IO::write(writer, a, dummy); if (os_) *os_ << oss.str() << endl; // read 'b' in from stream, ignoring SpectrumList (default) Run b; istringstream iss(oss.str()); IO::read(iss, b, IO::IgnoreSpectrumList); // IO::IgnoreSpectrumList // compare 'a' and 'b' Diff diff(a,b); if (diff && os_) *os_ << "diff:\n" << diff << endl; unit_assert(diff); unit_assert(diff.a_b.spectrumListPtr.get()); unit_assert(diff.a_b.spectrumListPtr->size() == 1); unit_assert(diff.a_b.spectrumListPtr->spectrum(0)->userParams.size() == 1); // read 'c' in from stream, reading SpectrumList Run c; iss.seekg(0); IO::read(iss, c, IO::ReadSpectrumList); // compare 'a' and 'c' diff(a,c); if (diff && os_) *os_ << "diff:\n" << diff << endl; unit_assert(!diff); // remove SpectrumList and ChromatogramList from a, and compare to b a.spectrumListPtr.reset(); a.chromatogramListPtr.reset(); diff(a, b); unit_assert(!diff); } void initializeTestData(MSData& msd) { msd.accession = "test accession"; msd.id = "test id"; // cvList msd.cvs.resize(1); CV& cv = msd.cvs.front(); cv.URI = "http://psidev.sourceforge.net/ms/xml/mzdata/psi-ms.2.0.2.obo"; cv.id = "MS"; cv.fullName = "Proteomics Standards Initiative Mass Spectrometry Ontology"; cv.version = "2.0.2"; // fileDescription FileContent& fc = msd.fileDescription.fileContent; fc.cvParams.push_back(MS_MSn_spectrum); fc.userParams.push_back(UserParam("number of cats", "4")); SourceFilePtr sfp(new SourceFile); sfp->id = "1"; sfp->name = "tiny1.RAW"; sfp->location = "file://F:/data/Exp01"; sfp->cvParams.push_back(MS_Thermo_RAW_format); sfp->cvParams.push_back(CVParam(MS_SHA_1,"71be39fb2700ab2f3c8b2234b91274968b6899b1")); msd.fileDescription.sourceFilePtrs.push_back(sfp); SourceFilePtr sfp_parameters(new SourceFile("sf_parameters", "parameters.par", "file:///C:/settings/")); msd.fileDescription.sourceFilePtrs.push_back(sfp_parameters); msd.fileDescription.contacts.resize(1); Contact& contact = msd.fileDescription.contacts.front(); contact.cvParams.push_back(CVParam(MS_contact_name, "William Pennington")); contact.cvParams.push_back(CVParam(MS_contact_address, "Higglesworth University, 12 Higglesworth Avenue, 12045, HI, USA")); contact.cvParams.push_back(CVParam(MS_contact_URL, "http://www.higglesworth.edu/")); contact.cvParams.push_back(CVParam(MS_contact_email, "wpennington@higglesworth.edu")); // paramGroupList ParamGroupPtr pg1(new ParamGroup); pg1->id = "CommonMS1SpectrumParams"; pg1->cvParams.push_back(MS_positive_scan); msd.paramGroupPtrs.push_back(pg1); ParamGroupPtr pg2(new ParamGroup); pg2->id = "CommonMS2SpectrumParams"; pg2->cvParams.push_back(MS_positive_scan); msd.paramGroupPtrs.push_back(pg2); // sampleList SamplePtr samplePtr(new Sample); samplePtr->id = "1"; samplePtr->name = "Sample1"; msd.samplePtrs.push_back(samplePtr); // instrumentConfigurationList InstrumentConfigurationPtr instrumentConfigurationPtr(new InstrumentConfiguration); instrumentConfigurationPtr->id = "LCQ Deca"; instrumentConfigurationPtr->cvParams.push_back(MS_LCQ_Deca); instrumentConfigurationPtr->cvParams.push_back(CVParam(MS_instrument_serial_number,"23433")); instrumentConfigurationPtr->componentList.push_back(Component(MS_nanoelectrospray, 1)); instrumentConfigurationPtr->componentList.push_back(Component(MS_quadrupole_ion_trap, 2)); instrumentConfigurationPtr->componentList.push_back(Component(MS_electron_multiplier, 3)); SoftwarePtr softwareXcalibur(new Software); softwareXcalibur->id = "Xcalibur"; softwareXcalibur->set(MS_Xcalibur); softwareXcalibur->version = "2.0.5"; instrumentConfigurationPtr->softwarePtr = softwareXcalibur; msd.instrumentConfigurationPtrs.push_back(instrumentConfigurationPtr); // softwareList SoftwarePtr softwareBioworks(new Software); softwareBioworks->id = "Bioworks"; softwareBioworks->set(MS_Bioworks); softwareBioworks->version = "3.3.1 sp1"; SoftwarePtr software_pwiz(new Software); software_pwiz->id = "pwiz"; software_pwiz->set(MS_pwiz); software_pwiz->version = "1.0"; msd.softwarePtrs.push_back(softwareBioworks); msd.softwarePtrs.push_back(software_pwiz); msd.softwarePtrs.push_back(softwareXcalibur); // dataProcessingList DataProcessingPtr dpXcalibur(new DataProcessing); dpXcalibur->id = "Xcalibur Processing"; ProcessingMethod procXcal; procXcal.order = 1; procXcal.softwarePtr = softwareXcalibur; procXcal.cvParams.push_back(CVParam(MS_deisotoping, false)); procXcal.cvParams.push_back(CVParam(MS_charge_deconvolution, false)); procXcal.cvParams.push_back(CVParam(MS_peak_picking, true)); dpXcalibur->processingMethods.push_back(procXcal); DataProcessingPtr dp_msconvert(new DataProcessing); dp_msconvert->id = "pwiz conversion"; ProcessingMethod proc_msconvert; proc_msconvert.order = 2; proc_msconvert.softwarePtr = software_pwiz; proc_msconvert.cvParams.push_back(MS_Conversion_to_mzML); dp_msconvert->processingMethods.push_back(proc_msconvert); msd.dataProcessingPtrs.push_back(dpXcalibur); msd.dataProcessingPtrs.push_back(dp_msconvert); ScanSettingsPtr as1(new ScanSettings("as1")); as1->sourceFilePtrs.push_back(sfp_parameters); Target t1; t1.set(MS_m_z, 1000); Target t2; t2.set(MS_m_z, 1200); as1->targets.push_back(t1); as1->targets.push_back(t2); msd.scanSettingsPtrs.push_back(as1); // run msd.run.id = "Exp01"; msd.run.defaultInstrumentConfigurationPtr = instrumentConfigurationPtr; msd.run.samplePtr = samplePtr; msd.run.startTimeStamp = "2007-06-27T15:23:45.00035"; msd.run.defaultSourceFilePtr = sfp; shared_ptr spectrumList(new SpectrumListSimple); msd.run.spectrumListPtr = spectrumList; spectrumList->spectra.push_back(SpectrumPtr(new Spectrum)); spectrumList->spectra.push_back(SpectrumPtr(new Spectrum)); Spectrum& s19 = *spectrumList->spectra[0]; s19.id = "S19"; s19.index = 0; s19.defaultArrayLength = 10; s19.cvParams.push_back(MS_MSn_spectrum); s19.set(MS_ms_level, 1); s19.cvParams.push_back(MS_centroid_spectrum); s19.cvParams.push_back(CVParam(MS_lowest_observed_m_z, 400.39)); s19.cvParams.push_back(CVParam(MS_highest_observed_m_z, 1795.56)); s19.cvParams.push_back(CVParam(MS_base_peak_m_z, 445.347)); s19.cvParams.push_back(CVParam(MS_base_peak_intensity, 120053)); s19.cvParams.push_back(CVParam(MS_total_ion_current, 1.66755e+007)); s19.scanList.scans.push_back(Scan()); Scan& s19scan = s19.scanList.scans.back(); s19scan.instrumentConfigurationPtr = instrumentConfigurationPtr; s19scan.paramGroupPtrs.push_back(pg1); s19scan.cvParams.push_back(CVParam(MS_scan_start_time, 5.890500, UO_minute)); s19scan.cvParams.push_back(CVParam(MS_filter_string, "+ c NSI Full ms [ 400.00-1800.00]")); s19scan.scanWindows.resize(1); ScanWindow& window = s19scan.scanWindows.front(); window.cvParams.push_back(CVParam(MS_scan_window_lower_limit, 400.000000)); window.cvParams.push_back(CVParam(MS_scan_window_upper_limit, 1800.000000)); BinaryDataArrayPtr s19_mz(new BinaryDataArray); s19_mz->dataProcessingPtr = dpXcalibur; s19_mz->cvParams.push_back(MS_m_z_array); s19_mz->data.resize(10); for (int i=0; i<10; i++) s19_mz->data[i] = i; BinaryDataArrayPtr s19_intensity(new BinaryDataArray); s19_intensity->dataProcessingPtr = dpXcalibur; s19_intensity->cvParams.push_back(MS_intensity_array); s19_intensity->data.resize(10); for (int i=0; i<10; i++) s19_intensity->data[i] = 10-i; s19.binaryDataArrayPtrs.push_back(s19_mz); s19.binaryDataArrayPtrs.push_back(s19_intensity); Spectrum& s20 = *spectrumList->spectra[1]; s20.id = "S20"; s20.index = 1; s20.defaultArrayLength = 10; s20.cvParams.push_back(MS_MSn_spectrum); s20.set(MS_ms_level, 2); s20.cvParams.push_back(MS_centroid_spectrum); s20.cvParams.push_back(CVParam(MS_lowest_observed_m_z, 320.39)); s20.cvParams.push_back(CVParam(MS_highest_observed_m_z, 1003.56)); s20.cvParams.push_back(CVParam(MS_base_peak_m_z, 456.347)); s20.cvParams.push_back(CVParam(MS_base_peak_intensity, 23433)); s20.cvParams.push_back(CVParam(MS_total_ion_current, 1.66755e+007)); s20.precursors.resize(1); Precursor& precursor = s20.precursors.front(); precursor.spectrumID= s19.id; precursor.selectedIons.resize(1); precursor.selectedIons[0].cvParams.push_back(CVParam(MS_selected_ion_m_z, 445.34)); precursor.selectedIons[0].cvParams.push_back(CVParam(MS_charge_state, 2)); precursor.activation.cvParams.push_back(MS_collision_induced_dissociation); precursor.activation.cvParams.push_back(CVParam(MS_collision_energy, 35.00, UO_electronvolt)); s20.scanList.scans.push_back(Scan()); Scan& s20scan = s20.scanList.scans.back(); s20scan.instrumentConfigurationPtr = instrumentConfigurationPtr; s20scan.paramGroupPtrs.push_back(pg2); s20scan.cvParams.push_back(CVParam(MS_scan_start_time, 5.990500, UO_minute)); s20scan.cvParams.push_back(CVParam(MS_filter_string, "+ c d Full ms2 445.35@cid35.00 [ 110.00-905.00]")); s20scan.scanWindows.resize(1); ScanWindow& window2 = s20scan.scanWindows.front(); window2.cvParams.push_back(CVParam(MS_scan_window_lower_limit, 110.000000)); window2.cvParams.push_back(CVParam(MS_scan_window_upper_limit, 905.000000)); BinaryDataArrayPtr s20_mz(new BinaryDataArray); s20_mz->dataProcessingPtr = dpXcalibur; s20_mz->cvParams.push_back(MS_m_z_array); s20_mz->data.resize(10); for (int i=0; i<10; i++) s20_mz->data[i] = i; BinaryDataArrayPtr s20_intensity(new BinaryDataArray); s20_intensity->dataProcessingPtr = dpXcalibur; s20_intensity->cvParams.push_back(MS_intensity_array); s20_intensity->data.resize(10); for (int i=0; i<10; i++) s20_intensity->data[i] = 10-i; s20.binaryDataArrayPtrs.push_back(s20_mz); s20.binaryDataArrayPtrs.push_back(s20_intensity); // chromatograms shared_ptr chromatogramList(new ChromatogramListSimple); msd.run.chromatogramListPtr = chromatogramList; chromatogramList->chromatograms.push_back(ChromatogramPtr(new Chromatogram)); Chromatogram& tic = *chromatogramList->chromatograms[0]; tic.id = "tic"; tic.index = 0; tic.defaultArrayLength = 10; tic.cvParams.push_back(MS_total_ion_current_chromatogram); BinaryDataArrayPtr tic_time(new BinaryDataArray); tic_time->dataProcessingPtr = dp_msconvert; tic_time->cvParams.push_back(MS_time_array); tic_time->data.resize(10); for (int i=0; i<10; i++) tic_time->data[i] = i; BinaryDataArrayPtr tic_intensity(new BinaryDataArray); tic_intensity->dataProcessingPtr = dp_msconvert; tic_intensity->cvParams.push_back(MS_intensity_array); tic_intensity->data.resize(10); for (int i=0; i<10; i++) tic_intensity->data[i] = 10-i; tic.binaryDataArrayPtrs.push_back(tic_time); tic.binaryDataArrayPtrs.push_back(tic_intensity); } void testMSData() { if (os_) *os_ << "testMSData():\n"; MSData a; initializeTestData(a); // write 'a' out to a stream ostringstream oss; XMLWriter writer(oss); IO::write(writer, a); if (os_) *os_ << oss.str() << endl; // read 'b' in from stream, ignoring SpectrumList (default) MSData b; istringstream iss(oss.str()); IO::read(iss, b); // IO::IgnoreSpectrumList // compare 'a' and 'b' Diff diff(a,b); if (diff && os_) *os_ << "diff:\n" << diff << endl; unit_assert(diff); unit_assert(diff.a_b.run.spectrumListPtr.get()); unit_assert(diff.a_b.run.spectrumListPtr->size() == 1); unit_assert(diff.a_b.run.spectrumListPtr->spectrum(0)->userParams.size() == 1); // read 'c' in from stream, reading SpectrumList MSData c; iss.seekg(0); IO::read(iss, c, IO::ReadSpectrumList); // compare 'a' and 'c' diff(a,c); if (diff && os_) *os_ << "diff:\n" << diff << endl; unit_assert(!diff); // remove SpectrumList and ChromatogramList from a, and compare to b a.run.spectrumListPtr.reset(); a.run.chromatogramListPtr.reset(); diff(a, b); unit_assert(!diff); } void test() { testCV(); testUserParam(); testCVParam(); testParamGroup(); testNamedParamContainer(); testSourceFile(); testNamedParamContainer(); testFileDescription(); testSample(); testComponent(); testComponentList(); testSoftware(); testInstrumentConfiguration(); testProcessingMethod(); testDataProcessing(); testNamedParamContainer(); testScanSettings(); testNamedParamContainer(); testNamedParamContainer(); testNamedParamContainer(); testPrecursor(); testProduct(); testNamedParamContainer(); testScan(); testScanList(); testBinaryDataArray(); testBinaryDataArrayExternalMetadata(); testSpectrum(); testChromatogram(); testSpectrumList(); testSpectrumListWithPositions(); testSpectrumListWriteProgress(); testChromatogramList(); testChromatogramListWithPositions(); testRun(); testMSData(); } int main(int argc, char* argv[]) { TEST_PROLOG_EX(argc, argv, "_MSData") try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); if (os_) *os_ << "ok\n"; } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/msdata/examples.cpp0000664000175100017510000005304212664775621021254 0ustar teamcityteamcity00000000000000// // $Id: examples.cpp 5759 2014-02-19 22:26:29Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "examples.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace msdata { namespace examples { PWIZ_API_DECL void initializeTiny(MSData& msd) { msd.id = "urn:lsid:psidev.info:mzML.instanceDocuments.tiny.pwiz"; // cvList msd.cvs = defaultCVList(); // fileDescription FileContent& fc = msd.fileDescription.fileContent; fc.set(MS_MSn_spectrum); fc.set(MS_centroid_spectrum); SourceFilePtr sfp(new SourceFile); sfp->id = "tiny1.yep"; sfp->name = "tiny1.yep"; sfp->location = "file://F:/data/Exp01"; sfp->set(MS_Bruker_Agilent_YEP_format); sfp->set(MS_SHA_1,"1234567890123456789012345678901234567890"); sfp->set(MS_Bruker_Agilent_YEP_nativeID_format); msd.fileDescription.sourceFilePtrs.push_back(sfp); SourceFilePtr sfp2(new SourceFile); sfp2->id = "tiny.wiff"; sfp2->name = "tiny.wiff"; sfp2->location = "file://F:/data/Exp01"; sfp2->set(MS_ABI_WIFF_format); sfp2->set(MS_SHA_1,"2345678901234567890123456789012345678901"); sfp2->set(MS_WIFF_nativeID_format); msd.fileDescription.sourceFilePtrs.push_back(sfp2); SourceFilePtr sfp_parameters(new SourceFile("sf_parameters", "parameters.par", "file://C:/settings/")); sfp_parameters->set(MS_parameter_file); sfp_parameters->set(MS_SHA_1, "3456789012345678901234567890123456789012"); sfp_parameters->set(MS_no_nativeID_format); msd.fileDescription.sourceFilePtrs.push_back(sfp_parameters); msd.fileDescription.contacts.resize(1); Contact& contact = msd.fileDescription.contacts.front(); contact.set(MS_contact_name, "William Pennington"); contact.set(MS_contact_affiliation, "Higglesworth University"); contact.set(MS_contact_address, "12 Higglesworth Avenue, 12045, HI, USA"); contact.set(MS_contact_URL, "http://www.higglesworth.edu/"); contact.set(MS_contact_email, "wpennington@higglesworth.edu"); // paramGroupList ParamGroupPtr pg1(new ParamGroup); pg1->id = "CommonMS1SpectrumParams"; pg1->set(MS_MS1_spectrum); pg1->set(MS_positive_scan); msd.paramGroupPtrs.push_back(pg1); ParamGroupPtr pg2(new ParamGroup); pg2->id = "CommonMS2SpectrumParams"; pg2->set(MS_MSn_spectrum); pg2->set(MS_negative_scan); msd.paramGroupPtrs.push_back(pg2); // sampleList SamplePtr samplePtr(new Sample); samplePtr->id = "20090101 - Sample 1"; samplePtr->name = "Sample 1"; msd.samplePtrs.push_back(samplePtr); // instrumentConfigurationList InstrumentConfigurationPtr instrumentConfigurationPtr(new InstrumentConfiguration("LCQ Deca")); instrumentConfigurationPtr->set(MS_LCQ_Deca); instrumentConfigurationPtr->set(MS_instrument_serial_number,"23433"); instrumentConfigurationPtr->componentList.push_back(Component(MS_nanoelectrospray, 1)); instrumentConfigurationPtr->componentList.push_back(Component(MS_quadrupole_ion_trap, 2)); instrumentConfigurationPtr->componentList.push_back(Component(MS_electron_multiplier, 3)); SoftwarePtr softwareCompassXtract(new Software); softwareCompassXtract->id = "CompassXtract"; softwareCompassXtract->set(MS_CompassXtract); softwareCompassXtract->version = "2.0.5"; instrumentConfigurationPtr->softwarePtr = softwareCompassXtract; msd.instrumentConfigurationPtrs.push_back(instrumentConfigurationPtr); // softwareList SoftwarePtr softwareBioworks(new Software); softwareBioworks->id = "Bioworks"; softwareBioworks->set(MS_Bioworks); softwareBioworks->version = "3.3.1 sp1"; SoftwarePtr softwarepwiz(new Software); softwarepwiz->id = "pwiz"; softwarepwiz->set(MS_pwiz); softwarepwiz->version = "1.0"; msd.softwarePtrs.push_back(softwareBioworks); msd.softwarePtrs.push_back(softwarepwiz); msd.softwarePtrs.push_back(softwareCompassXtract); // dataProcessingList DataProcessingPtr dpCompassXtract(new DataProcessing); dpCompassXtract->id = "CompassXtract processing"; ProcessingMethod procCXT; procCXT.order = 1; procCXT.softwarePtr = softwareCompassXtract; procCXT.set(MS_deisotoping); procCXT.set(MS_charge_deconvolution); procCXT.set(MS_peak_picking); dpCompassXtract->processingMethods.push_back(procCXT); DataProcessingPtr dppwiz(new DataProcessing("pwiz_processing")); ProcessingMethod procpwiz; procpwiz.order = 2; procpwiz.softwarePtr = softwarepwiz; procpwiz.set(MS_Conversion_to_mzML); dppwiz->processingMethods.push_back(procpwiz); msd.dataProcessingPtrs.push_back(dpCompassXtract); //msd.dataProcessingPtrs.push_back(dppwiz); ScanSettingsPtr as1(new ScanSettings("tiny scan settings")); as1->sourceFilePtrs.push_back(sfp_parameters); Target t1; t1.set(MS_selected_ion_m_z, 1000, MS_m_z); Target t2; t2.set(MS_selected_ion_m_z, 1200, MS_m_z); as1->targets.push_back(t1); as1->targets.push_back(t2); msd.scanSettingsPtrs.push_back(as1); // run msd.run.id = "Experiment 1"; msd.run.defaultInstrumentConfigurationPtr = instrumentConfigurationPtr; msd.run.samplePtr = samplePtr; msd.run.startTimeStamp = "2007-06-27T15:23:45.00035"; msd.run.defaultSourceFilePtr = sfp; shared_ptr spectrumList(new SpectrumListSimple); msd.run.spectrumListPtr = spectrumList; spectrumList->dp = dppwiz; spectrumList->spectra.push_back(SpectrumPtr(new Spectrum)); spectrumList->spectra.push_back(SpectrumPtr(new Spectrum)); spectrumList->spectra.push_back(SpectrumPtr(new Spectrum)); spectrumList->spectra.push_back(SpectrumPtr(new Spectrum)); spectrumList->spectra.push_back(SpectrumPtr(new Spectrum)); Spectrum& s19 = *spectrumList->spectra[0]; s19.id = "scan=19"; s19.index = 0; s19.set(MS_ms_level, 1); s19.set(MS_centroid_spectrum); s19.set(MS_lowest_observed_m_z, 400.39, MS_m_z); s19.set(MS_highest_observed_m_z, 1795.56, MS_m_z); s19.set(MS_base_peak_m_z, 445.347, MS_m_z); s19.set(MS_base_peak_intensity, 120053, MS_number_of_detector_counts); s19.set(MS_total_ion_current, 1.66755e+007); s19.paramGroupPtrs.push_back(pg1); s19.scanList.scans.push_back(Scan()); s19.scanList.set(MS_no_combination); Scan& s19scan = s19.scanList.scans.back(); s19scan.instrumentConfigurationPtr = instrumentConfigurationPtr; s19scan.set(MS_scan_start_time, 5.890500, UO_minute); s19scan.set(MS_filter_string, "+ c NSI Full ms [ 400.00-1800.00]"); s19scan.set(MS_preset_scan_configuration, 3); s19scan.scanWindows.resize(1); ScanWindow& window = s19.scanList.scans.back().scanWindows.front(); window.set(MS_scan_window_lower_limit, 400.000000, MS_m_z); window.set(MS_scan_window_upper_limit, 1800.000000, MS_m_z); BinaryDataArrayPtr s19_mz(new BinaryDataArray); s19_mz->dataProcessingPtr = dpCompassXtract; s19_mz->set(MS_m_z_array, "", MS_m_z); s19_mz->data.resize(15); for (int i=0; i<15; i++) s19_mz->data[i] = i; BinaryDataArrayPtr s19_intensity(new BinaryDataArray); s19_intensity->dataProcessingPtr = dpCompassXtract; s19_intensity->set(MS_intensity_array, "", MS_number_of_detector_counts); s19_intensity->data.resize(15); for (int i=0; i<15; i++) s19_intensity->data[i] = 15-i; s19.binaryDataArrayPtrs.push_back(s19_mz); s19.binaryDataArrayPtrs.push_back(s19_intensity); s19.defaultArrayLength = s19_mz->data.size(); Spectrum& s20 = *spectrumList->spectra[1]; s20.id = "scan=20"; s20.index = 1; s20.paramGroupPtrs.push_back(pg2); s20.set(MS_ms_level, 2); s20.set(MS_profile_spectrum); s20.set(MS_lowest_observed_m_z, 320.39, MS_m_z); s20.set(MS_highest_observed_m_z, 1003.56, MS_m_z); s20.set(MS_base_peak_m_z, 456.347, MS_m_z); s20.set(MS_base_peak_intensity, 23433, MS_number_of_detector_counts); s20.set(MS_total_ion_current, 1.66755e+007); s20.precursors.resize(1); Precursor& precursor = s20.precursors.front(); precursor.spectrumID= s19.id; precursor.isolationWindow.set(MS_isolation_window_target_m_z, 445.3, MS_m_z); precursor.isolationWindow.set(MS_isolation_window_lower_offset, .5, MS_m_z); precursor.isolationWindow.set(MS_isolation_window_upper_offset, .5, MS_m_z); precursor.selectedIons.resize(1); precursor.selectedIons[0].set(MS_selected_ion_m_z, 445.34, MS_m_z); precursor.selectedIons[0].set(MS_peak_intensity, 120053, MS_number_of_detector_counts); precursor.selectedIons[0].set(MS_charge_state, 2); precursor.activation.set(MS_collision_induced_dissociation); precursor.activation.set(MS_collision_energy, 35.00, UO_electronvolt); s20.scanList.scans.push_back(Scan()); s20.scanList.set(MS_no_combination); Scan& s20scan = s20.scanList.scans.back(); s20scan.instrumentConfigurationPtr = instrumentConfigurationPtr; s20scan.set(MS_scan_start_time, 5.990500, UO_minute); s20scan.set(MS_filter_string, "+ c d Full ms2 445.35@cid35.00 [ 110.00-905.00]"); s20scan.set(MS_preset_scan_configuration, 4); s20scan.scanWindows.resize(1); ScanWindow& window2 = s20scan.scanWindows.front(); window2.set(MS_scan_window_lower_limit, 110.000000, MS_m_z); window2.set(MS_scan_window_upper_limit, 905.000000, MS_m_z); BinaryDataArrayPtr s20_mz(new BinaryDataArray); s20_mz->dataProcessingPtr = dpCompassXtract; s20_mz->set(MS_m_z_array, "", MS_m_z); s20_mz->data.resize(10); for (int i=0; i<10; i++) s20_mz->data[i] = i*2; BinaryDataArrayPtr s20_intensity(new BinaryDataArray); s20_intensity->dataProcessingPtr = dpCompassXtract; s20_intensity->set(MS_intensity_array, "", MS_number_of_detector_counts); s20_intensity->data.resize(10); for (int i=0; i<10; i++) s20_intensity->data[i] = (10-i)*2; s20.binaryDataArrayPtrs.push_back(s20_mz); s20.binaryDataArrayPtrs.push_back(s20_intensity); s20.defaultArrayLength = s20_mz->data.size(); // spectrum with no data Spectrum& s21 = *spectrumList->spectra[2]; s21.id = "scan=21"; s21.index = 2; s21.paramGroupPtrs.push_back(pg1); s21.set(MS_ms_level, 1); s21.set(MS_centroid_spectrum); s21.userParams.push_back(UserParam("example", "spectrum with no data")); s21.setMZIntensityArrays(vector(), vector(), MS_number_of_detector_counts); s21.scanList.scans.push_back(Scan()); s21.scanList.scans.back().instrumentConfigurationPtr = instrumentConfigurationPtr; s21.scanList.set(MS_no_combination); // Cover ETD, ETD+SA, and ECD precursor activation mode usage Spectrum& s22 = *spectrumList->spectra[3]; s22.id = "scan=22"; s22.index = 3; s22.paramGroupPtrs.push_back(pg2); s22.set(MS_ms_level, 2); s22.set(MS_profile_spectrum); s22.set(MS_lowest_observed_m_z, 320.39, MS_m_z); s22.set(MS_highest_observed_m_z, 1003.56, MS_m_z); s22.set(MS_base_peak_m_z, 456.347, MS_m_z); s22.set(MS_base_peak_intensity, 23433, MS_number_of_detector_counts); s22.set(MS_total_ion_current, 1.66755e+007); s22.precursors.resize(1); Precursor& precursor22 = s22.precursors.front(); precursor22.spectrumID= s19.id; precursor22.isolationWindow.set(MS_isolation_window_target_m_z, 545.3, MS_m_z); precursor22.isolationWindow.set(MS_isolation_window_lower_offset, .5, MS_m_z); precursor22.isolationWindow.set(MS_isolation_window_upper_offset, .5, MS_m_z); precursor22.selectedIons.resize(1); precursor22.selectedIons[0].set(MS_selected_ion_m_z, 545.34, MS_m_z); precursor22.selectedIons[0].set(MS_peak_intensity, 120053, MS_number_of_detector_counts); precursor22.selectedIons[0].set(MS_charge_state, 2); precursor22.activation.set(MS_ETD); precursor22.activation.set(MS_CID); precursor22.activation.set(MS_collision_energy, 60.00, UO_electronvolt); s22.scanList.scans.push_back(Scan()); s22.scanList.set(MS_no_combination); Scan& s22scan = s22.scanList.scans.back(); s22scan.instrumentConfigurationPtr = instrumentConfigurationPtr; s22scan.set(MS_scan_start_time, 6.5, UO_minute); s22scan.set(MS_filter_string, "+ c d Full ms2 445.35@etd60.00 [ 110.00-905.00]"); s22scan.set(MS_preset_scan_configuration, 4); s22scan.scanWindows.resize(1); window2 = s22scan.scanWindows.front(); window2.set(MS_scan_window_lower_limit, 110.000000, MS_m_z); window2.set(MS_scan_window_upper_limit, 905.000000, MS_m_z); BinaryDataArrayPtr s22_mz(new BinaryDataArray); s22_mz->dataProcessingPtr = dpCompassXtract; s22_mz->set(MS_m_z_array, "", MS_m_z); s22_mz->data.resize(10); for (int i=0; i<10; i++) s22_mz->data[i] = i*2; BinaryDataArrayPtr s22_intensity(new BinaryDataArray); s22_intensity->dataProcessingPtr = dpCompassXtract; s22_intensity->set(MS_intensity_array, "", MS_number_of_detector_counts); s22_intensity->data.resize(10); for (int i=0; i<10; i++) s22_intensity->data[i] = (10-i)*2; s22.binaryDataArrayPtrs.push_back(s22_mz); s22.binaryDataArrayPtrs.push_back(s22_intensity); s22.defaultArrayLength = s22_mz->data.size(); // spectrum with MALDI spot information Spectrum& s23 = *spectrumList->spectra[4]; s23.id = "sample=1 period=1 cycle=23 experiment=1"; s23.index = 4; s23.spotID = "A1,42x42,4242x4242"; s23.sourceFilePtr = sfp2; s23.set(MS_ms_level, 1); s23.set(MS_centroid_spectrum); s23.set(MS_lowest_observed_m_z, 142.39, MS_m_z); s23.set(MS_highest_observed_m_z, 942.56, MS_m_z); s23.set(MS_base_peak_m_z, 422.42, MS_m_z); s23.set(MS_base_peak_intensity, 42, MS_number_of_detector_counts); s23.set(MS_total_ion_current, 4200); s23.userParams.push_back(UserParam("alternate source file", "to test a different nativeID format")); s23.paramGroupPtrs.push_back(pg1); s23.scanList.scans.push_back(Scan()); s23.scanList.set(MS_no_combination); Scan& s23scan = s23.scanList.scans.back(); s23scan.instrumentConfigurationPtr = instrumentConfigurationPtr; s23scan.set(MS_scan_start_time, 42.0500, UO_second); s23scan.set(MS_filter_string, "+ c MALDI Full ms [100.00-1000.00]"); s23scan.scanWindows.resize(1); ScanWindow& window3 = s23scan.scanWindows.front(); window3.set(MS_scan_window_lower_limit, 100.000000, MS_m_z); window3.set(MS_scan_window_upper_limit, 1000.000000, MS_m_z); s23.binaryDataArrayPtrs.push_back(s19_mz); s23.binaryDataArrayPtrs.push_back(s19_intensity); s23.defaultArrayLength = s19_mz->data.size(); // chromatograms shared_ptr chromatogramList(new ChromatogramListSimple); msd.run.chromatogramListPtr = chromatogramList; chromatogramList->dp = dppwiz; chromatogramList->chromatograms.push_back(ChromatogramPtr(new Chromatogram)); chromatogramList->chromatograms.push_back(ChromatogramPtr(new Chromatogram)); Chromatogram& tic = *chromatogramList->chromatograms[0]; tic.id = "tic"; tic.index = 0; tic.defaultArrayLength = 15; tic.dataProcessingPtr = dpCompassXtract; tic.set(MS_total_ion_current_chromatogram); BinaryDataArrayPtr tic_time(new BinaryDataArray); tic_time->dataProcessingPtr = dppwiz; tic_time->set(MS_time_array, "", UO_second); tic_time->data.resize(15); for (int i=0; i<15; i++) tic_time->data[i] = i; BinaryDataArrayPtr tic_intensity(new BinaryDataArray); tic_intensity->dataProcessingPtr = dppwiz; tic_intensity->set(MS_intensity_array, "", MS_number_of_detector_counts); tic_intensity->data.resize(15); for (int i=0; i<15; i++) tic_intensity->data[i] = 15-i; tic.binaryDataArrayPtrs.push_back(tic_time); tic.binaryDataArrayPtrs.push_back(tic_intensity); Chromatogram& sic = *chromatogramList->chromatograms[1]; sic.id = "sic"; sic.index = 1; sic.defaultArrayLength = 10; sic.dataProcessingPtr = dppwiz; sic.set(MS_selected_ion_current_chromatogram); sic.precursor.isolationWindow.set(MS_isolation_window_target_m_z, 456.7, MS_m_z); sic.precursor.activation.set(MS_CID); sic.product.isolationWindow.set(MS_isolation_window_target_m_z, 678.9, MS_m_z); BinaryDataArrayPtr sic_time(new BinaryDataArray); sic_time->dataProcessingPtr = dppwiz; sic_time->set(MS_time_array, "", UO_second); sic_time->data.resize(10); for (int i=0; i<10; i++) sic_time->data[i] = i; BinaryDataArrayPtr sic_intensity(new BinaryDataArray); sic_intensity->dataProcessingPtr = dppwiz; sic_intensity->set(MS_intensity_array, "", MS_number_of_detector_counts); sic_intensity->data.resize(10); for (int i=0; i<10; i++) sic_intensity->data[i] = 10-i; sic.binaryDataArrayPtrs.push_back(sic_time); sic.binaryDataArrayPtrs.push_back(sic_intensity); } // initializeTiny() PWIZ_API_DECL void addMIAPEExampleMetadata(MSData& msd) { msd.id = "urn:lsid:psidev.info:mzML.instanceDocuments.small_miape.pwiz"; msd.cvs = defaultCVList(); // TODO: move this to Reader_Thermo FileContent& fc = msd.fileDescription.fileContent; fc.userParams.push_back(UserParam("ProteoWizard", "Thermo RAW data converted to mzML, with additional MIAPE parameters added for illustration")); // fileDescription SourceFilePtr sfp_parameters(new SourceFile("sf_parameters", "parameters.par", "file:///C:/example/")); sfp_parameters->set(MS_parameter_file); sfp_parameters->set(MS_SHA_1, "unknown"); sfp_parameters->set(MS_no_nativeID_format); msd.fileDescription.sourceFilePtrs.push_back(sfp_parameters); Contact contact; contact.set(MS_contact_name, "William Pennington"); contact.set(MS_contact_affiliation, "Higglesworth University"); contact.set(MS_contact_address, "12 Higglesworth Avenue, 12045, HI, USA"); contact.set(MS_contact_URL, "http://www.higglesworth.edu/"); contact.set(MS_contact_email, "wpennington@higglesworth.edu"); msd.fileDescription.contacts.push_back(contact); // paramGroupList ParamGroupPtr pgInstrumentCustomization(new ParamGroup); pgInstrumentCustomization->id = "InstrumentCustomization"; pgInstrumentCustomization->set(MS_customization ,"none"); msd.paramGroupPtrs.push_back(pgInstrumentCustomization); ParamGroupPtr pgActivation(new ParamGroup); pgActivation->id = "CommonActivationParams"; pgActivation->set(MS_collision_induced_dissociation); pgActivation->set(MS_collision_energy, 35.00, UO_electronvolt); pgActivation->set(MS_collision_gas, "nitrogen"); msd.paramGroupPtrs.push_back(pgActivation); // sampleList SamplePtr sample1(new Sample); sample1->id = "sample1"; sample1->name = "Sample 1"; msd.samplePtrs.push_back(sample1); SamplePtr sample2(new Sample); sample2->id = "sample2"; sample2->name = "Sample 2"; msd.samplePtrs.push_back(sample2); // instrumentConfigurationList for (vector::const_iterator it=msd.instrumentConfigurationPtrs.begin(), end=msd.instrumentConfigurationPtrs.end(); it!=end; ++it) { for (size_t i=0; i < (*it)->componentList.size(); ++i) { Component& c = (*it)->componentList[i]; if (c.type == ComponentType_Source) c.set(MS_source_potential, "4.20", UO_volt); } } // dataProcesingList ProcessingMethod procMIAPE; procMIAPE.order = 1; procMIAPE.softwarePtr = msd.softwarePtrs.back(); procMIAPE.set(MS_deisotoping); procMIAPE.set(MS_charge_deconvolution); procMIAPE.set(MS_peak_picking); procMIAPE.set(MS_smoothing); procMIAPE.set(MS_baseline_reduction); procMIAPE.userParams.push_back(UserParam("signal-to-noise estimation", "none")); procMIAPE.userParams.push_back(UserParam("centroiding algorithm", "none")); procMIAPE.userParams.push_back(UserParam("charge states calculated", "none")); DataProcessingPtr dpMIAPE(new DataProcessing); msd.dataProcessingPtrs.push_back(dpMIAPE); dpMIAPE->id = "MIAPE example"; dpMIAPE->processingMethods.push_back(procMIAPE); // acquisition settings ScanSettingsPtr as1(new ScanSettings("acquisition settings MIAPE example")); as1->sourceFilePtrs.push_back(sfp_parameters); Target t1; t1.userParams.push_back(UserParam("precursorMz", "123.456")); t1.userParams.push_back(UserParam("fragmentMz", "456.789")); t1.userParams.push_back(UserParam("dwell time", "1", "seconds")); t1.userParams.push_back(UserParam("active time", "0.5", "seconds")); Target t2; t2.userParams.push_back(UserParam("precursorMz", "231.673")); t2.userParams.push_back(UserParam("fragmentMz", "566.328")); t2.userParams.push_back(UserParam("dwell time", "1", "seconds")); t2.userParams.push_back(UserParam("active time", "0.5", "seconds")); as1->targets.push_back(t1); as1->targets.push_back(t2); msd.scanSettingsPtrs.push_back(as1); // run msd.run.samplePtr = sample1; } // addMIAPEExampleMetadata() } // namespace examples } // namespace msdata } // namespace pwiz pwiz/pwiz/data/msdata/IO.hpp0000664000175100017510000002245112664775621017752 0ustar teamcityteamcity00000000000000// // $Id: IO.hpp 3013 2011-09-27 06:57:13Z pcbrefugee $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _IO_HPP_ #define _IO_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "MSData.hpp" #include "BinaryDataEncoder.hpp" #include "pwiz/utility/minimxml/XMLWriter.hpp" #include "pwiz/utility/misc/IterationListener.hpp" #include "boost/iostreams/positioning.hpp" namespace pwiz { namespace msdata { /// Identifying information for a spectrum /// subclassed to add private information for faster file IO in mzML and mzXML struct PWIZ_API_DECL SpectrumIdentityFromXML : SpectrumIdentity { /// for efficient read of peak lists after previous read of /// scan header in mzML and mzXML - avoids reparsing the header mutable boost::iostreams::stream_offset sourceFilePositionForBinarySpectrumData; SpectrumIdentityFromXML() : SpectrumIdentity(), sourceFilePositionForBinarySpectrumData((boost::iostreams::stream_offset)-1) {} }; /// Identifying information for a spectrum as read from mzML or mzXML /// subclassed to add private information for faster file IO in mzXML struct PWIZ_API_DECL SpectrumIdentityFromMzXML : SpectrumIdentityFromXML { /// for efficient read of peak lists after previous read of /// scan header in mzXML - avoids reparsing the header mutable unsigned int peaksCount; SpectrumIdentityFromMzXML() : SpectrumIdentityFromXML(), peaksCount(0) {} }; namespace IO { PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const CV& cv); PWIZ_API_DECL void read(std::istream& is, CV& cv); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const UserParam& userParam); PWIZ_API_DECL void read(std::istream& is, UserParam& userParam); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const CVParam& cv); PWIZ_API_DECL void read(std::istream& is, CVParam& cv); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const ParamGroup& paramGroup); PWIZ_API_DECL void read(std::istream& is, ParamGroup& paramGroup); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const FileContent& fc); PWIZ_API_DECL void read(std::istream& is, FileContent& fc); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const SourceFile& sf); PWIZ_API_DECL void read(std::istream& is, SourceFile& sf); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Contact& c); PWIZ_API_DECL void read(std::istream& is, Contact& c); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const FileDescription& fd); PWIZ_API_DECL void read(std::istream& is, FileDescription& fd); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Sample& sf); PWIZ_API_DECL void read(std::istream& is, Sample& sf); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Component& component); PWIZ_API_DECL void read(std::istream& is, Component& component); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const ComponentList& componentList); PWIZ_API_DECL void read(std::istream& is, ComponentList& componentList); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Software& software); PWIZ_API_DECL void read(std::istream& is, Software& software); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const InstrumentConfiguration& instrumentConfiguration); PWIZ_API_DECL void read(std::istream& is, InstrumentConfiguration& instrumentConfiguration); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const ProcessingMethod& processingMethod); PWIZ_API_DECL void read(std::istream& is, ProcessingMethod& processingMethod); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const DataProcessing& dataProcessing); PWIZ_API_DECL void read(std::istream& is, DataProcessing& dataProcessing); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Target& t); PWIZ_API_DECL void read(std::istream& is, Target& t); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const ScanSettings& scanSettings); PWIZ_API_DECL void read(std::istream& is, ScanSettings& scanSettings); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const IsolationWindow& isolationWindow); PWIZ_API_DECL void read(std::istream& is, IsolationWindow& isolationWindow); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const SelectedIon& selectedIon); PWIZ_API_DECL void read(std::istream& is, SelectedIon& selectedIon); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Activation& activation); PWIZ_API_DECL void read(std::istream& is, Activation& activation); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Precursor& precursor); PWIZ_API_DECL void read(std::istream& is, Precursor& precursor, const std::map* legacyIdRefToNativeId = 0); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Product& product); PWIZ_API_DECL void read(std::istream& is, Product& product); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const ScanWindow& selectionWindow); PWIZ_API_DECL void read(std::istream& is, ScanWindow& selectionWindow); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Scan& scan, const MSData& msd); PWIZ_API_DECL void read(std::istream& is, Scan& scan); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const ScanList& scanList, const MSData& msd); PWIZ_API_DECL void read(std::istream& is, ScanList& scanList); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const BinaryDataArray& binaryDataArray, const BinaryDataEncoder::Config& config = BinaryDataEncoder::Config()); PWIZ_API_DECL void read(std::istream& is, BinaryDataArray& binaryDataArray, const MSData* msd = 0); // // enum for preference in binary data read - ignore, read, read only binary if possible // enum PWIZ_API_DECL BinaryDataFlag {IgnoreBinaryData, ReadBinaryData, ReadBinaryDataOnly }; PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Spectrum& spectrum, const MSData& msd, const BinaryDataEncoder::Config& config = BinaryDataEncoder::Config()); PWIZ_API_DECL void read(std::istream& is, Spectrum& spectrum, BinaryDataFlag binaryDataFlag = IgnoreBinaryData, int version = 0, const std::map* legacyIdRefToNativeId = 0, const MSData* msd = 0, const SpectrumIdentityFromXML *id = 0); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Chromatogram& chromatogram, const BinaryDataEncoder::Config& config = BinaryDataEncoder::Config()); PWIZ_API_DECL void read(std::istream& is, Chromatogram& chromatogram, BinaryDataFlag binaryDataFlag = IgnoreBinaryData); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const SpectrumList& spectrumList, const MSData& msd, const BinaryDataEncoder::Config& config = BinaryDataEncoder::Config(), std::vector* spectrumPositions = 0, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry = 0); PWIZ_API_DECL void read(std::istream& is, SpectrumListSimple& spectrumListSimple); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const ChromatogramList& chromatogramList, const BinaryDataEncoder::Config& config = BinaryDataEncoder::Config(), std::vector* chromatogramPositions = 0, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry = 0); PWIZ_API_DECL void read(std::istream& is, ChromatogramListSimple& chromatogramListSimple); enum PWIZ_API_DECL SpectrumListFlag {IgnoreSpectrumList, ReadSpectrumList}; PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const Run& run, const MSData& msd, const BinaryDataEncoder::Config& config = BinaryDataEncoder::Config(), std::vector* spectrumPositions = 0, std::vector* chromatogramPositions = 0, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry = 0); PWIZ_API_DECL void read(std::istream& is, Run& run, SpectrumListFlag spectrumListFlag = IgnoreSpectrumList); PWIZ_API_DECL void write(minimxml::XMLWriter& writer, const MSData& msd, const BinaryDataEncoder::Config& config = BinaryDataEncoder::Config(), std::vector* spectrumPositions = 0, std::vector* chromatogramPositions = 0, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry = 0); PWIZ_API_DECL void read(std::istream& is, MSData& msd, SpectrumListFlag spectrumListFlag = IgnoreSpectrumList); } // namespace IO } // namespace msdata } // namespace pwiz #endif // _IO_HPP_ pwiz/pwiz/data/msdata/SpectrumList_BTDX.hpp0000664000175100017510000000273312664775621022723 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_BTDX.hpp 1188 2009-08-14 17:19:55Z chambm $ // // // Original author: Matt Chambers // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SPECTRUMLIST_BTDX_HPP_ #define _SPECTRUMLIST_BTDX_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "SpectrumListBase.hpp" #include #include namespace pwiz { namespace msdata { /// SpectrumList backed by a Bruker BioTools DataExchange XML file class PWIZ_API_DECL SpectrumList_BTDX : public SpectrumListBase { public: static SpectrumListPtr create(boost::shared_ptr is, const MSData& msd); }; } // namespace msdata } // namespace pwiz #endif // _SPECTRUMLIST_BTDX_HPP_ pwiz/pwiz/data/msdata/Index_mzML.hpp0000664000175100017510000000351412664775621021450 0ustar teamcityteamcity00000000000000// // $Id: Index_mzML.hpp 3011 2011-09-27 05:17:39Z pcbrefugee $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2011 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _INDEX_MZML_HPP_ #define _INDEX_MZML_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "MSData.hpp" #include #include #include namespace pwiz { namespace msdata { struct SpectrumIdentityFromXML; // forward ref struct PWIZ_API_DECL Index_mzML { Index_mzML(boost::shared_ptr is, const MSData& msd); void recreate(); size_t spectrumCount() const; const SpectrumIdentityFromXML& spectrumIdentity(size_t index) const; size_t findSpectrumId(const std::string& id) const; IndexList findSpectrumBySpotID(const std::string& spotID) const; const std::map& legacyIdRefToNativeId() const; size_t chromatogramCount() const; const ChromatogramIdentity& chromatogramIdentity(size_t index) const; size_t findChromatogramId(const std::string& id) const; private: struct Impl; boost::shared_ptr impl_; }; typedef boost::shared_ptr Index_mzML_Ptr; } // namespace msdata } // namespace pwiz #endif // _INDEX_MZML_HPP_ pwiz/pwiz/data/msdata/ReaderTest.cpp0000775000175100017510000002072212664775621021502 0ustar teamcityteamcity00000000000000// // $Id: ReaderTest.cpp 5759 2014-02-19 22:26:29Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "Reader.hpp" #include "examples.hpp" #include "MSDataFile.hpp" #include "pwiz/data/vendor_readers/ExtendedReaderList.hpp" #include using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::msdata; ostream* os_ = 0; class Reader1 : public Reader { public: struct ReaderConfig { string name; mutable bool done; ReaderConfig() : name("default"), done(false) {} }; ReaderConfig readerConfig; virtual std::string identify(const std::string& filename, const std::string& head) const { bool result = (filename == "1"); if (os_) *os_ << "Reader1::identify(): " << boolalpha << result << endl; return std::string (result?filename:std::string("")); } virtual void read(const std::string& filename, const std::string& head, MSData& result, int runIndex = 0, const Config& config = Config()) const { if (os_) *os_ << "Reader1::read()\n"; readerConfig.done = true; } virtual void read(const std::string& filename, const std::string& head, std::vector& results, const Config& config = Config()) const { results.push_back(MSDataPtr(new MSData)); read(filename, head, *results.back(), 0, config); } virtual const char *getType() const {return "Reader1";} // satisfy inheritance }; class Reader2 : public Reader { public: struct ReaderConfig { string color; mutable bool done; ReaderConfig() : color("orange"), done(false) {} }; ReaderConfig readerConfig; virtual std::string identify(const std::string& filename, const std::string& head) const { bool result = (filename == "2"); if (os_) *os_ << "Reader2::identify(): " << boolalpha << result << endl; return std::string (result?filename:std::string("")); } virtual void read(const std::string& filename, const std::string& head, MSData& result, int runIndex = 0, const Config& config = Config()) const { if (os_) *os_ << "Reader2::read()\n"; readerConfig.done = true; } virtual void read(const std::string& filename, const std::string& head, std::vector& results, const Config& config = Config()) const { results.push_back(MSDataPtr(new MSData)); read(filename, head, *results.back(), 0, config); } const char *getType() const {return "Reader2";} // satisfy inheritance }; void testGet() { if (os_) *os_ << "testGet()\n"; ReaderList readers; readers.push_back(ReaderPtr(new Reader1)); readers.push_back(ReaderPtr(new Reader2)); unit_assert(readers.size() == 2); Reader1* reader1 = readers.get(); unit_assert(reader1); if (os_) *os_ << "reader1 config: " << reader1->readerConfig.name << endl; unit_assert(reader1->readerConfig.name == "default"); reader1->readerConfig.name = "raw"; if (os_) *os_ << "reader1 config: " << reader1->readerConfig.name << endl; unit_assert(reader1->readerConfig.name == "raw"); Reader2* reader2 = readers.get(); unit_assert(reader2); if (os_) *os_ << "reader2 config: " << reader2->readerConfig.color << endl; unit_assert(reader2->readerConfig.color == "orange"); reader2->readerConfig.color = "purple"; if (os_) *os_ << "reader2 config: " << reader2->readerConfig.color << endl; unit_assert(reader2->readerConfig.color == "purple"); const ReaderList& const_readers = readers; const Reader2* constReader2 = const_readers.get(); unit_assert(constReader2); if (os_) *os_ << "constReader2 config: " << constReader2->readerConfig.color << endl; if (os_) *os_ << endl; } void testAccept() { if (os_) *os_ << "testAccept()\n"; ReaderList readers; readers.push_back(ReaderPtr(new Reader1)); readers.push_back(ReaderPtr(new Reader2)); if (os_) *os_ << "accept 1:\n"; unit_assert(readers.accept("1", "head")); if (os_) *os_ << "accept 2:\n"; unit_assert(readers.accept("2", "head")); if (os_) *os_ << "accept 3:\n"; unit_assert(!readers.accept("3", "head")); if (os_) *os_ << endl; } void testRead() { if (os_) *os_ << "testRead()\n"; ReaderList readers; readers.push_back(ReaderPtr(new Reader1)); readers.push_back(ReaderPtr(new Reader2)); MSData msd; // note: composite pattern with accept/read will cause two calls // to accept(); the alternative is to maintain state between accept() // and read(), which opens possibility for misuse. unit_assert(readers.get()->readerConfig.done == false); if (readers.accept("1", "head")) readers.read("1", "head", msd); unit_assert(readers.get()->readerConfig.done == true); readers.get()->readerConfig.done = false; unit_assert(readers.get()->readerConfig.done == false); if (readers.accept("2", "head")) readers.read("2", "head", msd); unit_assert(readers.get()->readerConfig.done == false); unit_assert(readers.get()->readerConfig.done == true); if (os_) *os_ << endl; } void testIdentifyFileFormat() { ReaderPtr readers(new ExtendedReaderList); {ofstream fs("testSpectraDataFile.mzedML"); fs << "";} unit_assert_operator_equal(MS_mzML_format, identifyFileFormat(readers, "testSpectraDataFile.mzedML")); bfs::remove("testSpectraDataFile.mzedML"); {ofstream fs("testSpectraDataFile.mzedXML"); fs << "";} unit_assert_operator_equal(MS_ISB_mzXML_format, identifyFileFormat(readers, "testSpectraDataFile.mzedXML")); bfs::remove("testSpectraDataFile.mzedXML"); { MSData msd; examples::initializeTiny(msd); MSDataFile::WriteConfig config; config.format = MSDataFile::Format_MZ5; #ifndef WITHOUT_MZ5 MSDataFile::write(msd, "testSpectraDataFile.Mz5", config); unit_assert_operator_equal(MS_mz5_format, identifyFileFormat(readers, "testSpectraDataFile.Mz5")); #endif } bfs::remove("testSpectraDataFile.Mz5"); {ofstream fs("testSpectraDataFile.mGF"); fs << "MGF";} unit_assert_operator_equal(MS_Mascot_MGF_format, identifyFileFormat(readers, "testSpectraDataFile.mGF")); bfs::remove("testSpectraDataFile.mGF"); {ofstream fs("testSpectraDataFile.Ms2"); fs << "MS2";} unit_assert_operator_equal(MS_MS2_format, identifyFileFormat(readers, "testSpectraDataFile.Ms2")); bfs::remove("testSpectraDataFile.Ms2"); {ofstream fs("testSpectraDataFile.wiFF"); fs << "WIFF";} unit_assert_operator_equal(MS_ABI_WIFF_format, identifyFileFormat(readers, "testSpectraDataFile.wiFF")); bfs::remove("testSpectraDataFile.wiFF"); {ofstream fs("_FUNC42.DAT"); fs << "Life, the Universe, and Everything";} unit_assert_operator_equal(MS_Waters_raw_format, identifyFileFormat(readers, ".")); bfs::remove("_FUNC42.DAT"); } void test() { testGet(); testAccept(); testRead(); testIdentifyFileFormat(); } int main(int argc, char* argv[]) { TEST_PROLOG_EX(argc, argv, "_MSData") try { if (argc==2 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/msdata/BinaryDataEncoder.cpp0000664000175100017510000004647212664775621022765 0ustar teamcityteamcity00000000000000// // $Id: BinaryDataEncoder.cpp 6945 2014-11-26 18:58:33Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "BinaryDataEncoder.hpp" #include "pwiz/utility/misc/Base64.hpp" #include "pwiz/utility/misc/endian.hpp" #include "boost/static_assert.hpp" #include "boost/iostreams/filtering_streambuf.hpp" #include "boost/iostreams/filtering_stream.hpp" #include "boost/iostreams/copy.hpp" #include #include "iosfwd" #include "boost/iostreams/categories.hpp" #include "boost/iostreams/filter/zlib.hpp" #include "boost/iostreams/device/array.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/data/msdata/MSNumpress.hpp" namespace pwiz { namespace msdata { using namespace pwiz::util; using namespace pwiz::cv; using namespace boost::iostreams; // // BinaryDataEncoder::Impl // class BinaryDataEncoder::Impl { public: Impl(const Config& config) : config_(config) {} void encode(const vector& data, string& result, size_t* binaryByteCount); void encode(const double* data, size_t dataSize, std::string& result, size_t* binaryByteCount); void decode(const char *encodedData, size_t len, vector& result); void decode(const string& encodedData, vector& result) { decode(encodedData.c_str(),encodedData.length(),result); } const Config & getConfig() const { return config_; } private: Config config_; }; BOOST_STATIC_ASSERT(sizeof(float) == 4); BOOST_STATIC_ASSERT(sizeof(double) == 8); struct DoubleToFloat { float operator()(double d) {return float(d);} }; void BinaryDataEncoder::Impl::encode(const vector& data, string& result, size_t* binaryByteCount) { if (data.empty()) return; encode(&data[0], data.size(), result, binaryByteCount); } // formerly returned a string, but those are not guaranteed to have // contiguous storage space in older C++ standards, so use vector instead // thx to Johan Teleman template void filterArray(const void* byteBuffer, size_t byteCount, vector &result) { result.reserve(byteCount); // preallocate (more than we need), for speed filtering_ostream fos; fos.push(filter_type()); fos.push(back_inserter(result)); fos.write((const char*)byteBuffer, byteCount); fos.pop(); fos.pop(); // forces buffer to flush /* // original implementation, using technique in boost iostreams docs // this doesn't flush properly in all cases -- see unit test ostringstream result; array_source source(reinterpret_cast(byteBuffer), byteCount); filtering_streambuf in; in.push(filter_type()); in.push(source); boost::iostreams::copy(in, result); return result.str(); */ } void BinaryDataEncoder::Impl::encode(const double* data, size_t dataSize, std::string& result, size_t* binaryByteCount) { // using MSNumpress, from johan.teleman@immun.lth.se size_t byteCount; const void* byteBuffer; vector compressed; vector numpressed; vector data32; vector data64endianized; if (Numpress_None != config_.numpress) { // lossy numerical representation try { switch(config_.numpress) { case Numpress_Linear: numpressed.resize(dataSize * sizeof(double) + 8); break; case Numpress_Pic: numpressed.resize(dataSize * sizeof(double)); break; case Numpress_Slof: numpressed.resize(dataSize * 2 + 8); break; default: throw runtime_error("[BinaryDataEncoder::encode()] unknown numpress mode"); break; } vector unpressed; // for checking excessive accurary loss double numpressErrorTolerance = 0.0; switch (config_.numpress) { case Numpress_Linear: byteCount = MSNumpress::encodeLinear(data, dataSize, &numpressed[0], config_.numpressFixedPoint); numpressed.resize(byteCount); if ((numpressErrorTolerance=config_.numpressLinearErrorTolerance) > 0) // decompress to check accuracy loss MSNumpress::decodeLinear(numpressed,unpressed); break; case Numpress_Pic: byteCount = MSNumpress::encodePic(data, dataSize, &numpressed[0]); numpressed.resize(byteCount); numpressErrorTolerance = 0.5; // it's an integer rounding, so always +- 0.5 MSNumpress::decodePic(numpressed,unpressed); // but susceptable to overflow, so always check break; case Numpress_Slof: byteCount = MSNumpress::encodeSlof(data, dataSize, &numpressed[0], config_.numpressFixedPoint); numpressed.resize(byteCount); if ((numpressErrorTolerance=config_.numpressSlofErrorTolerance) > 0) // decompress to check accuracy loss MSNumpress::decodeSlof(numpressed,unpressed); break; default: break; } // now check to see if encoding introduces excessive error int n=-1; if (numpressErrorTolerance) { if (Numpress_Pic == config_.numpress) // integer rounding, abs accuracy is +- 0.5 { for (n=(int)dataSize;n--;) // check for overflow, strange rounding { if ((!boost::math::isfinite(unpressed[n])) || (fabs(data[n]-unpressed[n])>=1.0)) break; } } else // check for tolerance as well as overflow { for (n=(int)dataSize;n--;) { double d,u; if (!boost::math::isfinite(u = unpressed[n])||!boost::math::isfinite(d = data[n])) break; if (!d) { if (fabs(u) > numpressErrorTolerance) break; } else if (!u) { if (fabs(d) > numpressErrorTolerance) break; } else if (fabs(1.0-(d/u)) > numpressErrorTolerance) break; } } } if (n>=0) config_.numpress = Numpress_None; // excessive error, don't numpress else byteBuffer = reinterpret_cast(&numpressed[0]); } catch (int e) { cerr << "MZNumpress encoder threw exception: " << e << endl; } catch (...) { cerr << "Unknown exception while encoding " << dataSize << " doubles" << endl; } } if (Numpress_None == config_.numpress) { // may need 64->32bit conversion and byte ordering // // We use buffer abstractions, since we may need to change buffers during // downconversion and compression -- these are eventually passed to // the Base64 encoder. Note that: // - byteBuffer and byteCount must remain valid at the end of any block // in this function // - by default, no processing is done, resulting in no buffer changes // and fall through to Base64 encoding // byteBuffer = reinterpret_cast(data); byteCount = dataSize * sizeof(double); // 64-bit -> 32-bit downconversion if (config_.precision == Precision_32) { data32.resize(dataSize); transform(data, data+dataSize, data32.begin(), DoubleToFloat()); byteBuffer = reinterpret_cast(&data32[0]); byteCount = data32.size() * sizeof(float); } // byte ordering #ifdef PWIZ_LITTLE_ENDIAN bool mustEndianize = (config_.byteOrder == ByteOrder_BigEndian); #elif defined(PWIZ_BIG_ENDIAN) bool mustEndianize = (config_.byteOrder == ByteOrder_LittleEndian); #endif if (mustEndianize) { if (config_.precision == Precision_32) { unsigned int* p = reinterpret_cast(&data32[0]); transform(p, p+data32.size(), p, endianize32); } else // Precision_64 { data64endianized.resize(dataSize); const unsigned long long* from = reinterpret_cast(data); unsigned long long* to = reinterpret_cast(&data64endianized[0]); transform(from, from+dataSize, to, endianize64); byteBuffer = reinterpret_cast(&data64endianized[0]); byteCount = dataSize * sizeof(double); } } } // compression if (config_.compression == Compression_Zlib) { filterArray(byteBuffer, byteCount,compressed); if (!compressed.empty()) { byteBuffer = reinterpret_cast(&compressed[0]); byteCount = compressed.size(); } else { throw runtime_error("[BinaryDataEncoder::encode()] Compression error?"); } } // Base64 encoding result.resize(Base64::binaryToTextSize(byteCount)); // std::string storage is not guaranteed contiguous in older C++ standards, // and on long strings this has caused problems in the wild. So test for // actual contiguousness, and fall back to std::vector if needed // thx Johan Teleman size_t textSize; char *first = &result[0]; char *last = &result[result.size()-1]; if ((int)result.size() == 1+(last-first)) // pointer math agrees with [] operator textSize = Base64::binaryToText(byteBuffer, byteCount, &result[0]); else { std::vector contig; // work in this contiguous memory then copy to string contig.resize(result.size()); textSize = Base64::binaryToText(byteBuffer, byteCount, &contig[0]); copy(contig.begin(), contig.end(), result.begin()); } result.resize(textSize); if (binaryByteCount != NULL) *binaryByteCount = byteCount; // size before base64 encoding } template void copyBuffer(const void* byteBuffer, size_t byteCount, vector& result) { const float_type* floatBuffer = reinterpret_cast(byteBuffer); if (byteCount % sizeof(float_type) != 0) throw runtime_error("[BinaryDataEncoder::copyBuffer()] Bad byteCount."); size_t floatCount = byteCount / sizeof(float_type); result.resize(floatCount); copy(floatBuffer, floatBuffer+floatCount, result.begin()); } void BinaryDataEncoder::Impl::decode(const char *encodedData, size_t length, vector& result) { if (!encodedData || !length) return; // Base64 decoding vector binary(Base64::textToBinarySize(length)); size_t binarySize = Base64::textToBinary(encodedData, length, &binary[0]); binary.resize(binarySize); // buffer abstractions void* byteBuffer = &binary[0]; size_t byteCount = binarySize; size_t initialSize; // decompression vector decompressed; switch (config_.compression) { case Compression_Zlib: { filterArray(byteBuffer, byteCount,decompressed); if (!decompressed.empty()) { byteBuffer = reinterpret_cast(&decompressed[0]); byteCount = decompressed.size(); } else { throw runtime_error("[BinaryDataEncoder::decode()] Compression error?"); } } break; case Compression_None: break; default: throw runtime_error("[BinaryDataEncoder::decode()] unknown compression type"); break; } // numpress expansion or endian correction switch (config_.numpress) { case Numpress_Linear: initialSize = byteCount * 2; if (result.size() < initialSize) result.resize(initialSize); try { size_t count = MSNumpress::decodeLinear((const unsigned char *)byteBuffer, byteCount, &result[0]); result.resize(count); } catch (...) { throw runtime_error("BinaryDataEncoder::Impl::decode error in numpress linear decompression"); } break; case Numpress_Pic: initialSize = byteCount * 2; if (result.size() < initialSize) result.resize(initialSize); try { size_t count = MSNumpress::decodePic((const unsigned char *)byteBuffer, byteCount, &result[0]); result.resize(count); } catch (...) { throw runtime_error("BinaryDataEncoder::Impl::decode error in numpress pic decompression"); } break; case Numpress_Slof: initialSize = byteCount / 2; if (result.size() < initialSize) result.resize(initialSize); try { size_t count = MSNumpress::decodeSlof((const unsigned char *)byteBuffer, byteCount, &result[0]); result.resize(count); } catch (...) { throw runtime_error("BinaryDataEncoder::Impl::decode error in numpress slof decompression"); } break; case Numpress_None: { // endianization for non-numpress cases #ifdef PWIZ_LITTLE_ENDIAN bool mustEndianize = (config_.byteOrder == ByteOrder_BigEndian); #elif defined(PWIZ_BIG_ENDIAN) bool mustEndianize = (config_.byteOrder == ByteOrder_LittleEndian); #endif if (mustEndianize) { if (config_.precision == Precision_32) { unsigned int* p = reinterpret_cast(byteBuffer); size_t floatCount = byteCount / sizeof(float); transform(p, p+floatCount, p, endianize32); } else // Precision_64 { unsigned long long* p = reinterpret_cast(byteBuffer); size_t doubleCount = byteCount / sizeof(double); transform(p, p+doubleCount, p, endianize64); } } // (upconversion and) copy to result buffer if (config_.precision == Precision_32) copyBuffer(byteBuffer, byteCount, result); else // Precision_64 copyBuffer(byteBuffer, byteCount, result); } break; default: throw runtime_error("BinaryDataEncoder::Impl::decode unknown numpress method"); break; } } // // BinaryDataEncoder // PWIZ_API_DECL BinaryDataEncoder::BinaryDataEncoder(const Config& config) : impl_(new Impl(config)) {} PWIZ_API_DECL void BinaryDataEncoder::encode(const std::vector& data, std::string& result, size_t* binaryByteCount /*= NULL*/) const { impl_->encode(data, result, binaryByteCount); } PWIZ_API_DECL void BinaryDataEncoder::encode(const double* data, size_t dataSize, std::string& result, size_t* binaryByteCount /*= NULL*/) const { impl_->encode(data, dataSize, result, binaryByteCount); } PWIZ_API_DECL void BinaryDataEncoder::decode(const char * encodedData, size_t len, std::vector& result) const { impl_->decode(encodedData, len, result); } PWIZ_API_DECL const BinaryDataEncoder::Config& BinaryDataEncoder::getConfig() const // get the config actually used - may differ from input for numpress use { return impl_->getConfig(); } void writeConfig(ostream& os, const BinaryDataEncoder::Config& config, CVID cvid) { BinaryDataEncoder::Precision p; BinaryDataEncoder::Numpress c; map::const_iterator pOverrideItr; map::const_iterator cOverrideItr; cOverrideItr = config.numpressOverrides.find(cvid); if (cOverrideItr != config.numpressOverrides.end()) c = cOverrideItr->second; else c = config.numpress; const char *commaspace = (BinaryDataEncoder::Compression_Zlib == config.compression)?", ":" "; switch (c) { case BinaryDataEncoder::Numpress_Linear: os << "Compression-Numpress-Linear" << commaspace; break; case BinaryDataEncoder::Numpress_Pic: os << "Compression-Numpress-Pic" << commaspace; break; case BinaryDataEncoder::Numpress_Slof: os << "Compression-Numpress-Slof" << commaspace; break; case BinaryDataEncoder::Numpress_None: break; default: throw runtime_error("[BinaryDataEncoder::writeConfig] Unknown binary numpress mode"); break; } switch (config.compression) { case BinaryDataEncoder::Compression_Zlib : os << "Compression-Zlib"; break; case BinaryDataEncoder::Compression_None : if (BinaryDataEncoder::Numpress_None == c) os << "Compression-None"; break; default: throw runtime_error("[BinaryDataEncoder::writeConfig] Unknown binary numeric compression"); } pOverrideItr = config.precisionOverrides.find(cvid); if (pOverrideItr != config.precisionOverrides.end()) p = pOverrideItr->second; else p = config.precision; switch (p) { case BinaryDataEncoder::Precision_64: os << ", 64-bit"; break; case BinaryDataEncoder::Precision_32: os << ", 32-bit"; break; } } PWIZ_API_DECL ostream& operator<<(ostream& os, const BinaryDataEncoder::Config& config) { BinaryDataEncoder::Config usedConfig = config; os << endl << " m/z: "; writeConfig(os, config, MS_m_z_array); os << endl << " intensity: "; writeConfig(os, config, MS_intensity_array); os << endl << " rt: "; writeConfig(os, config, MS_time_array); os << endl << (config.byteOrder==BinaryDataEncoder::ByteOrder_LittleEndian ? "ByteOrder_LittleEndian" : "ByteOrder_BigEndian") << endl; return os; } } // namespace msdata } // namespace pwiz pwiz/pwiz/data/msdata/ChromatogramList_mzML_Test.cpp0000664000175100017510000000735212664775621024656 0ustar teamcityteamcity00000000000000// // $Id: ChromatogramList_mzML_Test.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "ChromatogramList_mzML.hpp" #include "Serializer_mzML.hpp" // depends on Serializer_mzML::write() only #include "examples.hpp" #include "pwiz/utility/minimxml/XMLWriter.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::cv; using namespace pwiz::msdata; using namespace pwiz::util; using namespace pwiz::minimxml; ostream* os_ = 0; void test(bool indexed) { if (os_) *os_ << "test(): indexed=\"" << boolalpha << indexed << "\"\n"; MSData tiny; examples::initializeTiny(tiny); Serializer_mzML::Config config; config.indexed = indexed; Serializer_mzML serializer(config); ostringstream oss; serializer.write(oss, tiny); if (os_) *os_ << "oss:\n" << oss.str() << endl; shared_ptr is(new istringstream(oss.str())); // dummy would normally be read in from file MSData dummy; // so we don't have any dangling references //dummy.instrumentPtrs.push_back(InstrumentPtr(new Instrument("LCQ_Deca"))); dummy.dataProcessingPtrs.push_back(DataProcessingPtr(new DataProcessing("pwiz_processing"))); dummy.dataProcessingPtrs.push_back(DataProcessingPtr(new DataProcessing("CompassXtract processing"))); Index_mzML_Ptr index(new Index_mzML(is, dummy)); ChromatogramListPtr sl = ChromatogramList_mzML::create(is, dummy, index); // check easy functions unit_assert(sl.get()); unit_assert(sl->size() == 2); unit_assert(sl->find("tic") == 0); unit_assert(sl->find("sic") == 1); // check tic ChromatogramPtr s = sl->chromatogram(0); // read without binary data unit_assert(s.get()); unit_assert(s->id == "tic"); unit_assert(s->binaryDataArrayPtrs.empty()); unit_assert(sl->chromatogramIdentity(0).index == 0); unit_assert(sl->chromatogramIdentity(0).id == "tic"); s = sl->chromatogram(0, true); // read with binary data vector pairs; s->getTimeIntensityPairs(pairs); unit_assert(pairs.size() == 15); for (int i=0; i<15; i++) unit_assert(pairs[i].time==i && pairs[i].intensity==15-i); // check sic s = sl->chromatogram(1, true); unit_assert(s.get()); unit_assert(s->id == "sic"); unit_assert(sl->chromatogramIdentity(1).index == 1); unit_assert(sl->chromatogramIdentity(1).id == "sic"); pairs.clear(); s->getTimeIntensityPairs(pairs); unit_assert(pairs.size() == 10); for (int i=0; i<10; i++) unit_assert(pairs[i].time==i && pairs[i].intensity==(10-i)); } void test() { bool indexed = true; test(indexed); indexed = false; test(indexed); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/msdata/Serializer_mzXML.hpp0000664000175100017510000000467612664775621022654 0ustar teamcityteamcity00000000000000// // $Id: Serializer_mzXML.hpp 1189 2009-08-14 17:36:06Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SERIALIZER_MZXML_HPP_ #define _SERIALIZER_MZXML_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "MSData.hpp" #include "BinaryDataEncoder.hpp" #include "pwiz/utility/misc/IterationListener.hpp" namespace pwiz { namespace msdata { /// MSData <-> mzXML stream serialization class PWIZ_API_DECL Serializer_mzXML { public: /// Serializer_mzXML configuration struct PWIZ_API_DECL Config { /// configuration for binary data encoding in write() /// note: byteOrder is ignored (mzXML always big endian) BinaryDataEncoder::Config binaryDataEncoderConfig; /// (indexed==true): read/write with bool indexed; Config() : indexed(true) {} }; /// constructor Serializer_mzXML(const Config& config = Config()); /// write MSData object to ostream as mzXML; /// iterationListenerRegistry may be used to receive progress updates void write(std::ostream& os, const MSData& msd, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry = 0) const; /// read in MSData object from an mzXML istream /// note: istream may be managed by MSData's SpectrumList, to allow for /// lazy evaluation of Spectrum data void read(boost::shared_ptr is, MSData& msd) const; private: class Impl; boost::shared_ptr impl_; Serializer_mzXML(Serializer_mzXML&); Serializer_mzXML& operator=(Serializer_mzXML&); }; PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const Serializer_mzXML::Config& config); } // namespace msdata } // namespace pwiz #endif // _SERIALIZER_MZXML_HPP_ pwiz/pwiz/data/msdata/Serializer_MGF.hpp0000664000175100017510000000356712664775621022254 0ustar teamcityteamcity00000000000000// // $Id: Serializer_MGF.hpp 1188 2009-08-14 17:19:55Z chambm $ // // // Original author: Matt Chambers // // Copyright 2008 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _SERIALIZER_MGF_HPP_ #define _SERIALIZER_MGF_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "MSData.hpp" #include "BinaryDataEncoder.hpp" #include "pwiz/utility/misc/IterationListener.hpp" namespace pwiz { namespace msdata { /// MSData <-> MGF stream serialization class PWIZ_API_DECL Serializer_MGF { public: /// constructor Serializer_MGF(); /// write MSData object to ostream as MGF; /// iterationListenerRegistry may be used to receive progress updates void write(std::ostream& os, const MSData& msd, const pwiz::util::IterationListenerRegistry* iterationListenerRegistry = 0) const; /// read in MSData object from an MGF istream /// note: istream may be managed by MSData's SpectrumList, to allow for /// lazy evaluation of Spectrum data void read(boost::shared_ptr is, MSData& msd) const; private: class Impl; boost::shared_ptr impl_; Serializer_MGF(Serializer_MGF&); Serializer_MGF& operator=(Serializer_MGF&); }; } // namespace msdata } // namespace pwiz #endif // _SERIALIZER_MGF_HPP_ pwiz/pwiz/data/msdata/SpectrumInfo.cpp0000664000175100017510000001212712664775621022053 0ustar teamcityteamcity00000000000000// // $Id: SpectrumInfo.cpp 2842 2011-07-07 22:11:07Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumInfo.hpp" #include "pwiz/utility/misc/Exception.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace msdata { PWIZ_API_DECL SpectrumInfo::SpectrumInfo() : index((size_t)-1), scanNumber(0), massAnalyzerType(CVID_Unknown), scanEvent(0), msLevel(0), isZoomScan(false), retentionTime(0), mzLow(0), mzHigh(0), basePeakMZ(0), basePeakIntensity(0), totalIonCurrent(0), thermoMonoisotopicMZ(0), ionInjectionTime(0) {} PWIZ_API_DECL SpectrumInfo::SpectrumInfo(const Spectrum& spectrum) : index((size_t)-1), scanNumber(0), massAnalyzerType(CVID_Unknown), scanEvent(0), msLevel(0), isZoomScan(false), retentionTime(0), mzLow(0), mzHigh(0), basePeakMZ(0), basePeakIntensity(0), totalIonCurrent(0), thermoMonoisotopicMZ(0), ionInjectionTime(0) { update(spectrum); } PWIZ_API_DECL void SpectrumInfo::update(const Spectrum& spectrum, bool getBinaryData) { *this = SpectrumInfo(); clearBinaryData(); id = spectrum.id; index = spectrum.index; scanNumber = id::valueAs(spectrum.id, "scan"); Scan dummy; const Scan& scan = spectrum.scanList.scans.empty() ? dummy : spectrum.scanList.scans[0]; massAnalyzerType = CVID_Unknown; if (scan.instrumentConfigurationPtr.get()) try { massAnalyzerType = scan.instrumentConfigurationPtr->componentList.analyzer(0) .cvParamChild(MS_mass_analyzer_type).cvid; } catch (out_of_range&) { // ignore out-of-range exception } scanEvent = scan.cvParam(MS_preset_scan_configuration).valueAs(); msLevel = spectrum.cvParam(MS_ms_level).valueAs(); isZoomScan = spectrum.hasCVParam(MS_zoom_scan); retentionTime = scan.cvParam(MS_scan_start_time).timeInSeconds(); filterString = scan.cvParam(MS_filter_string).value; mzLow = spectrum.cvParam(MS_lowest_observed_m_z).valueAs(); mzHigh = spectrum.cvParam(MS_highest_observed_m_z).valueAs(); basePeakMZ = spectrum.cvParam(MS_base_peak_m_z).valueAs(); basePeakIntensity = spectrum.cvParam(MS_base_peak_intensity).valueAs(); totalIonCurrent = spectrum.cvParam(MS_total_ion_current).valueAs(); ionInjectionTime = scan.cvParam(MS_ion_injection_time).valueAs(); UserParam userParamMonoisotopicMZ = scan.userParam("[Thermo Trailer Extra]Monoisotopic M/Z:"); if (!userParamMonoisotopicMZ.name.empty()) thermoMonoisotopicMZ = userParamMonoisotopicMZ.valueAs(); for (vector::const_iterator it=spectrum.precursors.begin(); it!=spectrum.precursors.end(); ++it) { PrecursorInfo precursorInfo; precursorInfo.index = 0; // TODO if (!it->selectedIons.empty()) { precursorInfo.mz = it->selectedIons[0].cvParam(MS_selected_ion_m_z).valueAs(); precursorInfo.charge = it->selectedIons[0].cvParam(MS_charge_state).valueAs(); precursorInfo.intensity = it->selectedIons[0].cvParam(MS_peak_intensity).valueAs(); } precursors.push_back(precursorInfo); } dataSize = spectrum.defaultArrayLength; if (getBinaryData && !spectrum.binaryDataArrayPtrs.empty()) spectrum.getMZIntensityPairs(data); } PWIZ_API_DECL void SpectrumInfo::clearBinaryData() { vector nothing; data.swap(nothing); } PWIZ_API_DECL string SpectrumInfo::massAnalyzerTypeAbbreviation() const { string result = "Unknown"; if (cvIsA(massAnalyzerType, MS_ion_trap)) result = "IonTrap"; else if (massAnalyzerType == MS_FT_ICR) result = "FT"; else if (massAnalyzerType == MS_orbitrap) result = "Orbitrap"; return result; } PWIZ_API_DECL double SpectrumInfo::mzFromFilterString() const { istringstream iss(filterString); vector tokens; copy(istream_iterator(iss), istream_iterator(), back_inserter(tokens)); for (vector::const_iterator it=tokens.begin(), end=tokens.end(); it!=end; ++it) { string::size_type at = it->find("@"); if (at != string::npos) return lexical_cast(it->substr(0,at)); } return 0; } } // namespace msdata } // namespace pwiz pwiz/pwiz/data/msdata/Index_mzML.cpp0000664000175100017510000003510412664775621021443 0ustar teamcityteamcity00000000000000// // $Id: Index_mzML.cpp 4601 2013-05-29 23:23:30Z pcbrefugee $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2011 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Index_mzML.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/minimxml/SAXParser.hpp" #include "boost/iostreams/positioning.hpp" #include "pwiz/data/msdata/IO.hpp" using namespace pwiz::util; using namespace pwiz::minimxml; using boost::iostreams::offset_to_position; namespace pwiz { namespace msdata { struct Index_mzML::Impl { Impl(const boost::shared_ptr& is, int schemaVersion) : is_(is), schemaVersion_(schemaVersion), spectrumCount_(0), chromatogramCount_(0) { createIndex(); } void recreate() const; void readIndex() const; void createIndex() const; void createMaps() const; boost::shared_ptr is_; int schemaVersion_; mutable size_t spectrumCount_; mutable vector spectrumIndex_; mutable map spectrumIdToIndex_; mutable map spotIDToIndexList_; mutable map legacyIdRefToNativeId_; mutable size_t chromatogramCount_; mutable vector chromatogramIndex_; mutable map chromatogramIdToIndex_; }; namespace { class HandlerIndexListOffset : public SAXParser::Handler { public: HandlerIndexListOffset(stream_offset& indexListOffset) : indexListOffset_(indexListOffset) { parseCharacters = true; autoUnescapeCharacters = false; } virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name != "indexListOffset") throw runtime_error("[Index_mzML::HandlerIndexOffset] Unexpected element name: " + name); return Status::Ok; } virtual Status characters(const SAXParser::saxstring& text, stream_offset position) { indexListOffset_ = lexical_cast(text); return Status::Ok; } private: stream_offset& indexListOffset_; }; struct HandlerOffset : public SAXParser::Handler { SpectrumIdentity* spectrumIdentity; ChromatogramIdentity* chromatogramIdentity; map* legacyIdRefToNativeId; HandlerOffset() : spectrumIdentity(0), chromatogramIdentity(0) { parseCharacters = true; autoUnescapeCharacters = false; } virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name != "offset") throw runtime_error("[Index_mzML::HandlerOffset] Unexpected element name: " + name); if (spectrumIdentity) { getAttribute(attributes, "idRef", spectrumIdentity->id); getAttribute(attributes, "spotID", spectrumIdentity->spotID); // mzML 1.0 if (version == 1) { string idRef, nativeID; getAttribute(attributes, "idRef", idRef); getAttribute(attributes, "nativeID", nativeID); if (nativeID.empty()) spectrumIdentity->id = idRef; else { try { lexical_cast(nativeID); spectrumIdentity->id = "scan=" + nativeID; } catch(exception&) { spectrumIdentity->id = nativeID; } (*legacyIdRefToNativeId)[idRef] = spectrumIdentity->id; } } } else if (chromatogramIdentity) { getAttribute(attributes, "idRef", chromatogramIdentity->id); } else throw runtime_error("[Index_mzML::HandlerOffset] Null identity."); return Status::Ok; } virtual Status characters(const SAXParser::saxstring& text, stream_offset position) { if (spectrumIdentity) spectrumIdentity->sourceFilePosition = lexical_cast(text); else if (chromatogramIdentity) chromatogramIdentity->sourceFilePosition = lexical_cast(text); else throw runtime_error("[Index_mzML::HandlerOffset] Null identity."); return Status::Ok; } }; class HandlerIndexList : public SAXParser::Handler { public: HandlerIndexList(int schemaVersion_, size_t& spectrumCount, vector& spectrumIndex, map& legacyIdRefToNativeId, size_t& chromatogramCount, vector& chromatogramIndex) : spectrumCount_(spectrumCount), spectrumIndex_(spectrumIndex), chromatogramCount_(chromatogramCount), chromatogramIndex_(chromatogramIndex), validIndexOffset_(false) { handlerOffset_.version = schemaVersion_; handlerOffset_.legacyIdRefToNativeId = &legacyIdRefToNativeId; } virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "indexList") { validIndexOffset_ = true; // looks like indexOffset landed us in the right place return Status::Ok; } else if (!validIndexOffset_) // "indexList" should have been first element throw runtime_error("[Index_mzML::HandlerIndex] element \"indexList\" not found at expected offset - bad indexOffset value, probably"); else if (name == "index") { string indexName; getAttribute(attributes, "name", indexName); if (indexName == "spectrum") inSpectrumIndex_ = true; else if (indexName == "chromatogram") inSpectrumIndex_ = false; else throw runtime_error("[Index_mzML::HandlerIndex] Unexpected index name: " + indexName); return Status::Ok; } else if (name == "offset") { if (inSpectrumIndex_) { handlerOffset_.chromatogramIdentity = 0; spectrumIndex_.push_back(SpectrumIdentityFromXML()); handlerOffset_.spectrumIdentity = &spectrumIndex_.back(); handlerOffset_.spectrumIdentity->index = spectrumCount_; ++spectrumCount_; } else { handlerOffset_.spectrumIdentity = 0; chromatogramIndex_.push_back(ChromatogramIdentity()); handlerOffset_.chromatogramIdentity = &chromatogramIndex_.back(); handlerOffset_.chromatogramIdentity->index = chromatogramCount_; ++chromatogramCount_; } return Status(Status::Delegate, &handlerOffset_); } else throw runtime_error("[Index_mzML::HandlerIndex] Unexpected element name: " + name); } private: size_t& spectrumCount_; vector& spectrumIndex_; size_t& chromatogramCount_; vector& chromatogramIndex_; bool validIndexOffset_; bool inSpectrumIndex_; HandlerOffset handlerOffset_; }; class HandlerIndexCreator : public SAXParser::Handler { public: HandlerIndexCreator(int schemaVersion_, size_t& spectrumCount, vector& spectrumIndex, map& legacyIdRefToNativeId, size_t& chromatogramCount, vector& chromatogramIndex) : spectrumCount_(spectrumCount), spectrumIndex_(spectrumIndex), chromatogramCount_(chromatogramCount), chromatogramIndex_(chromatogramIndex) {} virtual Status startElement(const string& name, const Attributes& attributes, stream_offset position) { if (name == "spectrum") { SpectrumIdentityFromXML* si; spectrumIndex_.push_back(SpectrumIdentityFromXML()); si = &spectrumIndex_.back(); getAttribute(attributes, "id", si->id); getAttribute(attributes, "spotID", si->spotID); si->index = spectrumCount_; si->sourceFilePosition = position; ++spectrumCount_; } else if (name == "chromatogram") { ChromatogramIdentity* ci; chromatogramIndex_.push_back(ChromatogramIdentity()); ci = &chromatogramIndex_.back(); getAttribute(attributes, "id", ci->id); ci->index = chromatogramCount_; ci->sourceFilePosition = position; ++chromatogramCount_; } else if (name == "indexList") return Status::Done; return Status::Ok; } private: size_t& spectrumCount_; vector& spectrumIndex_; size_t& chromatogramCount_; vector& chromatogramIndex_; }; } // namespace void Index_mzML::Impl::readIndex() const { // find const int bufferSize = 512; string buffer(bufferSize, '\0'); is_->seekg(-bufferSize, std::ios::end); is_->read(&buffer[0], bufferSize); string::size_type indexIndexOffset = buffer.find(""); if (indexIndexOffset == string::npos) throw runtime_error("Index_mzML::readIndex()] not found."); is_->seekg(-bufferSize + static_cast(indexIndexOffset), std::ios::end); if (!*is_) throw runtime_error("Index_mzML::readIndex()] Error seeking to ."); // read boost::iostreams::stream_offset indexListOffset = 0; HandlerIndexListOffset handlerIndexListOffset(indexListOffset); SAXParser::parse(*is_, handlerIndexListOffset); if (indexListOffset == 0) throw runtime_error("Index_mzML::readIndex()] Error parsing ."); // read is_->seekg(offset_to_position(indexListOffset)); if (!*is_) throw runtime_error("[Index_mzML::readIndex()] Error seeking to ."); HandlerIndexList handlerIndexList(schemaVersion_, spectrumCount_, spectrumIndex_, legacyIdRefToNativeId_, chromatogramCount_, chromatogramIndex_); SAXParser::parse(*is_, handlerIndexList); } void Index_mzML::Impl::createIndex() const { //boost::call_once(indexSizeSet_.flag, boost::bind(&SpectrumList_mzMLImpl::setIndexSize, this)); spectrumIndex_.clear(); chromatogramIndex_.clear(); // resize the index assuming the count attribute is accurate //index_.resize(size_); try { readIndex(); } catch (runtime_error&) { // TODO: log warning that the index was corrupt/missing is_->clear(); is_->seekg(0); HandlerIndexCreator handler(schemaVersion_, spectrumCount_, spectrumIndex_, legacyIdRefToNativeId_, chromatogramCount_, chromatogramIndex_); SAXParser::parse(*is_, handler); } createMaps(); } void Index_mzML::Impl::createMaps() const { // actually just init - build when/if actually called for spectrumIdToIndex_.clear(); spotIDToIndexList_.clear(); chromatogramIdToIndex_.clear(); } PWIZ_API_DECL Index_mzML::Index_mzML(boost::shared_ptr is, const MSData& msd) : impl_(new Impl(is, bal::starts_with(msd.version(), "1.0") ? 1 : 0)) {} PWIZ_API_DECL void Index_mzML::recreate() {impl_->createIndex();} PWIZ_API_DECL size_t Index_mzML::spectrumCount() const {return impl_->spectrumCount_;} PWIZ_API_DECL const SpectrumIdentityFromXML& Index_mzML::spectrumIdentity(size_t index) const {return impl_->spectrumIndex_[index];} PWIZ_API_DECL const map& Index_mzML::legacyIdRefToNativeId() const {return impl_->legacyIdRefToNativeId_;} PWIZ_API_DECL size_t Index_mzML::chromatogramCount() const {return impl_->chromatogramCount_;} PWIZ_API_DECL const ChromatogramIdentity& Index_mzML::chromatogramIdentity(size_t index) const {return impl_->chromatogramIndex_[index];} PWIZ_API_DECL size_t Index_mzML::findSpectrumId(const std::string& id) const { if (!impl_->spectrumIdToIndex_.size()) { // first use BOOST_FOREACH(const SpectrumIdentityFromXML& si, impl_->spectrumIndex_) { impl_->spectrumIdToIndex_[si.id] = si.index; } } map::const_iterator itr = impl_->spectrumIdToIndex_.find(id); return itr == impl_->spectrumIdToIndex_.end() ? spectrumCount() : itr->second; } PWIZ_API_DECL IndexList Index_mzML::findSpectrumBySpotID(const std::string& spotID) const { if (!impl_->spotIDToIndexList_.size()) { // first use BOOST_FOREACH(const SpectrumIdentityFromXML& si, impl_->spectrumIndex_) { if (!si.spotID.empty()) impl_->spotIDToIndexList_[si.spotID].push_back(si.index); } } map::const_iterator itr = impl_->spotIDToIndexList_.find(spotID); return itr == impl_->spotIDToIndexList_.end() ? IndexList() : itr->second; } PWIZ_API_DECL size_t Index_mzML::findChromatogramId(const std::string& id) const { if (!impl_->chromatogramIdToIndex_.size()) { // first use BOOST_FOREACH(const ChromatogramIdentity& ci, impl_->chromatogramIndex_) impl_->chromatogramIdToIndex_[ci.id] = ci.index; } map::const_iterator itr = impl_->chromatogramIdToIndex_.find(id); return itr == impl_->chromatogramIdToIndex_.end() ? chromatogramCount() : itr->second; } } // namespace msdata } // namespace pwiz pwiz/pwiz/utility/findmf/base/base/utilities/interpolation.hpp0000664000175100017510000002646712664775616026774 0ustar teamcityteamcity00000000000000// // $Id: interpolation.hpp 5313 2013-12-17 18:06:54Z chambm $ // // // Original author: Witold Wolski // // Copyright : ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef INTERPOLATIONUTILITIES_H #define INTERPOLATIONUTILITIES_H #include "pwiz/utility/findmf/base/base/constants.hpp" #include namespace ralab { namespace base { namespace base { namespace utilities { /// LinearInterpolate Functor template struct LinearInterpolate { TReal epsilon_; LinearInterpolate(TReal epsilon = std::numeric_limits::epsilon() ) :epsilon_(epsilon){} inline TReal operator() ( TReal y1, //!< y1 TReal y2, //!< y2 TReal mu //!< location parameter 0,1 ) { if(mu < epsilon_) return y1; else if(-(mu - 1.) < epsilon_) return y2; else return ( y1 * (1-mu) + y2 * mu ) ; } };// /// CosineInterpolate Functor /// Linear interpolation results in discontinuities at each point. /// Often a smoother interpolating function is desirable, perhaps the simplest is cosine interpolation. /// A suitable orientated piece of a cosine function serves /// to provide a smooth transition between adjacent segments. template struct CosineInterpolate { /*!\brief operator */ inline TReal operator()( TReal y1,//!< y1 TReal y2,//!< y2 TReal mu//!< location parameter in [0.,1.] ) { TReal mu2; mu2 = (1. - cos(mu* ralab::constants::PI))/2; return(y1*( 1. -mu2 )+y2*mu2); } }; /// CubicInterpolate Functor /// Cubic interpolation is the simplest method that offers true continuity between the segments. /// As such it requires more than just the two endpoints of the segment but also the two points on either side of them. /// So the function requires 4 points in all labeled y0, y1, y2, and y3, in the code below. /// mu still behaves the same way for interpolating between the segment y1 to y2. /// This doe s raise issues for how to interpolate between the first and last segments. /// In the examples here I just haven't bothered. /// A common solution is the dream up two extra points at the start and end of the sequence, /// the new points are created so that they have a slope equal to the slope of the start or end segment. template struct CubicInterpolate { TReal epsilon_; CubicInterpolate(TReal epsilon = std::numeric_limits::epsilon() ):epsilon_(epsilon) {} /*!\brief operator */ inline TReal operator() ( TReal y0,//!< y0 TReal y1,//!< y1 TReal y2,//!< y2 TReal y3,//!< y3 double mu//!< location parameter in [0.,1.] ) { if(mu < epsilon_) { return y1; } else if(-(mu - 1.) < epsilon_) { return y2; } else { TReal a0,a1,a2,a3,mu2; mu2 = mu*mu; a0 = y3 - y2 - y0 + y1; a1 = y0 - y1 - a0; a2 = y2 - y0; a3 = y1; return(a0*mu*mu2 + a1*mu2 + a2*mu + a3); } } }; /// HermiteInterpolation. /// Hermite interpolation like cubic requires 4 points so that it can achieve a higher degree of continuity. /// In addition it has nice tension and biasing controls. /// Tension can be used to tighten up the curvature at the known points. /// The bias is used to twist the curve about the known points. /// The examples shown here have the default tension and bias values of 0, /// it will be left as an exercise for the reader to explore different tension and bias values. template struct HermiteInterpolate { TReal tension_; TReal bias_; TReal epsilon_; HermiteInterpolate( TReal tension,//!< 1 is high, 0 normal, -1 is low TReal bias,//!< 0 is even, positive is towards first segment, negative towards the other TReal epsilon = std::numeric_limits::epsilon() ): tension_(tension), bias_(bias), epsilon_(epsilon) {} /*!\brief operator */ inline TReal operator ()( TReal y0,//!< y0 TReal y1,//!< y1 TReal y2,//!< y2 TReal y3,//!< y3 TReal mu //!< location ) { if(mu < epsilon_) { return y1; } else if(-(mu - 1.) < epsilon_) { return y2; } else { TReal m0,m1,mu2,mu3; TReal a0,a1,a2,a3; mu2 = mu * mu; mu3 = mu2 * mu; m0 = (y1-y0)*(1+bias_)*(1-tension_)/2; m0 += (y2-y1)*(1-bias_)*(1-tension_)/2; m1 = (y2-y1)*(1+bias_)*(1-tension_)/2; m1 += (y3-y2)*(1-bias_)*(1-tension_)/2; a0 = 2*mu3 - 3*mu2 + 1; a1 = mu3 - 2*mu2 + mu; a2 = mu3 - mu2; a3 = -2*mu3 + 3*mu2; return( a0*y1 + a1*m0 + a2*m1 + a3*y2 ); } } }; // HermiteInterpolation /// Cubic or Hermite interpolation worker template< typename YInputIterator, typename XInputIterator, typename OutputIterator, typename TFunctor > static void interpolateCubicHermite ( YInputIterator begY, YInputIterator endY, XInputIterator begX, XInputIterator endX, OutputIterator out, //!< interpolated values, same length as x. TFunctor & functor, //!< either CubicInterpolate or HermiteInterpolate int start_index = 0 ) { typedef typename std::iterator_traits::value_type TReal; //size_t nrX = std::distance( begX , endX ); size_t nrY = std::distance( begY , endY ); OutputIterator outI = out; for( unsigned int i = 0 ; begX != endX ; ++i , ++begX, ++outI ) { double xd = *begX - start_index; int index = static_cast(floor(xd)); //interpolate TReal mu = xd - static_cast(index); if(index < -1) { *outI = *begY; } else if(index == -1) { TReal y1 = *begY; TReal y2 = *begY; TReal y3 = *begY; TReal y4 = *(begY+1); *outI = functor(y1 , y2 , y3 , y4 , mu ); } //extrapolate else if(index == 0 ) { TReal y1 = 0; TReal y2 = *begY; TReal y3 = *(begY+1); TReal y4 = *(begY+2); *outI = functor(y1 , y2 , y3 , y4 , mu ); } else if( index > 0 && index < static_cast(nrY - 2) )//the normal case { YInputIterator begTmp = (begY + index - 1); TReal y1 = *begTmp; TReal y2 = *(begTmp + 1); TReal y3 = *(begTmp + 2); TReal y4 = *(begTmp + 3); *outI = functor(y1 , y2 , y3 , y4 , mu ); } else if(index == static_cast(nrY-2) ) //you are getting out of range { YInputIterator begTmp = (begY + index - 1); TReal y1 = *begTmp; TReal y2 = *(begTmp+1); TReal y3 = *(begTmp+2); TReal y4 = 0 ; *outI = functor(y1 , y2 , y3 , y4 ,mu); } else if(index == static_cast(nrY-1) ) //you are even farther out... { YInputIterator begTmp = (begY + index - 1); TReal y1 = *begTmp; TReal y2 = *(begTmp+1); TReal y3 = *(begTmp+1); TReal y4 = *(begTmp+1); *outI = functor(y1 , y2 , y3 , y4 , mu ); } else { *outI = *(endY-1); } }//end for }//end interpolate_cubic /// Linear cubic interpolator worker template < typename YInputIterator, typename XInputIterator, typename OutputIterator, typename TFunctor > static void interpolateLinearCosine ( YInputIterator y_p, //!< y values equidistantly spaced. spacing is [0,1,2, .... ,len(y)] YInputIterator endY, XInputIterator x_p, //!< points to interpolate at XInputIterator endX, OutputIterator out_p, //!< interpolated values, same length as x. TFunctor & interpolator, //!< interpolation functor, either: CosineInterpolate, LinearInterpolate. int start_index = 0 //!< if y values are placed on a grid with start_index != 0 ) { typedef typename std::iterator_traits::value_type TReal ; size_t nrX = std::distance(x_p,endX); size_t nrY = std::distance(y_p,endY); TReal xd; for(unsigned int i = 0 ; i < nrX; ++i, ++x_p, ++out_p) { xd = * x_p - start_index; double indexd = floor(xd); int index = static_cast( indexd ); assert(fabs (index - indexd) < 0.001); //interpolate if(index < 0 ) { *out_p = *y_p; }else if( index < static_cast(nrY-1) ) { TReal mu = xd - indexd; YInputIterator y1_p = (y_p + index); TReal y1 = *y1_p; TReal y2 = *(++y1_p); *out_p = interpolator(y1,y2,mu); } else { *out_p = *(y_p + (nrY-1)); } }//end for }//end interpolate cubic }//end utilities }//end base }//base }//ralab #endif pwiz/pwiz/utility/findmf/base/base/utilities/base.hpp0000664000175100017510000000313712664775616025004 0ustar teamcityteamcity00000000000000// // $Id: base.hpp 5313 2013-12-17 18:06:54Z chambm $ // // // Original author: Witold Wolski // // Copyright : ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef BASEUTILITIES_H #define BASEUTILITIES_H namespace ralab { namespace base { namespace base { namespace utilities { // class generator: template struct SeqPlus { TReal m_from; TReal m_by; SeqPlus(TReal from) : m_from(from), m_by(1) {} TReal operator()() { TReal current = m_from ; m_from += m_by; return current; } }; template struct SeqMinus { TReal m_from; TReal m_by; SeqMinus(TReal from) : m_from(from), m_by(1) {} TReal operator()() { TReal current = m_from ; m_from -= m_by; return current; } }; } } //base } //base }//ralab #endif // BASE_H pwiz/pwiz/data/common/MemoryIndexTest.cpp0000664000175100017510000000461112664775620022552 0ustar teamcityteamcity00000000000000// // $Id: MemoryIndexTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "MemoryIndex.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::util; using namespace pwiz::data; ostream* os_ = 0; void test() { if (os_) cout << "Testing MemoryIndex" << endl; vector entries; for (size_t i=0; i < 10; ++i) { Index::Entry entry; entry.id = lexical_cast(i); entry.index = i; entry.offset = i*100; entries.push_back(entry); } MemoryIndex index; unit_assert(index.size() == 0); unit_assert(!index.find("42").get()); unit_assert(!index.find(42).get()); index.create(entries); unit_assert(index.size() == 10); for (size_t i=0; i < 10; ++i) { Index::EntryPtr entryPtr = index.find(i); unit_assert(entryPtr.get()); unit_assert(entryPtr->id == lexical_cast(i)); unit_assert(entryPtr->index == i); unit_assert(entryPtr->offset == Index::stream_offset(i*100)); entryPtr = index.find(entryPtr->id); unit_assert(entryPtr.get()); unit_assert(entryPtr->id == lexical_cast(i)); unit_assert(entryPtr->index == i); unit_assert(entryPtr->offset == Index::stream_offset(i*100)); } unit_assert(!index.find("42").get()); unit_assert(!index.find(42).get()); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/common/Unimod.hpp0000664000175100017510000001215612664775620020715 0ustar teamcityteamcity00000000000000// // $Id: Unimod.hpp 4922 2013-09-05 22:33:08Z pcbrefugee $ // // // Original author: Matt Chambers // // Copyright 2011 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _UNIMOD_HPP_ #define _UNIMOD_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/utility/chemistry/Chemistry.hpp" #include "pwiz/utility/chemistry/MZTolerance.hpp" #include "cv.hpp" #include #include namespace pwiz { namespace data { namespace unimod { using namespace cv; using namespace chemistry; using namespace boost::logic; BOOST_BITFIELD_EX(Site, PWIZ_API_DECL, (Any)(1<<0) (NTerminus)(1<<1) (CTerminus)(1<<2) (Alanine)(1<<3) (Cysteine)(1<<4) (AsparticAcid)(1<<5) (GlutamicAcid)(1<<6) (Phenylalanine)(1<<7) (Glycine)(1<<8) (Histidine)(1<<9) (Isoleucine)(1<<10) (Lysine)(1<<11) (Leucine)(1<<12) (Methionine)(1<<13) (Asparagine)(1<<14) (Proline)(1<<15) (Glutamine)(1<<16) (Arginine)(1<<17) (Serine)(1<<18) (Threonine)(1<<19) (Selenocysteine)(1<<20) (Valine)(1<<21) (Tryptophan)(1<<22) (Tyrosine)(1<<23) ) BOOST_BITFIELD_DOMAIN_OPERATORS(Site) BOOST_ENUM_EX(Position, PWIZ_API_DECL, (Anywhere) (AnyNTerminus) (AnyCTerminus) (ProteinNTerminus) (ProteinCTerminus) ) BOOST_ENUM_DOMAIN_OPERATORS(Position) BOOST_BITFIELD_EX(Classification, PWIZ_API_DECL, (Any)(1<<0) (Artifact)(1<<1) (ChemicalDerivative)(1<<2) (CoTranslational)(1<<3) (IsotopicLabel)(1<<4) (Multiple)(1<<5) (NLinkedGlycosylation)(1<<6) (NonStandardResidue)(1<<7) (OLinkedGlycosylation)(1<<8) (OtherGlycosylation)(1<<9) (Other)(1<<10) (PostTranslational)(1<<11) (PreTranslational)(1<<12) (Substitution)(1<<13) ) BOOST_BITFIELD_DOMAIN_OPERATORS(Classification) /// a modification from Unimod struct PWIZ_API_DECL Modification { struct PWIZ_API_DECL Specificity { Site site; Position position; bool hidden; Classification classification; }; CVID cvid; std::string name; Formula deltaComposition; double deltaMonoisotopicMass() const; double deltaAverageMass() const; bool approved; std::vector specificities; }; /// returns the Site given a one-letter residue code, or: /// 'x' for Site::Any, 'n' for Site::NTerminus, 'c' for Site::CTerminus PWIZ_API_DECL Site site(char symbol); /// returns a Position corresponding to one of the following CVIDs: /// CVID_Unknown: Position::Anywhere /// MS_modification_specificity_peptide_N_term: Position::AnyNTerminus /// MS_modification_specificity_peptide_C_term: Position::AnyCTerminus /// Else: invalid_argument exception PWIZ_API_DECL Position position(CVID cvid = CVID_Unknown); /// the entire list of Unimod modifications PWIZ_API_DECL const std::vector& modifications(); /// get a list of modifications by mass and tolerance; /// - mass is treated as monoisotopic if monoisotopic=true; if indeterminate, both average and monoisotopic lookups are done /// - if approved is not indeterminate, only approved/unapproved modifications are considered /// - the site, position, and classification parameters filter the resulting modifications such that /// every modification must have at least one specificity matching all three criteria; /// - if hidden is not indeterminate, matching site/position/classification specificities must be hidden (or not) PWIZ_API_DECL std::vector modifications(double mass, double tolerance, tribool monoisotopic = true, tribool approved = true, Site site = Site::Any, Position position = Position::Anywhere, Classification classification = Classification::Any, tribool hidden = indeterminate); /// find a modification by CVID PWIZ_API_DECL const Modification& modification(CVID cvid); /// find a modification by title, e.g. "Phospho" not "Phosphorylation" PWIZ_API_DECL const Modification& modification(const std::string& title); } // namespace unimod } // namespace data } // namespace pwiz #endif // _UNIMOD_HPP_ pwiz/pwiz/data/common/MemoryIndex.cpp0000664000175100017510000000450612664775620021715 0ustar teamcityteamcity00000000000000// // $Id: MemoryIndex.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "MemoryIndex.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace data { class MemoryIndex::Impl { map idToEntryMap; vector indexEntries; public: virtual void create(std::vector& entries) { indexEntries.reserve(entries.size()); BOOST_FOREACH(const Entry& entry, entries) { EntryPtr entryPtr(new Entry(entry)); idToEntryMap[entry.id] = entryPtr; indexEntries.push_back(entryPtr); } } virtual size_t size() const { return idToEntryMap.size(); } virtual EntryPtr find(const std::string& id) const { map::const_iterator result = idToEntryMap.find(id); if (result == idToEntryMap.end()) return EntryPtr(); return result->second; } virtual EntryPtr find(size_t index) const { if (index >= indexEntries.size()) return EntryPtr(); return indexEntries[index]; } }; PWIZ_API_DECL MemoryIndex::MemoryIndex() : impl_(new Impl) {} PWIZ_API_DECL void MemoryIndex::create(vector& entries) {impl_->create(entries);} PWIZ_API_DECL size_t MemoryIndex::size() const {return impl_->size();} PWIZ_API_DECL Index::EntryPtr MemoryIndex::find(const string& id) const {return impl_->find(id);} PWIZ_API_DECL Index::EntryPtr MemoryIndex::find(size_t index) const {return impl_->find(index);} } // namespace data } // namespace pwiz pwiz/pwiz/data/common/cvgen.cpp0000664000175100017510000005617612664775620020571 0ustar teamcityteamcity00000000000000// // $Id: cvgen.cpp 6909 2014-11-19 17:18:29Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "obo.hpp" #include "boost/filesystem/path.hpp" #include "boost/filesystem/fstream.hpp" #include "boost/xpressive/xpressive_dynamic.hpp" #include "pwiz/utility/misc/Std.hpp" using namespace pwiz::data; namespace bfs = boost::filesystem; namespace bxp = boost::xpressive; // // This program selectively parses OBO format controlled vocabulary files // and generates C++ code (one hpp file and one cpp file). // void writeCopyright(ostream& os, const string& filename) { os << "//\n" << "// $Id: cvgen.cpp 6909 2014-11-19 17:18:29Z chambm $" << endl << "//\n" "//\n" "// Darren Kessner \n" "//\n" "// Copyright 2007 Spielberg Family Center for Applied Proteomics\n" "// Cedars-Sinai Medical Center, Los Angeles, California 90048\n" "//\n" "// Licensed under the Apache License, Version 2.0 (the \"License\");\n" "// you may not use this file except in compliance with the License.\n" "// You may obtain a copy of the License at\n" "//\n" "// http://www.apache.org/licenses/LICENSE-2.0\n" "//\n" "// Unless required by applicable law or agreed to in writing, software\n" "// distributed under the License is distributed on an \"AS IS\" BASIS,\n" "// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" "// See the License for the specific language governing permissions and\n" "// limitations under the License.\n" "//\n" "// This file was generated by cvgen.\n" "//\n" "// Do not edit this file! Your changes will be lost next time cvgen is run -\n" "// see pwiz/scripts/misc/update_cv.bat for info on how that works.\n" "// Instead, edit cvgen.cpp itself, or the cv.inl include file if adding static\n" "// code or data.\n" "//\n\n\n"; } string includeGuardString(const string& basename) { string includeGuard = basename; transform(includeGuard.begin(), includeGuard.end(), includeGuard.begin(), (int(*)(int))toupper); return "_" + includeGuard + "_HPP_"; } void namespaceBegin(ostream& os, const string& name) { os << "namespace pwiz {\nnamespace cv {\n\n\n"; } void namespaceEnd(ostream& os, const string& name) { os << "} // namespace cv\n} // namespace pwiz\n\n\n"; } inline char toAllowableChar(char a) { return isalnum(a) ? a : '_'; } string enumName(const string& prefix, const string& name, bool isObsolete) { string result = name; transform(result.begin(), result.end(), result.begin(), toAllowableChar); result = prefix + "_" + result + (isObsolete ? "_OBSOLETE" : ""); return result; } string enumName(const Term& term) { return enumName(term.prefix, term.name, term.isObsolete); } const size_t enumBlockSize_ = 100000000; size_t enumValue(const Term& term, size_t index) { return term.id + (enumBlockSize_ * index); } // OBO format can use C-style escape characters; these need to be escaped when writing a quoted string string escape_copy(const string& str) { string copy(str); bal::replace_all(copy, "\\", "\\\\"); bal::replace_all(copy, "\"", "\\\""); return copy; } vector< map > termMaps; vector< map > correctedEnumNameMaps; void writeHpp(const vector& obos, const string& basename, const bfs::path& outputDir) { string filename = basename + ".hpp"; bfs::path filenameFullPath = outputDir / filename; bfs::ofstream os(filenameFullPath, ios::binary); writeCopyright(os, filename); string includeGuard = includeGuardString(basename); os << "#ifndef " << includeGuard << endl << "#define " << includeGuard << "\n\n\n" << "#include \n" << "#include \n" << "#include \n" << "#include \"pwiz/utility/misc/Export.hpp\"\n" << "\n\n"; for (vector::const_iterator obo=obos.begin(); obo!=obos.end(); ++obo) { string filename = bfs::path(obo->filename).filename().string(); os << "// [" << filename << "]\n"; string fileDefine = bal::to_upper_copy(filename); transform(fileDefine.begin(), fileDefine.end(), fileDefine.begin(), toAllowableChar); os << "#define _" << fileDefine << "_\n"; for (vector::const_iterator it=obo->header.begin(); it!=obo->header.end(); ++it) os << "// " << *it << endl; os << "//\n"; } os << "\n\n"; namespaceBegin(os, basename); os << "/// enumeration of controlled vocabulary (CV) terms, generated from OBO file(s)\n" "enum PWIZ_API_DECL CVID\n{\n" " CVID_Unknown = -1"; for (vector::const_iterator obo=obos.begin(); obo!=obos.end(); ++obo) BOOST_FOREACH(const Term& term, obo->terms) { string& eName = correctedEnumNameMaps[obo-obos.begin()][term.id]; os << ",\n\n" << " /// " << term.name << ": " << term.def << "\n" << " " << eName << " = " << enumValue(term, obo-obos.begin()); if (obo->prefix == "MS") // add synonyms for PSI-MS only { BOOST_FOREACH(const string& synonym, term.exactSynonyms) { os << ",\n\n" << " /// " << synonym << " (" << term.name << "): " << term.def << "\n" << " " << enumName(term.prefix, synonym, term.isObsolete) << " = " << eName; } } } os << "\n}; // enum CVID\n\n\n"; os << "/// Information about an ontology or CV source and a short 'lookup' tag to refer to.\n" "struct PWIZ_API_DECL CV\n" "{\n" " /// the short label to be used as a reference tag with which to refer to this particular Controlled Vocabulary source description (e.g., from the cvLabel attribute, in CVParamType elements).\n" " std::string id;\n" "\n" " /// the URI for the resource.\n" " std::string URI;\n" "\n" " /// the usual name for the resource (e.g. The PSI-MS Controlled Vocabulary).\n" " std::string fullName;\n" "\n" " /// the version of the CV from which the referred-to terms are drawn.\n" " std::string version;\n" "\n" " /// returns true iff id, URI, fullName, and version are all pairwise equal\n" " bool operator==(const CV& that) const;\n" "\n" " /// returns ture iff id, URI, fullName, and version are all empty\n" " bool empty() const;\n" "};\n\n\n"; os << "/// returns a CV object for the specified namespace (prefix);\n" "/// currently supported namespaces are: MS UO\n" "PWIZ_API_DECL const CV& cv(const std::string& prefix);\n\n\n"; os << "/// structure for holding CV term info\n" "struct PWIZ_API_DECL CVTermInfo\n" "{\n" " CVID cvid;\n" " std::string id;\n" " std::string name;\n" " std::string def;\n" " bool isObsolete;\n" "\n" " typedef std::vector id_list;\n" " id_list parentsIsA;\n" " id_list parentsPartOf;\n" " std::multimap otherRelations;\n" " std::vector exactSynonyms;\n" " std::multimap propertyValues;\n" "\n" " CVTermInfo() : cvid((CVID)-1) {}\n" " const std::string& shortName() const;\n" " std::string prefix() const;\n" "};\n\n\n"; os << "/// returns CV term info for the specified CVID\n" "PWIZ_API_DECL const CVTermInfo& cvTermInfo(CVID cvid);\n\n\n"; os << "/// returns CV term info for the specified id (accession number)\n" "PWIZ_API_DECL const CVTermInfo& cvTermInfo(const char* id);\n" "PWIZ_API_DECL const CVTermInfo& cvTermInfo(const std::string& id);\n\n\n"; os << "/// returns true iff child IsA parent in the CV\n" "PWIZ_API_DECL bool cvIsA(CVID child, CVID parent);\n\n\n"; os << "/// returns vector of all valid CVIDs\n" "PWIZ_API_DECL const std::vector& cvids();\n\n\n"; namespaceEnd(os, basename); os << "#endif // " << includeGuard << "\n\n\n"; } void writeCpp(const vector& obos, const string& basename, const bfs::path& outputDir) { string filename = basename + ".cpp"; bfs::path filenameFullPath = outputDir / filename; bfs::ofstream os(filenameFullPath, ios::binary); writeCopyright(os, filename); os << "#define PWIZ_SOURCE\n\n" << "#include \"" << basename << ".hpp\"\n" << "#include \"pwiz/utility/misc/Std.hpp\"\n" << "#include \"pwiz/utility/misc/Singleton.hpp\"\n" << "\n\n"; namespaceBegin(os, basename); os << "namespace {\n\n\n"; os << "struct TermInfo\n" "{\n" " CVID cvid;\n" " const char* id;\n" " const char* name;\n" " const char* def;\n" " bool isObsolete;\n" "};\n\n\n"; os << "const TermInfo termInfos_[] =\n{\n"; os << " {CVID_Unknown, \"??:0000000\", \"CVID_Unknown\", \"CVID_Unknown\", false},\n"; for (vector::const_iterator obo=obos.begin(); obo!=obos.end(); ++obo) BOOST_FOREACH(const Term& term, obo->terms) { string& eName = correctedEnumNameMaps[obo-obos.begin()][term.id]; string correctName = term.name; if (eName != enumName(term)) correctName += " (" + term.prefix + ":" + lexical_cast(enumValue(term, obo-obos.begin())) + ")"; os << " {" << eName << ", " << "\"" << term.prefix << ":" << (term.prefix != "UNIMOD" ? setw(7) : setw(1) ) << setfill('0') << term.id << "\", " << "\"" << escape_copy(correctName) << "\", " << "\"" << escape_copy(term.def) << "\", " << (term.isObsolete ? "true" : "false") // setw(7) screws up direct output << "},\n"; } os << "}; // termInfos_\n\n\n"; os << "const size_t termInfosSize_ = sizeof(termInfos_)/sizeof(TermInfo);\n\n\n"; os << "struct CVIDPair\n" "{\n" " CVID first;\n" " CVID second;\n" "};\n\n\n"; os << "CVIDPair relationsIsA_[] =\n{\n"; for (vector::const_iterator obo=obos.begin(); obo!=obos.end(); ++obo) BOOST_FOREACH(const Term& term, obo->terms) BOOST_FOREACH(const Term::id_type& id, term.parentsIsA) os << " {" << correctedEnumNameMaps[obo-obos.begin()][term.id] << ", " << correctedEnumNameMaps[obo-obos.begin()][id] << "},\n"; os << "}; // relationsIsA_\n\n\n"; os << "const size_t relationsIsASize_ = sizeof(relationsIsA_)/sizeof(CVIDPair);\n\n\n"; os << "CVIDPair relationsPartOf_[] =\n{\n"; for (vector::const_iterator obo=obos.begin(); obo!=obos.end(); ++obo) BOOST_FOREACH(const Term& term, obo->terms) BOOST_FOREACH(const Term::id_type& id, term.parentsPartOf) os << " {" << correctedEnumNameMaps[obo-obos.begin()][term.id] << ", " << correctedEnumNameMaps[obo-obos.begin()][id] << "},\n"; os << "}; // relationsPartOf_\n\n\n"; os << "const size_t relationsPartOfSize_ = sizeof(relationsPartOf_)/sizeof(CVIDPair);\n\n\n"; os << "struct OtherRelationPair\n" "{\n" " CVID subject;\n" " const char* relation;\n" " CVID object;\n" "};\n\n\n"; os << "OtherRelationPair relationsOther_[] =\n" << "{\n" << " {CVID_Unknown, \"Unknown\", CVID_Unknown},\n"; for (vector::const_iterator obo=obos.begin(); obo!=obos.end(); ++obo) BOOST_FOREACH(const Term& term, obo->terms) for (Term::relation_map::const_iterator jt=term.relations.begin(); jt!=term.relations.end(); ++jt) { const Term* relatedTerm = NULL; vector::const_iterator obo2; for (obo2=obos.begin(); obo2!=obos.end(); ++obo2) { if (jt->second.first != obo2->prefix) continue; set::const_iterator relatedTermItr = obo2->terms.find(Term(jt->second.second)); if (relatedTermItr != obo2->terms.end()) { relatedTerm = &*relatedTermItr; break; } } if (!relatedTerm) { if ("PATO" != jt->second.first) // we don't follow the UO -> PATO relationships because we don't download pato.obo cerr << "[writeCpp] Warning: unable to find object of term relationship for term \"" << term.name << "\"." << endl; } else os << " {" << correctedEnumNameMaps[obo-obos.begin()][term.id] << ", " << "\"" << jt->first << "\", " << correctedEnumNameMaps[obo2-obos.begin()][relatedTerm->id] << "},\n"; } os << "}; // relationsOther_\n\n\n"; os << "const size_t relationsOtherSize_ = sizeof(relationsOther_)/sizeof(OtherRelationPair);\n\n\n"; os << "struct CVIDStringPair\n" "{\n" " CVID first;\n" " const char* second;\n" "};\n\n\n"; os << "CVIDStringPair relationsExactSynonym_[] =\n" "{\n" " {CVID_Unknown, \"Unknown\"},\n"; for (vector::const_iterator obo=obos.begin(); obo!=obos.end(); ++obo) BOOST_FOREACH(const Term& term, obo->terms) BOOST_FOREACH(const string& synonym, term.exactSynonyms) os << " {" << correctedEnumNameMaps[obo-obos.begin()][term.id] << ", \"" << synonym << "\"},\n"; os << "}; // relationsExactSynonym_\n\n\n"; os << "const size_t relationsExactSynonymSize_ = sizeof(relationsExactSynonym_)/sizeof(CVIDStringPair);\n\n\n"; os << "struct PropertyValuePair\n" "{\n" " CVID term;\n" " const char* name;\n" " const char* value;\n" "};\n\n\n"; typedef pair NameValuePair; os << "PropertyValuePair propertyValue_[] =\n" "{\n" " {CVID_Unknown, \"Unknown\", \"Unknown\"},\n"; for (vector::const_iterator obo=obos.begin(); obo!=obos.end(); ++obo) { if (obo->prefix != "UNIMOD") // we currently only use UNIMOD properties continue; BOOST_FOREACH(const Term& term, obo->terms) BOOST_FOREACH(const NameValuePair& nameValuePair, term.propertyValues) { if (!(bal::ends_with(nameValuePair.first, "_classification") || bal::ends_with(nameValuePair.first, "_position") || bal::ends_with(nameValuePair.first, "_hidden") || bal::ends_with(nameValuePair.first, "_site") || nameValuePair.first == "delta_composition" || nameValuePair.first == "approved")) continue; os << " {" << correctedEnumNameMaps[obo-obos.begin()][term.id] << ", \"" << nameValuePair.first << "\", \"" << nameValuePair.second << "\"},\n"; } } os << "}; // propertyValue_\n\n\n"; os << "const size_t propertyValueSize_ = sizeof(propertyValue_)/sizeof(PropertyValuePair);\n\n\n"; os << "class CVTermData : public boost::singleton\n" "{\n" " public:\n" " CVTermData(boost::restricted)\n" " {\n" " for (const TermInfo* it=termInfos_; it!=termInfos_+termInfosSize_; ++it)\n" " {\n" " CVTermInfo temp;\n" " temp.cvid = it->cvid;\n" " temp.id = it->id;\n" " temp.name = it->name;\n" " temp.def = it->def;\n" " temp.isObsolete = it->isObsolete;\n" " infoMap_[temp.cvid] = temp;\n" " cvids_.push_back(it->cvid);\n" " }\n" "\n" " for (const CVIDPair* it=relationsIsA_; it!=relationsIsA_+relationsIsASize_; ++it)\n" " infoMap_[it->first].parentsIsA.push_back(it->second);\n" "\n" " for (const CVIDPair* it=relationsPartOf_; it!=relationsPartOf_+relationsPartOfSize_; ++it)\n" " infoMap_[it->first].parentsPartOf.push_back(it->second);\n" "\n" " for (const OtherRelationPair* it=relationsOther_; it!=relationsOther_+relationsOtherSize_; ++it)\n" " infoMap_[it->subject].otherRelations.insert(make_pair(it->relation, it->object));\n" "\n" " for (const CVIDStringPair* it=relationsExactSynonym_; it!=relationsExactSynonym_+relationsExactSynonymSize_; ++it)\n" " infoMap_[it->first].exactSynonyms.push_back(it->second);\n" "\n" " for (const PropertyValuePair* it=propertyValue_; it!=propertyValue_+propertyValueSize_; ++it)\n" " infoMap_[it->term].propertyValues.insert(make_pair(it->name, it->value));\n" "\n"; // TODO: is there a way to get these from the OBOs? os << " cvMap_[\"MS\"].fullName = \"Proteomics Standards Initiative Mass Spectrometry Ontology\";\n" " cvMap_[\"MS\"].URI = \"http://psidev.cvs.sourceforge.net/*checkout*/psidev/psi/psi-ms/mzML/controlledVocabulary/psi-ms.obo\";\n" "\n" " cvMap_[\"UO\"].fullName = \"Unit Ontology\";\n" " cvMap_[\"UO\"].URI = \"http://obo.cvs.sourceforge.net/*checkout*/obo/obo/ontology/phenotype/unit.obo\";\n" "\n" " cvMap_[\"UNIMOD\"].fullName = \"UNIMOD\";\n" " cvMap_[\"UNIMOD\"].URI = \"http://www.unimod.org/obo/unimod.obo\";\n" "\n"; // populate CV ids and versions from OBO headers for (vector::const_iterator obo=obos.begin(); obo!=obos.end(); ++obo) { os << " cvMap_[\"" << obo->prefix << "\"].id = \"" << obo->prefix << "\";\n"; string version; for (size_t i=0; i < obo->header.size(); ++i) { bxp::sregex e = bxp::sregex::compile(".*?[^-]version: (\\S+)"); bxp::smatch what; if (regex_match(obo->header[i], what, e)) { version = what[1]; break; } } if (version.empty()) { // since UNIMOD doesn't update its 'date' field, // we use the maximum "date_time_modified" property_value string max_date_time_modified; bxp::sregex e = bxp::sregex::compile("(\\d+-\\d+-\\d+).*"); bxp::smatch what; BOOST_FOREACH(const Term& term, obo->terms) BOOST_FOREACH(const NameValuePair& nameValuePair, term.propertyValues) if (nameValuePair.first == "date_time_modified" && regex_match(nameValuePair.second, what, e)) { if (max_date_time_modified.empty() || what[1].str() > max_date_time_modified) max_date_time_modified = what[1]; continue; // to the next term } version = max_date_time_modified; } if (version.empty()) { for (size_t i=0; i < obo->header.size(); ++i) { bxp::sregex e = bxp::sregex::compile("\\s*date: (\\S+).*"); bxp::smatch what; if (regex_match(obo->header[i], what, e)) { version = what[1]; break; } } } if (version.empty()) version = "unknown"; os << " cvMap_[\"" << obo->prefix << "\"].version = \"" << version << "\";\n\n"; } os << " }\n" "\n" " inline const map& infoMap() const {return infoMap_;}\n" " inline const map& cvMap() const {return cvMap_;}\n" " inline const vector& cvids() const {return cvids_;}\n" "\n" " private:\n" " map infoMap_;\n" " map cvMap_;\n" " vector cvids_;\n" "};\n\n\n"; os << "const char* oboPrefixes_[] =\n" "{\n"; for (vector::const_iterator obo=obos.begin(); obo!=obos.end(); ++obo) os << " \"" << obo->prefix << "\",\n"; os << "};\n\n\n"; os << "const size_t oboPrefixesSize_ = sizeof(oboPrefixes_)/sizeof(const char*);\n\n\n" "const size_t enumBlockSize_ = " << enumBlockSize_ << ";\n\n\n" "struct StringEquals\n" "{\n" " bool operator()(const string& yours) {return mine==yours;}\n" " string mine;\n" " StringEquals(const string& _mine) : mine(_mine) {}\n" "};\n\n\n"; os << "} // namespace\n\n\n"; os << "#include \"cv.inl\" // code and data that doesn't change with CV releases\n\n"; namespaceEnd(os, basename); } void generateFiles(const vector& obos, const string& basename, const bfs::path& outputDir) { // populate term maps for each OBO termMaps.resize(obos.size()); correctedEnumNameMaps.resize(obos.size()); for (vector::const_iterator obo=obos.begin(); obo!=obos.end(); ++obo) { multiset enumNames; BOOST_FOREACH(const Term& term, obo->terms) enumNames.insert(enumName(term)); BOOST_FOREACH(const Term& term, obo->terms) { termMaps[obo-obos.begin()][term.id] = &term; string& eName = correctedEnumNameMaps[obo-obos.begin()][term.id] = enumName(term); if (enumNames.count(eName) > 1) eName += "_" + lexical_cast(enumValue(term, obo-obos.begin())); } } writeHpp(obos, basename, outputDir); writeCpp(obos, basename, outputDir); } int main(int argc, char* argv[]) { if (argc < 2) { cout << "Usage: cvgen file.obo [...]\n"; cout << "Parse input file(s) and output cv.hpp and cv.cpp.\n"; return 1; } try { bfs::path exeDir(bfs::path(argv[0]).branch_path()); vector obos; for (int i=1; i // // Copyright 2011 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Unimod.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/Singleton.hpp" using namespace pwiz::cv; using namespace pwiz::chemistry; using namespace boost::logic; namespace pwiz { namespace data { namespace unimod { struct UnimodData : public boost::singleton { vector modifications; map indexByCVID; map indexByTitle; multimap indexByMonoisotopicMass; multimap indexByAverageMass; UnimodData(boost::restricted) { // dictionary of chemical "bricks" used in unimod formulas map brickFormulaByTitle; brickFormulaByTitle["Hex"] = Formula("H10 C6 O5"); brickFormulaByTitle["HexNAc"] = Formula("H13 C8 N1 O5"); brickFormulaByTitle["dHex"] = Formula("C6 H10 O4"); brickFormulaByTitle["HexA"] = Formula("C6 H8 O6"); brickFormulaByTitle["Kdn"] = Formula("C9 H14 O8"); brickFormulaByTitle["Kdo"] = Formula("C8 H12 O7"); brickFormulaByTitle["NeuAc"] = Formula("C11 H17 N1 O8"); brickFormulaByTitle["NeuGc"] = Formula("C11 H17 N1 O9"); brickFormulaByTitle["Pent"] = Formula("C5 H8 O4"); brickFormulaByTitle["Hep"] = Formula("C7 H12 O6"); brickFormulaByTitle["C"] = Formula("C1"); brickFormulaByTitle["H"] = Formula("H1"); brickFormulaByTitle["O"] = Formula("O1"); brickFormulaByTitle["N"] = Formula("N1"); brickFormulaByTitle["S"] = Formula("S1"); brickFormulaByTitle["P"] = Formula("P1"); brickFormulaByTitle["13C"] = Formula("_13C1"); brickFormulaByTitle["2H"] = Formula("_2H1"); brickFormulaByTitle["18O"] = Formula("_18O1"); brickFormulaByTitle["15N"] = Formula("_15N1"); map siteMap; siteMap["N-term"] = Site::NTerminus; siteMap["C-term"] = Site::CTerminus; BOOST_FOREACH(char aa, string("ABCDEFGHIJKLMNPQRSTUVWXYZ")) siteMap[string(1, aa)] = site(aa); map positionMap; positionMap["Anywhere"] = Position::Anywhere; positionMap["Any N-term"] = Position::AnyNTerminus; positionMap["Any C-term"] = Position::AnyCTerminus; positionMap["Protein N-term"] = Position::ProteinNTerminus; positionMap["Protein C-term"] = Position::ProteinCTerminus; map classificationMap; classificationMap["Artefact"] = Classification::Artifact; classificationMap["Chemical derivative"] = Classification::ChemicalDerivative; classificationMap["Co-translational"] = Classification::CoTranslational; classificationMap["Isotopic label"] = Classification::IsotopicLabel; classificationMap["Multiple"] = Classification::Multiple; classificationMap["N-linked glycosylation"] = Classification::NLinkedGlycosylation; classificationMap["Non-standard residue"] = Classification::NonStandardResidue; classificationMap["O-linked glycosylation"] = Classification::OLinkedGlycosylation; classificationMap["Other glycosylation"] = Classification::OtherGlycosylation; classificationMap["Other"] = Classification::Other; classificationMap["Post-translational"] = Classification::PostTranslational; classificationMap["Pre-translational"] = Classification::PreTranslational; classificationMap["AA substitution"] = Classification::Substitution; vector formulaTokens; BOOST_FOREACH(CVID cvid, cvids()) { const CVTermInfo& term = cvTermInfo(cvid); if (!bal::starts_with(term.id, "UNIMOD") || bal::ends_with(term.id, ":0")) continue; try { Modification mod; mod.cvid = term.cvid; mod.name = term.name; multimap::const_iterator itr; itr = term.propertyValues.find("delta_composition"); if (itr == term.propertyValues.end()) throw runtime_error("no delta_composition property for term \"" + term.id + "\""); formulaTokens.clear(); bal::split(formulaTokens, itr->second, bal::is_space()); // () if quantity>1 or just for quantity=1 BOOST_FOREACH(string& token, formulaTokens) { Formula brickFormula; size_t openParenthesis = token.find_first_of('('); if (openParenthesis != string::npos) { brickFormula = getBrickFormula(token.substr(0, openParenthesis), brickFormulaByTitle); size_t closeParenthesis = token.find_first_of(')', openParenthesis+1); if (closeParenthesis == string::npos) throw runtime_error("unmatched opening parenthesis in \"" + token + "\""); int brickQuantity = lexical_cast(token.substr(openParenthesis+1, closeParenthesis-openParenthesis-1)); brickFormula *= brickQuantity; } else brickFormula = getBrickFormula(token, brickFormulaByTitle); mod.deltaComposition += brickFormula; } itr = term.propertyValues.find("approved"); if (itr == term.propertyValues.end()) throw runtime_error("no approved property for term \"" + term.id + "\""); mod.approved = itr->second == "1"; multimap::const_iterator end = term.propertyValues.end(); // properties are ordered asciibetically: // spec_1_classification // spec_1_hidden // spec_1_position // spec_1_site itr = term.propertyValues.lower_bound("spec_"); while (true) { Modification::Specificity spec; map::const_iterator itr2 = classificationMap.find(itr->second); if (itr2 == classificationMap.end()) throw runtime_error("unknown classification \"" + itr->second + "\" for term \"" + term.id + "\""); spec.classification = itr2->second; // skip redundant classification properties for the current site do {++itr;} while (itr != end && bal::ends_with(itr->first, "classification")); assert(itr != end && bal::starts_with(itr->first, "spec")); spec.hidden = itr->second == "1"; // skip redundant hidden properties for the current site do {++itr;} while (itr != end && bal::ends_with(itr->first, "hidden")); assert(itr != end && bal::starts_with(itr->first, "spec")); map::const_iterator itr3 = positionMap.find(itr->second); if (itr3 == positionMap.end()) throw runtime_error("unknown position \"" + itr->second + "\" for term \"" + term.id + "\""); spec.position = itr3->second; // skip redundant position properties for the current site do {++itr;} while (itr != end && bal::ends_with(itr->first, "position")); assert(itr != end && bal::starts_with(itr->first, "spec")); map::const_iterator itr4 = siteMap.find(itr->second); if (itr4 == siteMap.end()) throw runtime_error("unknown site \"" + itr->second + "\" for term \"" + term.id + "\""); spec.site = itr4->second; mod.specificities.push_back(spec); // add copies of the currently specificity for each site, e.g. // spec_1_site = S // spec_1_site = T ++itr; while (itr != end && bal::ends_with(itr->first, "site")) { itr4 = siteMap.find(itr->second); if (itr4 == siteMap.end()) throw runtime_error("unknown site \"" + itr->second + "\" for term \"" + term.id + "\""); spec.site = itr4->second; mod.specificities.push_back(spec); ++itr; } if (itr == end || !bal::starts_with(itr->first, "spec_")) break; } modifications.push_back(mod); size_t modIndex = modifications.size() - 1; indexByCVID[mod.cvid] = modIndex; indexByTitle[mod.name] = modIndex; indexByMonoisotopicMass.insert(make_pair(mod.deltaMonoisotopicMass(), modIndex)); indexByAverageMass.insert(make_pair(mod.deltaAverageMass(), modIndex)); } catch (exception&) { // TODO: log this error //cerr << "[UnimodData::ctor] error parsing term \"" << term.id << "\": " << e.what() << "\n"; //throw runtime_error("[UnimodData::ctor] error parsing mod \"" + title + "\""); } } } Formula getBrickFormula(const string& brick, const map& brickFormulaByTitle) const { map::const_iterator itr = brickFormulaByTitle.find(brick); if (itr != brickFormulaByTitle.end()) return itr->second; try { // handle less common elements like Cl, Cu, Se, etc. return Formula(brick + "1"); } catch (runtime_error&) { throw invalid_argument("[UnimodData::getBrickFormula] unknown element or brick \"" + brick + "\""); } } }; PWIZ_API_DECL Site site(char symbol) { // maps character to a corresponding Site bitmask const static size_t nil = Site(Site::not_mask).value(); const static size_t symbolMap[] = { nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil, // 0-19 nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil, // 20-39 nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil, // 40-59 nil,nil,nil,nil,nil, // 60-64 Site(Site::Alanine).value(), // A (65) Site(Site::Asparagine | Site::AsparticAcid).value(), // B Site(Site::Cysteine).value(), Site(Site::AsparticAcid).value(), Site(Site::GlutamicAcid).value(), Site(Site::Phenylalanine).value(), Site(Site::Glycine).value(), Site(Site::Histidine).value(), Site(Site::Isoleucine).value(), Site(Site::Leucine | Site::Isoleucine).value(), // J Site(Site::Lysine).value(), Site(Site::Leucine).value(), Site(Site::Methionine).value(), Site(Site::Asparagine).value(), nil, // O Site(Site::Proline).value(), Site(Site::Glutamine).value(), Site(Site::Arginine).value(), Site(Site::Serine).value(), Site(Site::Threonine).value(), Site(Site::Selenocysteine).value(), // U Site(Site::Valine).value(), Site(Site::Tryptophan).value(), Site(Site::Any).value(), // X Site(Site::Tyrosine).value(), Site(Site::Glutamine | Site::GlutamicAcid).value(), // Z nil,nil,nil,nil,nil,nil,nil,nil, // [ \ ] ^ _ ` a b Site(Site::CTerminus).value(), // c nil,nil,nil,nil,nil,nil,nil,nil,nil,nil, // d e f g h i j k l m Site(Site::NTerminus).value(), // n nil,nil,nil,nil,nil,nil,nil,nil,nil, // o p q r s t u v w Site(Site::Any).value() // x }; if (symbol > 'x' || (symbol != 'x' && symbolMap[(size_t) symbol] == nil)) throw invalid_argument("[unimod::site] invalid symbol \"" + string(1, symbol) + "\""); return Site::get_by_value(symbolMap[(size_t) symbol]).get(); } PWIZ_API_DECL Position position(CVID cvid) { switch (cvid) { case CVID_Unknown: return Position::Anywhere; case MS_modification_specificity_peptide_N_term: return Position::AnyNTerminus; case MS_modification_specificity_peptide_C_term: return Position::AnyCTerminus; case MS_modification_specificity_protein_N_term: return Position::ProteinNTerminus; case MS_modification_specificity_protein_C_term: return Position::ProteinCTerminus; default: throw invalid_argument("[unimod::position] invalid cvid \"" + cvTermInfo(cvid).shortName() + "\" (" + lexical_cast(cvid) + ")"); } } PWIZ_API_DECL double Modification::deltaMonoisotopicMass() const {return deltaComposition.monoisotopicMass();} PWIZ_API_DECL double Modification::deltaAverageMass() const {return deltaComposition.molecularWeight();} PWIZ_API_DECL const std::vector& modifications() {return UnimodData::instance->modifications;} PWIZ_API_DECL vector modifications(double mass, double tolerance, tribool monoisotopic /*= true*/, tribool approved /*= true*/, Site site /*= Site::Any*/, Position position /*= Position::Anywhere*/, Classification classification /*= Classification::Any*/, tribool hidden /*= tribool::indeterminate*/) { UnimodData::lease unimodData; vector result; multimap::const_iterator itr, end; // assume monoisotopic if (monoisotopic || indeterminate(monoisotopic)) { itr = unimodData->indexByMonoisotopicMass.lower_bound(mass - tolerance); end = unimodData->indexByMonoisotopicMass.upper_bound(mass + tolerance); } else { itr = unimodData->indexByAverageMass.lower_bound(mass - tolerance); end = unimodData->indexByAverageMass.upper_bound(mass + tolerance); } for (; itr != end; ++itr) { const Modification& mod = unimodData->modifications[itr->second]; if (!indeterminate(approved) && approved != mod.approved) continue; BOOST_FOREACH(const Modification::Specificity& specificity, mod.specificities) { if ((site == Site::Any || site[specificity.site]) && (position == Position::Anywhere || position == specificity.position) && (classification == Classification::Any || classification[specificity.classification]) && (indeterminate(hidden) || hidden == specificity.hidden)) { result.push_back(mod); break; } } } // for indeterminate mass type, append the results of the equivalent average mass call if (indeterminate(monoisotopic)) { vector avgResults = modifications(mass, tolerance, false, approved, site, position, classification, hidden); set existingResults; BOOST_FOREACH(const Modification& mod, result) existingResults.insert(mod.cvid); BOOST_FOREACH(const Modification& mod, avgResults) if (!existingResults.count(mod.cvid)) result.push_back(mod); } return result; } PWIZ_API_DECL const Modification& modification(CVID cvid) { UnimodData::lease unimodData; map::const_iterator itr = unimodData->indexByCVID.find(cvid); if (itr == unimodData->indexByCVID.end()) throw runtime_error("[unimod::modification] invalid cvid \"" + cvTermInfo(cvid).shortName() + "\""); return unimodData->modifications[itr->second]; } PWIZ_API_DECL const Modification& modification(const std::string& title) { UnimodData::lease unimodData; map::const_iterator itr = unimodData->indexByTitle.find(title); if (itr == unimodData->indexByTitle.end()) throw runtime_error("[unimod::modification] invalid title \"" + title + "\""); return unimodData->modifications[itr->second]; } } // namespace unimod } // namespace data } // namespace pwiz pwiz/pwiz/data/common/obo.hpp0000664000175100017510000000453612664775620020244 0ustar teamcityteamcity00000000000000// // $Id: obo.hpp 2778 2011-06-14 16:08:39Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _OBO_HPP_ #define _OBO_HPP_ #include "pwiz/utility/misc/Export.hpp" #include #include #include #include #include namespace pwiz { namespace data { /// a single controlled vocabulary term struct PWIZ_API_DECL Term { typedef unsigned int id_type; typedef std::vector id_list; typedef std::multimap > relation_map; const static id_type MAX_ID; std::string prefix; id_type id; std::string name; std::string def; id_list parentsIsA; id_list parentsPartOf; relation_map relations; // other than is_a and part_of std::multimap propertyValues; std::vector exactSynonyms; bool isObsolete; Term(id_type id = MAX_ID) : id(id), isObsolete(false) {} bool operator< (const Term& rhs) const {return id < rhs.id;} }; /// /// Represents a selectively parsed OBO file. /// /// Note that the following are currently ignored during parsing: /// - comments /// - dbxrefs /// - synonym tags other than exact_synonym /// - non-Term stanzas /// struct PWIZ_API_DECL OBO { std::string filename; std::vector header; std::string prefix; // e.g. "MS", "UO" std::set terms; OBO(){} OBO(const std::string& filename); }; PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const Term& term); PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const OBO& obo); } // namespace data } // namespace pwiz #endif // _OBO_HPP_ pwiz/pwiz/data/common/UnimodTest.cpp0000664000175100017510000002377612664775620021562 0ustar teamcityteamcity00000000000000// // $Id: UnimodTest.cpp 6865 2014-10-31 21:47:12Z chambm $ // // // Original author: Matt Chambers // // Copyright 2011 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include "Unimod.hpp" #include using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::chemistry; using namespace pwiz::data::unimod; using namespace boost::logic; ostream* os_ = 0; void test() { if (os_) *os_ << "test()\n"; unit_assert_operator_equal(Site::Any, site('x')); unit_assert_operator_equal(Site::Any, site('X')); unit_assert_operator_equal(Site::NTerminus, site('n')); unit_assert_operator_equal(Site::CTerminus, site('c')); unit_assert_operator_equal(Site::Alanine, site('A')); unit_assert_operator_equal(Site::Tyrosine, site('Y')); unit_assert_operator_equal((Site::Asparagine | Site::AsparticAcid), site('B')); unit_assert_operator_equal((Site::Glutamine | Site::GlutamicAcid), site('Z')); unit_assert_throws_what(site('1'), invalid_argument, "[unimod::site] invalid symbol \"1\""); unit_assert_throws_what(site('z'), invalid_argument, "[unimod::site] invalid symbol \"z\""); unit_assert_operator_equal(Position::Anywhere, position()); unit_assert_operator_equal(Position::AnyNTerminus, position(MS_modification_specificity_peptide_N_term)); unit_assert_operator_equal(Position::AnyCTerminus, position(MS_modification_specificity_peptide_C_term)); unit_assert_throws_what(position(MS_matrix_assisted_laser_desorption_ionization), invalid_argument, "[unimod::position] invalid cvid \"MALDI\" (1000075)"); if (os_) *os_ << "Unimod entries: " << modifications().size() << endl; unit_assert(modifications().size() > 500); const Modification& acetyl = modification("Acetyl"); unit_assert_operator_equal(UNIMOD_Acetyl, acetyl.cvid); unit_assert_operator_equal(&acetyl, &modification(UNIMOD_Acetyl)); unit_assert_operator_equal("Acetyl", acetyl.name); unit_assert(acetyl.approved); unit_assert_operator_equal("C2H2O1", acetyl.deltaComposition.formula()); unit_assert_operator_equal(8, acetyl.specificities.size()); unit_assert_operator_equal(Site::Lysine, acetyl.specificities[0].site); unit_assert_operator_equal(Position::Anywhere, acetyl.specificities[0].position); unit_assert_operator_equal(false, acetyl.specificities[0].hidden); unit_assert_operator_equal(Classification::Multiple, acetyl.specificities[0].classification); unit_assert_operator_equal(Site::NTerminus, acetyl.specificities[1].site); unit_assert_operator_equal(Position::AnyNTerminus, acetyl.specificities[1].position); unit_assert_operator_equal(false, acetyl.specificities[1].hidden); unit_assert_operator_equal(Classification::Multiple, acetyl.specificities[1].classification); unit_assert_operator_equal(Site::Cysteine, acetyl.specificities[2].site); unit_assert_operator_equal(Position::Anywhere, acetyl.specificities[2].position); unit_assert_operator_equal(true, acetyl.specificities[2].hidden); unit_assert_operator_equal(Classification::PostTranslational, acetyl.specificities[2].classification); unit_assert_operator_equal(Site::NTerminus, acetyl.specificities[4].site); unit_assert_operator_equal(Position::ProteinNTerminus, acetyl.specificities[4].position); unit_assert_operator_equal(false, acetyl.specificities[4].hidden); unit_assert_operator_equal(Classification::PostTranslational, acetyl.specificities[4].classification); unit_assert_operator_equal(UNIMOD_Acetyl, modifications(acetyl.deltaMonoisotopicMass(), 0)[0].cvid); unit_assert_operator_equal(UNIMOD_Acetyl, modifications(acetyl.deltaAverageMass(), 0, false)[0].cvid); // test a position-only filter unit_assert_operator_equal(1, modifications(acetyl.deltaMonoisotopicMass(), 0.0001, indeterminate, indeterminate, Site::Any, Position::AnyNTerminus).size()); unit_assert_operator_equal(UNIMOD_Acetyl, modifications(acetyl.deltaMonoisotopicMass(), 0.5, indeterminate, indeterminate, Site::Any, Position::AnyNTerminus)[0].cvid); const Modification& hse = modification("Met->Hse"); unit_assert_operator_equal(UNIMOD_Met__Hse, hse.cvid); unit_assert_operator_equal("Met->Hse", hse.name); unit_assert(hse.approved); unit_assert_operator_equal("C-1H-2O1S-1", hse.deltaComposition.formula()); unit_assert_operator_equal(Site::Methionine, hse.specificities[0].site); unit_assert_operator_equal(Position::AnyCTerminus, hse.specificities[0].position); unit_assert_operator_equal(false, hse.specificities[0].hidden); unit_assert_operator_equal(Classification::ChemicalDerivative, hse.specificities[0].classification); const Modification& oxidation = modification(UNIMOD_Oxidation); // 3 mods have the same mass as oxidation unit_assert_operator_equal(3, modifications(oxidation.deltaMonoisotopicMass(), 0, true, indeterminate).size()); unit_assert_operator_equal(3, modifications(oxidation.deltaAverageMass(), 0, false, indeterminate).size()); // only one of those mods happen on Methionine unit_assert_operator_equal(1, modifications(oxidation.deltaMonoisotopicMass(), 0, true, indeterminate, Site::Methionine).size()); unit_assert_operator_equal(1, modifications(oxidation.deltaAverageMass(), 0, false, indeterminate, Site::Methionine).size()); // oxidation also happens on Proline (test multi-bit Site mask) unit_assert_operator_equal(1, modifications(oxidation.deltaAverageMass(), 0, false, indeterminate, Site::Methionine | Site::Proline).size()); // add Alanine as a site and it could be a substitution unit_assert_operator_equal(2, modifications(oxidation.deltaAverageMass(), 0, false, indeterminate, Site::Methionine | Site::Alanine).size()); // 18 mods are 28 +/- 1 unit_assert_operator_equal(18, modifications(28, 1, true, indeterminate).size()); // only two of those mods happen post-translationally on protein N-termini unit_assert_operator_equal(2, modifications(28, 1, true, indeterminate, Site::Any, Position::ProteinNTerminus, Classification::PostTranslational).size()); const Modification& phospho = modification(UNIMOD_Phospho); // phospho on S and T are grouped (property names are duplicated) unit_assert_operator_equal(UNIMOD_Phospho, modifications(phospho.deltaMonoisotopicMass(), 0, true, true, Site::Serine)[0].cvid); unit_assert_operator_equal(UNIMOD_Phospho, modifications(phospho.deltaMonoisotopicMass(), 0, true, true, Site::Threonine)[0].cvid); unit_assert_operator_equal(UNIMOD_Phospho, modifications(phospho.deltaMonoisotopicMass(), 0, true, true, Site::Tyrosine)[0].cvid); // test multi-bit Site mask unit_assert_operator_equal(UNIMOD_Phospho, modifications(phospho.deltaMonoisotopicMass(), 0, true, true, Site::Serine | Site::Tyrosine)[0].cvid); // there are no unapproved mods at phospho's mass unit_assert_operator_equal(0, modifications(phospho.deltaMonoisotopicMass(), 0, true, false).size()); // phospho and sulfo are only distinguishable with PPM mass accuracy double mass_2000Da_1ppm = 2000 - (2000 - MZTolerance(1, MZTolerance::PPM)); unit_assert_operator_equal(2, modifications(phospho.deltaMonoisotopicMass(), 0.5, true, true, Site::Serine).size()); unit_assert_operator_equal(1, modifications(phospho.deltaMonoisotopicMass(), mass_2000Da_1ppm, true, true, Site::Serine).size()); // test indeterminate and average mass unit_assert_operator_equal(2, modifications(phospho.deltaMonoisotopicMass(), 0.1, indeterminate, true, Site::Serine).size()); unit_assert_operator_equal(2, modifications(phospho.deltaAverageMass(), 0.1, indeterminate, true, Site::Serine).size()); unit_assert_operator_equal(2, modifications(phospho.deltaAverageMass(), 0.1, false, true, Site::Serine).size()); // test negative mass unit_assert_operator_equal(UNIMOD_Gln__pyro_Glu, modifications(-17.0265, mass_2000Da_1ppm, true, true, Site::Glutamine, Position::AnyNTerminus)[0].cvid); // at 14.5 +/- 0.5 there are 3 approved mods and 6 unapproved unit_assert_operator_equal(3, modifications(14.5, 0.5, true, true).size()); unit_assert_operator_equal(9, modifications(14.5, 0.5, true, false).size()); // all 9 unapproved mods are hidden unit_assert_operator_equal(0, modifications(14.5, 0.5, true, false, Site::Any, Position::Anywhere, Classification::Any, false).size()); // test ambiguous residue; this mod could be a Q->P substitution unit_assert_operator_equal(1, modifications(-31, 0.01, true, indeterminate, site('Z')).size()); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/common/diff_std_test.cpp0000664000175100017510000002134512664775620022276 0ustar teamcityteamcity00000000000000// // $Id: diff_std_test.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Robert Burke // // Copyright 2009 Spielberg Family Center for Applied Proteomics // University of Southern California, Los Angeles, California 90033 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "diff_std.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::data; using namespace pwiz::data::diff_impl; ostream* os_ = 0; void testString(const string& a, const string& b) { if (os_) *os_ << "diff_string(\"" << a << "\", \"" << b << "\")" << endl; string a_b, b_a; diff_string(a, b, a_b, b_a); if (os_) *os_ << "a-b: " << a_b << "\nb-a: " << b_a << endl; if (a == b) unit_assert(a_b.empty() && b_a.empty()); else unit_assert(!a_b.empty() && !b_a.empty()); } template void testIntegralReally(integral_type a, integral_type b) { if (os_) *os_ << "diff_integral(\"" << a << "\", \"" << b << "\")" << endl; integral_type a_b, b_a; diff_integral(a, b, a_b, b_a, BaseDiffConfig()); if (a == b) unit_assert(a_b == integral_type() && b_a == integral_type()); else unit_assert(a_b != integral_type() || b_a != integral_type()); } template void testIntegral() { testIntegralReally(1, 1); testIntegralReally(-1, 1); testIntegralReally(-1, -1); testIntegralReally(1, 0); testIntegralReally(-1, 0); } template void testFloating(floating_type a, floating_type b, floating_type precision) { floating_type a_b, b_a; BaseDiffConfig config((double) precision); diff_floating(a, b, a_b, b_a, config); if (fabs(a - b) <= config.precision + std::numeric_limits::epsilon()) unit_assert(a_b == floating_type() && b_a == floating_type()); else unit_assert(a_b == fabs(a - b) && b_a == fabs(a - b)); } void testCV() { if (os_) *os_ << "testCV()\n"; CV a, b; a.URI = "uri"; a.id = "cvLabel"; a.fullName = "fullName"; a.version = "version"; b = a; Diff diff; diff(a,b); unit_assert(diff.a_b.empty()); unit_assert(diff.b_a.empty()); unit_assert(!diff); a.version = "version_changed"; diff(a,b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.URI.empty() && diff.b_a.URI.empty()); unit_assert(diff.a_b.id.empty() && diff.b_a.id.empty()); unit_assert(diff.a_b.fullName.empty() && diff.b_a.fullName.empty()); unit_assert(diff.a_b.version == "version_changed"); unit_assert(diff.b_a.version == "version"); } void testUserParam() { if (os_) *os_ << "testUserParam()\n"; UserParam a, b; a.name = "name"; a.value = "value"; a.type = "type"; a.units = UO_minute; b = a; Diff diff(a, b); unit_assert(!diff); unit_assert(diff.a_b.empty()); unit_assert(diff.b_a.empty()); b.value = "value_changed"; a.units = UO_second; unit_assert(diff(a,b)); if (os_) *os_ << diff << endl; unit_assert(diff.a_b.name == "name"); unit_assert(diff.b_a.name == "name"); unit_assert(diff.a_b.value == "value"); unit_assert(diff.b_a.value == "value_changed"); unit_assert(diff.a_b.type.empty() && diff.b_a.type.empty()); unit_assert(diff.a_b.units == UO_second); unit_assert(diff.b_a.units == UO_minute); } void testCVParam() { if (os_) *os_ << "testCVParam()\n"; CVParam a, b, c; a.cvid = MS_ionization_type; a.value = "420"; c = b = a; Diff diff(a, b); unit_assert(!diff); unit_assert(diff.a_b.empty()); unit_assert(diff.b_a.empty()); b.value = "value_changed"; diff(a,b); unit_assert(diff); if (os_) *os_ << diff << endl; unit_assert(diff.a_b.cvid == MS_ionization_type); unit_assert(diff.b_a.cvid == MS_ionization_type); unit_assert(diff.a_b.value == "420"); unit_assert(diff.b_a.value == "value_changed"); c.value = "421"; // prove fix for bug that wouldn't catch diff in int values diff(a,c); unit_assert(diff); if (os_) *os_ << diff << endl; unit_assert(diff.a_b.cvid == MS_ionization_type); unit_assert(diff.b_a.cvid == MS_ionization_type); unit_assert(diff.a_b.value == "420"); unit_assert(diff.b_a.value == "421"); a.value = "4.1e5"; // make sure we handle scientific notation properly c.value = "4.1"; diff(a,c); unit_assert(diff); if (os_) *os_ << diff << endl; a.value = "4.1e5"; // make sure we handle scientific notation properly c.value = "410000.0"; diff(a,c); unit_assert(!diff); if (os_) *os_ << diff << endl; a.value = "1a"; // make sure we aren't naive about things that start out as ints c.value = "1b"; diff(a,c); unit_assert(diff); if (os_) *os_ << diff << endl; } void testParamContainer() { if (os_) *os_ << "testParamContainer()\n"; ParamGroupPtr pgp1(new ParamGroup("pg1")); ParamGroupPtr pgp2(new ParamGroup("pg2")); ParamGroupPtr pgp3(new ParamGroup("pg3")); ParamContainer a, b; a.userParams.push_back(UserParam("common")); b.userParams.push_back(UserParam("common")); a.cvParams.push_back(MS_m_z); b.cvParams.push_back(MS_m_z); a.paramGroupPtrs.push_back(pgp1); b.paramGroupPtrs.push_back(pgp1); Diff diff(a, b); unit_assert(!diff); a.userParams.push_back(UserParam("different", "1")); b.userParams.push_back(UserParam("different", "2")); a.cvParams.push_back(MS_charge_state); b.cvParams.push_back(MS_peak_intensity); a.paramGroupPtrs.push_back(pgp2); b.paramGroupPtrs.push_back(pgp3); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.userParams.size() == 1); unit_assert(diff.a_b.userParams[0] == UserParam("different","1")); unit_assert(diff.b_a.userParams.size() == 1); unit_assert(diff.b_a.userParams[0] == UserParam("different","2")); unit_assert(diff.a_b.cvParams.size() == 1); unit_assert(diff.a_b.cvParams[0] == MS_charge_state); unit_assert(diff.b_a.cvParams.size() == 1); unit_assert(diff.b_a.cvParams[0] == MS_peak_intensity); unit_assert(diff.a_b.paramGroupPtrs.size() == 1); unit_assert(diff.a_b.paramGroupPtrs[0]->id == "pg2"); unit_assert(diff.b_a.paramGroupPtrs.size() == 1); unit_assert(diff.b_a.paramGroupPtrs[0]->id == "pg3"); } void testParamGroup() { if (os_) *os_ << "testParamGroup()\n"; ParamGroup a("pg"), b("pg"); a.userParams.push_back(UserParam("common")); b.userParams.push_back(UserParam("common")); Diff diff(a, b); unit_assert(!diff); a.userParams.push_back(UserParam("different", "1")); b.userParams.push_back(UserParam("different", "2")); diff(a, b); if (os_) *os_ << diff << endl; unit_assert(diff); unit_assert(diff.a_b.userParams.size() == 1); unit_assert(diff.a_b.userParams[0] == UserParam("different","1")); unit_assert(diff.b_a.userParams.size() == 1); unit_assert(diff.b_a.userParams[0] == UserParam("different","2")); } void test() { testString("goober", "goober"); testString("goober", "goo"); testIntegral(); testIntegral(); testIntegral(); testIntegral(); testIntegral(); testIntegral(); testFloating(1.f, 1.f, 1.e-6f); testFloating(1.f, 1.0000000001f, 1.e-6f); testFloating(1.f, 1.00001f, 1.e-6f); testFloating(4.f, 4.2f, 1.f); testFloating(1, 1, 1e-6); testFloating(1, 1.0000000001, 1e-6); testFloating(1, 1.00001, 1e-6); testFloating(4, 4.2, 1); testCV(); testUserParam(); testCVParam(); testParamContainer(); testParamGroup(); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/common/diff_std.hpp0000664000175100017510000003053312664775620021243 0ustar teamcityteamcity00000000000000// // $Id: diff_std.hpp 3725 2012-06-20 05:31:18Z pcbrefugee $ // // // Original author: Robert Burke // // Copyright 2009 Spielberg Family Center for Applied Proteomics // University of Southern California, Los Angeles, California 90033 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _DIFF_STD_HPP_ #define _DIFF_STD_HPP_ #include "pwiz/utility/misc/Export.hpp" #include #include #include #include #include #include "ParamTypes.hpp" #include namespace pwiz { namespace data { struct BaseDiffConfig { BaseDiffConfig(double _precision = 1e-6) : precision(_precision), partialDiffOK(false), ignoreVersions(false) {} double precision; bool partialDiffOK; // if true, can stop checking at first difference found bool ignoreVersions; // if true, don't sweat version number mismatches }; namespace diff_impl { PWIZ_API_DECL void diff(const std::string& a, const std::string& b, std::string& a_b, std::string& b_a, const BaseDiffConfig& config); // special handling for strings which are likely // to differ only by a trailing version number PWIZ_API_DECL void diff_ids(const std::string& a, const std::string& b, std::string& a_b, std::string& b_a, const BaseDiffConfig& config); PWIZ_API_DECL void diff(const boost::logic::tribool& a, const boost::logic::tribool& b, boost::logic::tribool& a_b, boost::logic::tribool& b_a, const BaseDiffConfig& config); PWIZ_API_DECL void diff(const CV& a, const CV& b, CV& a_b, CV& b_a, const BaseDiffConfig& config); PWIZ_API_DECL void diff(CVID a, CVID b, CVID& a_b, CVID& b_a, const BaseDiffConfig& config); PWIZ_API_DECL void diff(const CVParam& a, const CVParam& b, CVParam& a_b, CVParam& b_a, const BaseDiffConfig& config); PWIZ_API_DECL void diff(const UserParam& a, const UserParam& b, UserParam& a_b, UserParam& b_a, const BaseDiffConfig& config); PWIZ_API_DECL void diff(const ParamContainer& a, const ParamContainer& b, ParamContainer& a_b, ParamContainer& b_a, const BaseDiffConfig& config); PWIZ_API_DECL void diff(const ParamGroup& a, const ParamGroup& b, ParamGroup& a_b, ParamGroup& b_a, const BaseDiffConfig& config); } // namespace diff_impl /// /// Calculate diffs of objects in a ProteoWizard data model hierarchy. /// /// A diff between two objects a and b calculates the set differences /// a\b and b\a. /// /// The Diff struct acts as a functor, but also stores the /// results of the diff calculation. /// /// The bool conversion operator is provided to indicate whether /// the two objects are different (either a\b or b\a is non-empty). /// /// object_type requirements: /// object_type a; /// a.empty(); /// pwiz::data::diff::diff(const object_type& a, const object_type& b, object_result_type& a_b, object_result_type& b_a); /// /// config_type must be pwiz::data::diff::BaseDiffConfig or derived from it /// template struct Diff { Diff(const config_type& config = config_type()) : config_(config) {} Diff(const object_type& a, const object_type& b, const config_type& config = config_type()) : config_(config) { diff_impl::diff(a, b, a_b, b_a, config_); } object_result_type a_b; object_result_type b_a; /// conversion to bool, with same semantics as *nix diff command: /// true == different /// false == not different operator bool() {return !(a_b.empty() && b_a.empty());} Diff& operator()(const object_type& a, const object_type& b) { diff_impl::diff(a, b, a_b, b_a, config_); return *this; } private: config_type config_; }; template std::string diff_string(const diff_type& diff) { std::ostringstream os; textwriter_type write(os, 1); if (!diff.a_b.empty()) { os << "+\n"; write(diff.a_b); } if (!diff.b_a.empty()) { os << "-\n"; write(diff.b_a); } return os.str(); } /// stream insertion of Diff results template std::ostream& operator<<(std::ostream& os, const Diff& diff) { textwriter_type write(os, 1); if (!diff.a_b.empty()) { os << "+\n"; write(diff.a_b); } if (!diff.b_a.empty()) { os << "-\n"; write(diff.b_a); } return os; } namespace diff_impl { template void diff_string(const string_type& a, const string_type& b, string_type& a_b, string_type& b_a) { a_b.clear(); b_a.clear(); if (a != b) { a_b = a; b_a = b; } } template void diff_char(const char_type& a, const char_type& b, char_type& a_b, char_type& b_a) { a_b = 0; b_a = 0; if (a != b) { a_b = a; b_a = b; } } template void diff_integral(const integral_type& a, const integral_type& b, integral_type& a_b, integral_type& b_a, const BaseDiffConfig& config) { a_b = integral_type(); b_a = integral_type(); if (a != b) { a_b = static_cast(a); b_a = static_cast(b); } } template void diff_floating(const floating_type& a, const floating_type& b, floating_type& a_b, floating_type& b_a, const BaseDiffConfig& config) { a_b = 0; b_a = 0; if (fabs(a - b) > config.precision + std::numeric_limits::epsilon()) { a_b = fabs(a - b); b_a = fabs(a - b); } } /// measure maximum relative difference between elements in the vectors template floating_type maxdiff(const std::vector& a, const std::vector& b) { if (a.size() != b.size()) throw std::runtime_error("[Diff::maxdiff()] Sizes differ."); typename std::vector::const_iterator i = a.begin(); typename std::vector::const_iterator j = b.begin(); floating_type max = 0; for (; i!=a.end(); ++i, ++j) { floating_type denominator = std::min(*i, *j); if (denominator == 0) denominator = 1; floating_type current = fabs(*i - *j)/denominator; if (max < current) max = current; } return max; } template void vector_diff(const std::vector& a, const std::vector& b, std::vector& a_b, std::vector& b_a) { // calculate set differences of two vectors a_b.clear(); b_a.clear(); for (typename std::vector::const_iterator it=a.begin(); it!=a.end(); ++it) if (std::find(b.begin(), b.end(), *it) == b.end()) a_b.push_back(*it); for (typename std::vector::const_iterator it=b.begin(); it!=b.end(); ++it) if (std::find(a.begin(), a.end(), *it) == a.end()) b_a.push_back(*it); } template struct HasID { const std::string& id_; HasID(const std::string& id) : id_(id) {} bool operator()(const boost::shared_ptr& objectPtr) {return objectPtr->id == id_;} }; template class Same { public: Same(const object_type& object, const config_type& config) : mine_(object), config_(config) {} bool operator()(const object_type& yours) { // true iff yours is the same as mine return !Diff(mine_, yours, config_); } private: const object_type& mine_; const config_type& config_; }; template void vector_diff_diff(const std::vector& a, const std::vector& b, std::vector& a_b, std::vector& b_a, const config_type& config) { // calculate set differences of two vectors, using diff on each object a_b.clear(); b_a.clear(); for (typename std::vector::const_iterator it=a.begin(); it!=a.end(); ++it) if (std::find_if(b.begin(), b.end(), Same(*it, config)) == b.end()) a_b.push_back(*it); for (typename std::vector::const_iterator it=b.begin(); it!=b.end(); ++it) if (std::find_if(a.begin(), a.end(), Same(*it, config)) == a.end()) b_a.push_back(*it); } template class SameDeep { public: SameDeep(const object_type& object, const config_type& config) : mine_(object), config_(config) {} bool operator()(const boost::shared_ptr& yours) { // true iff yours is the same as mine return !Diff(mine_, *yours, config_); } private: const object_type& mine_; const config_type& config_; }; template void vector_diff_deep(const std::vector< boost::shared_ptr >& a, const std::vector< boost::shared_ptr >& b, std::vector< boost::shared_ptr >& a_b, std::vector< boost::shared_ptr >& b_a, const config_type& config) { // calculate set differences of two vectors of ObjectPtrs (deep compare using diff) a_b.clear(); b_a.clear(); config_type quick_config(config); quick_config.partialDiffOK = true; // for fastest check in SameDeep for (typename std::vector< boost::shared_ptr >::const_iterator it=a.begin(); it!=a.end(); ++it) if (std::find_if(b.begin(), b.end(), SameDeep(**it, quick_config)) == b.end()) a_b.push_back(*it); for (typename std::vector< boost::shared_ptr >::const_iterator it=b.begin(); it!=b.end(); ++it) if (std::find_if(a.begin(), a.end(), SameDeep(**it, quick_config)) == a.end()) b_a.push_back(*it); } template void ptr_diff(const boost::shared_ptr& a, const boost::shared_ptr& b, boost::shared_ptr& a_b, boost::shared_ptr& b_a, const config_type& config) { if (!a.get() && !b.get()) return; boost::shared_ptr a_temp = a.get() ? a : boost::shared_ptr(new object_type); boost::shared_ptr b_temp = b.get() ? b : boost::shared_ptr(new object_type); if (!a_b.get()) a_b = boost::shared_ptr(new object_type); if (!b_a.get()) b_a = boost::shared_ptr(new object_type); diff(*a_temp, *b_temp, *a_b, *b_a, config); if (a_b->empty()) a_b = boost::shared_ptr(); if (b_a->empty()) b_a = boost::shared_ptr(); } } // namespace diff_impl } // namespace data } // namespace pwiz #endif // _DIFF_STD_HPP_ pwiz/pwiz/data/common/BinaryIndexStreamTest.cpp0000664000175100017510000001555512664775620023713 0ustar teamcityteamcity00000000000000// // $Id: BinaryIndexStreamTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "BinaryIndexStream.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include "boost/thread/thread.hpp" #include "boost/thread/barrier.hpp" using namespace pwiz::util; using namespace pwiz::data; ostream* os_ = 0; void test() { if (os_) cout << "Testing BinaryIndexStream (single thread)" << endl; shared_ptr indexStreamPtr(new stringstream); // test initial creation and usage of the index stream { vector entries; for (size_t i=0; i < 10; ++i) { Index::Entry entry; entry.id = lexical_cast(i); entry.index = i; entry.offset = i*100; entries.push_back(entry); } BinaryIndexStream index(indexStreamPtr); unit_assert(index.size() == 0); unit_assert(!index.find("42").get()); unit_assert(!index.find(42).get()); index.create(entries); unit_assert(index.size() == 10); for (size_t i=0; i < 10; ++i) { Index::EntryPtr entryPtr = index.find(i); unit_assert(entryPtr.get()); unit_assert(entryPtr->id == lexical_cast(i)); unit_assert(entryPtr->index == i); unit_assert(entryPtr->offset == Index::stream_offset(i*100)); entryPtr = index.find(entryPtr->id); unit_assert(entryPtr.get()); unit_assert(entryPtr->id == lexical_cast(i)); unit_assert(entryPtr->index == i); unit_assert(entryPtr->offset == Index::stream_offset(i*100)); } unit_assert(!index.find("42").get()); unit_assert(!index.find(42).get()); } // test re-use of an existing index stream { BinaryIndexStream index(indexStreamPtr); unit_assert(index.size() == 10); unit_assert(!index.find("42").get()); unit_assert(!index.find(42).get()); for (size_t i=0; i < 10; ++i) { Index::EntryPtr entryPtr = index.find(i); unit_assert(entryPtr.get()); unit_assert(entryPtr->id == lexical_cast(i)); unit_assert(entryPtr->index == i); unit_assert(entryPtr->offset == Index::stream_offset(i*100)); entryPtr = index.find(entryPtr->id); unit_assert(entryPtr.get()); unit_assert(entryPtr->id == lexical_cast(i)); unit_assert(entryPtr->index == i); unit_assert(entryPtr->offset == Index::stream_offset(i*100)); } unit_assert(!index.find("42").get()); unit_assert(!index.find(42).get()); } // test creating a new, smaller index in an existing index stream { vector entries; for (size_t i=0; i < 5; ++i) { Index::Entry entry; entry.id = lexical_cast(i); entry.index = i; entry.offset = i*100; entries.push_back(entry); } BinaryIndexStream index(indexStreamPtr); unit_assert(index.size() == 10); index.create(entries); unit_assert(index.size() == 5); for (size_t i=0; i < 5; ++i) { Index::EntryPtr entryPtr = index.find(i); unit_assert(entryPtr.get()); unit_assert(entryPtr->id == lexical_cast(i)); unit_assert(entryPtr->index == i); unit_assert(entryPtr->offset == Index::stream_offset(i*100)); entryPtr = index.find(entryPtr->id); unit_assert(entryPtr.get()); unit_assert(entryPtr->id == lexical_cast(i)); unit_assert(entryPtr->index == i); unit_assert(entryPtr->offset == Index::stream_offset(i*100)); } unit_assert(!index.find("5").get()); unit_assert(!index.find(5).get()); } } void testThreadSafetyWorker(boost::barrier* testBarrier, BinaryIndexStream* testIndex) { testBarrier->wait(); // wait until all threads have started BinaryIndexStream& index = *testIndex; try { for (size_t i=0; i < 10; ++i) { Index::EntryPtr entryPtr = index.find(i); unit_assert(entryPtr.get()); unit_assert(entryPtr->id == lexical_cast(i)); unit_assert(entryPtr->index == i); unit_assert(entryPtr->offset == Index::stream_offset(i*100)); entryPtr = index.find(entryPtr->id); unit_assert(entryPtr.get()); unit_assert(entryPtr->id == lexical_cast(i)); unit_assert(entryPtr->index == i); unit_assert(entryPtr->offset == Index::stream_offset(i*100)); } unit_assert(!index.find("42").get()); unit_assert(!index.find(42).get()); } catch (exception& e) { cerr << e.what() << endl; } catch (...) { cerr << "Caught unknown exception." << endl; } } void testThreadSafety() { if (os_) cout << "Testing BinaryIndexStream (multithreaded)" << endl; shared_ptr indexStreamPtr(new stringstream); // create a shared index stream vector entries; for (size_t i=0; i < 10; ++i) { Index::Entry entry; entry.id = lexical_cast(i); entry.index = i; entry.offset = i*100; entries.push_back(entry); } BinaryIndexStream index(indexStreamPtr); index.create(entries); unit_assert(index.size() == 10); // create workers to test using the stream const int testThreadCount = 100; boost::barrier testBarrier(testThreadCount); boost::thread_group testThreadGroup; for (int i=0; i < testThreadCount; ++i) testThreadGroup.add_thread(new boost::thread(&testThreadSafetyWorker, &testBarrier, &index)); testThreadGroup.join_all(); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); testThreadSafety(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/common/diff_std.cpp0000664000175100017510000001730112664775620021234 0ustar teamcityteamcity00000000000000// // $Id: diff_std.hpp 1656 2009-12-30 20:54:17Z chambm $ // // // Original author: Robert Burke // // Copyright 2009 Spielberg Family Center for Applied Proteomics // University of Southern California, Los Angeles, California 90033 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "diff_std.hpp" #include "pwiz/utility/misc/String.hpp" namespace pwiz { namespace data { namespace diff_impl { PWIZ_API_DECL void diff(const std::string& a, const std::string& b, std::string& a_b, std::string& b_a, const BaseDiffConfig& config) { diff_string(a, b, a_b, b_a); } // special string matching for ids, which // tend to have versions embedded at the end PWIZ_API_DECL void diff_ids(const std::string& a, const std::string& b, std::string& a_b, std::string& b_a, const BaseDiffConfig& config) { if (config.ignoreVersions && (a != b)) { // look for x.x.x at the of each string int aa,bb; int ndotsa=0; int ndotsb=0; for (aa=a.length();aa--;) { if (a[aa]=='.') ndotsa++; else if (!isdigit(a[aa])) break; } for (bb=b.length();bb--;) { if (b[bb]=='.') ndotsb++; else if (!isdigit(b[bb])) break; } if ((2==ndotsa) && (2==ndotsb) && (bb > 0) && (aa > 0) && (a.substr(0,aa) == b.substr(0,bb))) return; } diff_string(a, b, a_b, b_a); } PWIZ_API_DECL void diff(const boost::logic::tribool& a, const boost::logic::tribool& b, boost::logic::tribool& a_b, boost::logic::tribool& b_a, const BaseDiffConfig& config) { if (a != b) { a_b = a; b_a = b; } else { a_b = boost::logic::indeterminate; b_a = boost::logic::indeterminate; } } PWIZ_API_DECL void diff(const CV& a, const CV& b, CV& a_b, CV& b_a, const BaseDiffConfig& config) { diff_string(a.URI, b.URI, a_b.URI, b_a.URI); diff_string(a.id, b.id, a_b.id, b_a.id); diff_string(a.fullName, b.fullName, a_b.fullName, b_a.fullName); if (!config.ignoreVersions) diff_string(a.version, b.version, a_b.version, b_a.version); } PWIZ_API_DECL void diff(CVID a, CVID b, CVID& a_b, CVID& b_a, const BaseDiffConfig& config) { if (a!=b) { a_b = a; b_a = b; } else { a_b = b_a = CVID_Unknown; } } PWIZ_API_DECL void diff(const CVParam& a, const CVParam& b, CVParam& a_b, CVParam& b_a, const BaseDiffConfig& config) { diff(a.cvid, b.cvid, a_b.cvid, b_a.cvid, config); // start with a cheap string compare if (a.value==b.value) { a_b.value.clear(); b_a.value.clear(); } else { bool asString = false; // lexical_cast is happy to read "1.1" as "1" - and "1.9" the same way if ((std::string::npos == a.value.find_first_of(".eE")) && (std::string::npos == b.value.find_first_of(".eE"))) // any float-like chars? { try { // compare as ints if possible int ia = lexical_cast(a.value); int ib = lexical_cast(b.value); if (ia != ib) { a_b.value = lexical_cast(ia); b_a.value = lexical_cast(ib); } else // watch for something like "1a" vs "1b" { if ((std::string::npos == a.value.find_first_not_of("0123456789")) && (std::string::npos == b.value.find_first_not_of("0123456789"))) { a_b.value.clear(); b_a.value.clear(); } else { asString = true; } } } catch (boost::bad_lexical_cast&) { asString = true; } } else { // use precision to compare floating point values try { double aValue = lexical_cast(a.value); double bValue = lexical_cast(b.value); double a_bValue, b_aValue; diff_floating(aValue, bValue, a_bValue, b_aValue, config); if (a_bValue || b_aValue) { a_b.value = lexical_cast(a_bValue); b_a.value = lexical_cast(b_aValue); } else { a_b.value.clear(); b_a.value.clear(); } } catch (boost::bad_lexical_cast&) { asString = true; } } if (asString) { diff_string(a.value, b.value, a_b.value, b_a.value); } } diff(a.units, b.units, a_b.units, b_a.units, config); // provide names for context if (!a_b.empty() && a_b.cvid==CVID_Unknown) a_b.cvid = a.cvid; if (!b_a.empty() && b_a.cvid==CVID_Unknown) b_a.cvid = b.cvid; } PWIZ_API_DECL void diff(const UserParam& a, const UserParam& b, UserParam& a_b, UserParam& b_a, const BaseDiffConfig& config) { diff_string(a.name, b.name, a_b.name, b_a.name); diff_string(a.value, b.value, a_b.value, b_a.value); diff_string(a.type, b.type, a_b.type, b_a.type); diff(a.units, b.units, a_b.units, b_a.units, config); // provide names for context if (!a_b.empty() && a_b.name.empty()) a_b.name = a.name; if (!b_a.empty() && b_a.name.empty()) b_a.name = b.name; } PWIZ_API_DECL void diff(const ParamContainer& a, const ParamContainer& b, ParamContainer& a_b, ParamContainer& b_a, const BaseDiffConfig& config) { vector_diff_deep(a.paramGroupPtrs, b.paramGroupPtrs, a_b.paramGroupPtrs, b_a.paramGroupPtrs, config); vector_diff_diff(a.cvParams, b.cvParams, a_b.cvParams, b_a.cvParams, config); vector_diff_diff(a.userParams, b.userParams, a_b.userParams, b_a.userParams, config); } PWIZ_API_DECL void diff(const ParamGroup& a, const ParamGroup& b, ParamGroup& a_b, ParamGroup& b_a, const BaseDiffConfig& config) { diff(static_cast(a), b, a_b, b_a, config); diff_ids(a.id, b.id, a_b.id, b_a.id, config); // provide id for context if (!a_b.empty() || !b_a.empty()) { a_b.id = a.id; b_a.id = b.id; } } } // namespace diff_impl } // namespace data } // namespace pwiz pwiz/pwiz/data/common/ParamTypes.hpp0000664000175100017510000002425212664775620021547 0ustar teamcityteamcity00000000000000// // $Id: ParamTypes.hpp 6212 2014-05-20 22:38:47Z pcbrefugee $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PARAMTYPES_HPP_ #define _PARAMTYPES_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/utility/misc/optimized_lexical_cast.hpp" #include "cv.hpp" #include #include #include namespace pwiz { namespace data { using namespace pwiz::cv; /// represents a tag-value pair, where the tag comes from the controlled vocabulary struct PWIZ_API_DECL CVParam { CVID cvid; std::string value; CVID units; CVParam(CVID _cvid, float _value, CVID _units = CVID_Unknown) : cvid(_cvid), value(boost::lexical_cast(_value)), units(_units) {} CVParam(CVID _cvid, double _value, CVID _units = CVID_Unknown) : cvid(_cvid), value(boost::lexical_cast(_value)), units(_units) {} CVParam(CVID _cvid, int _value, CVID _units = CVID_Unknown) : cvid(_cvid), value(boost::lexical_cast(_value)), units(_units) {} CVParam(CVID _cvid, long _value, CVID _units = CVID_Unknown) : cvid(_cvid), value(boost::lexical_cast(_value)), units(_units) {} CVParam(CVID _cvid, unsigned int _value, CVID _units = CVID_Unknown) : cvid(_cvid), value(boost::lexical_cast(_value)), units(_units) {} CVParam(CVID _cvid, unsigned long _value, CVID _units = CVID_Unknown) : cvid(_cvid), value(boost::lexical_cast(_value)), units(_units) {} CVParam(CVID _cvid, std::string _value, CVID _units = CVID_Unknown) : cvid(_cvid), value(_value), units(_units) {} CVParam(CVID _cvid, const char* _value, CVID _units = CVID_Unknown) : cvid(_cvid), value(_value), units(_units) {} /// special case for bool (no lexical_cast) CVParam(CVID _cvid, bool _value, CVID _units = CVID_Unknown) : cvid(_cvid), value(_value ? "true" : "false"), units(_units) {} /// constructor for non-valued CVParams CVParam(CVID _cvid = CVID_Unknown) : cvid(_cvid), units(CVID_Unknown) {} ~CVParam(); /// templated value access with type conversion template value_type valueAs() const { return !value.empty() ? boost::lexical_cast(value) : boost::lexical_cast(0); } /// convenience function to return string for the cvid std::string name() const; /// convenience function to return string for the units std::string unitsName() const; /// convenience function to return time in seconds (throws if units not a time unit) double timeInSeconds() const; /// convenience function to return value without scientific notation (throws if not a double) std::string valueFixedNotation() const; /// equality operator bool operator==(const CVParam& that) const { return that.cvid==cvid && that.value==value && that.units==units; } /// inequality operator bool operator!=(const CVParam& that) const { return !operator==(that); } bool empty() const {return cvid==CVID_Unknown && value.empty() && units==CVID_Unknown;} }; /// functor for finding CVParam with specified exact CVID in a collection of CVParams: /// /// vector::const_iterator it = /// find_if(params.begin(), params.end(), CVParamIs(MS_software)); /// struct PWIZ_API_DECL CVParamIs { CVParamIs(CVID cvid) : cvid_(cvid) {} bool operator()(const CVParam& param) const {return param.cvid == cvid_;} CVID cvid_; }; /// functor for finding children of a specified CVID in a collection of CVParams: /// /// vector::const_iterator it = /// find_if(params.begin(), params.end(), CVParamIsChildOf(MS_software)); /// struct PWIZ_API_DECL CVParamIsChildOf { CVParamIsChildOf(CVID cvid) : cvid_(cvid) {} bool operator()(const CVParam& param) const {return cvIsA(param.cvid, cvid_);} CVID cvid_; }; /// special case for bool (no lexical_cast) /// (this has to be outside the class for gcc 3.4, inline for msvc) template<> inline bool CVParam::valueAs() const { return value == "true"; } PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const CVParam& param); /// Uncontrolled user parameters (essentially allowing free text). Before using these, one should verify whether there is an appropriate CV term available, and if so, use the CV term instead struct PWIZ_API_DECL UserParam { /// the name for the parameter. std::string name; /// the value for the parameter, where appropriate. std::string value; /// the datatype of the parameter, where appropriate (e.g.: xsd:float). std::string type; /// an optional CV parameter for the unit term associated with the value, if any (e.g. MS_electron_volt). CVID units; UserParam(const std::string& _name = "", const std::string& _value = "", const std::string& _type = "", CVID _units = CVID_Unknown); ~UserParam(); UserParam(const UserParam& other); UserParam& operator=(const UserParam& rhs); /// convenience function to return time in seconds (throws if units not a time unit) double timeInSeconds() const; /// Templated value access with type conversion template value_type valueAs() const { return !value.empty() ? boost::lexical_cast(value) : boost::lexical_cast(0); } /// returns true iff name, value, type, and units are all empty bool empty() const; /// returns true iff name, value, type, and units are all pairwise equal bool operator==(const UserParam& that) const; /// returns !(this==that) bool operator!=(const UserParam& that) const; }; // Special case for bool (outside the class for gcc 3.4, and inline for msvc) template<> inline bool UserParam::valueAs() const { return value == "true"; } struct ParamGroup; typedef boost::shared_ptr ParamGroupPtr; /// The base class for elements that may contain cvParams, userParams, or paramGroup references struct PWIZ_API_DECL ParamContainer { /// a collection of references to ParamGroups std::vector paramGroupPtrs; /// a collection of controlled vocabulary terms std::vector cvParams; /// a collection of uncontrolled user terms std::vector userParams; /// finds cvid in the container: /// - returns first CVParam result such that (result.cvid == cvid); /// - if not found, returns CVParam(CVID_Unknown) /// - recursive: looks into paramGroupPtrs CVParam cvParam(CVID cvid) const; /// finds child of cvid in the container: /// - returns first CVParam result such that (result.cvid is_a cvid); /// - if not found, CVParam(CVID_Unknown) /// - recursive: looks into paramGroupPtrs CVParam cvParamChild(CVID cvid) const; /// finds all children of cvid in the container: /// - returns all CVParam results such that (result.cvid is_a cvid); /// - if not found, empty vector /// - recursive: looks into paramGroupPtrs std::vector cvParamChildren(CVID cvid) const; /// returns true iff cvParams contains exact cvid (recursive) bool hasCVParam(CVID cvid) const; /// returns true iff cvParams contains a child (is_a) of cvid (recursive) bool hasCVParamChild(CVID cvid) const; /// finds UserParam with specified name /// - returns UserParam() if name not found /// - not recursive: looks only at local userParams UserParam userParam(const std::string&) const; /// set/add a CVParam (not recursive) void set(CVID cvid, const std::string& value = "", CVID units = CVID_Unknown); /// set/add a CVParam (not recursive) void set(CVID cvid, double value, CVID units = CVID_Unknown); /// set/add a CVParam (not recursive) void set(CVID cvid, int value, CVID units = CVID_Unknown); /// set/add a CVParam (not recursive) template void set(CVID cvid, value_type value, CVID units = CVID_Unknown) { set(cvid, boost::lexical_cast(value), units); } /// returns true iff the element contains no params or param groups bool empty() const; /// clears the collections void clear(); /// returns true iff this and that have the exact same cvParams and userParams /// - recursive: looks into paramGroupPtrs bool operator==(const ParamContainer& that) const; /// returns !(this==that) bool operator!=(const ParamContainer& that) const; }; /// special case for bool (outside the class for gcc 3.4, and inline for msvc) template<> inline void ParamContainer::set(CVID cvid, bool value, CVID units) { set(cvid, (value ? "true" : "false"), units); } /// A collection of CVParam and UserParam elements that can be referenced from elsewhere in this mzML document by using the 'paramGroupRef' element in that location to reference the 'id' attribute value of this element. struct PWIZ_API_DECL ParamGroup : public ParamContainer { /// the identifier with which to reference this ReferenceableParamGroup. std::string id; ParamGroup(const std::string& _id = ""); /// returns true iff the element contains no params or param groups bool empty() const; }; } // namespace data } // namespace pwiz #endif // _PARAMTYPES_HPP_ pwiz/pwiz/data/common/obotest.cpp0000664000175100017510000002004112664775620021124 0ustar teamcityteamcity00000000000000// // $Id: obotest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "obo.hpp" #include "pwiz/utility/misc/unit.hpp" #include #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::data; using namespace pwiz::util; ostream* os_ = 0; const char* oboText_ = "format-version: 1.0\n" "date: 01:10:2007 23:46\n" "saved-by: deutsch\n" "auto-generated-by: OBO-Edit 1.101\n" "default-namespace: PSI-MS\n" "\n" "[Term]\t\n" "id: MS:0000000\t\n" "name: MZ controlled vocabularies\t\n" "def: \"MZ controlled vocabularies.\" [PSI:MS]\t\n" "\n" "[Term]\r\n" "id: MS:0000001\r\n" "name: sample number\r\n" "def: \"A reference number relevant to the sample under study.\" [PSI:MS]\r\n" "relationship: part_of MS:1000548 ! sample attribute\r\n" "\n" "[Term]\n" "id: MS:0000011\n" "name: mass resolution\n" "def: \"The maximum m/z value at which two peaks can be resolved, according to one of the standard measures.\" [PSI:MS]\n" "is_a: MS:1000503 ! scan attribute\n" "\n" "[Term]\n" "id: MS:1000025\n" "name: magnetic field strength\n" "def: \"A property of space that produces a force on a charged particle equal to qv x B where q is the particle charge and v its velocity.\" [PSI:MS]\n" "related_synonym: \"Magnetic Field\" []\n" "exact_synonym: \"B\" []\n" "is_a: MS:1000480 ! mass analyzer attribute\n" "\n" "[Term]\n" "id: MS:1000030\n" "name: vendor\n" "def: \"Name of instrument vendor, replaced by MS:1000031 Model From Vendor.\" [PSI:MS]\n" "is_obsolete: true\n" "\n" "[Term]\n" "id: MS:1000035\n" "name: obsolete by definition\n" "def: \"OBSOLETE description\" [PSI:MS]\n" "\n" "[Term]\n" "id: MS:1001272\n" "name: (?<=R)(?\\!P)\n" "\n" "[Term]\n" "id: MS:1001280\n" "name: accuracy\n" "def: \"Accuracy is the degree of conformity of a measured mass to its actual value.\" [PSI:MS]\n" "xref: value-type:xsd\\:float \"The allowed value-type for this CV term.\"\n" "is_a: MS:1000480 ! mass analyzer attribute\n" "relationship: has_units MS:1000040 ! m/z\n" "relationship: has_units UO:0000169 ! parts per million\n" "\n" "[Term]\n" "id: MS:1001303\n" "name: Arg-C\n" "is_a: MS:1001045 ! cleavage agent name\n" "relationship: has_regexp MS:1001272 ! (?<=R)(?!P)\n" "\n" // OBO format 1.2 "[Term]\n" "id: MS:2000025\n" "name: magnetic field strength\n" "def: \"A property of space that produces a force on a charged particle equal to qv x B where q is the particle charge and v its velocity.\" [PSI:MS]\n" "synonym: \"B\" EXACT []\n" "synonym: \"Magnetic Field\" RELATED []\n" "is_a: MS:1000480 ! mass analyzer attribute\n" "\n" "[Term]\n" "id: MS:9999999\n" "name: unit\n" "namespace: unit.ontology\n" "def: \"description\" [ignore this Wikipedia:Wikipedia \"http://www.wikipedia.org/\"]\n" "\n" "[Term]\n" "id: MS:99999999\n" "name: Label:2H(4)+GlyGly\n" "def: \"Ubiquitination 2H4 lysine\" []\n" "property_value: record_id=\"853\"\n" "property_value: delta_mono_mass=\"118.068034\"\n" "property_value: delta_avge_mass=\"118.1273\"\n" "property_value: delta_composition=\"H(2) 2H(4) C(4) N(2) O(2)\"\n" "property_value: spec_group1=\"1\"\n" "property_value: spec_hidden_1=\"1\"\n" "property_value: spec_site_1=\"K\"\n" "property_value: spec_position_1=\"Anywhere\"\n" "property_value: spec_classification_1=\"Post-translational\"\n" "is_a: MS:0 ! unimod root node\n" "\n" ; void test() { const string& filename = "obotest_temp.txt"; ofstream temp(filename.c_str()); temp << oboText_ << endl; temp.close(); OBO obo(filename); if (os_) *os_ << obo << endl; unit_assert(obo.filename == filename); unit_assert(obo.header.size() == 5); unit_assert(obo.prefix == "MS"); unit_assert(obo.terms.size() == 12); // including obsolete terms set::const_iterator term = obo.terms.begin(); unit_assert(term->prefix == "MS"); unit_assert(term->id == 0); unit_assert(term->name == "MZ controlled vocabularies"); unit_assert(term->def == "MZ controlled vocabularies."); unit_assert(term->parentsPartOf.empty()); unit_assert(term->parentsIsA.empty()); ++term; unit_assert(term->id == 1); unit_assert(term->name == "sample number"); unit_assert(term->parentsPartOf.size() == 1); unit_assert(term->parentsPartOf[0] == 1000548); ++term; unit_assert(term->id == 11); unit_assert(term->name == "mass resolution"); unit_assert(term->parentsIsA.size() == 1); unit_assert(term->parentsIsA[0] == 1000503); ++term; unit_assert(term->id == 1000025); unit_assert(term->exactSynonyms.size() == 1); unit_assert(term->exactSynonyms[0] == "B"); ++term; unit_assert(term->id == 1000030); unit_assert(term->isObsolete); ++term; unit_assert(term->id == 1000035); unit_assert(term->isObsolete); // test unescaping "\!" ++term; unit_assert(term->id == 1001272); unit_assert(term->name == "(?<=R)(?!P)"); // test other relationships ++term; unit_assert(term->id == 1001280); unit_assert(term->relations.size() == 2); unit_assert(term->relations.begin()->first == "has_units"); unit_assert(term->relations.begin()->second.first == "MS"); unit_assert(term->relations.begin()->second.second == 1000040); unit_assert(term->relations.rbegin()->second.first == "UO"); unit_assert(term->relations.rbegin()->second.second == 169); ++term; unit_assert(term->id == 1001303); unit_assert(term->name == "Arg-C"); unit_assert(term->relations.size() == 1); unit_assert(term->relations.begin()->first == "has_regexp"); unit_assert(term->relations.begin()->second.first == "MS"); unit_assert(term->relations.begin()->second.second == 1001272); // test term with OBO 1.2 synonym format ++term; unit_assert(term->id == 2000025); unit_assert(term->exactSynonyms.size() == 1); unit_assert(term->exactSynonyms[0] == "B"); // test term with [stuff to ignore] ++term; unit_assert(term->id == 9999999); unit_assert(term->def == "description"); ++term; // test property values unit_assert(term->id == 99999999); unit_assert(term->name == "Label:2H(4)+GlyGly"); unit_assert(term->def == "Ubiquitination 2H4 lysine"); unit_assert(term->propertyValues.size() == 9); unit_assert(term->propertyValues.find("record_id")->second == "853"); unit_assert(term->propertyValues.find("delta_mono_mass")->second == "118.068034"); unit_assert(term->propertyValues.find("delta_avge_mass")->second == "118.1273"); unit_assert(term->propertyValues.find("delta_composition")->second == "H(2) 2H(4) C(4) N(2) O(2)"); unit_assert(term->propertyValues.find("spec_classification_1")->second == "Post-translational"); boost::filesystem::remove(filename); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/common/cv.cpp0000664000175100017510000613057412664775620020100 0ustar teamcityteamcity00000000000000// // $Id: cv.cpp 8981 2015-10-12 20:20:31Z chambm $ // // // Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // This file was generated by cvgen. // // Do not edit this file! Your changes will be lost next time cvgen is run - // see pwiz/scripts/misc/update_cv.bat for info on how that works. // Instead, edit cvgen.cpp itself, or the cv.inl include file if adding static // code or data. // #define PWIZ_SOURCE #include "cv.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/utility/misc/Singleton.hpp" namespace pwiz { namespace cv { namespace { struct TermInfo { CVID cvid; const char* id; const char* name; const char* def; bool isObsolete; }; const TermInfo termInfos_[] = { {CVID_Unknown, "??:0000000", "CVID_Unknown", "CVID_Unknown", false}, {MS_Proteomics_Standards_Initiative_Mass_Spectrometry_Vocabularies, "MS:0000000", "Proteomics Standards Initiative Mass Spectrometry Vocabularies", "Proteomics Standards Initiative Mass Spectrometry Vocabularies.", false}, {MS_sample_number, "MS:1000001", "sample number", "A reference number relevant to the sample under study.", false}, {MS_sample_name, "MS:1000002", "sample name", "A reference string relevant to the sample under study.", false}, {MS_sample_state, "MS:1000003", "sample state", "The chemical phase of a pure sample, or the state of a mixed sample.", false}, {MS_sample_mass, "MS:1000004", "sample mass", "Total mass of sample used.", false}, {MS_sample_volume, "MS:1000005", "sample volume", "Total volume of solution used.", false}, {MS_sample_concentration, "MS:1000006", "sample concentration", "Concentration of sample in picomol/ul, femtomol/ul or attomol/ul solution used.", false}, {MS_inlet_type, "MS:1000007", "inlet type", "The nature of the sample inlet.", false}, {MS_ionization_type, "MS:1000008", "ionization type", "The method by which gas phase ions are generated from the sample.", false}, {MS_ionization_mode_OBSOLETE, "MS:1000009", "ionization mode", "Whether positive or negative ions are selected for analysis by the spectrometer.", true}, {MS_analyzer_type_OBSOLETE, "MS:1000010", "analyzer type", "The common name of the particular analyzer stage being described. Synonym of mass analyzer, should be obsoleted.", true}, {MS_mass_resolution, "MS:1000011", "mass resolution", "Smallest mass difference between two equal magnitude peaks so that the valley between them is a specified fraction of the peak height.", false}, {MS_resolution_measurement_method, "MS:1000012", "resolution measurement method", "Which of the available standard measures is used to define whether two peaks are separate.", false}, {MS_resolution_type_OBSOLETE, "MS:1000013", "resolution type", "Specify the nature of resolution for the mass analyzer. Resolution is usually either constant with respect to m/z or proportional to m/z.", true}, {MS_accuracy, "MS:1000014", "accuracy", "Accuracy is the degree of conformity of a measured mass to its actual value.", false}, {MS_scan_rate, "MS:1000015", "scan rate", "Rate in Th/sec for scanning analyzers.", false}, {MS_scan_start_time, "MS:1000016", "scan start time", "The time that an analyzer started a scan, relative to the start of the MS run.", false}, {MS_Scan_Function_OBSOLETE, "MS:1000017", "Scan Function", "Describes the type of mass analysis being performed. Two primary modes are: typical acquisition over a range of masses (Mass Scan), and Selected Ion Detection. The primary difference is that Selected Ion Detection produces a single value for the signal at the selected mass rather than producing a mass spectrum.", true}, {MS_scan_direction, "MS:1000018", "scan direction", "Direction in terms of m/z of the scan for scanning analyzers (low to high, or high to low).", false}, {MS_scan_law, "MS:1000019", "scan law", "Describes the function in control of the m/z scan (for scanning instruments). Commonly the scan function is linear, but in principle any function can be used.", false}, {MS_scanning_method_OBSOLETE, "MS:1000020", "scanning method", "Describes the acquisition data type produced by a tandem mass spectrometry experiment.", true}, {MS_reflectron_state, "MS:1000021", "reflectron state", "Status of the reflectron, turned on or off.", false}, {MS_TOF_Total_Path_Length, "MS:1000022", "TOF Total Path Length", "The length of the field free drift space in a time of flight mass spectrometer.", false}, {MS_isolation_width_OBSOLETE, "MS:1000023", "isolation width", "The total width (i.e. not half for plus-or-minus) of the gate applied around a selected precursor ion.", true}, {MS_final_MS_exponent, "MS:1000024", "final MS exponent", "Final MS level achieved when performing PFF with the ion trap (e.g. MS E10).", false}, {MS_magnetic_field_strength, "MS:1000025", "magnetic field strength", "A property of space that produces a force on a charged particle equal to qv x B where q is the particle charge and v its velocity.", false}, {MS_detector_type, "MS:1000026", "detector type", "Type of detector used in the mass spectrometer.", false}, {MS_detector_acquisition_mode, "MS:1000027", "detector acquisition mode", "Method by which detector signal is acquired by the data system.", false}, {MS_detector_resolution, "MS:1000028", "detector resolution", "The resolving power of the detector to detect the smallest difference between two ions so that the valley between them is a specified fraction of the peak height.", false}, {MS_sampling_frequency, "MS:1000029", "sampling frequency", "The rate of signal sampling (measurement) with respect to time.", false}, {MS_vendor_OBSOLETE, "MS:1000030", "vendor", "Name of instrument vendor.", true}, {MS_instrument_model, "MS:1000031", "instrument model", "Instrument model name not including the vendor's name.", false}, {MS_customization, "MS:1000032", "customization", "Free text description of a single customization made to the instrument; for several modifications, use several entries.", false}, {MS_deisotoping, "MS:1000033", "deisotoping", "The removal of isotope peaks to represent the fragment ion as one data point and is commonly done to reduce complexity. It is done in conjunction with the charge state deconvolution.", false}, {MS_charge_deconvolution, "MS:1000034", "charge deconvolution", "The determination of the mass of an ion based on the mass spectral peaks that represent multiple-charge ions.", false}, {MS_peak_picking, "MS:1000035", "peak picking", "Spectral peak processing conducted on the acquired data to convert profile data to centroided data.", false}, {MS_scan_mode_OBSOLETE, "MS:1000036", "scan mode", "OBSOLETE.", true}, {MS_polarity_OBSOLETE, "MS:1000037", "polarity", "Terms to describe the polarity setting of the instrument.", true}, {MS_minute_OBSOLETE, "MS:1000038", "minute", "Acquisition time in minutes.", true}, {MS_second_OBSOLETE, "MS:1000039", "second", "Acquisition time in seconds.", true}, {MS_m_z, "MS:1000040", "m/z", "Three-character symbol m/z is used to denote the quantity formed by dividing the mass of an ion in unified atomic mass units by its charge number (regardless of sign). The symbol is written in italicized lower case letters with no spaces. Note 1: The term mass-to-charge-ratio is deprecated. Mass-to-charge ratio has been used for the abscissa of a mass spectrum, although the quantity measured is not the quotient of the ion's mass to its electric charge. The three-character symbol m/z is recommended for the quantity that is the independent variable in a mass spectrum Note 2: The proposed unit thomson (Th) is deprecated.", false}, {MS_charge_state, "MS:1000041", "charge state", "The charge state of the ion, single or multiple and positive or negatively charged.", false}, {MS_peak_intensity, "MS:1000042", "peak intensity", "Intensity of ions as measured by the height or area of a peak in a mass spectrum.", false}, {MS_intensity_unit, "MS:1000043", "intensity unit", "Intensity units are commonly arbitrary. Detected in counts per second (cps) when using counting detectors, but measured in volts when using analog detectors.", false}, {MS_dissociation_method, "MS:1000044", "dissociation method", "Fragmentation method used for dissociation or fragmentation.", false}, {MS_collision_energy, "MS:1000045", "collision energy", "Energy for an ion experiencing collision with a stationary gas particle resulting in dissociation of the ion.", false}, {MS_energy_unit_OBSOLETE, "MS:1000046", "energy unit", "Energy units are represented in either eV or Joules.", true}, {MS_emulsion, "MS:1000047", "emulsion", "State if the sample is in emulsion form.", false}, {MS_gaseous_sample_state, "MS:1000048", "gaseous sample state", "State if the sample is in gaseous form.", false}, {MS_liquid_sample_state, "MS:1000049", "liquid sample state", "State if the sample is in liquid form.", false}, {MS_solid_sample_state, "MS:1000050", "solid sample state", "State if the sample is in solid form.", false}, {MS_solution, "MS:1000051", "solution", "State if the sample is in solution form.", false}, {MS_suspension, "MS:1000052", "suspension", "State if the sample is in suspension form.", false}, {MS_sample_batch, "MS:1000053", "sample batch", "Sample batch lot identifier.", false}, {MS_chromatography_OBSOLETE, "MS:1000054", "chromatography", "Chromatographic conditions used to obtain the sample.", true}, {MS_continuous_flow_fast_atom_bombardment, "MS:1000055", "continuous flow fast atom bombardment", "Fast atom bombardment ionization in which the analyte in solution is entrained in a flowing liquid matrix.", false}, {MS_direct_inlet, "MS:1000056", "direct inlet", "The sample is directly inserted into the ion source, usually on the end of a heatable probe.", false}, {MS_electrospray_inlet, "MS:1000057", "electrospray inlet", "Inlet used for introducing the liquid sample into an electrospray ionization source.", false}, {MS_flow_injection_analysis, "MS:1000058", "flow injection analysis", "Sample is directly injected or infused into the ionization source.", false}, {MS_inductively_coupled_plasma, "MS:1000059", "inductively coupled plasma", "A gas discharge ion source in which the energy to the plasma is supplied by electromagnetic induction.", false}, {MS_infusion, "MS:1000060", "infusion", "The continuous flow of solution of a sample into the ionization source.", false}, {MS_jet_separator, "MS:1000061", "jet separator", "A device that separates carrier gas from gaseous analyte molecules on the basis of diffusivity.", false}, {MS_membrane_separator, "MS:1000062", "membrane separator", "A device to separate carrier molecules from analyte molecules on the basis of ease of diffusion across a semipermeable membrane.", false}, {MS_moving_belt, "MS:1000063", "moving belt", "Continuous moving surface in the form of a belt which passes through an ion source carrying analyte molecules.", false}, {MS_moving_wire, "MS:1000064", "moving wire", "Continuous moving surface in the form of a wire which passes through an ion source carrying analyte molecules.", false}, {MS_open_split, "MS:1000065", "open split", "A division of flowing stream of liquid into two streams.", false}, {MS_particle_beam, "MS:1000066", "particle beam", "Method for generating ions from a solution of an analyte.", false}, {MS_reservoir, "MS:1000067", "reservoir", "A sample inlet method involving a reservoir.", false}, {MS_septum, "MS:1000068", "septum", "A disc composed of a flexible material that seals the entrance to the reservoir. Can also be entrance to the vacuum chamber.", false}, {MS_thermospray_inlet, "MS:1000069", "thermospray inlet", "A method for generating gas phase ions from a solution of an analyte by rapid heating of the sample.", false}, {MS_atmospheric_pressure_chemical_ionization, "MS:1000070", "atmospheric pressure chemical ionization", "Chemical ionization that takes place at atmospheric pressure as opposed to the reduced pressure is normally used for chemical ionization.", false}, {MS_chemical_ionization, "MS:1000071", "chemical ionization", "The formation of a new ion by the reaction of a neutral species with an ion. The process may involve transfer of an electron, a proton or other charged species between the reactants. When a positive ion results from chemical ionization the term may be used without qualification. When a negative ion results the term negative ion chemical ionization should be used. Note that this term is not synonymous with chemi-ionization.", false}, {MS_Electronic_Ionization_OBSOLETE, "MS:1000072", "Electronic Ionization", "The ionization of an atom or molecule by electrons that are typically accelerated to energies between 50 and 150 eV. Usually 70 eV electrons are used to produce positive ions. The term 'electron impact' is not recommended.", true}, {MS_electrospray_ionization, "MS:1000073", "electrospray ionization", "A process in which ionized species in the gas phase are produced from an analyte-containing solution via highly charged fine droplets, by means of spraying the solution from a narrow-bore needle tip at atmospheric pressure in the presence of a high electric field. When a pressurized gas is used to aid in the formation of a stable spray, the term pneumatically assisted electrospray ionization is used. The term ion spray is not recommended.", false}, {MS_fast_atom_bombardment_ionization, "MS:1000074", "fast atom bombardment ionization", "The ionization of any species by the interaction of a focused beam of neutral atoms having a translational energy of several thousand eV with a sample that is typically dissolved in a solvent matrix. See also secondary ionization.", false}, {MS_matrix_assisted_laser_desorption_ionization, "MS:1000075", "matrix-assisted laser desorption ionization", "The formation of gas-phase ions from molecules that are present in a solid or solvent matrix that is irradiated with a pulsed laser. See also laser desorption/ionization.", false}, {MS_negative_ion_mode_OBSOLETE, "MS:1000076", "negative ion mode", "OBSOLETE.", true}, {MS_positive_ion_mode_OBSOLETE, "MS:1000077", "positive ion mode", "OBSOLETE.", true}, {MS_axial_ejection_linear_ion_trap, "MS:1000078", "axial ejection linear ion trap", "A linear ion trap mass spectrometer where ions are ejected along the axis of the analyzer.", false}, {MS_fourier_transform_ion_cyclotron_resonance_mass_spectrometer, "MS:1000079", "fourier transform ion cyclotron resonance mass spectrometer", "A mass spectrometer based on the principle of ion cyclotron resonance in which an ion in a magnetic field moves in a circular orbit at a frequency characteristic of its m/z value. Ions are coherently excited to a larger radius orbit using a pulse of radio frequency energy and their image charge is detected on receiver plates as a time domain signal. Fourier transformation of the time domain signal results in a frequency domain signal which is converted to a mass spectrum based in the inverse relationship between frequency and m/z.", false}, {MS_magnetic_sector, "MS:1000080", "magnetic sector", "A device that produces a magnetic field perpendicular to a charged particle beam that deflects the beam to an extent that is proportional to the particle momentum per unit charge. For a monoenergetic beam, the deflection is proportional to m/z.", false}, {MS_quadrupole, "MS:1000081", "quadrupole", "A mass spectrometer that consists of four parallel rods whose centers form the corners of a square and whose opposing poles are connected. The voltage applied to the rods is a superposition of a static potential and a sinusoidal radio frequency potential. The motion of an ion in the x and y dimensions is described by the Matthieu equation whose solutions show that ions in a particular m/z range can be transmitted along the z axis.", false}, {MS_quadrupole_ion_trap, "MS:1000082", "quadrupole ion trap", "Quadrupole Ion Trap mass analyzer captures the ions in a three dimensional ion trap and then selectively ejects them by varying the RF and DC potentials.", false}, {MS_radial_ejection_linear_ion_trap, "MS:1000083", "radial ejection linear ion trap", "A linear ion trap mass spectrometer where ions are ejected along the radius of the analyzer.", false}, {MS_time_of_flight, "MS:1000084", "time-of-flight", "Instrument that separates ions by m/z in a field-free region after acceleration to a fixed acceleration energy.", false}, {MS_baseline, "MS:1000085", "baseline", "An attribute of resolution when recording the detector response in absence of the analyte.", false}, {MS_full_width_at_half_maximum, "MS:1000086", "full width at half-maximum", "A measure of resolution represented as width of the peak at half peak height.", false}, {MS_ten_percent_valley, "MS:1000087", "ten percent valley", "An attribute of resolution when the ratio between adjacent signals is 10% of the signal height.", false}, {MS_constant_OBSOLETE, "MS:1000088", "constant", "When resolution is constant with respect to m/z.", true}, {MS_proportional_OBSOLETE, "MS:1000089", "proportional", "When resolution is proportional with respect to m/z.", true}, {MS_mass_scan_OBSOLETE, "MS:1000090", "mass scan", "A variation of instrument where a selected mass is scanned.", true}, {MS_selected_ion_detection_OBSOLETE, "MS:1000091", "selected ion detection", "Please see Single Ion Monitoring.", true}, {MS_decreasing_m_z_scan, "MS:1000092", "decreasing m/z scan", "High to low direction in terms of m/z of the scan for scanning analyzers.", false}, {MS_increasing_m_z_scan, "MS:1000093", "increasing m/z scan", "Low to high direction in terms of m/z of the scan for scanning analyzers.", false}, {MS_exponential, "MS:1000094", "exponential", "The mass scan is done in exponential mode.", false}, {MS_linear_OBSOLETE, "MS:1000095", "linear", "The mass scan is done in linear mode.", true}, {MS_quadratic, "MS:1000096", "quadratic", "The mass scan is done in quadratic mode.", false}, {MS_constant_neutral_mass_loss_OBSOLETE, "MS:1000097", "constant neutral mass loss", "A spectrum formed of all product ions that have been produced with a selected m/z decrement from any precursor ions. The spectrum shown correlates to the precursor ion spectrum. See also neutral loss spectrum.", true}, {MS_multiple_ion_monitoring_OBSOLETE, "MS:1000098", "multiple ion monitoring", "Data acquired when monitoring the ion current of a few specific m/z values. Remap to MS:1000205 -Selected Ion Monitoring.", true}, {MS_multiple_reaction_monitoring_OBSOLETE, "MS:1000099", "multiple reaction monitoring", "This term is not recommended. See Selected Reaction Monitoring.", true}, {MS_precursor_ion_scan_OBSOLETE, "MS:1000100", "precursor ion scan", "The specific scan function or process that will record a precursor ion spectrum.", true}, {MS_product_ion_scan_OBSOLETE, "MS:1000101", "product ion scan", "The specific scan function or process that records product ion spectrum.", true}, {MS_single_ion_monitoring_OBSOLETE, "MS:1000102", "single ion monitoring", "The operation of a mass spectrometer to monitor a single ion rather than scanning entire mass spectrum.", true}, {MS_single_reaction_monitoring_OBSOLETE, "MS:1000103", "single reaction monitoring", "This term is not recommended. See Selected Reaction Monitoring.", true}, {MS_None____OBSOLETE, "MS:1000104", "None ??", "None.", true}, {MS_reflectron_off, "MS:1000105", "reflectron off", "Reflectron is off.", false}, {MS_reflectron_on, "MS:1000106", "reflectron on", "Reflectron is on.", false}, {MS_channeltron, "MS:1000107", "channeltron", "A horn-shaped (or cone-shaped) continuous dynode particle multiplier. The ion strikes the inner surface of the device and induces the production of secondary electrons that in turn impinge on the inner surfaces to produce more secondary electrons. This avalanche effect produces an increase in signal in the final measured current pulse.", false}, {MS_conversion_dynode_electron_multiplier, "MS:1000108", "conversion dynode electron multiplier", "A surface that is held at high potential so that ions striking the surface produce electrons that are subsequently detected.", false}, {MS_conversion_dynode_photomultiplier, "MS:1000109", "conversion dynode photomultiplier", "A detector in which ions strike a conversion dynode to produce electrons that in turn generate photons through a phosphorescent screen that are detected by a photomultiplier.", false}, {MS_daly_detector, "MS:1000110", "daly detector", "Detector consisting of a conversion dynode, scintillator and photomultiplier. The metal knob at high potential emits secondary electrons when ions impinge on the surface. The secondary electrons are accelerated onto the scintillator that produces light that is then detected by the photomultiplier detector.", false}, {MS_electron_multiplier_tube, "MS:1000111", "electron multiplier tube", "A device to amplify the current of a beam or packet of charged particles or photons by incidence upon the surface of an electrode to produce secondary electrons.", false}, {MS_faraday_cup, "MS:1000112", "faraday cup", "A conducting cup or chamber that intercepts a charged particle beam and is electrically connected to a current measuring device.", false}, {MS_focal_plane_array, "MS:1000113", "focal plane array", "An array of detectors for spatially disperse ion beams in which all ions simultaneously impinge on the detector plane.", false}, {MS_microchannel_plate_detector, "MS:1000114", "microchannel plate detector", "A thin plate that contains a closely spaced array of channels that each act as a continuous dynode particle multiplier. A charged particle, fast neutral particle, or photon striking the plate causes a cascade of secondary electrons that ultimately exits the opposite side of the plate.", false}, {MS_multi_collector, "MS:1000115", "multi-collector", "A detector system commonly used in inductively coupled plasma mass spectrometers.", false}, {MS_photomultiplier, "MS:1000116", "photomultiplier", "A detector for conversion of the ion/electron signal into photon(s) which are then amplified and detected.", false}, {MS_analog_digital_converter, "MS:1000117", "analog-digital converter", "Analog-to-digital converter (abbreviated ADC, A/D or A to D) is an electronic integrated circuit (i/c) that converts continuous signals to discrete digital numbers.", false}, {MS_pulse_counting, "MS:1000118", "pulse counting", "Definition to do.", false}, {MS_time_digital_converter, "MS:1000119", "time-digital converter", "A device for converting a signal of sporadic pluses into a digital representation of their time indices.", false}, {MS_transient_recorder, "MS:1000120", "transient recorder", "A detector acquisition mode used for detecting transient signals.", false}, {MS_SCIEX_instrument_model, "MS:1000121", "SCIEX instrument model", "The brand of instruments from the joint venture between Applied Biosystems and MDS Analytical Technologies (formerly MDS SCIEX). Previously branded as \\\"Applied Biosystems|MDS SCIEX\\\".", false}, {MS_Bruker_Daltonics_instrument_model, "MS:1000122", "Bruker Daltonics instrument model", "Bruker Daltonics' instrument model.", false}, {MS_IonSpec_instrument_model, "MS:1000123", "IonSpec instrument model", "IonSpec corporation instrument model.", false}, {MS_Shimadzu_instrument_model, "MS:1000124", "Shimadzu instrument model", "Shimadzu corporation instrument model.", false}, {MS_Thermo_Finnigan_instrument_model, "MS:1000125", "Thermo Finnigan instrument model", "ThermoFinnigan from Thermo Electron Corporation instrument model.", false}, {MS_Waters_instrument_model, "MS:1000126", "Waters instrument model", "Waters Corporation instrument model.", false}, {MS_centroid_spectrum, "MS:1000127", "centroid spectrum", "Processing of profile data to produce spectra that contains discrete peaks of zero width. Often used to reduce the size of dataset.", false}, {MS_profile_spectrum, "MS:1000128", "profile spectrum", "A profile mass spectrum is created when data is recorded with ion current (counts per second) on one axis and mass/charge ratio on another axis.", false}, {MS_negative_scan, "MS:1000129", "negative scan", "Polarity of the scan is negative.", false}, {MS_positive_scan, "MS:1000130", "positive scan", "Polarity of the scan is positive.", false}, {MS_number_of_detector_counts, "MS:1000131", "number of detector counts", "The number of counted events observed in one or a group of elements of a detector.", false}, {MS_percent_of_base_peak, "MS:1000132", "percent of base peak", "The magnitude of a peak or measurement element expressed in terms of the percentage of the magnitude of the base peak intensity.", false}, {MS_collision_induced_dissociation, "MS:1000133", "collision-induced dissociation", "The dissociation of an ion after collisional excitation. The term collisional-activated dissociation is not recommended.", false}, {MS_plasma_desorption, "MS:1000134", "plasma desorption", "The ionization of material in a solid sample by bombarding it with ionic or neutral atoms formed as a result of the fission of a suitable nuclide, typically 252Cf. Synonymous with fission fragment ionization.", false}, {MS_post_source_decay, "MS:1000135", "post-source decay", "A technique specific to reflectron time-of-flight mass spectrometers where product ions of metastable transitions or collision-induced dissociations generated in the drift tube prior to entering the reflectron are m/z separated to yield product ion spectra.", false}, {MS_surface_induced_dissociation, "MS:1000136", "surface-induced dissociation", "Fragmentation that results from the collision of an ion with a surface.", false}, {MS_electron_volt_OBSOLETE, "MS:1000137", "electron volt", "A non-SI unit of energy (eV) defined as the energy acquired by a particle containing one unit of charge through a potential difference of one volt. An electron-volt is equal to 1.602 176 53(14) x 10^-19 J.", true}, {MS_normalized_collision_energy, "MS:1000138", "normalized collision energy", "Instrument setting, expressed in percent, for adjusting collisional energies of ions in an effort to provide equivalent excitation of all ions.", false}, {MS_4000_QTRAP, "MS:1000139", "4000 QTRAP", "Applied Biosystems/MDS SCIEX Q 4000 TRAP MS.", false}, {MS_4700_Proteomics_Analyzer, "MS:1000140", "4700 Proteomics Analyzer", "Applied Biosystems/MDS SCIEX 4700 Proteomics Analyzer MS.", false}, {MS_apex_IV, "MS:1000141", "apex IV", "Bruker Daltonics' apex IV: ESI, MALDI, Nanospray, APCI, APPI, Qh-FT_ICR.", false}, {MS_apex_Q, "MS:1000142", "apex Q", "Bruker Daltonics' apex Q: ESI, MALDI, Nanospray, APCI, APPI, Qh-FT_ICR.", false}, {MS_API_150EX, "MS:1000143", "API 150EX", "Applied Biosystems/MDS SCIEX API 150EX MS.", false}, {MS_API_150EX_Prep, "MS:1000144", "API 150EX Prep", "Applied Biosystems/MDS SCIEX API 150EX Prep MS.", false}, {MS_API_2000, "MS:1000145", "API 2000", "Applied Biosystems/MDS SCIEX API 2000 MS.", false}, {MS_API_3000, "MS:1000146", "API 3000", "Applied Biosystems/MDS SCIEX API 3000 MS.", false}, {MS_API_4000, "MS:1000147", "API 4000", "Applied Biosystems/MDS SCIEX API 4000 MS.", false}, {MS_autoflex_II, "MS:1000148", "autoflex II", "Bruker Daltonics' autoflex II: MALDI TOF.", false}, {MS_autoflex_TOF_TOF, "MS:1000149", "autoflex TOF/TOF", "Bruker Daltonics' autoflex TOF/TOF MS: MALDI TOF.", false}, {MS_Auto_Spec_Ultima_NT, "MS:1000150", "Auto Spec Ultima NT", "Waters AutoSpec Ultima NT MS.", false}, {MS_BioTOF_II, "MS:1000151", "BioTOF II", "Bruker Daltonics' BioTOF II: ESI TOF.", false}, {MS_BioTOF_Q, "MS:1000152", "BioTOF-Q", "Bruker Daltonics' BioTOF-Q: ESI Q-TOF.", false}, {MS_DELTA_plusAdvantage, "MS:1000153", "DELTA plusAdvantage", "ThermoFinnigan DELTA plusAdvantage MS.", false}, {MS_DELTAplusXP, "MS:1000154", "DELTAplusXP", "ThermoFinnigan DELTAplusXP MS.", false}, {MS_ELEMENT2_OBSOLETE, "MS:1000155", "ELEMENT2", "ThermoFinnigan ELEMENT2 MS.", true}, {MS_esquire_4000, "MS:1000156", "esquire 4000", "Bruker Daltonics' esquire 4000: linear ion trap, ESI, MALDI, Nanospray, APCI, APPI.", false}, {MS_esquire_6000, "MS:1000157", "esquire 6000", "Bruker Daltonics' esquire 6000: linear ion trap, ESI, MALDI, Nanospray, APCI, APPI.", false}, {MS_explorer, "MS:1000158", "explorer", "IonSpec Explorer MS.", false}, {MS_GCT, "MS:1000159", "GCT", "Waters oa-ToF based GCT.", false}, {MS_HCT, "MS:1000160", "HCT", "Bruker Daltonics' HCT: ESI Q-TOF, Nanospray, APCI, APPI.", false}, {MS_HCTplus, "MS:1000161", "HCTplus", "Bruker Daltonics' HCTplus: ESI Q-TOF, Nanospray, APCI, APPI.", false}, {MS_HiRes_ESI, "MS:1000162", "HiRes ESI", "IonSpec HiResESI MS.", false}, {MS_HiRes_MALDI, "MS:1000163", "HiRes MALDI", "IonSpec HiResMALDI MS.", false}, {MS_IsoPrime, "MS:1000164", "IsoPrime", "Waters IsoPrime MS.", false}, {MS_IsoProbe, "MS:1000165", "IsoProbe", "Waters IsoProbe MS.", false}, {MS_IsoProbe_T, "MS:1000166", "IsoProbe T", "Waters IsoProbe T MS.", false}, {MS_LCQ_Advantage, "MS:1000167", "LCQ Advantage", "ThermoFinnigan LCQ Advantage MS.", false}, {MS_LCQ_Classic, "MS:1000168", "LCQ Classic", "ThermoFinnigan LCQ Classic MS.", false}, {MS_LCQ_Deca_XP_Plus, "MS:1000169", "LCQ Deca XP Plus", "ThermoFinnigan LCQ Deca XP Plus MS.", false}, {MS_M_LDI_L, "MS:1000170", "M@LDI L", "Waters oa-ToF based MALDI L.", false}, {MS_M_LDI_LR, "MS:1000171", "M@LDI LR", "Waters oa-ToF based MALDI LR.", false}, {MS_MAT253, "MS:1000172", "MAT253", "ThermoFinnigan MAT253 MS.", false}, {MS_MAT900XP, "MS:1000173", "MAT900XP", "ThermoFinnigan MAT900XP MS.", false}, {MS_MAT900XP_Trap, "MS:1000174", "MAT900XP Trap", "ThermoFinnigan MAT900XP Trap MS.", false}, {MS_MAT95XP, "MS:1000175", "MAT95XP", "ThermoFinnigan MAT95XP MS.", false}, {MS_MAT95XP_Trap, "MS:1000176", "MAT95XP Trap", "ThermoFinnigan MAT95XP Trap MS.", false}, {MS_microflex, "MS:1000177", "microflex", "Bruker Daltonics' microflex: MALDI TOF.", false}, {MS_microTOF_LC, "MS:1000178", "microTOF LC", "Bruker Daltonics' microTOF LC: ESI TOF, Nanospray, APCI, APPI.", false}, {MS_neptune, "MS:1000179", "neptune", "ThermoFinnigan NEPTUNE MS.", false}, {MS_NG_5400, "MS:1000180", "NG-5400", "Waters NG-5400 MS.", false}, {MS_OMEGA, "MS:1000181", "OMEGA", "IonSpec OMEGA MS.", false}, {MS_OMEGA_2001, "MS:1000182", "OMEGA-2001", "IonSpec OMEGA-2001 MS.", false}, {MS_OmniFlex, "MS:1000183", "OmniFlex", "Bruker Daltonics' OmniFlex: MALDI TOF.", false}, {MS_Platform_ICP, "MS:1000184", "Platform ICP", "Waters Platform ICP MS.", false}, {MS_PolarisQ, "MS:1000185", "PolarisQ", "ThermoFinnigan PolarisQ MS.", false}, {MS_proteomics_solution_1, "MS:1000186", "proteomics solution 1", "Applied Biosystems/MDS SCIEX Proteomics Solution 1 MS.", false}, {MS_Q_TRAP, "MS:1000187", "Q TRAP", "Applied Biosystems/MDS SCIEX Q TRAP MS.", false}, {MS_Q_Tof_micro, "MS:1000188", "Q-Tof micro", "Waters oa-ToF based Q-Tof micro.", false}, {MS_Q_Tof_ultima, "MS:1000189", "Q-Tof ultima", "Waters oa-ToF based Q-Tof Ultima.", false}, {MS_QSTAR, "MS:1000190", "QSTAR", "Applied Biosystems/MDS SCIEX QSTAR MS.", false}, {MS_quattro_micro, "MS:1000191", "quattro micro", "Waters oa-ToF based micro.", false}, {MS_Quattro_UItima, "MS:1000192", "Quattro UItima", "Waters oa-ToF based Ultima.", false}, {MS_Surveyor_MSQ, "MS:1000193", "Surveyor MSQ", "ThermoFinnigan Surveyor MSQ MS.", false}, {MS_SymBiot_I, "MS:1000194", "SymBiot I", "Applied Biosystems/MDS SCIEX SymBiot I MS.", false}, {MS_SymBiot_XVI, "MS:1000195", "SymBiot XVI", "Applied Biosystems/MDS SCIEX SymBiot XVI MS.", false}, {MS_TEMPUS_TOF, "MS:1000196", "TEMPUS TOF", "ThermoFinnigan TEMPUS TOF MS.", false}, {MS_TRACE_DSQ, "MS:1000197", "TRACE DSQ", "ThermoFinnigan TRACE DSQ MS.", false}, {MS_TRITON, "MS:1000198", "TRITON", "ThermoFinnigan TRITON MS.", false}, {MS_TSQ_Quantum, "MS:1000199", "TSQ Quantum", "ThermoFinnigan TSQ Quantum MS.", false}, {MS_ultima, "MS:1000200", "ultima", "IonSpec Ultima MS.", false}, {MS_ultraflex, "MS:1000201", "ultraflex", "Bruker Daltonics' ultraflex: MALDI TOF.", false}, {MS_ultraflex_TOF_TOF, "MS:1000202", "ultraflex TOF/TOF", "Bruker Daltonics' ultraflex TOF/TOF: MALDI TOF.", false}, {MS_Voyager_DE_PRO, "MS:1000203", "Voyager-DE PRO", "Applied Biosystems/MDS SCIEX Voyager-DE PRO MS.", false}, {MS_Voyager_DE_STR, "MS:1000204", "Voyager-DE STR", "Applied Biosystems/MDS SCIEX Voyager-DE STR MS.", false}, {MS_selected_ion_monitoring, "MS:1000205", "selected ion monitoring", "The operation of a mass spectrometer in which the intensities of several specific m/z values are recorded rather than the entire mass spectrum.", false}, {MS_selected_reaction_monitoring, "MS:1000206", "selected reaction monitoring", "Data acquired from specific product ions corresponding to m/z selected precursor ions recorded via multiple stages of mass spectrometry. Selected reaction monitoring can be performed in time or in space.", false}, {MS_accurate_mass_OBSOLETE, "MS:1000207", "accurate mass", "An experimentally determined mass that is can be to determine a unique elemental formula. For ions less than 200 u, a measurement with 5 ppm accuracy is sufficient to determine the elemental composition.", true}, {MS_average_mass_OBSOLETE, "MS:1000208", "average mass", "The mass of an ion or molecule calculated using the average mass of each element weighted for its natural isotopic abundance.", true}, {MS_appearance_energy_OBSOLETE, "MS:1000209", "appearance energy", "The minimum energy that must be imparted to an atom or molecule to produce a specified ion. The term appearance potential is not recommended.", true}, {MS_base_peak, "MS:1000210", "base peak", "The peak in a mass spectrum that has the greatest intensity. This term may be applied to the spectra of pure substances or mixtures.", false}, {MS_OBSOLETE_charge_number_OBSOLETE, "MS:1000211", "OBSOLETE charge number", "OBSOLETE. The total charge on an ion divided by the electron charge e. OBSOLETED 2009-10-27 since this was viewed as a duplication of 00041 charge state.", true}, {MS_dalton_OBSOLETE, "MS:1000212", "dalton", "A non-SI unit of mass (symbol Da) that is equal to the unified atomic mass unit: 1.660 538 86(28) x 10^-27 kg.", true}, {MS_electron_affinity_OBSOLETE, "MS:1000213", "electron affinity", "The electron affinity of M is the minimum energy required for the process M- ? M + e where M- and M are in their ground rotational, vibrational and electronic states and the electron has zero kinetic energy.", true}, {MS_electron_energy_obsolete_OBSOLETE, "MS:1000214", "electron energy obsolete", "The potential difference through which electrons are accelerated before they are used to bring about electron ionization.", true}, {MS_exact_mass_OBSOLETE, "MS:1000215", "exact mass", "The calculated mass of an ion or molecule containing a single isotope of each atom.", true}, {MS_field_free_region, "MS:1000216", "field-free region", "A section of a mass spectrometer in which there are no electric or magnetic fields.", false}, {MS_ionization_cross_section_OBSOLETE, "MS:1000217", "ionization cross section", "A measure of the probability that a given ionization process will occur when an atom or molecule interacts with a photon, electron, atom or molecule.", true}, {MS_ionization_efficiency_OBSOLETE, "MS:1000218", "ionization efficiency", "The ratio of the number of ions formed to the number of electrons, molecules or photons used.", true}, {MS_ionization_energy_OBSOLETE, "MS:1000219", "ionization energy", "The minimum energy required to remove an electron from an atom or molecule to produce a positive ion.", true}, {MS_isotope_dilution_mass_spectrometry_OBSOLETE, "MS:1000220", "isotope dilution mass spectrometry", "A quantitative mass spectrometry technique in which an isotopically enriched compound is used as an internal standard.", true}, {MS_magnetic_deflection, "MS:1000221", "magnetic deflection", "The deflection of charged particles in a magnetic field due to a force equal to qvxB where q is the particle charge, v its velocity and B the magnetic field. Magnetic deflection of an ion beam is used for m/z separation in a magnetic sector mass spectrometer.", false}, {MS_mass_defect_OBSOLETE, "MS:1000222", "mass defect", "The difference between the monoisotopic and nominal mass of a molecule or atom.", true}, {MS_mass_number_OBSOLETE, "MS:1000223", "mass number", "The sum of the protons and neutrons in an atom, molecule or ion.", true}, {MS_molecular_mass_OBSOLETE, "MS:1000224", "molecular mass", "The mass of one mole of a molecular substance (6.022 1415(10) x 10^23 molecules).", true}, {MS_monoisotopic_mass_OBSOLETE, "MS:1000225", "monoisotopic mass", "The mass of an ion or molecule calculated using the mass of the most abundant isotope of each element.", true}, {MS_molecular_beam_mass_spectrometry_OBSOLETE, "MS:1000226", "molecular beam mass spectrometry", "A mass spectrometry technique in which the sample is introduced into the mass spectrometer as a molecular beam.", true}, {MS_multiphoton_ionization, "MS:1000227", "multiphoton ionization", "Photoionization of an atom or molecule in which in two or more photons are absorbed.", false}, {MS_nitrogen_rule_OBSOLETE, "MS:1000228", "nitrogen rule", "An organic molecule containing the elements C, H, O, S, P, or halogen has an odd nominal mass if it contains an odd number of nitrogen atoms.", true}, {MS_nominal_mass_OBSOLETE, "MS:1000229", "nominal mass", "The mass of an ion or molecule calculated using the mass of the most abundant isotope of each element rounded to the nearest integer value.", true}, {MS_odd_electron_rule_OBSOLETE, "MS:1000230", "odd-electron rule", "Odd-electron ions may dissociate to form either odd or even-electron ions, whereas even-electron ions generally form even-electron fragment ions.", true}, {MS_peak, "MS:1000231", "peak", "A localized region of relatively large ion signal in a mass spectrum. Although peaks are often associated with particular ions, the terms peak and ion should not be used interchangeably.", false}, {MS_peak_intensity_OBSOLETE, "MS:1000232", "peak intensity", "The height or area of a peak in a mass spectrum.", true}, {MS_proton_affinity_OBSOLETE, "MS:1000233", "proton affinity", "The proton affinity of a species M is defined as the negative of the enthalpy change for the reaction M + H+ ->[M+H]+, where all species are in their ground rotational, vibrational and electronic states.", true}, {MS_mass_resolving_power_OBSOLETE, "MS:1000234", "mass resolving power", "In a mass spectrum, the observed mass divided by the difference between two masses that can be separated. The method by which delta m was obtained and the mass at which the measurement was made should be reported.", true}, {MS_total_ion_current_chromatogram, "MS:1000235", "total ion current chromatogram", "Chromatogram obtained by plotting the total ion current detected in each of a series of mass spectra recorded as a function of retention time.", false}, {MS_transmission, "MS:1000236", "transmission", "The ratio of the number of ions leaving a region of a mass spectrometer to the number entering that region.", false}, {MS_unified_atomic_mass_unit_OBSOLETE, "MS:1000237", "unified atomic mass unit", "A non-SI unit of mass (u) defined as one twelfth of ^12 C in its ground state and equal to 1.660 538 86(28) x 10^-27 kg.", true}, {MS_accelerator_mass_spectrometry_OBSOLETE, "MS:1000238", "accelerator mass spectrometry", "A mass spectrometry technique in which atoms extracted from a sample are ionized, accelerated to MeV energies and separated according to their momentum, charge and energy.", true}, {MS_atmospheric_pressure_matrix_assisted_laser_desorption_ionization, "MS:1000239", "atmospheric pressure matrix-assisted laser desorption ionization", "Matrix-assisted laser desorption ionization in which the sample target is at atmospheric pressure and the ions formed by the pulsed laser are sampled through a small aperture into the mass spectrometer.", false}, {MS_atmospheric_pressure_ionization, "MS:1000240", "atmospheric pressure ionization", "Any ionization process in which ions are formed in the gas phase at atmospheric pressure.", false}, {MS_Atmostpheric_Pressure_Photoionization_OBSOLETE, "MS:1000241", "Atmostpheric Pressure Photoionization", "Atmospheric pressure chemical ionization in which the reactant ions are generated by photo-ionization.", true}, {MS_blackbody_infrared_radiative_dissociation, "MS:1000242", "blackbody infrared radiative dissociation", "A special case of infrared multiphoton dissociation wherein excitation of the reactant ion is caused by absorption of infrared photons radiating from heated blackbody surroundings, which are usually the walls of a vacuum chamber. See also infrared multiphoton dissociation.", false}, {MS_charge_remote_fragmentation_OBSOLETE, "MS:1000243", "charge-remote fragmentation", "A fragmentation of an even-electron ion in which the cleaved bond is not adjacent to the apparent charge site.", true}, {MS_consecutive_reaction_monitoring_OBSOLETE_1000244, "MS:1000244", "consecutive reaction monitoring (MS:1000244)", "MSn experiment with three or more stages of m/z separation and in which a particular multi-step reaction path is monitored.", true}, {MS_charge_stripping, "MS:1000245", "charge stripping", "The reaction of a positive ion with an atom or molecule that results in the removal of one or more electrons from the ion.", false}, {MS_delayed_extraction, "MS:1000246", "delayed extraction", "The application of the accelerating voltage pulse after a time delay in desorption ionization from a surface. The extraction delay can produce energy focusing in a time-of-flight mass spectrometer.", false}, {MS_desorption_ionization, "MS:1000247", "desorption ionization", "The formation of ions from a solid or liquid material after the rapid vaporization of that sample.", false}, {MS_direct_insertion_probe, "MS:1000248", "direct insertion probe", "A device for introducing a solid or liquid sample into a mass spectrometer ion source for desorption ionization.", false}, {MS_direct_liquid_introduction, "MS:1000249", "direct liquid introduction", "The delivery of a liquid sample into a mass spectrometer for spray or desorption ionization.", false}, {MS_electron_capture_dissociation, "MS:1000250", "electron capture dissociation", "A process in which a multiply protonated molecules interacts with a low energy electrons. Capture of the electron leads the liberation of energy and a reduction in charge state of the ion with the production of the (M + nH) (n-1)+ odd electron ion, which readily fragments.", false}, {MS_even_electron_ion_OBSOLETE, "MS:1000251", "even-electron ion", "An ion containing no unpaired electrons in its ground electronic state, e.g. CH3+ in its ground state.", true}, {MS_electron_induced_excitation_in_organics_OBSOLETE, "MS:1000252", "electron-induced excitation in organics", "The reaction of an ion with an electron in which the translational energy of the collision is converted into internal energy of the ion.", true}, {MS_electron_multiplier, "MS:1000253", "electron multiplier", "A device to amplify the current of a beam or packet of charged particles or photons by incidence upon the surface of an electrode to produce secondary electrons. The secondary electrons are then accelerated to other electrodes or parts of a continuous electrode to produce further secondary electrons.", false}, {MS_electrostatic_energy_analyzer, "MS:1000254", "electrostatic energy analyzer", "A device consisting of conducting parallel plates, concentric cylinders or concentric spheres that separates charged particles according to their kinetic energy by means of an electric field that is constant in time.", false}, {MS_flowing_afterglow, "MS:1000255", "flowing afterglow", "An ion source immersed in a flow of helium or other inert buffer gas that carries the ions through a meter-long reactor at pressures around 100 Pa.", false}, {MS_high_field_asymmetric_waveform_ion_mobility_spectrometry_OBSOLETE, "MS:1000256", "high-field asymmetric waveform ion mobility spectrometry", "The separation of ions between two concentric cylindrical electrodes due to application of a high voltage asymmetric waveform whereby ions migrate towards one of the two electrodes depending on the ratio of the high- to low-field mobility of the ion.", true}, {MS_field_desorption, "MS:1000257", "field desorption", "The formation of gas-phase ions from a material deposited on a solid surface in the presence of a high electric field. Because this process may encompass ionization by field ionization or other mechanisms, it is not recommended as a synonym for field desorption ionization.", false}, {MS_field_ionization, "MS:1000258", "field ionization", "The removal of electrons from any species by interaction with a high electric field.", false}, {MS_glow_discharge_ionization, "MS:1000259", "glow discharge ionization", "The formation of ions in the gas phase and from solid samples at the cathode by application of a voltage to a low pressure gas.", false}, {MS_ion_kinetic_energy_spectrometry_OBSOLETE, "MS:1000260", "ion kinetic energy spectrometry", "A method of analysis in which a beam of ions is separated according to the ratio of its translational energy to charge.", true}, {MS_ion_mobility_spectrometry_OBSOLETE, "MS:1000261", "ion mobility spectrometry", "The separation of ions according to their velocity through a buffer gas under the influence of an electric field.", true}, {MS_infrared_multiphoton_dissociation, "MS:1000262", "infrared multiphoton dissociation", "Multiphoton ionization where the reactant ion dissociates as a result of the absorption of multiple infrared photons.", false}, {MS_isotope_ratio_mass_spectrometry_OBSOLETE, "MS:1000263", "isotope ratio mass spectrometry", "The measurement of the relative quantity of the different isotopes of an element in a material with a mass spectrometer.", true}, {MS_ion_trap, "MS:1000264", "ion trap", "A device for spatially confining ions using electric and magnetic fields alone or in combination.", false}, {MS_kinetic_energy_release_distribution_OBSOLETE, "MS:1000265", "kinetic energy release distribution", "Distribution of values of translational kinetic energy release for an ensemble of metastable ions undergoing a specific dissociation reaction.", true}, {MS_Laser_Desorption_OBSOLETE, "MS:1000266", "Laser Desorption", "The formation of ions through the interaction of a laser with a material or with gas-phase ions or molecules.", true}, {MS_mass_analyzed_ion_kinetic_energy_spectrometry_OBSOLETE, "MS:1000267", "mass analyzed ion kinetic energy spectrometry", "Spectra that are obtained from a sector mass spectrometer that incorporates at least one magnetic sector plus one electric sector in reverse geometry. The accelerating voltage, V, and the magnetic sector field, B, are set at fixed values to select the precursor ions, which are then allowed to dissociate or to react in a field free region between the two sectors. The kinetic energy product ions of m/z selected precursor ions is analyzed by scanning the electric sector field, E. The width of the product ion spectrum peaks is related to the kinetic energy release distribution (KERD) for the dissociation process.", true}, {MS_mass_spectrometry_OBSOLETE, "MS:1000268", "mass spectrometry", "The branch of science that deals with all aspects of mass spectrometers and the results obtained with these instruments.", true}, {MS_mass_spectrometry_mass_spectrometry_OBSOLETE, "MS:1000269", "mass spectrometry/mass spectrometry", "The acquisition, study and spectra of the electrically charged products or precursors of a m/z selected ion or ions.", true}, {MS_multiple_stage_mass_spectrometry_OBSOLETE, "MS:1000270", "multiple stage mass spectrometry", "Multiple stages of precursor ion m/z selection followed by product ion detection for successive progeny ions.", true}, {MS_Negative_Ion_chemical_ionization, "MS:1000271", "Negative Ion chemical ionization", "Chemical ionization that results in the formation of negative ions.", false}, {MS_neutralization_reionization_mass_spectrometry, "MS:1000272", "neutralization reionization mass spectrometry", "With this technique, m/z selected ions form neutrals by charge transfer to a collision gas or by dissociation. The neutrals are separated from the remaining ions and ionized in collisions with a second gas. This method is used to investigate reaction intermediates and other unstable species.", false}, {MS_photoionization, "MS:1000273", "photoionization", "The ionization of an atom or molecule by a photon, written M + h? ? M^+ + e. The term photon impact is not recommended.", false}, {MS_pyrolysis_mass_spectrometry, "MS:1000274", "pyrolysis mass spectrometry", "A mass spectrometry technique in which the sample is heated to the point of decomposition and the gaseous decomposition products are introduced into the ion source.", false}, {MS_collision_quadrupole, "MS:1000275", "collision quadrupole", "A transmission quadrupole to which an oscillating potential is applied so as to focus a beam of ions through a collision gas with no m/z separation.", false}, {MS_resonance_enhanced_multiphoton_ionization, "MS:1000276", "resonance enhanced multiphoton ionization", "Multiphoton ionization in which the ionization cross section is significantly enhanced because the energy of the incident photons is resonant with an intermediate excited state of the neutral species.", false}, {MS_residual_gas_analyzer_OBSOLETE, "MS:1000277", "residual gas analyzer", "A mass spectrometer used to measure the composition and pressure of gasses in an evacuated chamber.", true}, {MS_surface_enhanced_laser_desorption_ionization, "MS:1000278", "surface enhanced laser desorption ionization", "The formation of ionized species in the gas phase from analytes deposited on a particular surface substrate which is irradiated with a laser beam of which wavelength is absorbed by the surface. See also desorption/ionization on silicon and laser desorption/ionization.", false}, {MS_surface_enhanced_neat_desorption, "MS:1000279", "surface enhanced neat desorption", "Matrix-assisted laser desorption ionization in which the matrix is covalently linked to the target surface.", false}, {MS_suface_ionization_OBSOLETE, "MS:1000280", "suface ionization", "The ionization of a neutral species when it interacts with a solid surface with an appropriate work function and temperature.", true}, {MS_selected_ion_flow_tube, "MS:1000281", "selected ion flow tube", "A device in which m/z selected ions are entrained in an inert carrier gas and undergo ion-molecule reactions.", false}, {MS_sustained_off_resonance_irradiation, "MS:1000282", "sustained off-resonance irradiation", "A technique associated with Fourier transform ion cyclotron resonance (FT-ICR) mass spectrometry to carry out ion/neutral reactions such as low-energy collision-induced dissociation. A radio-frequency electric field of slightly off-resonance to the cyclotron frequency of the reactant ion cyclically accelerates and decelerates the reactant ion that is confined in the Penning ion trap. The ion's orbit does not exceed the dimensions of ion trap while the ion undergoes an ion/neutral species process that produces a high average translational energy for an extended time.", false}, {MS_Spark_Source_Mass_Spectrometry_OBSOLETE, "MS:1000283", "Spark Source Mass Spectrometry", "Mass spectrometry using spark ionization.", true}, {MS_stored_waveform_inverse_fourier_transform, "MS:1000284", "stored waveform inverse fourier transform", "A technique to create excitation waveforms for ions in FT-ICR mass spectrometer or Paul ion trap. An excitation waveform in the time-domain is generated by taking the inverse Fourier transform of an appropriate frequency-domain programmed excitation spectrum, in which the resonance frequencies of ions to be excited are included. This technique may be used for selection of precursor ions in MS2 experiments.", false}, {MS_total_ion_current, "MS:1000285", "total ion current", "The sum of all the separate ion currents carried by the ions of different m/z contributing to a complete mass spectrum or in a specified m/z range of a mass spectrum.", false}, {MS_time_lag_focusing, "MS:1000286", "time lag focusing", "Energy focusing in a time-of-flight mass spectrometer that is accomplished by introducing a time delay between the formation of the ions and the application of the accelerating voltage pulse.", false}, {MS_time_of_flight_mass_spectrometer_OBSOLETE, "MS:1000287", "time-of-flight mass spectrometer", "An instrument that separates ions by m/z in a field-free region after acceleration to a fixed kinetic energy.", true}, {MS_cyclotron, "MS:1000288", "cyclotron", "A device that uses an oscillating electric field and magnetic field to accelerate charged particles.", false}, {MS_double_focusing_mass_spectrometer_OBSOLETE, "MS:1000289", "double-focusing mass spectrometer", "A mass spectrometer that uses a magnetic sector for m/z focusing and an electric sector for energy focusing of an ion beam.", true}, {MS_hybrid_mass_spectrometer_OBSOLETE, "MS:1000290", "hybrid mass spectrometer", "A mass spectrometer that combines m/z analyzers of different types to perform tandem mass spectrometry.", true}, {MS_linear_ion_trap, "MS:1000291", "linear ion trap", "A two dimensional Paul ion trap in which ions are confined in the axial dimension by means of an electric field at the ends of the trap.", false}, {MS_mass_spectrograph_obsolete_OBSOLETE, "MS:1000292", "mass spectrograph obsolete", "An instrument that separates a beam of ions according to their mass-to-charge ratio in which the ions are directed onto a focal plane detector such as a photographic plate.", true}, {MS_mass_spectrometer_OBSOLETE, "MS:1000293", "mass spectrometer", "An instrument that measures the mass-to-charge ratio and relative abundances of ions.", true}, {MS_mass_spectrum, "MS:1000294", "mass spectrum", "A plot of the relative abundance of a beam or other collection of ions as a function of the mass-to-charge ratio (m/z).", false}, {MS_mattauch_herzog_geometry_OBSOLETE, "MS:1000295", "mattauch-herzog geometry", "An arrangement for a double-focusing mass spectrometer in which a deflection of ?/(4 ?(2)) radians in a radial electric field is followed by a magnetic deflection of ?/2 radians.", true}, {MS_nier_johnson_geometry_OBSOLETE, "MS:1000296", "nier-johnson geometry", "An arrangement for a double-focusing mass spectrometer in which a deflection of ?/2 radians in a radial electric field analyzer is followed by a magnetic deflection of ?/3 radians.", true}, {MS_paul_ion_trap_OBSOLETE, "MS:1000297", "paul ion trap", "A device that permits the trapping of ions by means of an alternating current voltage. The ejection of ions with a m/z less than a prescribed value and retention of those with higher mass depends on the application of radio frequency voltages between a ring electrode and two end-cap electrodes to confine the ions in a circular path. The choice of these voltages determines the m/z below which ions are ejected.", true}, {MS_prolate_traochoidal_mass_spectrometer_OBSOLETE, "MS:1000298", "prolate traochoidal mass spectrometer", "A mass spectrometer in which the ions of different m/z are separated by means of crossed electric and magnetic fields in such a way that the selected ions follow a prolate trochoidal path.", true}, {MS_quistor_OBSOLETE, "MS:1000299", "quistor", "An abbreviation of quadrupole ion storage trap. This term is synonymous with Paul Ion Trap. If so then add a synonym to paul and obsolete this term.", true}, {MS_reflectron, "MS:1000300", "reflectron", "A time-of-flight mass spectrometer that uses a static electric field to reverse the direction of travel of the ions entering it. A reflectron improves mass resolution by assuring that ions of the same m/z but different kinetic energy arrive at the detector at the same time.", false}, {MS_sector_mass_spectrometer_OBSOLETE, "MS:1000301", "sector mass spectrometer", "A mass spectrometer consisting of one or more magnetic sectors for m/z selection in a beam of ions. Such instruments may also have one or more electric sectors for energy selection.", true}, {MS_tandem_mass_spectrometer_OBSOLETE, "MS:1000302", "tandem mass spectrometer", "A mass spectrometer designed for mass spectrometry/mass spectrometry.", true}, {MS_transmission_quadrupole_mass_spectrometer_OBSOLETE, "MS:1000303", "transmission quadrupole mass spectrometer", "A mass spectrometer that consists of four parallel rods whose centers form the corners of a square and whose opposing poles are connected. The voltage applied to the rods is a superposition of a static potential and a sinusoidal radio frequency potential. The motion of an ion in the x and y dimensions is described by the Matthieu equation whose solutions show that ions in a particular m/z range can be transmitted along the z axis.", true}, {MS_accelerating_voltage, "MS:1000304", "accelerating voltage", "The electrical potential used to impart kinetic energy to ions in a mass spectrometer.", false}, {MS_cyclotron_motion_OBSOLETE, "MS:1000305", "cyclotron motion", "The circular motion of a charged particle moving at velocity v in a magnetic field B that results from the force qvB.", true}, {MS_dynamic_mass_spectrometry_OBSOLETE, "MS:1000306", "dynamic mass spectrometry", "A mass spectrometer in which m/z separation using one or more electric fields that vary with time.", true}, {MS_einzel_lens, "MS:1000307", "einzel lens", "Three element charged particle lens in which the first and third elements are held at the same voltage. Such a lens produces focusing without changing the translational energy of the particle.", false}, {MS_electric_field_strength, "MS:1000308", "electric field strength", "The magnitude of the force per unit charge at a given point in space.", false}, {MS_first_stability_region, "MS:1000309", "first stability region", "The region of a Mathieu stability diagram closest to the origin. Ions within this region can traverse the full length of a transmission quadrupole.", false}, {MS_fringing_field, "MS:1000310", "fringing field", "The electric or magnetic field that extends from the edge of a sector, lens or other ion optics element.", false}, {MS_kinetic_energy_analyzer, "MS:1000311", "kinetic energy analyzer", "A device for measuring the kinetic energy of charged particles using a retarding field, time-of-flight, or the extent of deflection in an electric or magnetic field.", false}, {MS_mass_limit_OBSOLETE, "MS:1000312", "mass limit", "The m/z value above which ions cannot be detected in a mass spectrometer.", true}, {MS_scan_m_z_range__OBSOLETE, "MS:1000313", "scan m/z range?", "The limit of m/z over which a mass spectrometer can detect ions.", true}, {MS_mass_selective_axial_ejection_OBSOLETE, "MS:1000314", "mass selective axial ejection", "The use of mass selective instability to eject ions of selected m/z values from an ion trap.", true}, {MS_mass_selective_instability_OBSOLETE, "MS:1000315", "mass selective instability", "A method for selective ejection of ions according to their m/z value in an ion trap.", true}, {MS_mathieu_stability_diagram_OBSOLETE, "MS:1000316", "mathieu stability diagram", "A graphical representation expressed in terms of reduced coordinates that describes charged particle motion in a quadrupole mass filter or quadrupole ion trap mass spectrometer.", true}, {MS_orthogonal_extraction_OBSOLETE, "MS:1000317", "orthogonal extraction", "The pulsed acceleration of ions perpendicular to their direction of travel into a time-of-flight mass spectrometer. Ions may be extracted from a directional ion source, drift tube or m/z separation stage.", true}, {MS_resonance_ion_ejection_OBSOLETE, "MS:1000318", "resonance ion ejection", "A mode of ion ejection in a quadrupole ion trap that relies on a auxiliary radio frequency voltage that is applied to the end-cap electrodes. The voltage is tuned to the secular frequency of a particular ion to eject it.", true}, {MS_space_charge_effect, "MS:1000319", "space charge effect", "The mutual repulsion of particles of like charge that limits the current in a charged-particle beam and causes beams or packets of charged particles to expand radially over time.", false}, {MS_static_field, "MS:1000320", "static field", "An electric or magnetic field that does not change in time.", false}, {MS_2E_Mass_Spectrum_OBSOLETE, "MS:1000321", "2E Mass Spectrum", "A mass spectrum obtained by setting the electric sector field E to twice the value required to transmit the main ion-beam thereby allowing ions with a kinetic energy-to-charge ratio twice that of the main ion-beam to be transmitted. Product ions resulting from partial charge transfer reactions such as m^2+ + N ? m^+ + N^+ that occur in a collision cell (containing a gas, N) located in a field-free region preceding a magnetic and electric sector combination are detected. When the magnetic sector field B is scanned, a mass spectrum of singly charged product ions of doubly charged precursor ions is obtained.", true}, {MS_charge_inversion_mass_spectrum, "MS:1000322", "charge inversion mass spectrum", "The measurement of the relative abundance of ions that result from a charge inversion reaction as a function of m/z.", false}, {MS_constant_neutral_loss_scan_OBSOLETE, "MS:1000323", "constant neutral loss scan", "Spectrum of all precursor ions that undergo a selected m/z decrement.", true}, {MS_constant_neutral_gain_scan_OBSOLETE, "MS:1000324", "constant neutral gain scan", "Spectrum of all precursor ions that undergo a selected m/z increment.", true}, {MS_constant_neutral_gain_spectrum, "MS:1000325", "constant neutral gain spectrum", "A spectrum formed of all product ions that have been produced by gain of a pre-selected neutral mass following the reaction with and addition of the gas in a collision cell.", false}, {MS_constant_neutral_loss_spectrum, "MS:1000326", "constant neutral loss spectrum", "A spectrum formed of all product ions that have been produced with a selected m/z decrement from any precursor ions. The spectrum shown correlates to the precursor ion spectrum. See also neutral loss spectrum.", false}, {MS_consecutive_reaction_monitoring_OBSOLETE_1000327, "MS:1000327", "consecutive reaction monitoring (MS:1000327)", "A type of MS2 experiments with three or more stages of m/z separation and in which a particular multi-step reaction path is monitored.", true}, {MS_e_2_mass_spectrum, "MS:1000328", "e/2 mass spectrum", "A mass spectrum obtained using a sector mass spectrometer in which the electric sector field E is set to half the value required to transmit the main ion-beam. This spectrum records the signal from doubly charged product ions of charge-stripping reactions.", false}, {MS_linked_scan_OBSOLETE, "MS:1000329", "linked scan", "A scan in an instrument with two or more m/z analysers or in a sector mass spectrometer that incorporates at least one magnetic sector and one electric sector. Two or more of the analyzers are scanned simultaneously so as to preserve a predetermined relationship between scan parameters to produce a product ion, precursor ion or constant neutral loss spectrum.", true}, {MS_linked_scan_at_constant_b_e_OBSOLETE, "MS:1000330", "linked scan at constant b/e", "A linked scan at constant B/E may be performed on a sector mass spectrometer that incorporates at least one magnetic sector plus one electric sector. The magnetic field B and the electric field E are scanned simultaneously while the accelerating voltage V is held constant, so as to maintain the ratio of the two fields constant. This linked scan may record a product ion spectrum of dissociation or other reactions occurring in a field free region preceding the two sectors.", true}, {MS_Linked_Scan_at_Constant_E2_V_OBSOLETE, "MS:1000331", "Linked Scan at Constant E2/V", "A linked scan performed on a sector instrument that incorporates at least one electric sector plus one magnetic sector. The electric sector field, E, and the accelerating voltage, V, are scanned simultaneously, so as to maintain the ratio E2/V at a constant value. This linked scan recordss a product ion spectrum of dissociation or other reactions occurring in a field free region (FFR) preceding the two sectors.", true}, {MS_Linked_Scan_at_Constant_B2_E_OBSOLETE, "MS:1000332", "Linked Scan at Constant B2/E", "A linked scan performed on a sector mass spectrometer that incorporates at least one electric sector plus one magnetic sector in either order. The accelerating voltage is fixed and the magnetic field, B, and the electric field, E, are scanned simultaneously so as to maintain the ratio B2/E at a constant value. This linked scan records a precursor ion spectrum of dissociation or other reactions occurring in the field free region preceding the two sectors. The term B2/E linked scan is not recommended.", true}, {MS_Linked_Scan_at_Constant_B_1__E_E0___1_2___E_OBSOLETE, "MS:1000333", "Linked Scan at Constant B[1-(E/E0)]^1/2 / E", "A linked scan performed on a sector instrument that incorporates at least one electric sector plus one magnetic sector placed in either order. The accelerating voltage is fixed while scanning the magnetic field, B, and electric field, E, simultaneously, so as to maintain the quantity B[1-(E/E0)]1/2/E at a constant value. This linked scan records a constant neutral mass loss (or gain) spectrum of dissociation or other reactions occurring in a field free region preceding the two sectors. E0 is the electric field required to transmit the singly charged analog of the desired neutral fragment. The term B[1-(E/E0)]1/2/E linked scan.", true}, {MS_MS_MS_in_Time_OBSOLETE, "MS:1000334", "MS/MS in Time", "A tandem mass spectrometry method in which product ion spectra are recorded in a single m/z analyzer (such as a Paul Ion Trap or FTMS) in discreet steps over time. Ions in a specific m/z range are selected, dissociated, and the product ions analyzed sequentially in time.", true}, {MS_MS_MS_in_Space_OBSOLETE, "MS:1000335", "MS/MS in Space", "A tandem mass spectrometry method in which product ion spectra are recorded in m/z analyzers separated in space. Specific m/z separation functions are designed such that in one section of the instrument ions are selected, dissociated in an intermediate region, and the product ions are then transmitted to another analyser for m/z separation and data acquisition.", true}, {MS_neutral_loss, "MS:1000336", "neutral loss", "The loss of an uncharged species during a rearrangement process.", false}, {MS_nth_generation_product_ion_OBSOLETE, "MS:1000337", "nth generation product ion", "Serial product ions from dissociation of selected precursor ions where n refers to the number of stages of dissociation. The term granddaughter ion is deprecated.", true}, {MS_nth_generation_product_ion_scan_OBSOLETE, "MS:1000338", "nth generation product ion scan", "The specific scan functions or processes that record the appropriate generation of product ion or ions of any m/z selected precursor ions.", true}, {MS_nth_generation_product_ion_spectrum_OBSOLETE, "MS:1000339", "nth generation product ion spectrum", "The mass spectrum recorded from any mass spectrometer in which the appropriate scan function can be set to record the appropriate generation product ion or ions of m/z selected precursor ions.", true}, {MS_precursor_ion_OBSOLETE, "MS:1000340", "precursor ion", "An ion that reacts to form particular product ions. The reaction can be unimolecular dissociation, ion/molecule reaction, isomerization, or change in charge state. The term parent ion is deprecated.", true}, {MS_precursor_ion_spectrum, "MS:1000341", "precursor ion spectrum", "Spectrum generated by scanning precursor m/z while monitoring a fixed product m/z.", false}, {MS_product_ion_OBSOLETE, "MS:1000342", "product ion", "An ion formed as the product of a reaction involving a particular precursor ion. The reaction can be unimolecular dissociation to form fragment ions, an ion/molecule reaction, or simply involve a change in the number of charges. The term fragment ion is deprecated. The term daughter ion is deprecated.", true}, {MS_product_ion_spectrum_OBSOLETE, "MS:1000343", "product ion spectrum", "A mass spectrum recorded from any spectrometer in which the appropriate m/z separation scan function is set to record the product ion or ions of selected precursor ions.", true}, {MS_progeny_ion_OBSOLETE, "MS:1000344", "progeny ion", "A charged product of a series of consecutive reactions that includes product ions, 1st generation product ions, 2nd generation product ions, etc. Given the sequential fragmentation scheme: M1+ -> M2+ -> M3+ -> M4+ -> M5+. M4+ is the precursor ion of M5+, a 1st generation product ion of M3+, a 2nd generation product ion of M2+ and a 3rd generation product ion of M1+.", true}, {MS_array_detector, "MS:1000345", "array detector", "Detector comprising several ion collection elements, arranged in a line or grid where each element is an individual detector.", false}, {MS_conversion_dynode, "MS:1000346", "conversion dynode", "A surface that is held at high potential such that ions striking the surface produce electrons that are subsequently detected.", false}, {MS_dynode, "MS:1000347", "dynode", "One of a series of electrodes in a photomultiplier tube. Such an arrangement is able to amplify the current emitted by the photocathode.", false}, {MS_focal_plane_collector, "MS:1000348", "focal plane collector", "A detector for spatially disperse ion beams in which all ions simultaneously impinge on the detector plane.", false}, {MS_ion_to_photon_detector, "MS:1000349", "ion-to-photon detector", "A detector in which ions strike a conversion dynode to produce electrons that in turn strike a phosphor and the resulting photons are detected by a photomultiplier.", false}, {MS_point_collector, "MS:1000350", "point collector", "A detector in which the ion beam is focused onto a point and the individual ions arrive sequentially.", false}, {MS_postacceleration_detector, "MS:1000351", "postacceleration detector", "A detector in which the charged particles are accelerated to a high velocity and impinge on a conversion dynode, emitting secondary electrons. The electrons are accelerated onto a phosphor screen, which emits photons that are in turn detected using a photomultiplier or other photon detector.", false}, {MS_secondary_electron_OBSOLETE, "MS:1000352", "secondary electron", "Electrons that are ejected from a sample surface as a result of bombardment by a primary beam of atoms, ions or photons. WAS IN DETECTOR TYPE. Where should it go.", true}, {MS_adduct_ion_OBSOLETE, "MS:1000353", "adduct ion", "Ion formed by the interaction of an ion with one or more atoms or molecules to form an ion containing all the constituent atoms of the precursor ion as well as the additional atoms from the associated atoms or molecules.", true}, {MS_aromatic_ion_OBSOLETE, "MS:1000354", "aromatic ion", "A planar cyclic ion that obeys the Hueckel (4n + 2) rule where n is a positive integer representing the number of conjugated Pi electrons. Charge delocalization leads to greater stability compared to a hypothetical localized structure.", true}, {MS_analog_ion_OBSOLETE, "MS:1000355", "analog ion", "Ions that have similar chemical valence, for example the acetyl cation CH3-CO+ and the thioacetyl cation CH3-CS+.", true}, {MS_anti_aromatic_ion_OBSOLETE, "MS:1000356", "anti-aromatic ion", "A planar cyclic ion with 4n ? electrons and is therefore not aromatic.", true}, {MS_cationized_molecule_OBSOLETE, "MS:1000357", "cationized molecule", "An ion formed by the association of a cation with a neutral molecule, M, for example [M+ Na]+ and [M + K]+. The terms quasi-molecular ion and pseudo-molecular ion should not be used.", true}, {MS_cluster_ion_OBSOLETE, "MS:1000358", "cluster ion", "An ion formed by a multi-component atomic or molecular assembly of one or more ions with atoms or molecules, such as [(H20)nH]+, [(NaCl)nNa]+ and [(H3PO3)nHPO3]-.", true}, {MS_Conventional_ion_OBSOLETE, "MS:1000359", "Conventional ion", "A radical cation or anion in which the charge site and the unpaired electron spin are both formally located in the same atom or group of atoms, as opposed to the spatially separate electronic configuration of distonic ions. The radical cation of methanol, CH3OH+, in which the charge and spin sites are formally located at the O atom is an example of a conventional ion, whereas .CH2-OH2+ is a distonic ion.", true}, {MS_diagnostic_ion_OBSOLETE, "MS:1000360", "diagnostic ion", "A product ion whose formation reveals structural or compositional information of its precursor. For instance, the phenyl cation in an electron ionization mass spectrum is a diagnostic ion for benzene and derivatives.", true}, {MS_dimeric_ion_OBSOLETE, "MS:1000361", "dimeric ion", "An ion formed by ionization of a dimer or by the association of an ion with its neutral counterpart such as [M2]+ or [M-H-M]+.", true}, {MS_distonic_ion_OBSOLETE, "MS:1000362", "distonic ion", "A radical cation or anion in which the charge site and the unpaired electron spin cannot be both formally located in the same atom or group of atoms as it can be with a conventional ion. For example, CH2-OH2+ is a distonic ion whereas the radical cation of methanol, CH3OH+ is a conventional ion.", true}, {MS_enium_ion_OBSOLETE, "MS:1000363", "enium ion", "A positively charged lower-valency ion of the nonmetallic elements. The methenium ion is CH3+. Other examples are the oxenium, sulfenium, nitrenium, phosphenium, and halenium ions.", true}, {MS_fragment_ion_OBSOLETE, "MS:1000364", "fragment ion", "A product ion that results from the dissociation of a precursor ion.", true}, {MS_ion__OBSOLETE, "MS:1000365", "ion?", "An atomic or molecular species having a net positive or negative electric charge.", true}, {MS_Isotopologue_ion_OBSOLETE, "MS:1000366", "Isotopologue ion", "An ion that differs only in the isotopic composition of one or more of its constituent atoms. For example CH4+ and CH3D+ or 10BF3 and 11BF3. The term isotopologue is a contraction of isotopic homologue.", true}, {MS_Isotopomeric_ion_OBSOLETE, "MS:1000367", "Isotopomeric ion", "Isomeric ion having the same numbers of each isotopic atom but differing in their positions. Isotopomeric ions can be either configurational isomers in which two atomic isotopes exchange positions or isotopic stereoisomers. The term isotopomer is a shortening of isotopic isomer.", true}, {MS_metastable_ion_OBSOLETE, "MS:1000368", "metastable ion", "An ion that is formed with internal energy higher than the threshold for dissociation but with a lifetime great enough to allow it to exit the ion source and enter the mass spectrometer where it dissociates before detection.", true}, {MS_molecular_ion_OBSOLETE, "MS:1000369", "molecular ion", "An ion formed by the removal of one or more electrons to form a positive ion or the addition off one or more electrons to form a negative ion.", true}, {MS_negative_ion_OBSOLETE, "MS:1000370", "negative ion", "An atomic or molecular species having a net negative electric charge.", true}, {MS_non_classical_ion_OBSOLETE, "MS:1000371", "non-classical ion", "Hyper-coordinated carbonium ion such as the penta-coordinated norbornyl cation. Note: Tri-coordinated carbenium ions are termed classical ions.", true}, {MS_onium_ion_OBSOLETE, "MS:1000372", "onium ion", "A positively charged hypervalent ion of the nonmetallic elements. Examples are the methonium ion CH5+, the hydrogenonium ion H3+ and the hydronium ion H3O+. Other examples are the carbonium, oxonium, sulfonium, nitronium, diazonium, phosphonium, and halonium ions. Onium ions are not limited to monopositive ions; multiply-charged onium ions exist such as the gitonic (proximal) oxonium dication H4O2+ and the distonic oxonium dication H2O+-CH2-CH2-OH2+.", true}, {MS_principal_ion_OBSOLETE, "MS:1000373", "principal ion", "Most abundant ion of an isotope cluster, such as the 11B79Br2 81Br+ ion of m/z 250 of the cluster of isotopologue molecular ions of BBr3. The term principal ion has also been used to describe ions that have been artificially isotopically enriched in one or more positions such as CH3 13CH3+ or CH2D2 +, but those are best defined as isotopologue ions.", true}, {MS_positive_ion_OBSOLETE, "MS:1000374", "positive ion", "An atomic or molecular species having a net positive electric charge.", true}, {MS_protonated_molecule_OBSOLETE, "MS:1000375", "protonated molecule", "An ion formed by interaction of a neutral molecule with a proton and represented by the symbol [M + H]+, where M is the neutral molecule. The term 'protonated molecular ion,' 'quasi-molecular ion' and 'pseudo-molecular ion' are not recommended.", true}, {MS_radical_ion_OBSOLETE, "MS:1000376", "radical ion", "An ion, either a cation or anion, containing unpaired electrons in its ground state. The unpaired electron is denoted by a superscript dot alongside the superscript symbol for charge, such as for the molecular ion of a molecule M, that is, M+. Radical ions with more than one charge and/or more than one unpaired electron are denoted such as M(2+)(2). Unless the positions of the unpaired electron and charge can be associated with specific atoms, superscript charge designation should be placed before the superscript dot designation.", true}, {MS_reference_ion_OBSOLETE, "MS:1000377", "reference ion", "A stable ion whose structure is known with certainty. These ions are usually formed by direct ionization of a neutral molecule of known structure and are used to verify by comparison the structure of an unknown ion.", true}, {MS_stable_ion_OBSOLETE, "MS:1000378", "stable ion", "An ion with internal energy sufficiently low that it does not rearrange or dissociate prior to detection in a mass spectrometer.", true}, {MS_unstable_ion_OBSOLETE, "MS:1000379", "unstable ion", "An ion with sufficient energy to dissociate within the ion source.", true}, {MS_adiabatic_ionization, "MS:1000380", "adiabatic ionization", "A process whereby an electron is removed from an atom, ion, or molecule to produce an ion in its lowest energy state.", false}, {MS_associative_ionization, "MS:1000381", "associative ionization", "An ionization process in which two excited atoms or molecules react to form a single positive ion and an electron.", false}, {MS_atmospheric_pressure_photoionization, "MS:1000382", "atmospheric pressure photoionization", "Atmospheric pressure chemical ionization in which the reactant ions are generated by photo-ionization.", false}, {MS_autodetachment, "MS:1000383", "autodetachment", "The formation of a neutral when a negative ion in a discrete state with an energy greater than the detachment threshold loses an electron spontaneously without further interaction with an energy source.", false}, {MS_autoionization, "MS:1000384", "autoionization", "The formation of an ion when an atom or molecule in a discrete state with an energy greater than the ionization threshold loses an electron spontaneously without further interaction with an energy source.", false}, {MS_charge_exchange_ionization, "MS:1000385", "charge exchange ionization", "The interaction of an ion with an atom or molecule in which the charge on the ion is transferred to the neutral without the dissociation of either. Synonymous with charge transfer ionization.", false}, {MS_chemi_ionization, "MS:1000386", "chemi-ionization", "The reaction of a neutral molecule with an internally excited molecule to form an ion. Note that this term is not synonymous with chemical ionization.", false}, {MS_desorption_ionization_on_silicon, "MS:1000387", "desorption/ionization on silicon", "The formation of ions by laser desorption ionization of a sample deposited on a porous silicon surface.", false}, {MS_dissociative_ionization, "MS:1000388", "dissociative ionization", "The reaction of a gas-phase molecule that results in its decomposition to form products, one of which is an ion.", false}, {MS_electron_ionization, "MS:1000389", "electron ionization", "The ionization of an atom or molecule by electrons that are typically accelerated to energies between 50 and 150 eV. Usually 70 eV electrons are used to produce positive ions. The term 'electron impact' is not recommended.", false}, {MS_ion_desolvation_OBSOLETE, "MS:1000390", "ion desolvation", "The removal of solvent molecules clustered around a gas-phase ion by means of heating and/or collisions with gas molecules.", true}, {MS_ion_pair_formation_OBSOLETE, "MS:1000391", "ion-pair formation", "The reaction of a molecule to form both a positive ion and negative ion fragment among the products.", true}, {MS_ionization_efficiency, "MS:1000392", "ionization efficiency", "The ratio of the number of ions formed to the number of electrons, molecules or photons used.", false}, {MS_laser_desorption_ionization, "MS:1000393", "laser desorption ionization", "The formation of gas-phase ions by the interaction of a pulsed laser with a solid or liquid material.", false}, {MS_liquid_secondary_ionization, "MS:1000395", "liquid secondary ionization", "The ionization of any species by the interaction of a focused beam of ions with a sample that is dissolved in a solvent matrix. See also fast atom bombardment and secondary ionization.", false}, {MS_membrane_inlet, "MS:1000396", "membrane inlet", "A semi-permeable membrane separator that permits the passage of gas sample directly to the mass spectrometer ion source.", false}, {MS_microelectrospray, "MS:1000397", "microelectrospray", "Electrospray ionization at a solvent flow rate of 300-800 nL/min where the flow is a result of a mechanical pump. See nanoelectrospray.", false}, {MS_nanoelectrospray, "MS:1000398", "nanoelectrospray", "Electrospray ionization at a flow rate less than ~25 nL/min. Nanoelectrospray is synonymous with nanospray. The flow is dependent on the potenial on the tip of the electrospray needle and/or a gas presure to push the sample through the needle. See also electrospray ionization and microelectrospray.", false}, {MS_penning_ionization, "MS:1000399", "penning ionization", "Ionization that occurs through the interaction of two or more neutral gaseous species, at least one of which is internally excited.", false}, {MS_plasma_desorption_ionization, "MS:1000400", "plasma desorption ionization", "The ionization of material in a solid sample by bombarding it with ionic or neutral atoms formed as a result of the fission of a suitable nuclide, typically 252Cf. Synonymous with fission fragment ionization.", false}, {MS_pre_ionization_state_OBSOLETE, "MS:1000401", "pre-ionization state", "An electronic state capable of undergoing auto-Ionization.", true}, {MS_secondary_ionization, "MS:1000402", "secondary ionization", "The process in which ions are ejected from a sample surface as a result of bombardment by a primary beam of atoms or ions.", false}, {MS_soft_ionization, "MS:1000403", "soft ionization", "The formation of gas-phase ions without extensive fragmentation.", false}, {MS_spark_ionization, "MS:1000404", "spark ionization", "The formation of ions from a solid material by an intermittent electrical discharge.", false}, {MS_surface_assisted_laser_desorption_ionization, "MS:1000405", "surface-assisted laser desorption ionization", "The formation of gas-phase ions from molecules that are deposited on a particular surface substrate that is irradiated with a pulsed laser. See also matrix-assisted laser desorption ionization.", false}, {MS_surface_ionization, "MS:1000406", "surface ionization", "The ionization of a neutral species when it interacts with a solid surface with an appropriate work function and temperature.", false}, {MS_thermal_ionization, "MS:1000407", "thermal ionization", "The ionization of a neutral species through contact with a high temperature surface.", false}, {MS_vertical_ionization, "MS:1000408", "vertical ionization", "A process in which an electron is removed from or added to a molecule without a change in the positions of the atoms. The resulting ion is typically in an excited vibrational state.", false}, {MS_association_reaction_OBSOLETE, "MS:1000409", "association reaction", "The reaction of an ion with a neutral species in which the reactants combine to form a single ion.", true}, {MS_alpha_cleavage_OBSOLETE, "MS:1000410", "alpha-cleavage", "A homolytic cleavage where the bond fission occurs between at the atom adjacent to the atom at the apparent charge site and an atom removed from the aparent charge site by two bonds.", true}, {MS_beta_cleavage_OBSOLETE, "MS:1000411", "beta-cleavage", "A homolytic cleavage where the bond fission occurs between at an atom removed from the apparent charge site atom by two bonds and an atom adjacent to that atom and removed from the aparent charge site by three bonds.", true}, {MS_buffer_gas, "MS:1000412", "buffer gas", "An inert gas used for collisional deactivation of internally excited ions.", false}, {MS_charge_induced_fragmentation_OBSOLETE, "MS:1000413", "charge-induced fragmentation", "Fragmentation of an odd electron ion in which the cleaved bond is adjacent to the apparent charge site. Synonymous with charge mediated fragmentation.", true}, {MS_charge_inversion_reaction_OBSOLETE, "MS:1000414", "charge inversion reaction", "Reaction of an ion with a neutral species in which the charge on the product ion is reversed in sign with respect to the reactant ion.", true}, {MS_charge_permutation_reaction_OBSOLETE, "MS:1000415", "charge permutation reaction", "The reaction of an ion with a neutral species with a resulting change in the magnitude or sign of the charge on the reactant ion.", true}, {MS_charge_stripping_reaction_OBSOLETE, "MS:1000416", "charge stripping reaction", "Reaction of a positive ion with a neutral species in which the positive charge on the product ion is greater than that on the reactant ion.", true}, {MS_charge_transfer_reaction_OBSOLETE, "MS:1000417", "charge transfer reaction", "The reaction of an ion with a neutral species in which some or all of the charge of the reactant ion is transferred to the neutral species.", true}, {MS_collisional_excitation_OBSOLETE, "MS:1000418", "collisional excitation", "The reaction of an ion with a neutral species in which the translational energy of the collision is converted into internal energy of the ion.", true}, {MS_collision_gas, "MS:1000419", "collision gas", "An inert gas used for collisional excitation. The term target gas is not recommended.", false}, {MS_heterolytic_cleavage_OBSOLETE, "MS:1000420", "heterolytic cleavage", "Fragmentation of a molecule or ion in which both electrons forming the single bond that is broken remain on one of the atoms that were originally bonded. This term is synonymous with heterolysis.", true}, {MS_high_energy_collision_OBSOLETE, "MS:1000421", "high energy collision", "Collision-induced dissociation process wherein the projectile ion has laboratory-frame translational energy higher than 1 keV.", true}, {MS_beam_type_collision_induced_dissociation, "MS:1000422", "beam-type collision-induced dissociation", "A collision-induced dissociation process that occurs in a beam-type collision cell.", false}, {MS_homolytic_cleavage_OBSOLETE, "MS:1000423", "homolytic cleavage", "Fragmentation of an odd electron ion that results from one of a pair of electrons that form a bond between two atoms moving to form a pair with the odd electron on the atom at the apparent charge site. Fragmentation results in the formation of an even electron ion and a radical. This reaction involves the movement of a single electron and is symbolized by a single-barbed arrow. Synonymous with Homolysis.", true}, {MS_hydrogen_deuterium_exchange_OBSOLETE, "MS:1000424", "hydrogen/deuterium exchange", "Exchange of hydrogen atoms with deuterium atoms in a molecule or pre-formed ion in solution prior to introduction into a mass spectrometer, or by reaction of an ion with a deuterated collision gas inside a mass spectrometer.", true}, {MS_ion_energy_loss_spectrum_OBSOLETE, "MS:1000425", "ion energy loss spectrum", "A plot of the relative abundance of a beam or other collection of ions as a function their loss of translational energy in reactions with neutral species.", true}, {MS_ionizing_collision_OBSOLETE, "MS:1000426", "ionizing collision", "The reaction of an ion with a neutral species in which one or more electrons are removed from either the ion or neutral.", true}, {MS_ion_molecule_reaction_OBSOLETE, "MS:1000427", "ion/molecule reaction", "The reaction of an ion with a neutral molecule. The term ion-molecule reaction is not recommended because the hyphen suggests a single species that is that is both an ion and a molecule.", true}, {MS_ion_neutral_complex_OBSOLETE, "MS:1000428", "ion/neutral complex", "A particular type of transition state that lies between precursor and product ions on the reaction coordinate of some ion reactions.", true}, {MS_ion_neutral_species_reaction_OBSOLETE, "MS:1000429", "ion/neutral species reaction", "A process wherein a charged species interacts with a neutral reactant to produce either chemically different species or changes in the internal energy of one or both of the reactants.", true}, {MS_ion_neutral_species_exchange_reaction_OBSOLETE, "MS:1000430", "ion/neutral species exchange reaction", "In this reaction an association reaction is accompanied by the subsequent or simultaneous liberation of a different neutral species as a product.", true}, {MS_kinetic_method_OBSOLETE, "MS:1000431", "kinetic method", "An approach to determination of ion thermodynamic quantities by a bracketing procedure in which the relative probabilities of competing ion fragmentations are measured via the relative abundances of the reaction products. The extended kinetic method takes the associated entropy changes into account.", true}, {MS_low_energy_collisions_OBSOLETE, "MS:1000432", "low energy collisions", "A collision between an ion and neutral species with translational energy approximately 1000 eV or lower.", true}, {MS_low_energy_collision_induced_dissociation, "MS:1000433", "low-energy collision-induced dissociation", "A collision-induced dissociation process wherein the precursor ion has the translational energy lower than approximately 1000 eV. This process typically requires multiple collisions and the collisional excitation is cumulative.", false}, {MS_McLafferty_Rearrangement_OBSOLETE, "MS:1000434", "McLafferty Rearrangement", "A dissociation reaction triggered by transfer of a hydrogen atom via a 6-member transition state to the formal radical/charge site from a carbon atom four atoms removed from the charge/radical site (the gamma-carbon); subsequent rearrangement of electron density leads to expulsion of an olefin molecule. This term was originally applied to ketone ions where the charge/radical site is the carbonyl oxygen, but it is now more widely applied.", true}, {MS_photodissociation, "MS:1000435", "photodissociation", "A process wherein the reactant ion is dissociated as a result of absorption of one or more photons.", false}, {MS_partial_charge_transfer_reaction_OBSOLETE, "MS:1000436", "partial charge transfer reaction", "Reaction of an ion with a neutral species in which some but not all of the ion charge is transferred to the neutral.", true}, {MS_ion_reaction_OBSOLETE, "MS:1000437", "ion reaction", "Chemical transformation involving an ion.", true}, {MS_superelastic_collision_OBSOLETE, "MS:1000438", "superelastic collision", "Collision in which the translational energy of the fast-moving collision partner is increased at the expense of internal energy of one or both collision partners.", true}, {MS_surface_induced_reaction_OBSOLETE, "MS:1000439", "surface-induced reaction", "A process wherein a reactant ion interacts with a surface to produce either chemically different species or a change in the internal energy of the reactant ion.", true}, {MS_unimolecular_dissociation_OBSOLETE, "MS:1000440", "unimolecular dissociation", "Fragmentation reaction in which the molecularity is treated as one, irrespective of whether the dissociative state is that of a metastable ion produced in the ion source or results from collisional excitation of a stable ion.", true}, {MS_scan, "MS:1000441", "scan", "Function or process of the mass spectrometer where it records a spectrum.", false}, {MS_spectrum, "MS:1000442", "spectrum", "A mass spectrum is an intensity vs m/z (mass-to-charge ratio) plot representing a chemical analysis.", false}, {MS_mass_analyzer_type, "MS:1000443", "mass analyzer type", "Mass analyzer separates the ions according to their mass-to-charge ratio.", false}, {MS_m_z_Separation_Method_OBSOLETE, "MS:1000444", "m/z Separation Method", "Mass/charge separation Method.", true}, {MS_sequential_m_z_separation_method_OBSOLETE, "MS:1000445", "sequential m/z separation method", "Sequential m/z separation method.", true}, {MS_fast_ion_bombardment, "MS:1000446", "fast ion bombardment", "The ionization of any species by the interaction of a focused beam of ions having a translational energy of several thousand eV with a solid sample.", false}, {MS_LTQ, "MS:1000447", "LTQ", "Finnigan LTQ MS.", false}, {MS_LTQ_FT, "MS:1000448", "LTQ FT", "Finnigan LTQ FT MS.", false}, {MS_LTQ_Orbitrap, "MS:1000449", "LTQ Orbitrap", "Finnigan LTQ Orbitrap MS.", false}, {MS_LXQ, "MS:1000450", "LXQ", "Finnigan LXQ MS.", false}, {MS_mass_analyzer, "MS:1000451", "mass analyzer", "Terms used to describe the Analyzer.", false}, {MS_data_transformation, "MS:1000452", "data transformation", "Terms used to describe types of data processing.", false}, {MS_detector, "MS:1000453", "detector", "The device that detects ions.", false}, {MS_instrument_additional_description_OBSOLETE, "MS:1000454", "instrument additional description", "Additional terms to describe the instrument as outlined in the mass spec doc, Appendix 1, section 1.5.", true}, {MS_ion_selection_attribute, "MS:1000455", "ion selection attribute", "Ion selection properties that are associated with a value.", false}, {MS_precursor_activation, "MS:1000456", "precursor activation", "Terms to describe the precursor activation.", false}, {MS_sample, "MS:1000457", "sample", "Terms to describe the sample.", false}, {MS_source, "MS:1000458", "source", "Terms to describe the source.", false}, {MS_spectrum_instrument_description_OBSOLETE, "MS:1000459", "spectrum instrument description", "Terms used to describe the spectrum.", true}, {MS_unit_OBSOLETE, "MS:1000460", "unit", "Terms to describe units.", true}, {MS_additional_description_OBSOLETE, "MS:1000461", "additional description", "Terms to describe Additional.", true}, {MS_ion_optics, "MS:1000462", "ion optics", "Device used in the construction of a mass spectrometer to focus, contain or otherwise manipulate ions.", false}, {MS_instrument, "MS:1000463", "instrument", "Description of the instrument or the mass spectrometer.", false}, {MS_mass_unit_OBSOLETE, "MS:1000464", "mass unit", "A unit of measurement for mass.", true}, {MS_scan_polarity, "MS:1000465", "scan polarity", "An acquisition mode to which specifies weather polarity is negative, positive or alternating.", false}, {MS_alternating_OBSOLETE, "MS:1000466", "alternating", "Alternating.", true}, {MS_1200_series_LC_MSD_SL, "MS:1000467", "1200 series LC/MSD SL", "The 1200 Series LC/MSD SL ion trap belongs to the Agilent LC/MSD ion trap family. It provides fast polarity switching and multisignal data acquisition capabilities in a single run while also providing 5 stages of automated data dependent MS2 and 11 stages of manual MS2.", false}, {MS_6110_Quadrupole_LC_MS, "MS:1000468", "6110 Quadrupole LC/MS", "The 6110 Quadrupole LC/MS system is a Agilent liquid chromatography instrument combined with an entry level single quadrupole mass spectrometer from the 6100 Series of Agilent quadrupole mass spectrometers. 6110 Quadrupole mass spectrometer has m/z range of 10-1500 and 2500 u/s scan speed. It proves useful for wide range of SIM quantitative applications.", false}, {MS_6120_Quadrupole_LC_MS, "MS:1000469", "6120 Quadrupole LC/MS", "The 6120 Quadrupole LC/MS system is a Agilent liquid chromatography instrument combined with a single quadrupole mass spectrometer from the 6100 Series of Agilent mass spectrometers. 6120 quadrupole mass spectrometer has m/z range of 10-1500, 2500 u/s scan speed and utilizes multiple signal acquisition.", false}, {MS_6130_Quadrupole_LC_MS, "MS:1000470", "6130 Quadrupole LC/MS", "The 6130 Quadrupole LC/MS system is a Agilent liquid chromatography instrument combined with a single quadrupole mass spectrometer from the 6100 series of Agilent mass spectrometers. The 6130 quadrupole mass spectrometer has m/z range of 2-3000, 2500 u/s scan speed in standard mode and 5250 u/s speed in fast-scan mode. It also uses multiple signal acquisition.", false}, {MS_6140_Quadrupole_LC_MS, "MS:1000471", "6140 Quadrupole LC/MS", "The 6140 Quadrupole LC/MS system is a Agilent liquid chromatography instrument combined with a single quadrupole mass spectrometer from the 6100 Series of Agilent quadrupole mass spectrometers. 6140 Quadrupole mass spectrometer has m/z range of 10-1350, 2500 u/s scan speed in standard mode and 10000 u/s speed in fast-scan mode. It also uses multiple signal acquisition.", false}, {MS_6210_Time_of_Flight_LC_MS, "MS:1000472", "6210 Time-of-Flight LC/MS", "The 6210 Time-of-Flight LC/MS is a Agilent liquid chromatography instrument combined with a Agilent time of flight mass spectrometer. This time of flight mass spectrometer has a m/z range of 50-12000, mass accuracy of less than 2 ppm and resolution greater than 13,000 at m/z 2722. It has multiple ion sources and can be used with multimode ion sources.", false}, {MS_6310_Ion_Trap_LC_MS, "MS:1000473", "6310 Ion Trap LC/MS", "The 6310 Ion Trap LC/MS is a Agilent liquid chromatography instrument combined with a 6300 series Agilent ion trap. It has a mass range of 50-2200 between 0.6 to 0.35 resolution and mass range of 200-4000 with resolution of 3-4. The scan speed varies from 1650-27000 for the respective mass ranges.", false}, {MS_6320_Ion_Trap_LC_MS, "MS:1000474", "6320 Ion Trap LC/MS", "The 6320 Ion Trap LC/MS is a Agilent liquid chromatography instrument combined with a 6300 series Agilent ion trap. It has a mass range of 50-2200 between 0.6 to 0.25 resolution and mass range of 200-4000 with resolution of less than 3. The scan speed varies from 1650-27000 for the respective mass ranges.", false}, {MS_6330_Ion_Trap_LC_MS, "MS:1000475", "6330 Ion Trap LC/MS", "The 6330 Ion Trap LC/MS is a Agilent liquid chromatography instrument combined with a 6300 series Agilent ion trap. It has a mass range of 50-2200 between 0.6 to 0.25 resolution and mass range of 200-4000 with resolution of less than 3. The scan speed varies from 1650-27000 for the respective mass ranges.", false}, {MS_6340_Ion_Trap_LC_MS, "MS:1000476", "6340 Ion Trap LC/MS", "The 6340 Ion Trap LC/MS is a Agilent liquid chromatography instrument combined with a 6300 series Agilent ion trap. It has a mass range of 50-2200 between 0.6 to 0.25 resolution and mass range of 200-4000 with resolution of less than 3. The scan speed varies from 1650-27000 for the respective mass ranges.", false}, {MS_6410_Triple_Quadrupole_LC_MS, "MS:1000477", "6410 Triple Quadrupole LC/MS", "The 6410 Quadrupole LC/MS system is a Agilent liquid chromatography instrument combined with a Agilent triple quadrupole mass spectrometer. Mass range of the mass spectrometer is 15-1650 m/z, resolution is at three settings of 0.7 u (unit), 1.2 u (wide) and 2.5 u (widest). The mass accuracy for 6410 mass spectrometer is 0.1 across the mass range. The collision cell is a hexapole with linear acceleration.", false}, {MS_1200_series_LC_MSD_VL, "MS:1000478", "1200 series LC/MSD VL", "The LC/MSD VL ion trap is part of the family of Agilent ion trap mass spectrometers. It has ESI, APCI and APPI ion sources and is a useful ion trap when the amount of sample is not the limiting factor.", false}, {MS_purgatory_OBSOLETE, "MS:1000479", "purgatory", "Terms that will likely become obsolete unless there are wails of dissent.", true}, {MS_mass_analyzer_attribute, "MS:1000480", "mass analyzer attribute", "Analyzer properties that are associated with a value.", false}, {MS_detector_attribute, "MS:1000481", "detector attribute", "Detector attribute recognized as a value.", false}, {MS_source_attribute, "MS:1000482", "source attribute", "Property of a source device that need a value.", false}, {MS_Thermo_Fisher_Scientific_instrument_model, "MS:1000483", "Thermo Fisher Scientific instrument model", "Thermo Fisher Scientific instrument model. The company has gone through several names including Thermo Finnigan, Thermo Scientific.", false}, {MS_orbitrap, "MS:1000484", "orbitrap", "An ion trapping device that consists of an outer barrel-like electrode and a coaxial inner spindle-like electrode that form an electrostatic field with quadro-logarithmic potential distribution. The frequency of harmonic oscillations of the orbitally trapped ions along the axis of the electrostatic field is independent of the ion velocity and is inversely proportional to the square root of m/z so that the trap can be used as a mass analyzer.", false}, {MS_nanospray_inlet, "MS:1000485", "nanospray inlet", "Nanospray Inlet.", false}, {MS_source_potential, "MS:1000486", "source potential", "Potential difference at the MS source in volts.", false}, {MS_ion_optics_attribute, "MS:1000487", "ion optics attribute", "Ion optics involves components that help focus ion streams in mass spectrometry.", false}, {MS_Hitachi_instrument_model, "MS:1000488", "Hitachi instrument model", "Hitachi instrument model.", false}, {MS_Varian_instrument_model, "MS:1000489", "Varian instrument model", "Varian instrument model.", false}, {MS_Agilent_instrument_model, "MS:1000490", "Agilent instrument model", "Agilent instrument model.", false}, {MS_Dionex_instrument_model, "MS:1000491", "Dionex instrument model", "Dionex instrument model.", false}, {MS_Thermo_Electron_instrument_model, "MS:1000492", "Thermo Electron instrument model", "Thermo Electron Corporation instrument model.", false}, {MS_Finnigan_MAT_instrument_model, "MS:1000493", "Finnigan MAT instrument model", "Finnigan MAT instrument model.", false}, {MS_Thermo_Scientific_instrument_model, "MS:1000494", "Thermo Scientific instrument model", "Thermo Scientific instrument model.", false}, {MS_Applied_Biosystems_instrument_model, "MS:1000495", "Applied Biosystems instrument model", "Applied Biosystems instrument model.", false}, {MS_instrument_attribute, "MS:1000496", "instrument attribute", "Instrument properties that are associated with a value.", false}, {MS_zoom_scan, "MS:1000497", "zoom scan", "Special scan mode, where data with improved resolution is acquired. This is typically achieved by scanning a more narrow m/z window or scanning with a lower scan rate.", false}, {MS_full_scan_OBSOLETE, "MS:1000498", "full scan", "Feature of the ion trap mass spectrometer where MS data is acquired over a mass range.", true}, {MS_spectrum_attribute, "MS:1000499", "spectrum attribute", "Spectrum properties that are associated with a value.", false}, {MS_scan_window_upper_limit, "MS:1000500", "scan window upper limit", "The lower m/z bound of a mass spectrometer scan window.", false}, {MS_scan_window_lower_limit, "MS:1000501", "scan window lower limit", "The upper m/z bound of a mass spectrometer scan window.", false}, {MS_dwell_time, "MS:1000502", "dwell time", "The time spent gathering data across a peak.", false}, {MS_scan_attribute, "MS:1000503", "scan attribute", "Scan properties that are associated with a value.", false}, {MS_base_peak_m_z, "MS:1000504", "base peak m/z", "M/z value of the signal of highest intensity in the mass spectrum.", false}, {MS_base_peak_intensity, "MS:1000505", "base peak intensity", "The intensity of the greatest peak in the mass spectrum.", false}, {MS_ion_role_OBSOLETE, "MS:1000506", "ion role", "Ion Role.", true}, {MS_ion_attribute_OBSOLETE, "MS:1000507", "ion attribute", "Ion properties that are associated with a value.", true}, {MS_ion_chemical_type_OBSOLETE, "MS:1000508", "ion chemical type", "Ion Type.", true}, {MS_activation_energy, "MS:1000509", "activation energy", "Activation Energy.", false}, {MS_precursor_activation_attribute, "MS:1000510", "precursor activation attribute", "Precursor Activation Attribute.", false}, {MS_ms_level, "MS:1000511", "ms level", "Stages of ms achieved in a multi stage mass spectrometry experiment.", false}, {MS_filter_string, "MS:1000512", "filter string", "A string unique to Thermo instrument describing instrument settings for the scan.", false}, {MS_binary_data_array, "MS:1000513", "binary data array", "A data array of values.", false}, {MS_m_z_array, "MS:1000514", "m/z array", "A data array of m/z values.", false}, {MS_intensity_array, "MS:1000515", "intensity array", "A data array of intensity values.", false}, {MS_charge_array, "MS:1000516", "charge array", "A data array of charge values.", false}, {MS_signal_to_noise_array, "MS:1000517", "signal to noise array", "A data array of signal-to-noise values.", false}, {MS_binary_data_type, "MS:1000518", "binary data type", "Encoding type of binary data specifying the binary representation and precision, e.g. 64-bit float.", false}, {MS_32_bit_integer, "MS:1000519", "32-bit integer", "Signed 32-bit little-endian integer.", false}, {MS_16_bit_float_OBSOLETE, "MS:1000520", "16-bit float", "Signed 16-bit float.", true}, {MS_32_bit_float, "MS:1000521", "32-bit float", "32-bit precision little-endian floating point conforming to IEEE-754.", false}, {MS_64_bit_integer, "MS:1000522", "64-bit integer", "Signed 64-bit little-endian integer.", false}, {MS_64_bit_float, "MS:1000523", "64-bit float", "64-bit precision little-endian floating point conforming to IEEE-754.", false}, {MS_data_file_content, "MS:1000524", "data file content", "Describes the data content on the file.", false}, {MS_spectrum_representation, "MS:1000525", "spectrum representation", "Way in which the spectrum is represented, either with regularly spaced data points or with a list of centroided peaks.", false}, {MS_Waters_raw_format, "MS:1000526", "Waters raw format", "Waters data file format found in a Waters RAW directory, generated from an MS acquisition.", false}, {MS_highest_observed_m_z, "MS:1000527", "highest observed m/z", "Highest m/z value observed in the m/z array.", false}, {MS_lowest_observed_m_z, "MS:1000528", "lowest observed m/z", "Lowest m/z value observed in the m/z array.", false}, {MS_instrument_serial_number, "MS:1000529", "instrument serial number", "Serial Number of the instrument.", false}, {MS_file_format_conversion, "MS:1000530", "file format conversion", "Conversion of one file format to another.", false}, {MS_software, "MS:1000531", "software", "Software related to the recording or transformation of spectra.", false}, {MS_Xcalibur, "MS:1000532", "Xcalibur", "Thermo Finnigan software for data acquisition and analysis.", false}, {MS_Bioworks, "MS:1000533", "Bioworks", "Thermo Finnigan software for data analysis of peptides and proteins.", false}, {MS_MassLynx, "MS:1000534", "MassLynx", "Micromass software for data acquisition and analysis.", false}, {MS_FlexAnalysis, "MS:1000535", "FlexAnalysis", "Bruker software for data analysis.", false}, {MS_Data_Explorer, "MS:1000536", "Data Explorer", "Applied Biosystems software for data acquisition and analysis.", false}, {MS_4700_Explorer, "MS:1000537", "4700 Explorer", "Applied Biosystems software for data acquisition and analysis.", false}, {MS_massWolf, "MS:1000538", "massWolf", "A software for converting Waters raw directory format to mzXML or mzML. MassWolf was originally developed at the Institute for Systems Biology.", false}, {MS_Voyager_Biospectrometry_Workstation_System, "MS:1000539", "Voyager Biospectrometry Workstation System", "Applied Biosystems MALDI-TOF data acquisition and analysis system.", false}, {MS_FlexControl, "MS:1000540", "FlexControl", "Bruker software for data acquisition.", false}, {MS_ReAdW, "MS:1000541", "ReAdW", "A software program for converting Thermo Finnigan RAW file format to mzXML or mzML. ReAdW was originally developed at the Institute for Systems Biology. Its whimsical interleaved spelling and capitalization is pronounced \\\"readraw\\\".", false}, {MS_MzStar, "MS:1000542", "MzStar", "A software program for converting Applied Biosystems wiff file format to mzXML format. MzStar was originally developed at the Institute for Systems Biology. It is now obsoleted by the MzWiff program.", false}, {MS_data_processing_action, "MS:1000543", "data processing action", "Data processing attribute used to describe the type of data processing performed on the data file.", false}, {MS_Conversion_to_mzML, "MS:1000544", "Conversion to mzML", "Conversion of a file format to Proteomics Standards Initiative mzML file format.", false}, {MS_Conversion_to_mzXML, "MS:1000545", "Conversion to mzXML", "Conversion of a file format to Institute of Systems Biology mzXML file format.", false}, {MS_Conversion_to_mzData, "MS:1000546", "Conversion to mzData", "Conversion of a file format to Proteomics Standards Initiative mzData file format.", false}, {MS_object_attribute, "MS:1000547", "object attribute", "Object Attribute.", false}, {MS_sample_attribute, "MS:1000548", "sample attribute", "Sample properties that are associated with a value.", false}, {MS_selection_window_attribute, "MS:1000549", "selection window attribute", "Selection window properties that are associated with a value.", false}, {MS_time_unit_OBSOLETE, "MS:1000550", "time unit", "Time Unit.", true}, {MS_Analyst, "MS:1000551", "Analyst", "SCIEX or Applied Biosystems|MDS SCIEX software for data acquisition.", false}, {MS_maldi_spot_identifier_OBSOLETE, "MS:1000552", "maldi spot identifier", "Maldi Spot Identifier.", true}, {MS_Trapper, "MS:1000553", "Trapper", "A software program for converting Agilent MassHunter format to mzXML or mzML. Trapper was originally developed at the Institute for Systems Biology.", false}, {MS_LCQ_Deca, "MS:1000554", "LCQ Deca", "ThermoFinnigan LCQ Deca.", false}, {MS_LTQ_Orbitrap_Discovery, "MS:1000555", "LTQ Orbitrap Discovery", "LTQ Orbitrap Discovery.", false}, {MS_LTQ_Orbitrap_XL, "MS:1000556", "LTQ Orbitrap XL", "LTQ Orbitrap XL.", false}, {MS_LTQ_FT_Ultra, "MS:1000557", "LTQ FT Ultra", "LTQ FT Ultra.", false}, {MS_GC_Quantum, "MS:1000558", "GC Quantum", "GC Quantum.", false}, {MS_spectrum_type, "MS:1000559", "spectrum type", "Spectrum type.", false}, {MS_mass_spectrometer_file_format, "MS:1000560", "mass spectrometer file format", "The format of the file being used. This could be a instrument or vendor specific proprietary file format or a converted open file format.", false}, {MS_data_file_checksum_type, "MS:1000561", "data file checksum type", "Checksum is a form of redundancy check, a simple way to protect the integrity of data by detecting errors in data.", false}, {MS_ABI_WIFF_format, "MS:1000562", "ABI WIFF format", "Applied Biosystems WIFF file format.", false}, {MS_Thermo_RAW_format, "MS:1000563", "Thermo RAW format", "Thermo Scientific RAW file format.", false}, {MS_PSI_mzData_format, "MS:1000564", "PSI mzData format", "Proteomics Standards Inititative mzData file format.", false}, {MS_Micromass_PKL_format, "MS:1000565", "Micromass PKL format", "Micromass PKL file format.", false}, {MS_ISB_mzXML_format, "MS:1000566", "ISB mzXML format", "Institute of Systems Biology mzXML file format.", false}, {MS_Bruker_Agilent_YEP_format, "MS:1000567", "Bruker/Agilent YEP format", "Bruker/Agilent YEP file format.", false}, {MS_MD5, "MS:1000568", "MD5", "MD5 (Message-Digest algorithm 5) is a cryptographic hash function with a 128-bit hash value used to check the integrity of files.", false}, {MS_SHA_1, "MS:1000569", "SHA-1", "SHA-1 (Secure Hash Algorithm-1) is a cryptographic hash function designed by the National Security Agency (NSA) and published by the NIST as a U. S. government standard. It is also used to verify file integrity.", false}, {MS_spectra_combination, "MS:1000570", "spectra combination", "Method used to combine the mass spectra.", false}, {MS_sum_of_spectra, "MS:1000571", "sum of spectra", "Spectra Sum.", false}, {MS_binary_data_compression_type, "MS:1000572", "binary data compression type", "Compression Type.", false}, {MS_median_of_spectra, "MS:1000573", "median of spectra", "Spectra is combined by calculating the median of the spectra.", false}, {MS_zlib_compression, "MS:1000574", "zlib compression", "Zlib.", false}, {MS_mean_of_spectra, "MS:1000575", "mean of spectra", "Spectra is combined by calculating the mean of the spectra.", false}, {MS_no_compression, "MS:1000576", "no compression", "No Compression.", false}, {MS_raw_data_file, "MS:1000577", "raw data file", "Describes the type of file and its content.", false}, {MS_LCQ_Fleet, "MS:1000578", "LCQ Fleet", "LCQ Fleet.", false}, {MS_MS1_spectrum, "MS:1000579", "MS1 spectrum", "Mass spectrum created by a single-stage MS experiment or the first stage of a multi-stage experiment.", false}, {MS_MSn_spectrum, "MS:1000580", "MSn spectrum", "MSn refers to multi-stage MS2 experiments designed to record product ion spectra where n is the number of product ion stages (progeny ions). For ion traps, sequential MS/MS experiments can be undertaken where n > 2 whereas for a simple triple quadrupole system n=2. Use the term ms level (MS:1000511) for specifying n.", false}, {MS_CRM_spectrum, "MS:1000581", "CRM spectrum", "Spectrum generated from MSn experiment with three or more stages of m/z separation and in which a particular multi-step reaction path is monitored.", false}, {MS_SIM_spectrum, "MS:1000582", "SIM spectrum", "Spectrum obtained with the operation of a mass spectrometer in which the abundances of one ion or several ions of specific m/z values are recorded rather than the entire mass spectrum (Selected Ion Monitoring).", false}, {MS_SRM_spectrum, "MS:1000583", "SRM spectrum", "Spectrum obtained when data are acquired from specific product ions corresponding to m/z values of selected precursor ions a recorded via two or more stages of mass spectrometry. The precursor/product ion pair is called a transition pair. Data can be obtained for a single transition pair or multiple transition pairs. Multiple time segments of different transition pairs can exist in a single file. Single precursor ions can have multiple product ions consitituting multiple transition pairs. Selected reaction monitoring can be performed as tandem mass spectrometry in time or tandem mass spectrometry in space.", false}, {MS_mzML_format, "MS:1000584", "mzML format", "Proteomics Standards Inititative mzML file format.", false}, {MS_contact_attribute, "MS:1000585", "contact attribute", "Details about a person or organization to contact in case of concern or discussion about the file.", false}, {MS_contact_name, "MS:1000586", "contact name", "Name of the contact person or organization.", false}, {MS_contact_address, "MS:1000587", "contact address", "Postal address of the contact person or organization.", false}, {MS_contact_URL, "MS:1000588", "contact URL", "Uniform Resource Locator related to the contact person or organization.", false}, {MS_contact_email, "MS:1000589", "contact email", "Email address of the contact person or organization.", false}, {MS_contact_affiliation, "MS:1000590", "contact affiliation", "Home institution of the contact person.", false}, {MS_MzWiff, "MS:1000591", "MzWiff", "A software program for converting Applied Biosystems wiff file format to the mzXML or mzML format. MzWiff is currently maintained at the Institute for Systems Biology. It replaces the slower mzStar program.", false}, {MS_smoothing, "MS:1000592", "smoothing", "A process of reducing spikes of intensity in order to reduce noise while preserving real peak signal. Many algorithms can be applied for this process.", false}, {MS_baseline_reduction, "MS:1000593", "baseline reduction", "A process of removal of varying intensities generated due to variable energy absorption before further processing can take place. Baseline reduction facilitates meaningful comparision between intensities of m/z values.", false}, {MS_low_intensity_data_point_removal, "MS:1000594", "low intensity data point removal", "The removal of very low intensity data points that are likely to be spurious noise rather than real signal.", false}, {MS_time_array, "MS:1000595", "time array", "A data array of relative time offset values from a reference time.", false}, {MS_measurement_method, "MS:1000596", "measurement method", "An attribute of resolution when recording the detector response in absence of the analyte.", false}, {MS_ion_optics_type, "MS:1000597", "ion optics type", "The electrical potential used to impart kinetic energy to ions in a mass spectrometer.", false}, {MS_electron_transfer_dissociation, "MS:1000598", "electron transfer dissociation", "A process to fragment ions in a mass spectrometer by inducing fragmentation of cations (e.g. peptides or proteins) by transferring electrons to them.", false}, {MS_pulsed_q_dissociation, "MS:1000599", "pulsed q dissociation", "A process that involves precursor ion activation at high Q, a time delay to allow the precursor to fragment, then a rapid pulse to low Q where all fragment ions are trapped. The product ions can then be scanned out of the ion trap and detected.", false}, {MS_Proteios, "MS:1000600", "Proteios", "Database application and analysis platform for proteomics.", false}, {MS_ProteinLynx_Global_Server, "MS:1000601", "ProteinLynx Global Server", "Waters software for data analysis.", false}, {MS_Shimadzu_MALDI_TOF_instrument_model, "MS:1000602", "Shimadzu MALDI-TOF instrument model", "Shimadzu MALDI-TOF instrument model.", false}, {MS_Shimadzu_Scientific_Instruments_instrument_model, "MS:1000603", "Shimadzu Scientific Instruments instrument model", "Shimadzu Scientific Instruments instrument model.", false}, {MS_LCMS_IT_TOF, "MS:1000604", "LCMS-IT-TOF", "Shimadzu Scientific Instruments LCMS-IT-TOF MS.", false}, {MS_LCMS_2010EV, "MS:1000605", "LCMS-2010EV", "Shimadzu Scientific Instruments LCMS-2010EV MS.", false}, {MS_LCMS_2010A, "MS:1000606", "LCMS-2010A", "Shimadzu Scientific Instruments LCMS-2010A MS.", false}, {MS_AXIMA_CFR_MALDI_TOF, "MS:1000607", "AXIMA CFR MALDI-TOF", "Shimadzu Biotech AXIMA CFR MALDI-TOF MS.", false}, {MS_AXIMA_QIT, "MS:1000608", "AXIMA-QIT", "Shimadzu Biotech AXIMA-QIT MS.", false}, {MS_AXIMA_CFR_plus, "MS:1000609", "AXIMA-CFR plus", "Shimadzu Biotech AXIMA-CFR plus MS.", false}, {MS_AXIMA_Performance_MALDI_TOF_TOF, "MS:1000610", "AXIMA Performance MALDI-TOF/TOF", "Shimadzu Biotech AXIMA Performance MALDI-TOF/TOF MS.", false}, {MS_AXIMA_Confidence_MALDI_TOF, "MS:1000611", "AXIMA Confidence MALDI-TOF", "Shimadzu Biotech AXIMA Confidence MALDI-TOF (curved field reflectron) MS.", false}, {MS_AXIMA_Assurance_Linear_MALDI_TOF, "MS:1000612", "AXIMA Assurance Linear MALDI-TOF", "Shimadzu Biotech AXIMA Assurance Linear MALDI-TOF MS.", false}, {MS_DTA_format, "MS:1000613", "DTA format", "SEQUEST DTA file format.", false}, {MS_ProteinLynx_Global_Server_mass_spectrum_XML_format, "MS:1000614", "ProteinLynx Global Server mass spectrum XML format", "Peak list file format used by ProteinLynx Global Server.", false}, {MS_ProteoWizard_software, "MS:1000615", "ProteoWizard software", "ProteoWizard software for data processing and analysis. Primarily developed by the labs of P. Malick and D. Tabb.", false}, {MS_preset_scan_configuration, "MS:1000616", "preset scan configuration", "A user-defined scan configuration that specifies the instrumental settings in which a spectrum is acquired. An instrument may cycle through a list of preset scan configurations to acquire data. This is a more generic term for the Thermo \\\"scan event\\\", which is defined in the Thermo Xcalibur glossary as: a mass spectrometer scan that is defined by choosing the necessary scan parameter settings. Multiple scan events can be defined for each segment of time.", false}, {MS_wavelength_array, "MS:1000617", "wavelength array", "A data array of electromagnetic radiation wavelength values.", false}, {MS_highest_observed_wavelength, "MS:1000618", "highest observed wavelength", "Highest wavelength observed in an EMR spectrum.", false}, {MS_lowest_observed_wavelength, "MS:1000619", "lowest observed wavelength", "Lowest wavelength observed in an EMR spectrum.", false}, {MS_PDA_spectrum_OBSOLETE, "MS:1000620", "PDA spectrum", "Spectrum generated from a photodiode array detector (ultraviolet/visible spectrum).", true}, {MS_photodiode_array_detector, "MS:1000621", "photodiode array detector", "An array detector used to record spectra in the ultraviolet and visible region of light.", false}, {MS_Surveyor_PDA, "MS:1000622", "Surveyor PDA", "Surveyor PDA.", false}, {MS_Accela_PDA, "MS:1000623", "Accela PDA", "Accela PDA.", false}, {MS_inductive_detector, "MS:1000624", "inductive detector", "Inductive detector.", false}, {MS_chromatogram, "MS:1000625", "chromatogram", "The representation of detector response versus time.", false}, {MS_chromatogram_type, "MS:1000626", "chromatogram type", "Broad category or type of a chromatogram.", false}, {MS_selected_ion_current_chromatogram, "MS:1000627", "selected ion current chromatogram", "Chromatogram created by creating an array of the measurements of a specific single ion current at each time point.", false}, {MS_basepeak_chromatogram, "MS:1000628", "basepeak chromatogram", "Chromatogram created by creating an array of the most intense peaks at each time point.", false}, {MS_low_intensity_threshold, "MS:1000629", "low intensity threshold", "Threshold below which some action is taken.", false}, {MS_data_processing_parameter, "MS:1000630", "data processing parameter", "Data processing parameter used in the data processing performed on the data file.", false}, {MS_high_intensity_threshold, "MS:1000631", "high intensity threshold", "Threshold above which some action is taken.", false}, {MS_Q_Tof_Premier, "MS:1000632", "Q-Tof Premier", "Waters oa-ToF based Q-Tof Premier.", false}, {MS_possible_charge_state, "MS:1000633", "possible charge state", "A possible charge state of the ion in a situation where the charge of an ion is known to be one of several possible values rather than a completely unknown value or determined to be a specific charge with reasonable certainty.", false}, {MS_DSQ, "MS:1000634", "DSQ", "ThermoFinnigan DSQ GC-MS.", false}, {MS_ITQ_700, "MS:1000635", "ITQ 700", "Thermo Scientific ITQ 700 GC-MS.", false}, {MS_ITQ_900, "MS:1000636", "ITQ 900", "Thermo Scientific ITQ 900 GC-MS.", false}, {MS_ITQ_1100, "MS:1000637", "ITQ 1100", "Thermo Scientific ITQ 1100 GC-MS.", false}, {MS_LTQ_XL_ETD, "MS:1000638", "LTQ XL ETD", "Thermo Scientific LTQ XL MS with ETD.", false}, {MS_LTQ_Orbitrap_XL_ETD, "MS:1000639", "LTQ Orbitrap XL ETD", "Thermo Scientific LTQ Orbitrap XL MS with ETD.", false}, {MS_DFS, "MS:1000640", "DFS", "Thermo Scientific DFS HR GC-MS.", false}, {MS_DSQ_II, "MS:1000641", "DSQ II", "Thermo Scientific DSQ II GC-MS.", false}, {MS_MALDI_LTQ_XL, "MS:1000642", "MALDI LTQ XL", "Thermo Scientific MALDI LTQ XL MS.", false}, {MS_MALDI_LTQ_Orbitrap, "MS:1000643", "MALDI LTQ Orbitrap", "Thermo Scientific MALDI LTQ Orbitrap MS.", false}, {MS_TSQ_Quantum_Access, "MS:1000644", "TSQ Quantum Access", "Thermo Scientific TSQ Quantum Access MS.", false}, {MS_Element_XR, "MS:1000645", "Element XR", "Thermo Scientific Element XR HR-ICP-MS.", false}, {MS_Element_2, "MS:1000646", "Element 2", "Thermo Scientific Element 2 HR-ICP-MS.", false}, {MS_Element_GD, "MS:1000647", "Element GD", "Thermo Scientific Element GD Glow Discharge MS.", false}, {MS_GC_IsoLink, "MS:1000648", "GC IsoLink", "Thermo Scientific GC IsoLink Isotope Ratio MS.", false}, {MS_Exactive, "MS:1000649", "Exactive", "Thermo Scientific Exactive MS.", false}, {MS_Proteome_Discoverer, "MS:1000650", "Proteome Discoverer", "Thermo Scientific software for data analysis of peptides and proteins.", false}, {MS_3200_QTRAP, "MS:1000651", "3200 QTRAP", "SCIEX or Applied Biosystems|MDS SCIEX QTRAP 3200.", false}, {MS_4800_Plus_MALDI_TOF_TOF, "MS:1000652", "4800 Plus MALDI TOF/TOF", "SCIEX or Applied Biosystems|MDS SCIEX 4800 Plus MALDI TOF-TOF Analyzer.", false}, {MS_API_3200, "MS:1000653", "API 3200", "SCIEX or Applied Biosystems|MDS SCIEX API 3200 MS.", false}, {MS_API_5000, "MS:1000654", "API 5000", "SCIEX or Applied Biosystems|MDS SCIEX API 5000 MS.", false}, {MS_QSTAR_Elite, "MS:1000655", "QSTAR Elite", "SCIEX or Applied Biosystems|MDS SCIEX QSTAR Elite.", false}, {MS_QSTAR_Pulsar, "MS:1000656", "QSTAR Pulsar", "Applied Biosystems|MDS SCIEX QSTAR Pulsar.", false}, {MS_QSTAR_XL, "MS:1000657", "QSTAR XL", "Applied Biosystems|MDS SCIEX QSTAR XL.", false}, {MS_4800_Proteomics_Analyzer, "MS:1000658", "4800 Proteomics Analyzer", "Applied Biosystems|MDS SCIEX 4800 Proteomics Analyzer.", false}, {MS_4000_Series_Explorer_Software, "MS:1000659", "4000 Series Explorer Software", "SCIEX or Applied Biosystems software for data acquisition and analysis.", false}, {MS_GPS_Explorer, "MS:1000661", "GPS Explorer", "SCIEX or Applied Biosystems software for data acquisition and analysis.", false}, {MS_LightSight_Software, "MS:1000662", "LightSight Software", "SCIEX or Applied Biosystems|MDS SCIEX software metabolite identification.", false}, {MS_ProteinPilot_Software, "MS:1000663", "ProteinPilot Software", "SCIEX or Applied Biosystems|MDS SCIEX software for protein ID and quant.", false}, {MS_TissueView_Software, "MS:1000664", "TissueView Software", "Applied Biosystems|MDS SCIEX software for tissue imaging.", false}, {MS_MarkerView_Software, "MS:1000665", "MarkerView Software", "Applied Biosystems|MDS SCIEX software for metabolomics and biomarker profiling.", false}, {MS_MRMPilot_Software, "MS:1000666", "MRMPilot Software", "Applied Biosystems|MDS SCIEX software for MRM assay development.", false}, {MS_BioAnalyst, "MS:1000667", "BioAnalyst", "Applied Biosystems|MDS SCIEX software for bio-related data exploration.", false}, {MS_Pro_ID, "MS:1000668", "Pro ID", "Applied Biosystems|MDS SCIEX software for protein identification.", false}, {MS_Pro_ICAT, "MS:1000669", "Pro ICAT", "Applied Biosystems|MDS SCIEX software for protein ID and quant by ICAT.", false}, {MS_Pro_Quant, "MS:1000670", "Pro Quant", "Applied Biosystems|MDS SCIEX software for protein ID and quant by iTRAQ.", false}, {MS_Pro_BLAST, "MS:1000671", "Pro BLAST", "Applied Biosystems|MDS SCIEX software for MS-BLAST identification.", false}, {MS_Cliquid, "MS:1000672", "Cliquid", "SCIEX Cliquid software for data analysis and quantitation.", false}, {MS_MIDAS_Workflow_Designer, "MS:1000673", "MIDAS Workflow Designer", "Applied Biosystems|MDS SCIEX software for MRM assay development.", false}, {MS_MultiQuant, "MS:1000674", "MultiQuant", "Applied Biosystems|MDS SCIEX software for MRM-based quantitation.", false}, {MS_6220_Time_of_Flight_LC_MS, "MS:1000675", "6220 Time-of-Flight LC/MS", "The 6220 Time-of-Flight LC/MS is a Agilent liquid chromatography instrument combined with a Agilent time of flight mass spectrometer. This time of flight mass spectrometer has a m/z range of 50-12000, mass accuracy of less than 2 ppm and resolution greater than 13,000 at m/z 2722. It has multiple ion sources and can be used with multimode ion sources.", false}, {MS_6510_Quadrupole_Time_of_Flight_LC_MS, "MS:1000676", "6510 Quadrupole Time-of-Flight LC/MS", "The 6510 Quadrupole Time-of-Flight LC/MS is a Agilent liquid chromatography instrument combined with a Agilent time of flight mass spectrometer. This time of flight mass spectrometer has a m/z range of 50-12000, mass accuracy of less than 2 ppm and resolution greater than 13,000 at m/z 2722. It has multiple ion sources and can be used with multimode ion sources.", false}, {MS_6520_Quadrupole_Time_of_Flight_LC_MS, "MS:1000677", "6520 Quadrupole Time-of-Flight LC/MS", "The 6520 Quadrupole Time-of-Flight LC/MS is a Agilent liquid chromatography instrument combined with a Agilent time of flight mass spectrometer. This time of flight mass spectrometer has a m/z range of 50-12000, mass accuracy of less than 2 ppm and resolution greater than 26,000 at m/z 2722. It has multiple ion sources and can be used with multimode ion sources.", false}, {MS_MassHunter_Data_Acquisition, "MS:1000678", "MassHunter Data Acquisition", "Software for data acquisition of 6000 series instruments.", false}, {MS_MassHunter_Easy_Access, "MS:1000679", "MassHunter Easy Access", "Software for open access data acquisition.", false}, {MS_MassHunter_Qualitative_Analysis, "MS:1000680", "MassHunter Qualitative Analysis", "Software for data analysis of data from 6000 series instruments.", false}, {MS_MassHunter_Quantitative_Analysis, "MS:1000681", "MassHunter Quantitative Analysis", "Software for quantitation of Triple Quadrupole and Quadrupole Time-of-Flight data.", false}, {MS_MassHunter_Metabolite_ID, "MS:1000682", "MassHunter Metabolite ID", "Software for identification of metabolites.", false}, {MS_MassHunter_BioConfirm, "MS:1000683", "MassHunter BioConfirm", "Software for protein characterization.", false}, {MS_Genespring_MS, "MS:1000684", "Genespring MS", "Software for quantitation and statistical analysis of TOF and Q-TOF LC/MS data.", false}, {MS_MassHunter_Mass_Profiler, "MS:1000685", "MassHunter Mass Profiler", "Software for quantitation and statistical analysis of TOF and Q-TOF LC/MS data.", false}, {MS_METLIN, "MS:1000686", "METLIN", "Personal Metabolite Database for MassHunter Workstation. Software for identification of human metabolites.", false}, {MS_Spectrum_Mill_for_MassHunter_Workstation, "MS:1000687", "Spectrum Mill for MassHunter Workstation", "Software for protein identification and characterization of complex protein digest mixtures.", false}, {MS_6300_Series_Ion_Trap_Data_Analysis_Software, "MS:1000688", "6300 Series Ion Trap Data Analysis Software", "Software for data analysis of 6300 series ion trap mass spectrometers.", false}, {MS_Agilent_software, "MS:1000689", "Agilent software", "Agilent software for data acquisition and analysis.", false}, {MS_SCIEX_software, "MS:1000690", "SCIEX software", "SCIEX or Applied Biosystems software for data acquisition and analysis.", false}, {MS_Applied_Biosystems_software, "MS:1000691", "Applied Biosystems software", "Applied Biosystems|MDS SCIEX software for data acquisition and analysis.", false}, {MS_Bruker_software, "MS:1000692", "Bruker software", "Bruker software for data acquisition and analysis.", false}, {MS_Thermo_Finnigan_software, "MS:1000693", "Thermo Finnigan software", "Thermo Finnigan software for data acquisition and analysis.", false}, {MS_Waters_software, "MS:1000694", "Waters software", "Waters software for data acquisition and analysis.", false}, {MS_apex_ultra, "MS:1000695", "apex ultra", "Bruker Daltonics' apex ultra: ESI, MALDI, Nanospray, APCI, APPI, Qh-FT_ICR.", false}, {MS_autoflex_III_smartbeam, "MS:1000696", "autoflex III smartbeam", "Bruker Daltonics' autoflex III smartbeam: MALDI TOF.", false}, {MS_Bruker_Daltonics_HCT_Series, "MS:1000697", "Bruker Daltonics HCT Series", "Bruker Daltonics' HCT Series.", false}, {MS_HCTultra, "MS:1000698", "HCTultra", "Bruker Daltonics' HCTultra: ESI TOF, Nanospray, APCI, APPI.", false}, {MS_HCTultra_PTM, "MS:1000699", "HCTultra PTM", "Bruker Daltonics' HCTultra PTM: ESI TOF, Nanospray, APCI, APPI, PTR.", false}, {MS_HCTultra_ETD_II, "MS:1000700", "HCTultra ETD II", "Bruker Daltonics' HCTultra ETD II: ESI Q-TOF, Nanospray, APCI, APPI, ETD.", false}, {MS_microflex_LT, "MS:1000701", "microflex LT", "Bruker Daltonics' microflex LT: MALDI TOF.", false}, {MS_micrOTOF, "MS:1000702", "micrOTOF", "Bruker Daltonics' micrOTOF: ESI TOF, APCI, APPI.", false}, {MS_micrOTOF_Q, "MS:1000703", "micrOTOF-Q", "Bruker Daltonics' micrOTOF-Q: ESI Q-TOF, Nanospray, APCI, APPI.", false}, {MS_micrOTOF_Q_II, "MS:1000704", "micrOTOF-Q II", "Bruker Daltonics' micrOTOF-Q II: ESI Q-TOF, Nanospray, APCI, APPI.", false}, {MS_ultraflex_III_TOF_TOF, "MS:1000705", "ultraflex III TOF/TOF", "Bruker Daltonics' ultraflex III TOF/TOF: MALDI TOF.", false}, {MS_apexControl, "MS:1000706", "apexControl", "Bruker software for data acquisition.", false}, {MS_BioTools, "MS:1000707", "BioTools", "Bruker software for data analysis.", false}, {MS_CLINPROT, "MS:1000708", "CLINPROT", "Bruker CLINPROT software.", false}, {MS_CLINPROT_micro, "MS:1000709", "CLINPROT micro", "Bruker CLINPROT micro software.", false}, {MS_CLINPROT_robot, "MS:1000710", "CLINPROT robot", "Bruker CLINPROT robot software.", false}, {MS_ClinProTools, "MS:1000711", "ClinProTools", "Bruker ClinProTools software.", false}, {MS_Compass, "MS:1000712", "Compass", "Bruker Compass software.", false}, {MS_Compass_for_HCT_esquire, "MS:1000713", "Compass for HCT/esquire", "Bruker Compass for HCT/esquire software.", false}, {MS_Compass_for_micrOTOF, "MS:1000714", "Compass for micrOTOF", "Bruker Compass for micrOTOF software.", false}, {MS_Compass_OpenAccess, "MS:1000715", "Compass OpenAccess", "Bruker compass OpenAccess software.", false}, {MS_Compass_Security_Pack, "MS:1000716", "Compass Security Pack", "Bruker compass Security Pack software.", false}, {MS_CompassXport, "MS:1000717", "CompassXport", "Bruker stand-alone software for data conversion.", false}, {MS_CompassXtract, "MS:1000718", "CompassXtract", "Bruker software library for data access.", false}, {MS_DataAnalysis, "MS:1000719", "DataAnalysis", "Bruker software for data analysis.", false}, {MS_dpControl, "MS:1000720", "dpControl", "Bruker software for data acquisition.", false}, {MS_esquireControl, "MS:1000721", "esquireControl", "Bruker software for data acquisition.", false}, {MS_flexImaging, "MS:1000722", "flexImaging", "Bruker software for data analysis.", false}, {MS_GENOLINK, "MS:1000723", "GENOLINK", "Bruker GENOLINK software.", false}, {MS_GenoTools, "MS:1000724", "GenoTools", "Bruker GenoTools software.", false}, {MS_HCTcontrol, "MS:1000725", "HCTcontrol", "Bruker software for data acquisition.", false}, {MS_micrOTOFcontrol, "MS:1000726", "micrOTOFcontrol", "Bruker software for data acquisition.", false}, {MS_PolyTools, "MS:1000727", "PolyTools", "Bruker PolyTools software.", false}, {MS_ProfileAnalysis, "MS:1000728", "ProfileAnalysis", "Bruker software for data analysis.", false}, {MS_PROTEINEER, "MS:1000729", "PROTEINEER", "Bruker PROTEINEER software.", false}, {MS_PROTEINEER_dp, "MS:1000730", "PROTEINEER dp", "Bruker PROTEINEER dp software.", false}, {MS_PROTEINEER_fc, "MS:1000731", "PROTEINEER fc", "Bruker PROTEINEER fc software.", false}, {MS_PROTEINEER_spII, "MS:1000732", "PROTEINEER spII", "Bruker PROTEINEER spII software.", false}, {MS_PROTEINEER_LC, "MS:1000733", "PROTEINEER-LC", "Bruker PROTEINEER-LC software.", false}, {MS_ProteinScape, "MS:1000734", "ProteinScape", "Bruker ProteinScape software.", false}, {MS_PureDisk, "MS:1000735", "PureDisk", "BrukerPureDisk software.", false}, {MS_QuantAnalysis, "MS:1000736", "QuantAnalysis", "Bruker software for data analysis.", false}, {MS_spControl, "MS:1000737", "spControl", "Bruker software for data acquisition.", false}, {MS_TargetAnalysis, "MS:1000738", "TargetAnalysis", "Bruker TargetAnalysis software.", false}, {MS_WARP_LC, "MS:1000739", "WARP-LC", "Bruker WARP-LC software.", false}, {MS_parameter_file, "MS:1000740", "parameter file", "Parameter file used to configure the acquisition of raw data on the instrument.", false}, {MS_Conversion_to_dta, "MS:1000741", "Conversion to dta", "Conversion to dta format.", false}, {MS_Bioworks_SRF_format, "MS:1000742", "Bioworks SRF format", "Thermo Finnigan SRF file format.", false}, {MS_TSQ_Quantum_Ultra_AM, "MS:1000743", "TSQ Quantum Ultra AM", "Thermo Scientific TSQ Quantum Ultra AM.", false}, {MS_selected_ion_m_z, "MS:1000744", "selected ion m/z", "Mass-to-charge ratio of an selected ion.", false}, {MS_retention_time_alignment, "MS:1000745", "retention time alignment", "The correction of the spectrum scan times, as used e.g. in label-free proteomics.", false}, {MS_high_intensity_data_point_removal, "MS:1000746", "high intensity data point removal", "The removal of very high intensity data points.", false}, {MS_completion_time, "MS:1000747", "completion time", "The time that a data processing action was finished.", false}, {MS_SSQ_7000, "MS:1000748", "SSQ 7000", "ThermoFinnigan SSQ 7000 MS.", false}, {MS_TSQ_7000, "MS:1000749", "TSQ 7000", "ThermoFinnigan TSQ 7000 MS.", false}, {MS_TSQ, "MS:1000750", "TSQ", "ThermoFinnigan TSQ MS.", false}, {MS_TSQ_Quantum_Ultra, "MS:1000751", "TSQ Quantum Ultra", "Thermo Scientific TSQ Quantum Ultra.", false}, {MS_TOPP_software, "MS:1000752", "TOPP software", "TOPP (The OpenMS proteomics pipeline) software.", false}, {MS_BaselineFilter, "MS:1000753", "BaselineFilter", "Removes the baseline from profile spectra using a top-hat filter.", false}, {MS_DBExporter, "MS:1000754", "DBExporter", "Exports data from an OpenMS database to a file.", false}, {MS_DBImporter, "MS:1000755", "DBImporter", "Imports data to an OpenMS database.", false}, {MS_FileConverter, "MS:1000756", "FileConverter", "Converts between different MS file formats.", false}, {MS_FileFilter, "MS:1000757", "FileFilter", "Extracts or manipulates portions of data from peak, feature or consensus feature files.", false}, {MS_FileMerger, "MS:1000758", "FileMerger", "Merges several MS files into one file.", false}, {MS_InternalCalibration, "MS:1000759", "InternalCalibration", "Applies an internal calibration.", false}, {MS_MapAligner_OBSOLETE, "MS:1000760", "MapAligner", "Corrects retention time distortions between maps.", true}, {MS_MapNormalizer, "MS:1000761", "MapNormalizer", "Normalizes peak intensities in an MS run.", false}, {MS_NoiseFilter_OBSOLETE, "MS:1000762", "NoiseFilter", "Removes noise from profile spectra by using different smoothing techniques.", true}, {MS_PeakPicker_OBSOLETE, "MS:1000763", "PeakPicker", "Finds mass spectrometric peaks in profile mass spectra.", true}, {MS_Resampler, "MS:1000764", "Resampler", "Transforms an LC/MS map into a resampled map or a png image.", false}, {MS_SpectraFilter_OBSOLETE, "MS:1000765", "SpectraFilter", "Applies a filter to peak spectra.", true}, {MS_TOFCalibration, "MS:1000766", "TOFCalibration", "Applies time of flight calibration.", false}, {MS_native_spectrum_identifier_format, "MS:1000767", "native spectrum identifier format", "Describes how the native spectrum identifiers are formated.", false}, {MS_Thermo_nativeID_format, "MS:1000768", "Thermo nativeID format", "Native format defined by controllerType=xsd:nonNegativeInteger controllerNumber=xsd:positiveInteger scan=xsd:positiveInteger.", false}, {MS_Waters_nativeID_format, "MS:1000769", "Waters nativeID format", "Native format defined by function=xsd:positiveInteger process=xsd:nonNegativeInteger scan=xsd:nonNegativeInteger.", false}, {MS_WIFF_nativeID_format, "MS:1000770", "WIFF nativeID format", "Native format defined by sample=xsd:nonNegativeInteger period=xsd:nonNegativeInteger cycle=xsd:nonNegativeInteger experiment=xsd:nonNegativeInteger.", false}, {MS_Bruker_Agilent_YEP_nativeID_format, "MS:1000771", "Bruker/Agilent YEP nativeID format", "Native format defined by scan=xsd:nonNegativeInteger.", false}, {MS_Bruker_BAF_nativeID_format, "MS:1000772", "Bruker BAF nativeID format", "Native format defined by scan=xsd:nonNegativeInteger.", false}, {MS_Bruker_FID_nativeID_format, "MS:1000773", "Bruker FID nativeID format", "Native format defined by file=xsd:IDREF.", false}, {MS_multiple_peak_list_nativeID_format, "MS:1000774", "multiple peak list nativeID format", "Native format defined by index=xsd:nonNegativeInteger.", false}, {MS_single_peak_list_nativeID_format, "MS:1000775", "single peak list nativeID format", "Native format defined by file=xsd:IDREF.", false}, {MS_scan_number_only_nativeID_format, "MS:1000776", "scan number only nativeID format", "Native format defined by scan=xsd:nonNegativeInteger.", false}, {MS_spectrum_identifier_nativeID_format, "MS:1000777", "spectrum identifier nativeID format", "Native format defined by spectrum=xsd:nonNegativeInteger.", false}, {MS_charge_state_calculation, "MS:1000778", "charge state calculation", "A process that infers the charge state of an MSn spectrum's precursor(s) by the application of some algorithm.", false}, {MS_below_precursor_intensity_dominance_charge_state_calculation, "MS:1000779", "below precursor intensity dominance charge state calculation", "Infers charge state as single or ambiguously multiple by determining the fraction of intensity below the precursor m/z.", false}, {MS_precursor_recalculation, "MS:1000780", "precursor recalculation", "A process that recalculates existing precursor selected ions with one or more algorithmically determined precursor selected ions.", false}, {MS_msPrefix_precursor_recalculation, "MS:1000781", "msPrefix precursor recalculation", "Recalculates one or more precursor selected ions by peak detection in the isolation windows of high accuracy MS precursor scans.", false}, {MS_Savitzky_Golay_smoothing, "MS:1000782", "Savitzky-Golay smoothing", "Reduces intensity spikes by applying local polynomial regression (of degree k) on a distribution (of at least k+1 equally spaced points) to determine the smoothed value for each point. It tends to preserve features of the distribution such as relative maxima, minima and width, which are usually 'flattened' by other adjacent averaging techniques.", false}, {MS_LOWESS_smoothing, "MS:1000783", "LOWESS smoothing", "Reduces intensity spikes by applying a modelling method known as locally weighted polynomial regression. At each point in the data set a low-degree polynomial is fit to a subset of the data, with explanatory variable values near the point whose response is being estimated. The polynomial is fit using weighted least squares, giving more weight to points near the point whose response is being estimated and less weight to points further away. The value of the regression function for the point is then obtained by evaluating the local polynomial using the explanatory variable values for that data point. The LOESS fit is complete after regression function values have been computed for each of the n data points. Many of the details of this method, such as the degree of the polynomial model and the weights, are flexible.", false}, {MS_Gaussian_smoothing, "MS:1000784", "Gaussian smoothing", "Reduces intensity spikes by convolving the data with a one-dimensional Gaussian function.", false}, {MS_moving_average_smoothing, "MS:1000785", "moving average smoothing", "Reduces intensity spikes by averaging each point with two or more adjacent points. The more adjacent points that used, the stronger the smoothing effect.", false}, {MS_non_standard_data_array, "MS:1000786", "non-standard data array", "A data array that contains data not covered by any other term in this group. Please do not use this term, if the binary data array type might be commonly used - contact the PSI-MS working group in order to have another CV term added.", false}, {MS_inclusive_low_intensity_threshold, "MS:1000787", "inclusive low intensity threshold", "Threshold at or below which some action is taken.", false}, {MS_inclusive_high_intensity_threshold, "MS:1000788", "inclusive high intensity threshold", "Threshold at or above which some action is taken.", false}, {MS_enhanced_multiply_charged_spectrum, "MS:1000789", "enhanced multiply charged spectrum", "MS1 spectrum that is enriched in multiply-charged ions compared to singly-charged ions.", false}, {MS_time_delayed_fragmentation_spectrum, "MS:1000790", "time-delayed fragmentation spectrum", "MSn spectrum in which the product ions are collected after a time delay, which allows the observation of lower energy fragmentation processes after precursor ion activation.", false}, {MS_enhanced_resolution_scan_OBSOLETE, "MS:1000791", "enhanced resolution scan", "Scan with enhanced resolution.", true}, {MS_isolation_window_attribute, "MS:1000792", "isolation window attribute", "Isolation window parameter.", false}, {MS_isolation_window_upper_limit_OBSOLETE, "MS:1000793", "isolation window upper limit", "The highest m/z being isolated in an isolation window.", true}, {MS_isolation_window_lower_limit_OBSOLETE, "MS:1000794", "isolation window lower limit", "The lowest m/z being isolated in an isolation window.", true}, {MS_no_combination, "MS:1000795", "no combination", "Use this term if only one scan was recorded or there is no information about scans available.", false}, {MS_spectrum_title, "MS:1000796", "spectrum title", "A free-form text title describing a spectrum.", false}, {MS_peak_list_scans, "MS:1000797", "peak list scans", "A list of scan numbers and or scan ranges associated with a peak list. If possible the list of scans should be converted to native spectrum identifiers instead of using this term.", false}, {MS_peak_list_raw_scans, "MS:1000798", "peak list raw scans", "A list of raw scans and or scan ranges used to generate a peak list. If possible the list of scans should be converted to native spectrum identifiers instead of using this term.", false}, {MS_custom_unreleased_software_tool, "MS:1000799", "custom unreleased software tool", "A software tool that has not yet been released. The value should describe the software. Please do not use this term for publicly available software - contact the PSI-MS working group in order to have another CV term added.", false}, {MS_mass_resolving_power, "MS:1000800", "mass resolving power", "The observed mass divided by the difference between two masses that can be separated: m/dm. The procedure by which dm was obtained and the mass at which the measurement was made should be reported.", false}, {MS_area_peak_picking, "MS:1000801", "area peak picking", "Spectral peak processing conducted on the acquired data to convert profile data to centroided data. The area defined by all raw data points that belong to the peak is reported.", false}, {MS_height_peak_picking, "MS:1000802", "height peak picking", "Spectral peak processing conducted on the acquired data to convert profile data to centroided data. The maximum intensity of all raw data points that belong to the peak is reported.", false}, {MS_analyzer_scan_offset, "MS:1000803", "analyzer scan offset", "Offset between two analyzers in a constant neutral loss or neutral gain scan. The value corresponds to the neutral loss or neutral gain value.", false}, {MS_electromagnetic_radiation_spectrum, "MS:1000804", "electromagnetic radiation spectrum", "A plot of the relative intensity of electromagnetic radiation as a function of the wavelength.", false}, {MS_emission_spectrum, "MS:1000805", "emission spectrum", "A plot of the relative intensity of electromagnetic radiation emitted by atoms or molecules when excited.", false}, {MS_absorption_spectrum, "MS:1000806", "absorption spectrum", "A plot of the relative intensity of electromagnetic radiation absorbed by atoms or molecules when excited.", false}, {MS_Th_s, "MS:1000807", "Th/s", "Unit describing the scan rate of a spectrum in Thomson per second.", false}, {MS_chromatogram_attribute, "MS:1000808", "chromatogram attribute", "Chromatogram properties that are associated with a value.", false}, {MS_chromatogram_title, "MS:1000809", "chromatogram title", "A free-form text title describing a chromatogram.", false}, {MS_mass_chromatogram, "MS:1000810", "mass chromatogram", "A plot of the relative abundance of a beam or other collection of ions as a function of the retention time.", false}, {MS_electromagnetic_radiation_chromatogram, "MS:1000811", "electromagnetic radiation chromatogram", "The measurement of electromagnetic properties as a function of the retention time.", false}, {MS_absorption_chromatogram, "MS:1000812", "absorption chromatogram", "The measurement of light absorbed by the sample as a function of the retention time.", false}, {MS_emission_chromatogram, "MS:1000813", "emission chromatogram", "The measurement of light emitted by the sample as a function of the retention time.", false}, {MS_counts_per_second, "MS:1000814", "counts per second", "The number of counted events observed per second in one or a group of elements of a detector.", false}, {MS_Bruker_BAF_format, "MS:1000815", "Bruker BAF format", "Bruker BAF raw file format.", false}, {MS_Bruker_U2_format, "MS:1000816", "Bruker U2 format", "Bruker HyStar U2 file format.", false}, {MS_HyStar, "MS:1000817", "HyStar", "Bruker software for hyphenated experiments.", false}, {MS_Acquity_UPLC_PDA, "MS:1000818", "Acquity UPLC PDA", "Acquity UPLC Photodiode Array Detector.", false}, {MS_Acquity_UPLC_FLR, "MS:1000819", "Acquity UPLC FLR", "Acquity UPLC Fluorescence Detector.", false}, {MS_flow_rate_array, "MS:1000820", "flow rate array", "A data array of flow rate measurements.", false}, {MS_pressure_array, "MS:1000821", "pressure array", "A data array of pressure measurements.", false}, {MS_temperature_array, "MS:1000822", "temperature array", "A data array of temperature measurements.", false}, {MS_Bruker_U2_nativeID_format, "MS:1000823", "Bruker U2 nativeID format", "Native format defined by declaration=xsd:nonNegativeInteger collection=xsd:nonNegativeInteger scan=xsd:nonNegativeInteger.", false}, {MS_no_nativeID_format, "MS:1000824", "no nativeID format", "No nativeID format indicates that the file tagged with this term does not contain spectra that can have a nativeID format.", false}, {MS_Bruker_FID_format, "MS:1000825", "Bruker FID format", "Bruker FID file format.", false}, {MS_elution_time, "MS:1000826", "elution time", "The time of elution from all used chromatographic columns (one or more) in the chromatographic separation step, relative to the start of the chromatography.", false}, {MS_isolation_window_target_m_z, "MS:1000827", "isolation window target m/z", "The primary or reference m/z about which the isolation window is defined.", false}, {MS_isolation_window_lower_offset, "MS:1000828", "isolation window lower offset", "The extent of the isolation window in m/z below the isolation window target m/z. The lower and upper offsets may be asymmetric about the target m/z.", false}, {MS_isolation_window_upper_offset, "MS:1000829", "isolation window upper offset", "The extent of the isolation window in m/z above the isolation window target m/z. The lower and upper offsets may be asymmetric about the target m/z.", false}, {MS_sample_preparation, "MS:1000831", "sample preparation", "Properties of the preparation steps which took place before the measurement was performed.", false}, {MS_MALDI_matrix_application, "MS:1000832", "MALDI matrix application", "Attributes to describe the technique how the sample is prepared with the matrix solution.", false}, {MS_matrix_application_type, "MS:1000833", "matrix application type", "Describes the technique how the matrix is put on the sample target.", false}, {MS_matrix_solution, "MS:1000834", "matrix solution", "Describes the chemical solution used as matrix.", false}, {MS_matrix_solution_concentration, "MS:1000835", "matrix solution concentration", "Concentration of the chemical solution used as matrix.", false}, {MS_dried_droplet_MALDI_matrix_preparation, "MS:1000836", "dried droplet MALDI matrix preparation", "Dried droplet in MALDI matrix preparation.", false}, {MS_printed_MALDI_matrix_preparation, "MS:1000837", "printed MALDI matrix preparation", "Printed MALDI matrix preparation.", false}, {MS_sprayed_MALDI_matrix_preparation, "MS:1000838", "sprayed MALDI matrix preparation", "Sprayed MALDI matrix preparation.", false}, {MS_precoated_MALDI_sample_plate, "MS:1000839", "precoated MALDI sample plate", "Precoated MALDI sample plate.", false}, {MS_laser, "MS:1000840", "laser", "Device that emits light (electromagnetic radiation) through a process called stimulated emission. The term is an acronym for Light Amplification by Stimulated Emission of Radiation.", false}, {MS_laser_attribute, "MS:1000841", "laser attribute", "Laser properties that are associated with a value.", false}, {MS_laser_type, "MS:1000842", "laser type", "Type of laser used used for desorption purpose.", false}, {MS_wavelength_OBSOLETE, "MS:1000843", "wavelength", "The distance between two peaks of the emitted laser beam.", true}, {MS_focus_diameter_x, "MS:1000844", "focus diameter x", "Describes the diameter of the laser beam in x direction.", false}, {MS_focus_diameter_y, "MS:1000845", "focus diameter y", "Describes the diameter of the laser beam in y direction.", false}, {MS_pulse_energy, "MS:1000846", "pulse energy", "Describes output energy of the laser system. May be attenuated by filters or other means.", false}, {MS_pulse_duration, "MS:1000847", "pulse duration", "Describes how long the laser beam was emitted from the laser device.", false}, {MS_attenuation, "MS:1000848", "attenuation", "Describes the reduction of the intensity of the laser beam energy.", false}, {MS_impact_angle, "MS:1000849", "impact angle", "Describes the angle between the laser beam and the sample target.", false}, {MS_gas_laser, "MS:1000850", "gas laser", "Laser which is powered by a gaseous medium.", false}, {MS_solid_state_laser, "MS:1000851", "solid-state laser", "Solid state laser materials are commonly made by doping a crystalline solid host with ions that provide the required energy states.", false}, {MS_dye_laser, "MS:1000852", "dye-laser", "Dye lasers use an organic dye as the gain medium.", false}, {MS_free_electron_laser, "MS:1000853", "free electron laser", "Free electron laser uses a relativistic electron beam as the lasing medium which move freely through a magnetic structure, hence the term.", false}, {MS_LTQ_XL, "MS:1000854", "LTQ XL", "Thermo Scientific LTQ XL MS.", false}, {MS_LTQ_Velos, "MS:1000855", "LTQ Velos", "Thermo Scientific LTQ Velos MS.", false}, {MS_LTQ_Velos_ETD, "MS:1000856", "LTQ Velos ETD", "Thermo Scientific LTQ Velos MS with ETD.", false}, {MS_run_attribute, "MS:1000857", "run attribute", "Properties of the described run.", false}, {MS_fraction_identifier, "MS:1000858", "fraction identifier", "Identier string that describes the sample fraction. This identifier should contain the fraction number(s) or similar information.", false}, {MS_molecule, "MS:1000859", "molecule", "A molecules is a fundamental component of a chemical compound that is the smallest part of the compound that can participate in a chemical reaction.", false}, {MS_peptide, "MS:1000860", "peptide", "A compound of low molecular weight that is composed of two or more amino acids.", false}, {MS_chemical_compound_attribute, "MS:1000861", "chemical compound attribute", "A describable property of a chemical compound.", false}, {MS_isoelectric_point, "MS:1000862", "isoelectric point", "The pH of a solution at which a charged molecule does not migrate in an electric field.", false}, {MS_predicted_isoelectric_point, "MS:1000863", "predicted isoelectric point", "The pH of a solution at which a charged molecule would not migrate in an electric field, as predicted by a software algorithm.", false}, {MS_chemical_compound_formula, "MS:1000864", "chemical compound formula", "A combination of symbols used to express the chemical composition of a compound.", false}, {MS_empirical_formula, "MS:1000865", "empirical formula", "A chemical formula which expresses the proportions of the elements present in a substance.", false}, {MS_molecular_formula, "MS:1000866", "molecular formula", "A chemical compound formula expressing the number of atoms of each element present in a compound, without indicating how they are linked.", false}, {MS_structural_formula, "MS:1000867", "structural formula", "A chemical formula showing the number of atoms of each element in a molecule, their spatial arrangement, and their linkage to each other.", false}, {MS_SMILES_string, "MS:1000868", "SMILES string", "The simplified molecular input line entry specification or SMILES is a specification for unambiguously describing the structure of a chemical compound using a short ASCII string.", false}, {MS_collision_gas_pressure, "MS:1000869", "collision gas pressure", "The gas pressure of the collision gas used for collisional excitation.", false}, {MS_4000_QTRAP_OBSOLETE, "MS:1000870", "4000 QTRAP", "SCIEX or Applied Biosystems|MDS SCIEX QTRAP 4000.", true}, {MS_SRM_software, "MS:1000871", "SRM software", "Software used to predict, select, or optimize transitions or analyze the results of selected reaction monitoring runs.", false}, {MS_MaRiMba, "MS:1000872", "MaRiMba", "Software used to predict transitions for selected reaction monitoring experiments based on observed spectrum libraries developed and distributed by the Institute for Systems Biology.", false}, {MS_peptide_attribute_calculation_software, "MS:1000873", "peptide attribute calculation software", "Software used to predict or calculate numerical attributes of peptides.", false}, {MS_SSRCalc, "MS:1000874", "SSRCalc", "Sequence Specific Retention Calculator estimates the retention time of peptides based on their sequence.", false}, {MS_declustering_potential, "MS:1000875", "declustering potential", "Potential difference between the orifice and the skimmer in volts.", false}, {MS_cone_voltage, "MS:1000876", "cone voltage", "Potential difference between the sampling cone/orifice in volts.", false}, {MS_tube_lens_voltage, "MS:1000877", "tube lens voltage", "Potential difference setting of the tube lens in volts.", false}, {MS_external_reference_identifier, "MS:1000878", "external reference identifier", "An identifier/accession number to an external reference database.", false}, {MS_PubMed_identifier, "MS:1000879", "PubMed identifier", "A unique identifier for a publication in the PubMed database (MIR:00000015).", false}, {MS_interchannel_delay, "MS:1000880", "interchannel delay", "The duration of intervals between scanning, during which the instrument configuration is switched.", false}, {MS_chemical_compound, "MS:1000881", "chemical compound", "A substance formed by chemical union of two or more elements or ingredients in definite proportion by weight.", false}, {MS_protein, "MS:1000882", "protein", "A compound composed of one or more chains of amino acids in a specific order determined by the base sequence of nucleotides in the DNA coding for the protein.", false}, {MS_protein_short_name, "MS:1000883", "protein short name", "A short name or symbol of a protein (e.g., HSF 1 or HSF1_HUMAN).", false}, {MS_protein_attribute, "MS:1000884", "protein attribute", "An nonphysical attribute describing a specific protein.", false}, {MS_protein_accession, "MS:1000885", "protein accession", "Accession number for a specific protein in a database.", false}, {MS_protein_name, "MS:1000886", "protein name", "A long name describing the function of the protein.", false}, {MS_peptide_attribute, "MS:1000887", "peptide attribute", "A nonphysical attribute that can be used to describe a peptide.", false}, {MS_unmodified_peptide_sequence, "MS:1000888", "unmodified peptide sequence", "A sequence of letter symbols denoting the order of amino acids that compose the peptide, without encoding any amino acid mass modifications that might be present.", false}, {MS_modified_peptide_sequence, "MS:1000889", "modified peptide sequence", "A sequence of letter symbols denoting the order of amino acids that compose the peptide plus the encoding any amino acid modifications that are present.", false}, {MS_peptide_labeling_state, "MS:1000890", "peptide labeling state", "A state description of how a peptide might be isotopically or isobarically labelled.", false}, {MS_heavy_labeled_peptide, "MS:1000891", "heavy labeled peptide", "A peptide that has been created or labelled with some heavier-than-usual isotopes.", false}, {MS_unlabeled_peptide, "MS:1000892", "unlabeled peptide", "A peptide that has not been labelled with heavier-than-usual isotopes. This is often referred to as \\\"light\\\" to distinguish from \\\"heavy\\\".", false}, {MS_peptide_group_label, "MS:1000893", "peptide group label", "An arbitrary string label used to mark a set of peptides that belong together in a set, whereby the members are differentiated by different isotopic labels. For example, the heavy and light forms of the same peptide will both be assigned the same peptide group label.", false}, {MS_retention_time, "MS:1000894", "retention time", "A time interval from the start of chromatography when an analyte exits a chromatographic column.", false}, {MS_local_retention_time, "MS:1000895", "local retention time", "A time interval from the start of chromatography when an analyte exits an unspecified local chromatographic column and instrumental setup.", false}, {MS_normalized_retention_time, "MS:1000896", "normalized retention time", "A time interval from the start of chromatography when an analyte exits a standardized reference chromatographic column and instrumental setup.", false}, {MS_predicted_retention_time, "MS:1000897", "predicted retention time", "A time interval from the start of chromatography when an analyte exits a chromatographic column as predicted by a referenced software application.", false}, {MS_standard, "MS:1000898", "standard", "Something, such as a practice or a product, that is widely recognized or employed, especially because of its excellence.", false}, {MS_de_facto_standard, "MS:1000899", "de facto standard", "A practice or product that has become a standard not because it has been approved by a standards organization but because it is widely used and recognized by the industry as being standard.", false}, {MS_minimum_information_standard, "MS:1000900", "minimum information standard", "A specification of a minimum amount of information needed to reproduce or fully interpret a scientific result.", false}, {MS_retention_time_normalization_standard, "MS:1000901", "retention time normalization standard", "A standard providing the retention times at which a set of reference compounds exit the reference chromatographic column.", false}, {MS_H_PINS_retention_time_normalization_standard, "MS:1000902", "H-PINS retention time normalization standard", "The de facto standard providing the retention times at which a set of halogenated reference peptides exit the reference chromatographic column.", false}, {MS_product_ion_series_ordinal, "MS:1000903", "product ion series ordinal", "The ordinal of the fragment within a specified ion series. (e.g. 8 for a y8 ion).", false}, {MS_product_ion_m_z_delta, "MS:1000904", "product ion m/z delta", "The difference in m/z of the predicted m/z based on the assigned product ion minus the actual observed peak m/z.", false}, {MS_percent_of_base_peak_times_100, "MS:1000905", "percent of base peak times 100", "The magnitude of a peak expressed in terms of the percentage of the magnitude of the base peak intensity multiplied by 100. The base peak is therefore 10000. This unit is common in normalized spectrum libraries.", false}, {MS_peak_intensity_rank, "MS:1000906", "peak intensity rank", "Ordinal specifying the rank in intensity of a peak in a spectrum. Base peak is 1. The next most intense peak is 2, etc.", false}, {MS_peak_targeting_suitability_rank, "MS:1000907", "peak targeting suitability rank", "Ordinal specifying the rank of a peak in a spectrum in terms of suitability for targeting. The most suitable peak is 1. The next most suitability peak is 2, etc. Suitability is algorithm and context dependant.", false}, {MS_transition, "MS:1000908", "transition", "A set of two m/z values corresponding to the precursor m/z and a fragment m/z that in combination can be used to identify or quantify a specific ion, although not necessarily uniquely.", false}, {MS_transition_validation_method, "MS:1000909", "transition validation method", "The strategy used to validate that a transition is effective.", false}, {MS_transition_optimized_on_specified_instrument, "MS:1000910", "transition optimized on specified instrument", "The transition has been optimized by direct injection of the peptide into an instrument specified in a separate term, and the optimum voltages and fragmentation energies have been determined.", false}, {MS_transition_validated_with_an_MS_MS_spectrum_on_specified_instrument, "MS:1000911", "transition validated with an MS/MS spectrum on specified instrument", "The transition has been validated by obtaining an MS2 spectrum and demonstrating that the peak is detectable on the instrument specified with a separate term.", false}, {MS_transition_purported_from_an_MS_MS_spectrum_on_a_different__specified_instrument, "MS:1000912", "transition purported from an MS/MS spectrum on a different, specified instrument", "The transition has been purported by obtaining an MS2 spectrum and demonstrating that the peak is detectable on the instrument specified with a separate term. However, the detecting instrument is of a different type (e.g. ion trap) than the instrument that the transition will eventually be used on (e.g. triple quad).", false}, {MS_transition_predicted_by_informatic_analysis, "MS:1000913", "transition predicted by informatic analysis", "The transition has been predicted by informatics software without any direct spectral evidence.", false}, {MS_tab_delimited_text_format, "MS:1000914", "tab delimited text format", "A file format that has two or more columns of tabular data where each column is separated by a TAB character.", false}, {MS_retention_time_window_attribute, "MS:1000915", "retention time window attribute", "An attribute of a window in time about which a peptide might elute from the column.", false}, {MS_retention_time_window_lower_offset, "MS:1000916", "retention time window lower offset", "The extent of the retention time window in time units below the target retention time. The lower and upper offsets may be asymmetric about the target time.", false}, {MS_retention_time_window_upper_offset, "MS:1000917", "retention time window upper offset", "The extent of the retention time window in time units above the target retention time. The lower and upper offsets may be asymmetric about the target time.", false}, {MS_target_list, "MS:1000918", "target list", "A list of peptides or compounds and their expected m/z coordinates that can be used to cause a mass spectrometry to obtain spectra of those molecules specifically.", false}, {MS_target_inclusion_exclusion_priority, "MS:1000919", "target inclusion exclusion priority", "A priority setting specifying whether included or excluded targets have priority over the other.", false}, {MS_includes_supersede_excludes, "MS:1000920", "includes supersede excludes", "A priority setting specifying that included targets have priority over the excluded targets if there is a conflict.", false}, {MS_excludes_supersede_includes, "MS:1000921", "excludes supersede includes", "A priority setting specifying that excluded targets have priority over the included targets if there is a conflict.", false}, {MS_Skyline, "MS:1000922", "Skyline", "Software used to predict, select, and optimize transitions as well as analyze the results of selected reaction monitoring runs developed and distributed by the MacCoss lab at the University of Washington.", false}, {MS_TIQAM, "MS:1000923", "TIQAM", "Software used to predict, select, and optimize transitions for selected reaction monitoring experiments developed and distributed by the Institute for Systems Biology.", false}, {MS_MaRiMba_OBSOLETE, "MS:1000924", "MaRiMba", "Software used to predict transitions for selected reaction monitoring experiments based on observed spectrum libraries developed and distributed by the Institute for Systems Biology.", true}, {MS_ATAQS, "MS:1000925", "ATAQS", "Software suite used to predict, select, and optimize transitions as well as analyze the results of selected reaction monitoring runs developed and distributed by the Institute for Systems Biology.", false}, {MS_product_interpretation_rank, "MS:1000926", "product interpretation rank", "The integer rank given an interpretation of an observed product ion. For example, if y8 is selected as the most likely interpretation of a peak, then it is assigned a rank of 1.", false}, {MS_ion_injection_time, "MS:1000927", "ion injection time", "The length of time spent filling an ion trapping device.", false}, {MS_calibration_spectrum, "MS:1000928", "calibration spectrum", "A spectrum derived from a special calibration source, rather than from the primary injected sample. A calibration spectrum is typically derived from a substance that can be used to correct systematic shift in m/z for spectra of the primary inject sample.", false}, {MS_Shimadzu_Biotech_nativeID_format, "MS:1000929", "Shimadzu Biotech nativeID format", "Native format defined by source=xsd:string start=xsd:nonNegativeInteger end=xsd:nonNegativeInteger.", false}, {MS_Shimadzu_Biotech_database_entity, "MS:1000930", "Shimadzu Biotech database entity", "Shimadzu Biotech format.", false}, {MS_QTRAP_5500, "MS:1000931", "QTRAP 5500", "Applied Biosystems|MDS SCIEX QTRAP 5500.", false}, {MS_TripleTOF_5600, "MS:1000932", "TripleTOF 5600", "SCIEX TripleTOF 5600, a quadrupole - quadrupole - time-of-flight mass spectrometer.", false}, {MS_protein_modifications, "MS:1000933", "protein modifications", "Encoding of modifications of the protein sequence from the specified accession, written in PEFF notation.", false}, {MS_gene_name, "MS:1000934", "gene name", "Name of the gene from which the protein is translated.", false}, {MS_spectrum_interpretation, "MS:1001000", "spectrum interpretation", "Collection of terms from the PSI Proteome Informatics standards describing the interpretation of spectra.", false}, {MS_SEQUEST_CleavesAt, "MS:1001005", "SEQUEST:CleavesAt", "", false}, {MS_SEQUEST_ViewCV, "MS:1001006", "SEQUEST:ViewCV", "SEQUEST View Input Parameters.", false}, {MS_SEQUEST_OutputLines, "MS:1001007", "SEQUEST:OutputLines", "Number of peptide results to show.", false}, {MS_SEQUEST_DescriptionLines, "MS:1001009", "SEQUEST:DescriptionLines", "Number of full protein descriptions to show for top N peptides.", false}, {MS_de_novo_search, "MS:1001010", "de novo search", "A de novo sequencing search (without database).", false}, {MS_search_database_details, "MS:1001011", "search database details", "Details about the database searched.", false}, {MS_database_source, "MS:1001012", "database source", "The organisation, project or laboratory from where the database is obtained (UniProt, NCBI, EBI, other).", false}, {MS_database_name, "MS:1001013", "database name", "The name of the search database (nr, SwissProt or est_human).", false}, {MS_database_local_file_path_OBSOLETE, "MS:1001014", "database local file path", "OBSOLETE: Use attribute in mzIdentML instead. Local file path of the search database from the search engine's point of view.", true}, {MS_database_original_uri, "MS:1001015", "database original uri", "URI, from where the search database was originally downloaded.", false}, {MS_database_version_OBSOLETE, "MS:1001016", "database version", "OBSOLETE: Use attribute in mzIdentML instead. Version of the search database.", true}, {MS_database_release_date_OBSOLETE, "MS:1001017", "database release date", "OBSOLETE: Use attribute in mzIdentML instead. Release date of the search database.", true}, {MS_database_type, "MS:1001018", "database type", "Database containing amino acid or nucleic acid sequences.", false}, {MS_database_filtering, "MS:1001019", "database filtering", "Was there filtering used on the database.", false}, {MS_DB_filter_taxonomy, "MS:1001020", "DB filter taxonomy", "A taxonomy filter was to the database search.", false}, {MS_DB_filter_on_accession_numbers, "MS:1001021", "DB filter on accession numbers", "Filtering applied specifically by accession number pattern.", false}, {MS_DB_MW_filter, "MS:1001022", "DB MW filter", "Filtering applied specifically by protein molecular weight, specified as either a range or above/below a threshold value.", false}, {MS_DB_PI_filter, "MS:1001023", "DB PI filter", "Filtering applied specifically by predicted protein isoelectric focussing point (pI), specified as either a range or above/below a threshold value.", false}, {MS_translation_frame, "MS:1001024", "translation frame", "The translated open reading frames from a nucleotide database considered in the search (range: 1-6).", false}, {MS_translation_table, "MS:1001025", "translation table", "The translation table used to translate the nucleotides to amino acids.", false}, {MS_SEQUEST_NormalizeXCorrValues, "MS:1001026", "SEQUEST:NormalizeXCorrValues", "", false}, {MS_DB_filter_on_sequence_pattern, "MS:1001027", "DB filter on sequence pattern", "Filtering applied specifically by amino acid sequence pattern.", false}, {MS_SEQUEST_SequenceHeaderFilter, "MS:1001028", "SEQUEST:SequenceHeaderFilter", "String in the header of a sequence entry for that entry to be searched.", false}, {MS_number_of_sequences_searched, "MS:1001029", "number of sequences searched", "The number of sequences (proteins / nucleotides) from the database search after filtering.", false}, {MS_number_of_peptide_seqs_compared_to_each_spectrum, "MS:1001030", "number of peptide seqs compared to each spectrum", "Number of peptide seqs compared to each spectrum.", false}, {MS_spectral_library_search, "MS:1001031", "spectral library search", "A search using a library of spectra.", false}, {MS_SEQUEST_SequencePartialFilter, "MS:1001032", "SEQUEST:SequencePartialFilter", "", false}, {MS_date___time_search_performed_OBSOLETE, "MS:1001035", "date / time search performed", "OBSOLETE: use attribute in mzIdentML instead. Date and time of the actual search run.", true}, {MS_search_time_taken, "MS:1001036", "search time taken", "The time taken to complete the search in seconds.", false}, {MS_SEQUEST_ShowFragmentIons, "MS:1001037", "SEQUEST:ShowFragmentIons", "Flag indicating that fragment ions should be shown.", false}, {MS_SEQUEST_Consensus, "MS:1001038", "SEQUEST:Consensus", "Specify depth as value of the CVParam.", false}, {MS_intermediate_analysis_format, "MS:1001040", "intermediate analysis format", "Type of the source file, the mzIdentML was created from.", false}, {MS_SEQUEST_sortCV, "MS:1001041", "SEQUEST:sortCV", "SEQUEST View / Sort Input Parameters.", false}, {MS_SEQUEST_LimitTo, "MS:1001042", "SEQUEST:LimitTo", "Specify \\\"number of dtas shown\\\" as value of the CVParam.", false}, {MS_cleavage_agent_details, "MS:1001044", "cleavage agent details", "Details of cleavage agent (enzyme).", false}, {MS_cleavage_agent_name, "MS:1001045", "cleavage agent name", "The name of the cleavage agent.", false}, {MS_SEQUEST_sort_by_dCn, "MS:1001046", "SEQUEST:sort by dCn", "Sort order of SEQUEST search results by the delta of the normalized correlation score.", false}, {MS_SEQUEST_sort_by_dM, "MS:1001047", "SEQUEST:sort by dM", "Sort order of SEQUEST search results by the difference between a theoretically calculated and the corresponding experimentally measured molecular mass M.", false}, {MS_SEQUEST_sort_by_Ions, "MS:1001048", "SEQUEST:sort by Ions", "Sort order of SEQUEST search results given by the ions.", false}, {MS_SEQUEST_sort_by_MH_, "MS:1001049", "SEQUEST:sort by MH+", "Sort order of SEQUEST search results given by the mass of the protonated ion.", false}, {MS_SEQUEST_sort_by_P, "MS:1001050", "SEQUEST:sort by P", "Sort order of SEQUEST search results given by the probability.", false}, {MS_multiple_enzyme_combination_rules_OBSOLETE, "MS:1001051", "multiple enzyme combination rules", "OBSOLETE: use attribute independent in mzIdentML instead. Description of multiple enzyme digestion protocol, if any.", true}, {MS_SEQUEST_sort_by_PreviousAminoAcid, "MS:1001052", "SEQUEST:sort by PreviousAminoAcid", "Sort order of SEQUEST search results given by the previous amino acid.", false}, {MS_SEQUEST_sort_by_Ref, "MS:1001053", "SEQUEST:sort by Ref", "Sort order of SEQUEST search results given by the reference.", false}, {MS_modification_parameters, "MS:1001055", "modification parameters", "Modification parameters for the search engine run.", false}, {MS_modification_specificity_rule, "MS:1001056", "modification specificity rule", "The specificity rules for the modifications applied by the search engine.", false}, {MS_tolerance_on_types_OBSOLETE, "MS:1001057", "tolerance on types", "OBSOLETE: Tolerance on types.", true}, {MS_quality_estimation_by_manual_validation, "MS:1001058", "quality estimation by manual validation", "The quality estimation was done manually.", false}, {MS_SEQUEST_sort_by_RSp, "MS:1001059", "SEQUEST:sort by RSp", "Sort order of SEQUEST search results given by the result 'Sp' of 'Rank/Sp' in the out file (peptide).", false}, {MS_quality_estimation_method_details, "MS:1001060", "quality estimation method details", "Method for quality estimation (manually or with decoy database).", false}, {MS_neutral_loss_OBSOLETE, "MS:1001061", "neutral loss", "OBSOLETE: replaced by MS:1000336 (neutral loss): Leave this to PSI-MOD.", true}, {MS_Mascot_MGF_format, "MS:1001062", "Mascot MGF format", "Mascot MGF file format.", false}, {MS_TODOscoring_model_OBSOLETE, "MS:1001065", "TODOscoring model", "OBSOLETE: There is Phenyx:ScoringModel for Phenyx! Scoring model (more detailed granularity). TODO: add some child terms.", true}, {MS_ions_series_considered_in_search, "MS:1001066", "ions series considered in search", "The description of the DEPRECATED ion fragment series (including charges and neutral losses) that are considered by the search engine.", false}, {MS_SEQUEST_sort_by_Sp, "MS:1001068", "SEQUEST:sort by Sp", "Sort order of SEQUEST search results by the Sp score.", false}, {MS_SEQUEST_sort_by_TIC, "MS:1001069", "SEQUEST:sort by TIC", "Sort order of SEQUEST search results given by the total ion current.", false}, {MS_SEQUEST_sort_by_Scan, "MS:1001070", "SEQUEST:sort by Scan", "Sort order of SEQUEST search results given by the scan number.", false}, {MS_SEQUEST_sort_by_Sequence, "MS:1001071", "SEQUEST:sort by Sequence", "Sort order of SEQUEST search results given by the sequence.", false}, {MS_SEQUEST_sort_by_Sf, "MS:1001072", "SEQUEST:sort by Sf", "Sort order of SEQUEST search results given by the SEQUEST result 'Sf'.", false}, {MS_database_type_amino_acid, "MS:1001073", "database type amino acid", "Database contains amino acid sequences.", false}, {MS_database_type_nucleotide, "MS:1001079", "database type nucleotide", "Database contains nucleic acid sequences.", false}, {MS_search_type, "MS:1001080", "search type", "Enumeration of type of search value (i.e. from PMF, sequence tag, MS2).", false}, {MS_pmf_search, "MS:1001081", "pmf search", "A peptide mass fingerprint search.", false}, {MS_tag_search, "MS:1001082", "tag search", "A sequence tag search.", false}, {MS_ms_ms_search, "MS:1001083", "ms-ms search", "An MS2 search (with fragment ions).", false}, {MS_database_nr, "MS:1001084", "database nr", "Non-redundant GenBank sequence database.", false}, {MS_protein_result_details, "MS:1001085", "protein result details", "Protein level information.", false}, {MS_SEQUEST_sort_by_XCorr, "MS:1001086", "SEQUEST:sort by XCorr", "Sort order of SEQUEST search results by the correlation score.", false}, {MS_SEQUEST_ProcessCV, "MS:1001087", "SEQUEST:ProcessCV", "SEQUEST View / Process Input Parameters.", false}, {MS_protein_description, "MS:1001088", "protein description", "The protein description line from the sequence entry in the source database FASTA file.", false}, {MS_molecule_taxonomy, "MS:1001089", "molecule taxonomy", "The taxonomy of the resultant molecule from the search.", false}, {MS_taxonomy_nomenclature_OBSOLETE, "MS:1001090", "taxonomy nomenclature", "OBSOLETE: The system used to indicate taxonomy. There should be an enumerated list of options: latin name, NCBI TaxID, common name, Swiss-Prot species ID (ex. RABIT from the full protein ID ALBU_RABIT).", true}, {MS_NoEnzyme_OBSOLETE, "MS:1001091", "NoEnzyme", "", true}, {MS_peptide_identification_confidence_metric, "MS:1001092", "peptide identification confidence metric", "Identification confidence metric for a peptide.", false}, {MS_sequence_coverage, "MS:1001093", "sequence coverage", "The percent coverage for the protein based upon the matched peptide sequences (can be calculated).", false}, {MS_SEQUEST_sort_by_z, "MS:1001094", "SEQUEST:sort by z", "Sort order of SEQUEST search results given by the charge.", false}, {MS_SEQUEST_ProcessAll, "MS:1001095", "SEQUEST:ProcessAll", "", false}, {MS_SEQUEST_TopPercentMostIntense, "MS:1001096", "SEQUEST:TopPercentMostIntense", "Specify \\\"percentage\\\" as value of the CVParam.", false}, {MS_distinct_peptide_sequences, "MS:1001097", "distinct peptide sequences", "This counts distinct sequences hitting the protein without regard to a minimal confidence threshold.", false}, {MS_confident_distinct_peptide_sequences, "MS:1001098", "confident distinct peptide sequences", "This counts the number of distinct peptide sequences. Multiple charge states and multiple modification states do NOT count as multiple sequences. The definition of 'confident' must be qualified elsewhere.", false}, {MS_confident_peptide_qualification, "MS:1001099", "confident peptide qualification", "The point of this entry is to define what is meant by confident for the term Confident distinct peptide sequence and/or Confident peptides. Example 1 - metric=Paragon:Confidence value=95 sense=greater than Example 2 - metric=Mascot:Eval value=0.05 sense=less than.", false}, {MS_confident_peptide_sequence_number, "MS:1001100", "confident peptide sequence number", "This counts the number of peptide sequences without regard to whether they are distinct. Multiple charges states and multiple modification states DO count as multiple peptides. The definition of 'confident' must be qualified elsewhere.", false}, {MS_protein_group_or_subset_relationship, "MS:1001101", "protein group or subset relationship", "Protein group or subset relationships.", false}, {MS_SEQUEST_Chromatogram, "MS:1001102", "SEQUEST:Chromatogram", "", false}, {MS_SEQUEST_InfoAndLog, "MS:1001103", "SEQUEST:InfoAndLog", "", false}, {MS_database_UniProtKB_Swiss_Prot, "MS:1001104", "database UniProtKB/Swiss-Prot", "The name of the UniProtKB/Swiss-Prot knowledgebase.", false}, {MS_peptide_result_details, "MS:1001105", "peptide result details", "Peptide level information.", false}, {MS_SEQUEST_TopNumber, "MS:1001106", "SEQUEST:TopNumber", "Specify \\\"number\\\" as value of the CVParam.", false}, {MS_data_stored_in_database, "MS:1001107", "data stored in database", "Source file for this mzIdentML was a data set in a database.", false}, {MS_param__a_ion, "MS:1001108", "param: a ion", "Parameter information, type of product: a ion with charge on the N-terminal side.", false}, {MS_SEQUEST_CullTo, "MS:1001109", "SEQUEST:CullTo", "Specify cull string as value of the CVParam.", false}, {MS_SEQUEST_modeCV, "MS:1001110", "SEQUEST:modeCV", "SEQUEST Mode Input Parameters.", false}, {MS_SEQUEST_Full, "MS:1001111", "SEQUEST:Full", "", false}, {MS_n_terminal_flanking_residue, "MS:1001112", "n-terminal flanking residue", "The residue preceding the first amino acid in the peptide sequence as it occurs in the protein. Use 'N-term' to denote if the peptide starts at the N terminus of the protein.", false}, {MS_c_terminal_flanking_residue, "MS:1001113", "c-terminal flanking residue", "The residue following the last amino acid in the peptide sequence as it occurs in the protein. Use 'C-term' to denote if the peptide ends at the C terminus of the protein.", false}, {MS_retention_time_s__OBSOLETE, "MS:1001114", "retention time(s)", "Retention time of the spectrum from the source file.", true}, {MS_scan_number_s__OBSOLETE, "MS:1001115", "scan number(s)", "OBSOLETE: use spectrumID attribute of SpectrumIdentificationResult. Take from mzData.", true}, {MS_single_protein_result_details, "MS:1001116", "single protein result details", "Results specific for one protein as part of a protein ambiguity group (a result not valid for all the other proteins in the protein ambiguity group).", false}, {MS_theoretical_mass, "MS:1001117", "theoretical mass", "The theoretical mass of the molecule (e.g. the peptide sequence and its modifications).", false}, {MS_param__b_ion, "MS:1001118", "param: b ion", "Parameter information, type of product: b ion with charge on the N-terminal side.", false}, {MS_param__c_ion, "MS:1001119", "param: c ion", "Parameter information, type of product: c ion with charge on the N-terminal side.", false}, {MS_SEQUEST_FormatAndLinks, "MS:1001120", "SEQUEST:FormatAndLinks", "", false}, {MS_number_of_matched_peaks, "MS:1001121", "number of matched peaks", "The number of peaks that were matched as qualified by the ion series considered field. If a peak matches multiple ions then only 1 would be added the count.", false}, {MS_ions_series_considered, "MS:1001122", "ions series considered", "The ion series that were used during the calculation of the count (e.g. a, b, c, d, v, w, x, y, z, a-H2O, a-NH3, b-H2O, b-NH3, y-H2O, y-NH3, b-H20, b+, z-, z+1, z+2, b-H3PO4, y-H3PO4, immonium, internal ya, internal yb).", false}, {MS_number_of_peaks_used, "MS:1001123", "number of peaks used", "The number of peaks from the original peak list that are used to calculate the scores for a particular search engine. All ions that have the opportunity to match or be counted even if they don't.", false}, {MS_number_of_peaks_submitted, "MS:1001124", "number of peaks submitted", "The number of peaks from the original peaks listed that were submitted to the search engine.", false}, {MS_manual_validation, "MS:1001125", "manual validation", "Result of quality estimation: decision of a manual validation.", false}, {MS_SEQUEST_Fast, "MS:1001126", "SEQUEST:Fast", "", false}, {MS_peptide_sharing_details, "MS:1001127", "peptide sharing details", "Accessions Containing Sequence - Accessions for each protein containing this peptide.", false}, {MS_SEQUEST_selectCV, "MS:1001128", "SEQUEST:selectCV", "SEQUEST Select Input Parameters.", false}, {MS_quantification_information, "MS:1001129", "quantification information", "Quantification information.", false}, {MS_peptide_raw_area_OBSOLETE, "MS:1001130", "peptide raw area", "Peptide raw area.", true}, {MS_error_on_peptide_area, "MS:1001131", "error on peptide area", "Error on peptide area.", false}, {MS_peptide_ratio, "MS:1001132", "peptide ratio", "Peptide ratio.", false}, {MS_error_on_peptide_ratio, "MS:1001133", "error on peptide ratio", "Error on peptide ratio.", false}, {MS_protein_ratio, "MS:1001134", "protein ratio", "Protein ratio.", false}, {MS_error_on_protein_ratio, "MS:1001135", "error on protein ratio", "Error on protein ratio.", false}, {MS_p_value__protein_diff_from_1_randomly__OBSOLETE, "MS:1001136", "p-value (protein diff from 1 randomly)", "P-value (protein diff from 1 randomly).", true}, {MS_absolute_quantity, "MS:1001137", "absolute quantity", "Absolute quantity in terms of real concentration or molecule copy number in sample.", false}, {MS_error_on_absolute_quantity, "MS:1001138", "error on absolute quantity", "Error on absolute quantity.", false}, {MS_quantitation_software_name, "MS:1001139", "quantitation software name", "Quantitation software name.", false}, {MS_quantitation_software_version_OBSOLETE, "MS:1001140", "quantitation software version", "Quantitation software version.", true}, {MS_intensity_of_precursor_ion, "MS:1001141", "intensity of precursor ion", "The intensity of the precursor ion.", false}, {MS_database_IPI_human, "MS:1001142", "database IPI_human", "International Protein Index database for Homo sapiens sequences.", false}, {MS_search_engine_specific_score_for_PSMs, "MS:1001143", "search engine specific score for PSMs", "Search engine specific peptide spectrum match scores.", false}, {MS_SEQUEST_SelectDefault, "MS:1001144", "SEQUEST:SelectDefault", "", false}, {MS_SEQUEST_SelectAdvancedCV, "MS:1001145", "SEQUEST:SelectAdvancedCV", "SEQUEST Select Advanced Input Parameters.", false}, {MS_param__a_ion_NH3_DEPRECATED, "MS:1001146", "param: a ion-NH3 DEPRECATED", "Ion a-NH3 parameter information, type of product: a ion with lost ammonia.", false}, {MS_protein_ambiguity_group_result_details, "MS:1001147", "protein ambiguity group result details", "", false}, {MS_param__a_ion_H2O_DEPRECATED, "MS:1001148", "param: a ion-H2O DEPRECATED", "Ion a-H2O if a significant and fragment includes STED.", false}, {MS_param__b_ion_NH3_DEPRECATED, "MS:1001149", "param: b ion-NH3 DEPRECATED", "Ion b-NH3 parameter information, type of product: b ion with lost ammonia.", false}, {MS_param__b_ion_H2O_DEPRECATED, "MS:1001150", "param: b ion-H2O DEPRECATED", "Ion b-H2O if b significant and fragment includes STED.", false}, {MS_param__y_ion_NH3_DEPRECATED, "MS:1001151", "param: y ion-NH3 DEPRECATED", "Ion y-NH3 parameter information, type of product: y ion with lost ammonia.", false}, {MS_param__y_ion_H2O_DEPRECATED, "MS:1001152", "param: y ion-H2O DEPRECATED", "", false}, {MS_search_engine_specific_score, "MS:1001153", "search engine specific score", "Search engine specific scores.", false}, {MS_SEQUEST_probability, "MS:1001154", "SEQUEST:probability", "The SEQUEST result 'Probability'.", false}, {MS_SEQUEST_xcorr, "MS:1001155", "SEQUEST:xcorr", "The SEQUEST result 'XCorr'.", false}, {MS_SEQUEST_deltacn, "MS:1001156", "SEQUEST:deltacn", "The SEQUEST result 'DeltaCn'.", false}, {MS_SEQUEST_sp, "MS:1001157", "SEQUEST:sp", "The SEQUEST result 'Sp' (protein).", false}, {MS_SEQUEST_Uniq, "MS:1001158", "SEQUEST:Uniq", "", false}, {MS_SEQUEST_expectation_value, "MS:1001159", "SEQUEST:expectation value", "The SEQUEST result 'Expectation value'.", false}, {MS_SEQUEST_sf, "MS:1001160", "SEQUEST:sf", "The SEQUEST result 'Sf'.", false}, {MS_SEQUEST_matched_ions, "MS:1001161", "SEQUEST:matched ions", "The SEQUEST result 'Matched Ions'.", false}, {MS_SEQUEST_total_ions, "MS:1001162", "SEQUEST:total ions", "The SEQUEST result 'Total Ions'.", false}, {MS_SEQUEST_consensus_score, "MS:1001163", "SEQUEST:consensus score", "The SEQUEST result 'Consensus Score'.", false}, {MS_Paragon_unused_protscore, "MS:1001164", "Paragon:unused protscore", "The Paragon result 'Unused ProtScore'.", false}, {MS_Paragon_total_protscore, "MS:1001165", "Paragon:total protscore", "The Paragon result 'Total ProtScore'.", false}, {MS_Paragon_score, "MS:1001166", "Paragon:score", "The Paragon result 'Score'.", false}, {MS_Paragon_confidence, "MS:1001167", "Paragon:confidence", "The Paragon result 'Confidence'.", false}, {MS_Paragon_expression_error_factor, "MS:1001168", "Paragon:expression error factor", "The Paragon result 'Expression Error Factor'.", false}, {MS_Paragon_expression_change_p_value, "MS:1001169", "Paragon:expression change p-value", "The Paragon result 'Expression change P-value'.", false}, {MS_Paragon_contrib, "MS:1001170", "Paragon:contrib", "The Paragon result 'Contrib'.", false}, {MS_Mascot_score, "MS:1001171", "Mascot:score", "The Mascot result 'Score'.", false}, {MS_Mascot_expectation_value, "MS:1001172", "Mascot:expectation value", "The Mascot result 'expectation value'.", false}, {MS_Mascot_matched_ions, "MS:1001173", "Mascot:matched ions", "The Mascot result 'Matched ions'.", false}, {MS_Mascot_total_ions, "MS:1001174", "Mascot:total ions", "The Mascot result 'Total ions'.", false}, {MS_peptide_shared_in_multiple_proteins, "MS:1001175", "peptide shared in multiple proteins", "A peptide matching multiple proteins.", false}, {MS______KR_____P_, "MS:1001176", "(?<=[KR])(?!P)", "Regular expression for Trypsin.", false}, {MS_number_of_molecular_hypothesis_considered, "MS:1001177", "number of molecular hypothesis considered", "Number of Molecular Hypothesis Considered - This is the number of molecules (e.g. peptides for proteomics) considered for a particular search.", false}, {MS_database_EST, "MS:1001178", "database EST", "Expressed sequence tag nucleotide sequence database.", false}, {MS_Cleavage_agent_regular_expression, "MS:1001180", "Cleavage agent regular expression", "Regular expressions for cleavage enzymes.", false}, {MS_search_statistics, "MS:1001184", "search statistics", "The details of the actual run of the search.", false}, {MS_modification_specificity_peptide_N_term, "MS:1001189", "modification specificity peptide N-term", "As parameter for search engine: apply the modification only at the N-terminus of a peptide.", false}, {MS_modification_specificity_peptide_C_term, "MS:1001190", "modification specificity peptide C-term", "As parameter for search engine: apply the modification only at the C-terminus of a peptide.", false}, {MS_p_value_OBSOLETE, "MS:1001191", "p-value", "Quality estimation by p-value.", true}, {MS_Expect_value, "MS:1001192", "Expect value", "Result of quality estimation: Expect value.", false}, {MS_confidence_score, "MS:1001193", "confidence score", "Result of quality estimation: confidence score.", false}, {MS_quality_estimation_with_decoy_database, "MS:1001194", "quality estimation with decoy database", "Quality estimation by decoy database.", false}, {MS_decoy_DB_type_reverse, "MS:1001195", "decoy DB type reverse", "Decoy type: Amino acids of protein sequences are used in reverse order.", false}, {MS_decoy_DB_type_randomized, "MS:1001196", "decoy DB type randomized", "Decoy type: Amino acids of protein sequences are randomized (keeping the original protein mass).", false}, {MS_DB_composition_target_decoy, "MS:1001197", "DB composition target+decoy", "Decoy database composition: database contains original (target) and decoy entries.", false}, {MS_protein_identification_confidence_metric, "MS:1001198", "protein identification confidence metric", "Identification confidence metric for a protein.", false}, {MS_Mascot_DAT_format, "MS:1001199", "Mascot DAT format", "Source file for this mzIdentML was in Mascot DAT file format.", false}, {MS_SEQUEST_out_file_format, "MS:1001200", "SEQUEST out file format", "Source file for this mzIdentML was in SEQUEST out file format.", false}, {MS_DB_MW_filter_maximum, "MS:1001201", "DB MW filter maximum", "Maximum value of molecular weight filter.", false}, {MS_DB_MW_filter_minimum, "MS:1001202", "DB MW filter minimum", "Minimum value of molecular weight filter.", false}, {MS_DB_PI_filter_maximum, "MS:1001203", "DB PI filter maximum", "Maximum value of isoelectric point filter.", false}, {MS_DB_PI_filter_minimum, "MS:1001204", "DB PI filter minimum", "Minimum value of isoelectric point filter.", false}, {MS_Mascot, "MS:1001207", "Mascot", "The name of the Mascot search engine.", false}, {MS_SEQUEST, "MS:1001208", "SEQUEST", "The name of the SEQUEST search engine.", false}, {MS_Phenyx, "MS:1001209", "Phenyx", "The name of the Phenyx search engine.", false}, {MS_mass_type_settings, "MS:1001210", "mass type settings", "The type of mass difference value to be considered by the search engine (monoisotopic or average).", false}, {MS_parent_mass_type_mono, "MS:1001211", "parent mass type mono", "Mass type setting for parent mass was monoisotopic.", false}, {MS_parent_mass_type_average, "MS:1001212", "parent mass type average", "Mass type setting for parent mass was average isotopic.", false}, {MS_search_result_details_OBSOLETE, "MS:1001213", "search result details", "OBSOLETE: Scores and global result characteristics.", true}, {MS_protein_level_global_FDR, "MS:1001214", "protein-level global FDR", "Estimation of the global false discovery rate of proteins.", false}, {MS_SEQUEST_PeptideSp, "MS:1001215", "SEQUEST:PeptideSp", "The SEQUEST result 'Sp' in out file (peptide).", false}, {MS_SEQUEST_PeptideRankSp, "MS:1001217", "SEQUEST:PeptideRankSp", "The SEQUEST result 'Sp' of 'Rank/Sp' in out file (peptide). Also called 'rsp'.", false}, {MS_SEQUEST_PeptideNumber, "MS:1001218", "SEQUEST:PeptideNumber", "The SEQUEST result '#' in out file (peptide).", false}, {MS_SEQUEST_PeptideIdnumber, "MS:1001219", "SEQUEST:PeptideIdnumber", "The SEQUEST result 'Id#' in out file (peptide).", false}, {MS_frag__y_ion, "MS:1001220", "frag: y ion", "Fragmentation information, type of product: y ion.", false}, {MS_fragmentation_information, "MS:1001221", "fragmentation information", "Fragmentation information like ion types.", false}, {MS_frag__b_ion___H2O, "MS:1001222", "frag: b ion - H2O", "Fragmentation information, type of product: b ion without water.", false}, {MS_frag__y_ion___H2O, "MS:1001223", "frag: y ion - H2O", "Fragmentation information, type of product: y ion without water.", false}, {MS_frag__b_ion, "MS:1001224", "frag: b ion", "Fragmentation information, type of product: b ion.", false}, {MS_product_ion_m_z, "MS:1001225", "product ion m/z", "The m/z of the product ion.", false}, {MS_product_ion_intensity, "MS:1001226", "product ion intensity", "The intensity of a single product ion.", false}, {MS_product_ion_m_z_error, "MS:1001227", "product ion m/z error", "The product ion m/z error.", false}, {MS_frag__x_ion, "MS:1001228", "frag: x ion", "Fragmentation information, type of product: x ion.", false}, {MS_frag__a_ion, "MS:1001229", "frag: a ion", "Fragmentation information, type of product: a ion.", false}, {MS_frag__z_ion, "MS:1001230", "frag: z ion", "Fragmentation information, type of product: z ion.", false}, {MS_frag__c_ion, "MS:1001231", "frag: c ion", "Fragmentation information, type of product: c ion.", false}, {MS_frag__b_ion___NH3, "MS:1001232", "frag: b ion - NH3", "Ion b-NH3 fragmentation information, type of product: b ion without ammonia.", false}, {MS_frag__y_ion___NH3, "MS:1001233", "frag: y ion - NH3", "Ion y-NH3 fragmentation information, type of product: y ion without ammonia.", false}, {MS_frag__a_ion___H2O, "MS:1001234", "frag: a ion - H2O", "Fragmentation information, type of product: a ion without water.", false}, {MS_frag__a_ion___NH3, "MS:1001235", "frag: a ion - NH3", "Ion a-NH3 fragmentation information, type of product: a ion without ammonia.", false}, {MS_frag__d_ion, "MS:1001236", "frag: d ion", "Fragmentation information, type of product: d ion.", false}, {MS_frag__v_ion, "MS:1001237", "frag: v ion", "Fragmentation information, type of product: v ion.", false}, {MS_frag__w_ion, "MS:1001238", "frag: w ion", "Fragmentation information, type of product: w ion.", false}, {MS_frag__immonium_ion, "MS:1001239", "frag: immonium ion", "Fragmentation information, type of product: immonium ion.", false}, {MS_non_identified_ion, "MS:1001240", "non-identified ion", "Non-identified ion.", false}, {MS_co_eluting_ion, "MS:1001241", "co-eluting ion", "Co-eluting ion.", false}, {MS_SEQUEST_out_folder, "MS:1001242", "SEQUEST out folder", "Source file for this mzIdentML was a SEQUEST folder with its out files.", false}, {MS_SEQUEST_summary, "MS:1001243", "SEQUEST summary", "Source file for this mzIdentML was a SEQUEST summary page (proteins).", false}, {MS_PerSeptive_PKS_format, "MS:1001245", "PerSeptive PKS format", "PerSeptive peak list file format.", false}, {MS_SCIEX_API_III_format, "MS:1001246", "SCIEX API III format", "PE SCIEX peak list file format.", false}, {MS_Bruker_XML_format, "MS:1001247", "Bruker XML format", "Bruker data exchange XML format.", false}, {MS_search_input_details, "MS:1001249", "search input details", "Details describing the search input.", false}, {MS_local_FDR, "MS:1001250", "local FDR", "Result of quality estimation: the local FDR at the current position of a sorted list.", false}, {MS_Trypsin, "MS:1001251", "Trypsin", "Enzyme trypsin.", false}, {MS_DB_source_EBI, "MS:1001252", "DB source EBI", "Database source EBI.", false}, {MS_DB_source_NCBI, "MS:1001253", "DB source NCBI", "Database source NCBI.", false}, {MS_DB_source_UniProt, "MS:1001254", "DB source UniProt", "Database source UniProt.", false}, {MS_fragment_mass_type_average, "MS:1001255", "fragment mass type average", "Mass type setting for fragment mass was average isotopic.", false}, {MS_fragment_mass_type_mono, "MS:1001256", "fragment mass type mono", "Mass type setting for fragment mass was monoisotopic.", false}, {MS_param__v_ion, "MS:1001257", "param: v ion", "Parameter information, type of product: side chain loss v ion.", false}, {MS_param__d_ion, "MS:1001258", "param: d ion", "Parameter information, type of product: side chain loss d ion.", false}, {MS_param__immonium_ion, "MS:1001259", "param: immonium ion", "Parameter information, type of product: immonium ion.", false}, {MS_param__w_ion, "MS:1001260", "param: w ion", "Parameter information, type of product: side chain loss w ion.", false}, {MS_param__x_ion, "MS:1001261", "param: x ion", "Parameter information, type of product: x ion with charge on the C-terminal side.", false}, {MS_param__y_ion, "MS:1001262", "param: y ion", "Parameter information, type of product: y ion with charge on the C-terminal side.", false}, {MS_param__z_ion, "MS:1001263", "param: z ion", "Parameter information, type of product: z ion with charge on the C-terminal side.", false}, {MS_role_type, "MS:1001266", "role type", "Role of a Person or Organization.", false}, {MS_software_vendor, "MS:1001267", "software vendor", "Software vendor role.", false}, {MS_programmer, "MS:1001268", "programmer", "Programmer role.", false}, {MS_instrument_vendor, "MS:1001269", "instrument vendor", "Instrument vendor role.", false}, {MS_lab_personnel, "MS:1001270", "lab personnel", "Lab personnel role.", false}, {MS_researcher, "MS:1001271", "researcher", "Researcher role.", false}, {MS_____R____P_, "MS:1001272", "(?<=R)(?!P)", "Regular expression for Arg-C.", false}, {MS_____BD__, "MS:1001273", "(?=[BD])", "Regular expression for Asp-N.", false}, {MS_____DE__, "MS:1001274", "(?=[DE])", "Regular expression for Asp-N-ambic.", false}, {MS_ProteinScape_SearchEvent, "MS:1001275", "ProteinScape SearchEvent", "Source data for this mzIdentML was a ProteinScape SearchEvent.", false}, {MS_ProteinScape_Gel, "MS:1001276", "ProteinScape Gel", "Source data for this mzIdentML was a ProteinScape Gel.", false}, {MS_decoy_DB_accession_regexp, "MS:1001283", "decoy DB accession regexp", "Specify the regular expression for decoy accession numbers.", false}, {MS_decoy_DB_derived_from_OBSOLETE, "MS:1001284", "decoy DB derived from", "The name of the database, the search database was derived from.", true}, {MS_database_IPI_mouse, "MS:1001285", "database IPI_mouse", "International Protein Index database for Mus musculus sequences.", false}, {MS_database_IPI_rat, "MS:1001286", "database IPI_rat", "International Protein Index database for Rattus norvegicus sequences.", false}, {MS_database_IPI_zebrafish, "MS:1001287", "database IPI_zebrafish", "International Protein Index database for Danio rerio sequences.", false}, {MS_database_IPI_chicken, "MS:1001288", "database IPI_chicken", "International Protein Index database for Gallus gallus sequences.", false}, {MS_database_IPI_cow, "MS:1001289", "database IPI_cow", "International Protein Index database for Bos taurus sequences.", false}, {MS_database_IPI_arabidopsis, "MS:1001290", "database IPI_arabidopsis", "International Protein Index database for Arabidopsis thaliana sequences.", false}, {MS_decoy_DB_from_nr_OBSOLETE, "MS:1001291", "decoy DB from nr", "Decoy database from a non-redundant GenBank sequence database.", true}, {MS_decoy_DB_from_IPI_rat_OBSOLETE, "MS:1001292", "decoy DB from IPI_rat", "Decoy database from a International Protein Index database for Rattus norvegicus.", true}, {MS_decoy_DB_from_IPI_mouse_OBSOLETE, "MS:1001293", "decoy DB from IPI_mouse", "Decoy database from a International Protein Index database for Mus musculus.", true}, {MS_decoy_DB_from_IPI_arabidopsis_OBSOLETE, "MS:1001294", "decoy DB from IPI_arabidopsis", "Decoy database from a International Protein Index database for Arabidopsis thaliana.", true}, {MS_decoy_DB_from_EST_OBSOLETE, "MS:1001295", "decoy DB from EST", "Decoy database from an expressed sequence tag nucleotide sequence database.", true}, {MS_decoy_DB_from_IPI_zebrafish_OBSOLETE, "MS:1001296", "decoy DB from IPI_zebrafish", "Decoy database from a International Protein Index database for Danio rerio.", true}, {MS_decoy_DB_from_UniProtKB_Swiss_Prot_OBSOLETE, "MS:1001297", "decoy DB from UniProtKB/Swiss-Prot", "Decoy database from a Swiss-Prot protein sequence database.", true}, {MS_decoy_DB_from_IPI_chicken_OBSOLETE, "MS:1001298", "decoy DB from IPI_chicken", "Decoy database from a International Protein Index database for Gallus gallus.", true}, {MS_decoy_DB_from_IPI_cow_OBSOLETE, "MS:1001299", "decoy DB from IPI_cow", "Decoy database from a International Protein Index database for Bos taurus.", true}, {MS_decoy_DB_from_IPI_human_OBSOLETE, "MS:1001300", "decoy DB from IPI_human", "Decoy database from a International Protein Index database for Homo sapiens.", true}, {MS_protein_rank, "MS:1001301", "protein rank", "The rank of the protein in a list sorted by the search engine.", false}, {MS_search_engine_specific_input_parameter, "MS:1001302", "search engine specific input parameter", "Search engine specific input parameters.", false}, {MS_Arg_C, "MS:1001303", "Arg-C", "Endoproteinase Arg-C.", false}, {MS_Asp_N, "MS:1001304", "Asp-N", "Endoproteinase Asp-N.", false}, {MS_Asp_N_ambic, "MS:1001305", "Asp-N_ambic", "Enzyme Asp-N, Ammonium Bicarbonate (AmBic).", false}, {MS_Chymotrypsin, "MS:1001306", "Chymotrypsin", "Enzyme chymotrypsin.", false}, {MS_CNBr, "MS:1001307", "CNBr", "Cyanogen bromide.", false}, {MS_Formic_acid, "MS:1001308", "Formic_acid", "Formic acid.", false}, {MS_Lys_C, "MS:1001309", "Lys-C", "Endoproteinase Lys-C.", false}, {MS_Lys_C_P, "MS:1001310", "Lys-C/P", "Proteinase Lys-C/P.", false}, {MS_PepsinA, "MS:1001311", "PepsinA", "PepsinA proteinase.", false}, {MS_TrypChymo, "MS:1001312", "TrypChymo", "Cleavage agent TrypChymo.", false}, {MS_Trypsin_P, "MS:1001313", "Trypsin/P", "Cleavage agent Trypsin/P.", false}, {MS_V8_DE, "MS:1001314", "V8-DE", "Cleavage agent V8-DE.", false}, {MS_V8_E, "MS:1001315", "V8-E", "Cleavage agent V8-E.", false}, {MS_Mascot_SigThreshold, "MS:1001316", "Mascot:SigThreshold", "Significance threshold below which the p-value of a peptide match must lie to be considered statistically significant (default 0.05).", false}, {MS_Mascot_MaxProteinHits, "MS:1001317", "Mascot:MaxProteinHits", "The number of protein hits to display in the report. If 'Auto', all protein hits that have a protein score exceeding the average peptide identity threshold are reported. Otherwise an integer at least 1.", false}, {MS_Mascot_ProteinScoringMethod, "MS:1001318", "Mascot:ProteinScoringMethod", "Mascot protein scoring method; either 'Standard' or 'MudPIT'.", false}, {MS_Mascot_MinMSMSThreshold, "MS:1001319", "Mascot:MinMSMSThreshold", "Mascot peptide match ion score threshold. If between 0 and 1, then peptide matches whose expect value exceeds the thresholds are suppressed; if at least 1, then peptide matches whose ion score is below the threshold are suppressed.", false}, {MS_Mascot_ShowHomologousProteinsWithSamePeptides, "MS:1001320", "Mascot:ShowHomologousProteinsWithSamePeptides", "If true, show (sequence or spectrum) same-set proteins. Otherwise they are suppressed.", false}, {MS_Mascot_ShowHomologousProteinsWithSubsetOfPeptides, "MS:1001321", "Mascot:ShowHomologousProteinsWithSubsetOfPeptides", "If true, show (sequence or spectrum) sub-set and subsumable proteins. Otherwise they are suppressed.", false}, {MS_Mascot_RequireBoldRed, "MS:1001322", "Mascot:RequireBoldRed", "Only used in Peptide Summary and Select Summary reports. If true, a peptide match must be 'bold red' to be included in the report; bold red means the peptide is a top ranking match in a query and appears for the first time (in linear order) in the list of protein hits.", false}, {MS_Mascot_UseUnigeneClustering, "MS:1001323", "Mascot:UseUnigeneClustering", "If true, then the search results are against a nucleic acid database and Unigene clustering is enabled. Otherwise UniGene clustering is not in use.", false}, {MS_Mascot_IncludeErrorTolerantMatches, "MS:1001324", "Mascot:IncludeErrorTolerantMatches", "If true, then the search results are error tolerant and peptide matches from the second pass are included in search results. Otherwise no error tolerant peptide matches are included.", false}, {MS_Mascot_ShowDecoyMatches, "MS:1001325", "Mascot:ShowDecoyMatches", "If true, then the search results are against an automatically generated decoy database and the reported peptide matches and protein hits come from the decoy database. Otherwise peptide matches and protein hits come from the original database.", false}, {MS_add_others_OBSOLETE, "MS:1001326", "add_others", "OBSOLETE.", true}, {MS_OMSSA_evalue, "MS:1001328", "OMSSA:evalue", "OMSSA E-value.", false}, {MS_OMSSA_pvalue, "MS:1001329", "OMSSA:pvalue", "OMSSA p-value.", false}, {MS_X_Tandem_expect, "MS:1001330", "X!Tandem:expect", "The X!Tandem expectation value.", false}, {MS_X_Tandem_hyperscore, "MS:1001331", "X!Tandem:hyperscore", "The X!Tandem hyperscore.", false}, {MS______FYWL_____P_, "MS:1001332", "(?<=[FYWL])(?!P)", "Regular expression for Chymotrypsin.", false}, {MS_____M_, "MS:1001333", "(?<=M)", "Regular expression for CNBr.", false}, {MS______D_______D__, "MS:1001334", "((?<=D))|((?=D))", "Regular expression for formic acid.", false}, {MS_____K____P_, "MS:1001335", "(?<=K)(?!P)", "Regular expression for Lys-C.", false}, {MS_____K_, "MS:1001336", "(?<=K)", "Regular expression for Lys-C/P.", false}, {MS______FL__, "MS:1001337", "(?<=[FL])", "Regular expression for PepsinA.", false}, {MS______FYWLKR_____P_, "MS:1001338", "(?<=[FYWLKR])(?!P)", "Regular expression for TrypChymo.", false}, {MS______KR__, "MS:1001339", "(?<=[KR])", "Regular expression for Trypsin/P.", false}, {MS______BDEZ_____P_, "MS:1001340", "(?<=[BDEZ])(?!P)", "Regular expression for V8-DE.", false}, {MS______EZ_____P_, "MS:1001341", "(?<=[EZ])(?!P)", "Regular expression for V8-E.", false}, {MS_database_sequence_details, "MS:1001342", "database sequence details", "Details about a single database sequence.", false}, {MS_NA_sequence, "MS:1001343", "NA sequence", "The sequence is a nucleic acid sequence.", false}, {MS_AA_sequence, "MS:1001344", "AA sequence", "The sequence is a amino acid sequence.", false}, {MS_mass_table_source, "MS:1001345", "mass table source", "Children of this term specify the source of the mass table used.", false}, {MS_AAIndex_mass_table, "MS:1001346", "AAIndex mass table", "The masses used in the mass table are taken from AAIndex.", false}, {MS_database_file_formats, "MS:1001347", "database file formats", "The children of this term define file formats of the sequence database used.", false}, {MS_FASTA_format, "MS:1001348", "FASTA format", "The sequence database was stored in the FASTA format.", false}, {MS_ASN_1, "MS:1001349", "ASN.1", "The sequence database was stored in the Abstract Syntax Notation 1 format.", false}, {MS_NCBI___p_, "MS:1001350", "NCBI *.p*", "The sequence database was stored in the NCBI formatdb (*.p*) format.", false}, {MS_clustal_aln, "MS:1001351", "clustal aln", "ClustalW ALN (multiple alignment) format.", false}, {MS_embl_em, "MS:1001352", "embl em", "EMBL entry format.", false}, {MS_NBRF_PIR, "MS:1001353", "NBRF PIR", "The NBRF PIR was used as format.", false}, {MS_mass_table_options, "MS:1001354", "mass table options", "Root node for options for the mass table used.", false}, {MS_peptide_descriptions, "MS:1001355", "peptide descriptions", "Descriptions of peptides.", false}, {MS_spectrum_descriptions, "MS:1001356", "spectrum descriptions", "Descriptions of the input spectra.", false}, {MS_spectrum_quality_descriptions, "MS:1001357", "spectrum quality descriptions", "Description of the quality of the input spectrum.", false}, {MS_msmsEval_quality, "MS:1001358", "msmsEval quality", "This term reports the quality of the spectrum assigned by msmsEval.", false}, {MS_ambiguous_residues, "MS:1001359", "ambiguous residues", "Children of this term describe ambiguous residues.", false}, {MS_alternate_single_letter_codes, "MS:1001360", "alternate single letter codes", "List of standard residue one letter codes which are used to replace a non-standard.", false}, {MS_alternate_mass, "MS:1001361", "alternate mass", "List of masses a non-standard letter code is replaced with.", false}, {MS_number_of_unmatched_peaks, "MS:1001362", "number of unmatched peaks", "The number of unmatched peaks.", false}, {MS_peptide_unique_to_one_protein, "MS:1001363", "peptide unique to one protein", "A peptide matching only one.", false}, {MS_distinct_peptide_level_global_FDR, "MS:1001364", "distinct peptide-level global FDR", "Estimation of the global false discovery rate for distinct peptides once redundant identifications of the same peptide have been removed (id est multiple PSMs have been collapsed to one entry).", false}, {MS_frag__internal_yb_ion, "MS:1001365", "frag: internal yb ion", "Fragmentation information, type of product: internal yb ion.", false}, {MS_frag__internal_ya_ion, "MS:1001366", "frag: internal ya ion", "Fragmentation information, type of product: internal ya ion.", false}, {MS_frag__z_1_ion, "MS:1001367", "frag: z+1 ion", "Fragmentation information, type of product: z+1 ion.", false}, {MS_frag__z_2_ion, "MS:1001368", "frag: z+2 ion", "Fragmentation information, type of product: z+2 ion.", false}, {MS_text_format, "MS:1001369", "text format", "Simple text file format of \\\"m/z [intensity]\\\" values for a PMF (or single MS2) search.", false}, {MS_Mascot_homology_threshold, "MS:1001370", "Mascot:homology threshold", "The Mascot result 'homology threshold'.", false}, {MS_Mascot_identity_threshold, "MS:1001371", "Mascot:identity threshold", "The Mascot result 'identity threshold'.", false}, {MS_SEQUEST_Sequences, "MS:1001372", "SEQUEST:Sequences", "", false}, {MS_SEQUEST_TIC, "MS:1001373", "SEQUEST:TIC", "SEQUEST total ion current.", false}, {MS_SEQUEST_Sum, "MS:1001374", "SEQUEST:Sum", "", false}, {MS_Phenyx_Instrument_Type, "MS:1001375", "Phenyx:Instrument Type", "The instrument type parameter value in Phenyx.", false}, {MS_Phenyx_Scoring_Model, "MS:1001376", "Phenyx:Scoring Model", "The selected scoring model in Phenyx.", false}, {MS_Phenyx_Default_Parent_Charge, "MS:1001377", "Phenyx:Default Parent Charge", "The default parent charge value in Phenyx.", false}, {MS_Phenyx_Trust_Parent_Charge, "MS:1001378", "Phenyx:Trust Parent Charge", "The parameter in Phenyx that specifies if the experimental charge state is to be considered as correct.", false}, {MS_Phenyx_Turbo, "MS:1001379", "Phenyx:Turbo", "The turbo mode parameter in Phenyx.", false}, {MS_Phenyx_Turbo_ErrorTol, "MS:1001380", "Phenyx:Turbo:ErrorTol", "The maximal allowed fragment m/z error filter considered in the turbo mode of Phenyx.", false}, {MS_Phenyx_Turbo_Coverage, "MS:1001381", "Phenyx:Turbo:Coverage", "The minimal peptide sequence coverage value, expressed in percent, considered in the turbo mode of Phenyx.", false}, {MS_Phenyx_Turbo_Series, "MS:1001382", "Phenyx:Turbo:Series", "The list of ion series considered in the turbo mode of Phenyx.", false}, {MS_Phenyx_MinPepLength, "MS:1001383", "Phenyx:MinPepLength", "The minimal number of residues for a peptide to be considered for a valid identification in Phenyx.", false}, {MS_Phenyx_MinPepzscore, "MS:1001384", "Phenyx:MinPepzscore", "The minimal peptide z-score for a peptide to be considered for a valid identification in Phenyx.", false}, {MS_Phenyx_MaxPepPvalue, "MS:1001385", "Phenyx:MaxPepPvalue", "The maximal peptide p-value for a peptide to be considered for a valid identification in Phenyx.", false}, {MS_Phenyx_AC_Score, "MS:1001386", "Phenyx:AC Score", "The minimal protein score required for a protein database entry to be displayed in the list of identified proteins in Phenyx.", false}, {MS_Phenyx_Conflict_Resolution, "MS:1001387", "Phenyx:Conflict Resolution", "The parameter in Phenyx that specifies if the conflict resolution algorithm is to be used.", false}, {MS_Phenyx_AC, "MS:1001388", "Phenyx:AC", "The primary sequence database identifier of a protein in Phenyx.", false}, {MS_Phenyx_ID, "MS:1001389", "Phenyx:ID", "A secondary sequence database identifier of a protein in Phenyx.", false}, {MS_Phenyx_Score, "MS:1001390", "Phenyx:Score", "The protein score of a protein match in Phenyx.", false}, {MS_Phenyx_Peptides1, "MS:1001391", "Phenyx:Peptides1", "First number of phenyx result \\\"#Peptides\\\".", false}, {MS_Phenyx_Peptides2, "MS:1001392", "Phenyx:Peptides2", "Second number of phenyx result \\\"#Peptides\\\".", false}, {MS_Phenyx_Auto, "MS:1001393", "Phenyx:Auto", "The value of the automatic peptide acceptance filter in Phenyx.", false}, {MS_Phenyx_User, "MS:1001394", "Phenyx:User", "The value of the user-defined peptide acceptance filter in Phenyx.", false}, {MS_Phenyx_Pepzscore, "MS:1001395", "Phenyx:Pepzscore", "The z-score value of a peptide sequence match in Phenyx.", false}, {MS_Phenyx_PepPvalue, "MS:1001396", "Phenyx:PepPvalue", "The p-value of a peptide sequence match in Phenyx.", false}, {MS_Phenyx_NumberOfMC, "MS:1001397", "Phenyx:NumberOfMC", "The number of missed cleavages of a peptide sequence in Phenyx.", false}, {MS_Phenyx_Modif, "MS:1001398", "Phenyx:Modif", "The expression of the nature and position(s) of modified residue(s) on a matched peptide sequence in Phenyx.", false}, {MS_OMSSA_csv_format, "MS:1001399", "OMSSA csv format", "Source file for this mzIdentML was in OMSSA csv file format.", false}, {MS_OMSSA_xml_format, "MS:1001400", "OMSSA xml format", "Source file for this mzIdentML was in OMSSA xml file format.", false}, {MS_X_Tandem_xml_format, "MS:1001401", "X!Tandem xml format", "Source file for this mzIdentML was in X!Tandem xml file format.", false}, {MS_spectrum_identification_result_details, "MS:1001405", "spectrum identification result details", "This subsection describes terms which can describe details of spectrum identification results.", false}, {MS_param__internal_yb_ion, "MS:1001406", "param: internal yb ion", "Parameter information, type of product: internal yb ion.", false}, {MS_param__internal_ya_ion, "MS:1001407", "param: internal ya ion", "Parameter information, type of product: internal ya ion.", false}, {MS_param__z_1_ion, "MS:1001408", "param: z+1 ion", "Parameter information, type of product: z+1 ion.", false}, {MS_param__z_2_ion, "MS:1001409", "param: z+2 ion", "Parameter information, type of product: z+2 ion.", false}, {MS_translation_start_codons, "MS:1001410", "translation start codons", "The translation start codons used to translate the nucleotides to amino acids.", false}, {MS_search_tolerance_specification, "MS:1001411", "search tolerance specification", "Specification of the search tolerance.", false}, {MS_search_tolerance_plus_value, "MS:1001412", "search tolerance plus value", "", false}, {MS_search_tolerance_minus_value, "MS:1001413", "search tolerance minus value", "", false}, {MS_MGF_scans_OBSOLETE, "MS:1001414", "MGF scans", "OBSOLETE: replaced by MS:1000797 (peak list scans): This term can hold the scans attribute from an MGF input file.", true}, {MS_MGF_raw_scans_OBSOLETE, "MS:1001415", "MGF raw scans", "OBSOLETE: replaced by MS:1000798 (peak list raw scans): This term can hold the raw scans attribute from an MGF input file.", true}, {MS_spectrum_title_OBSOLETE, "MS:1001416", "spectrum title", "OBSOLETE: replaced by MS:1000796 (spectrum title): Holds the spectrum title from different input file formats, e.g. MGF TITLE.", true}, {MS_SpectraST_dot, "MS:1001417", "SpectraST:dot", "SpectraST dot product of two spectra, measuring spectral similarity.", false}, {MS_SpectraST_dot_bias, "MS:1001418", "SpectraST:dot_bias", "SpectraST measure of how much of the dot product is dominated by a few peaks.", false}, {MS_SpectraST_discriminant_score_F, "MS:1001419", "SpectraST:discriminant score F", "SpectraST spectrum score.", false}, {MS_SpectraST_delta, "MS:1001420", "SpectraST:delta", "SpectraST normalised difference between dot product of top hit and runner-up.", false}, {MS_pepXML_format, "MS:1001421", "pepXML format", "Source file for this mzIdentML was in a pepXML file format.", false}, {MS_protXML_format, "MS:1001422", "protXML format", "Source file for this mzIdentML was in protXML file format.", false}, {MS_translation_table_description, "MS:1001423", "translation table description", "A URL that describes the translation table used to translate the nucleotides to amino acids.", false}, {MS_ProteinExtractor_Methodname, "MS:1001424", "ProteinExtractor:Methodname", "Name of the used method in the ProteinExtractor algorithm.", false}, {MS_ProteinExtractor_GenerateNonRedundant, "MS:1001425", "ProteinExtractor:GenerateNonRedundant", "Flag indicating if a non redundant scoring should be generated.", false}, {MS_ProteinExtractor_IncludeIdentified, "MS:1001426", "ProteinExtractor:IncludeIdentified", "Flag indicating if identified proteins should be included.", false}, {MS_ProteinExtractor_MaxNumberOfProteins, "MS:1001427", "ProteinExtractor:MaxNumberOfProteins", "The maximum number of proteins to consider.", false}, {MS_ProteinExtractor_MaxProteinMass, "MS:1001428", "ProteinExtractor:MaxProteinMass", "The maximum considered mass for a protein.", false}, {MS_ProteinExtractor_MinNumberOfPeptides, "MS:1001429", "ProteinExtractor:MinNumberOfPeptides", "The minimum number of proteins to consider.", false}, {MS_ProteinExtractor_UseMascot, "MS:1001430", "ProteinExtractor:UseMascot", "Flag indicating to include Mascot scoring for calculation of the ProteinExtractor meta score.", false}, {MS_ProteinExtractor_MascotPeptideScoreThreshold, "MS:1001431", "ProteinExtractor:MascotPeptideScoreThreshold", "Only peptides with scores higher than that threshold are taken into account in Mascot scoring for calculation of the ProteinExtractor meta score.", false}, {MS_ProteinExtractor_MascotUniqueScore, "MS:1001432", "ProteinExtractor:MascotUniqueScore", "In the final result each protein must have at least one peptide above this Mascot score threshold in ProteinExtractor meta score calculation.", false}, {MS_ProteinExtractor_MascotUseIdentityScore, "MS:1001433", "ProteinExtractor:MascotUseIdentityScore", "", false}, {MS_ProteinExtractor_MascotWeighting, "MS:1001434", "ProteinExtractor:MascotWeighting", "Influence of Mascot search engine in the process of merging the search engine specific protein lists into the global protein list of ProteinExtractor.", false}, {MS_ProteinExtractor_UseSequest, "MS:1001435", "ProteinExtractor:UseSequest", "Flag indicating to include SEQUEST scoring for calculation of the ProteinExtractor meta score.", false}, {MS_ProteinExtractor_SequestPeptideScoreThreshold, "MS:1001436", "ProteinExtractor:SequestPeptideScoreThreshold", "Only peptides with scores higher than that threshold are taken into account in SEQUEST scoring for calculation of the ProteinExtractor meta score.", false}, {MS_ProteinExtractor_SequestUniqueScore, "MS:1001437", "ProteinExtractor:SequestUniqueScore", "In the final result each protein must have at least one peptide above this SEQUEST score threshold in ProteinExtractor meta score calculation.", false}, {MS_ProteinExtractor_SequestWeighting, "MS:1001438", "ProteinExtractor:SequestWeighting", "Influence of SEQUEST search engine in the process of merging the search engine specific protein lists into the global protein list of ProteinExtractor.", false}, {MS_ProteinExtractor_UseProteinSolver, "MS:1001439", "ProteinExtractor:UseProteinSolver", "Flag indicating to include ProteinSolver scoring for calculation of the ProteinExtractor meta score.", false}, {MS_ProteinExtractor_ProteinSolverPeptideScoreThreshold, "MS:1001440", "ProteinExtractor:ProteinSolverPeptideScoreThreshold", "Only peptides with scores higher than that threshold are taken into account in ProteinSolver scoring for calculation of the ProteinExtractor meta score.", false}, {MS_ProteinExtractor_ProteinSolverUniqueScore, "MS:1001441", "ProteinExtractor:ProteinSolverUniqueScore", "In the final result each protein must have at least one peptide above this ProteinSolver score threshold in ProteinExtractor meta score calculation.", false}, {MS_ProteinExtractor_ProteinSolverWeighting, "MS:1001442", "ProteinExtractor:ProteinSolverWeighting", "Influence of ProteinSolver search engine in the process of merging the search engine specific protein lists into the global protein list of ProteinExtractor.", false}, {MS_ProteinExtractor_UsePhenyx, "MS:1001443", "ProteinExtractor:UsePhenyx", "Flag indicating to include Phenyx scoring for calculation of the ProteinExtractor meta score.", false}, {MS_ProteinExtractor_PhenyxPeptideScoreThreshold, "MS:1001444", "ProteinExtractor:PhenyxPeptideScoreThreshold", "Only peptides with scores higher than that threshold are taken into account in Phenyx scoring for calculation of the ProteinExtractor meta score.", false}, {MS_ProteinExtractor_PhenyxUniqueScore, "MS:1001445", "ProteinExtractor:PhenyxUniqueScore", "In the final result each protein must have at least one peptide above this Phenyx score threshold in ProteinExtractor meta score calculation.", false}, {MS_ProteinExtractor_PhenyxWeighting, "MS:1001446", "ProteinExtractor:PhenyxWeighting", "Influence of Phenyx search engine in the process of merging the search engine specific protein lists into the global protein list of ProteinExtractor.", false}, {MS_prot_FDR_threshold, "MS:1001447", "prot:FDR threshold", "False-discovery rate threshold for proteins.", false}, {MS_pep_FDR_threshold, "MS:1001448", "pep:FDR threshold", "False-discovery rate threshold for peptides.", false}, {MS_OMSSA_e_value_threshold, "MS:1001449", "OMSSA e-value threshold", "Threshold for OMSSA e-value for quality estimation.", false}, {MS_decoy_DB_details, "MS:1001450", "decoy DB details", "Details of decoy generation and database structure.", false}, {MS_decoy_DB_generation_algorithm, "MS:1001451", "decoy DB generation algorithm", "Name of algorithm used for decoy generation.", false}, {MS_decoy_DB_type_shuffle, "MS:1001452", "decoy DB type shuffle", "Decoy type: Amino acids of protein sequences are used in a random order.", false}, {MS_DB_composition_only_decoy, "MS:1001453", "DB composition only decoy", "Decoy database composition: database contains only decoy entries.", false}, {MS_quality_estimation_with_implicite_decoy_sequences, "MS:1001454", "quality estimation with implicite decoy sequences", "Decoy entries are generated during the search, not explicitly stored in a database (like Mascot Decoy).", false}, {MS_acquisition_software, "MS:1001455", "acquisition software", "Acquisition software.", false}, {MS_analysis_software, "MS:1001456", "analysis software", "Analysis software.", false}, {MS_data_processing_software, "MS:1001457", "data processing software", "Data processing software.", false}, {MS_spectrum_generation_information, "MS:1001458", "spectrum generation information", "Vocabularies describing the spectrum generation information.", false}, {MS_file_format, "MS:1001459", "file format", "Format of data files.", false}, {MS_unknown_modification, "MS:1001460", "unknown modification", "This term should be given if the modification was unknown.", false}, {MS_greylag, "MS:1001461", "greylag", "Greylag identification software.", false}, {MS_PEFF_format, "MS:1001462", "PEFF format", "The sequence database was stored in the PEFF (PSI enhanced FastA file) format.", false}, {MS_Phenyx_XML_format, "MS:1001463", "Phenyx XML format", "Phenyx open XML file format.", false}, {MS_DTASelect_format, "MS:1001464", "DTASelect format", "DTASelect file format.", false}, {MS_MS2_format, "MS:1001466", "MS2 format", "MS2 file format for MS2 spectral data.", false}, {MS_taxonomy__NCBI_TaxID, "MS:1001467", "taxonomy: NCBI TaxID", "This term is used if a NCBI TaxID is specified, e.g. 9606 for Homo sapiens.", false}, {MS_taxonomy__common_name, "MS:1001468", "taxonomy: common name", "This term is used if a common name is specified, e.g. human. Recommend using MS:1001467 (taxonomy: NCBI TaxID) where possible.", false}, {MS_taxonomy__scientific_name, "MS:1001469", "taxonomy: scientific name", "This term is used if a scientific name is specified, e.g. Homo sapiens. Recommend using MS:1001467 (taxonomy: NCBI TaxID) where possible.", false}, {MS_taxonomy__Swiss_Prot_ID, "MS:1001470", "taxonomy: Swiss-Prot ID", "This term is used if a swiss prot taxonomy id is specified, e.g. Human. Recommend using MS:1001467 (taxonomy: NCBI TaxID) where possible.", false}, {MS_peptide_modification_details, "MS:1001471", "peptide modification details", "The children of this term can be used to describe modifications.", false}, {MS_selected_ion_monitoring_chromatogram, "MS:1001472", "selected ion monitoring chromatogram", "Chromatogram created by creating an array of the measurements of a selectively monitored ion at each time point.", false}, {MS_selected_reaction_monitoring_chromatogram, "MS:1001473", "selected reaction monitoring chromatogram", "Chromatogram created by creating an array of the measurements of a selectively monitored reaction at each time point.", false}, {MS_consecutive_reaction_monitoring_chromatogram_OBSOLETE, "MS:1001474", "consecutive reaction monitoring chromatogram", "Chromatogram created by creating an array of the measurements of a series of monitored reactions at each time point.", true}, {MS_OMSSA, "MS:1001475", "OMSSA", "Open Mass Spectrometry Search Algorithm was used to analyze the spectra.", false}, {MS_X_Tandem, "MS:1001476", "X!Tandem", "X!Tandem was used to analyze the spectra.", false}, {MS_SpectraST, "MS:1001477", "SpectraST", "SpectraST was used to analyze the spectra.", false}, {MS_Mascot_Parser, "MS:1001478", "Mascot Parser", "Mascot Parser was used to analyze the spectra.", false}, {MS_null_terminated_ASCII_string, "MS:1001479", "null-terminated ASCII string", "Sequence of zero or more non-zero ASCII characters terminated by a single null (0) byte.", false}, {MS_SCIEX_TOF_TOF_nativeID_format, "MS:1001480", "SCIEX TOF/TOF nativeID format", "Native format defined by jobRun=xsd:nonNegativeInteger spotLabel=xsd:string spectrum=xsd:nonNegativeInteger.", false}, {MS_SCIEX_TOF_TOF_database, "MS:1001481", "SCIEX TOF/TOF database", "Applied Biosystems/MDS Analytical Technologies TOF/TOF instrument database.", false}, {MS_5800_TOF_TOF, "MS:1001482", "5800 TOF/TOF", "SCIEX 5800 TOF-TOF Analyzer.", false}, {MS_SCIEX_TOF_TOF_Series_Explorer_Software, "MS:1001483", "SCIEX TOF/TOF Series Explorer Software", "SCIEX or Applied Biosystems software for TOF/TOF data acquisition and analysis.", false}, {MS_intensity_normalization, "MS:1001484", "intensity normalization", "Normalization of data point intensities.", false}, {MS_m_z_calibration, "MS:1001485", "m/z calibration", "Calibration of data point m/z positions.", false}, {MS_data_filtering, "MS:1001486", "data filtering", "Filtering out part of the data.", false}, {MS_ProteinExtractor, "MS:1001487", "ProteinExtractor", "An algorithm for protein determination/assembly integrated into Bruker's ProteinScape.", false}, {MS_Mascot_Distiller, "MS:1001488", "Mascot Distiller", "Mascot Distiller.", false}, {MS_Mascot_Integra, "MS:1001489", "Mascot Integra", "Mascot Integra.", false}, {MS_Percolator, "MS:1001490", "Percolator", "Percolator.", false}, {MS_percolator_Q_value, "MS:1001491", "percolator:Q value", "Percolator:Q value.", false}, {MS_percolator_score, "MS:1001492", "percolator:score", "Percolator:score.", false}, {MS_percolator_PEP, "MS:1001493", "percolator:PEP", "Posterior error probability.", false}, {MS_no_threshold, "MS:1001494", "no threshold", "In case no threshold was used.", false}, {MS_ProteinScape_SearchResultId, "MS:1001495", "ProteinScape:SearchResultId", "The SearchResultId of this peptide as SearchResult in the ProteinScape database.", false}, {MS_ProteinScape_SearchEventId, "MS:1001496", "ProteinScape:SearchEventId", "The SearchEventId of the SearchEvent in the ProteinScape database.", false}, {MS_ProteinScape_ProfoundProbability, "MS:1001497", "ProteinScape:ProfoundProbability", "The Profound probability score stored by ProteinScape.", false}, {MS_Profound_z_value, "MS:1001498", "Profound:z value", "The Profound z value.", false}, {MS_Profound_Cluster, "MS:1001499", "Profound:Cluster", "The Profound cluster score.", false}, {MS_Profound_ClusterRank, "MS:1001500", "Profound:ClusterRank", "The Profound cluster rank.", false}, {MS_MSFit_Mowse_score, "MS:1001501", "MSFit:Mowse score", "The MSFit Mowse score.", false}, {MS_Sonar_Score, "MS:1001502", "Sonar:Score", "The Sonar score.", false}, {MS_ProteinScape_PFFSolverExp, "MS:1001503", "ProteinScape:PFFSolverExp", "The ProteinSolver exp value stored by ProteinScape.", false}, {MS_ProteinScape_PFFSolverScore, "MS:1001504", "ProteinScape:PFFSolverScore", "The ProteinSolver score stored by ProteinScape.", false}, {MS_ProteinScape_IntensityCoverage, "MS:1001505", "ProteinScape:IntensityCoverage", "The intensity coverage of the identified peaks in the spectrum calculated by ProteinScape.", false}, {MS_ProteinScape_SequestMetaScore, "MS:1001506", "ProteinScape:SequestMetaScore", "The SEQUEST meta score calculated by ProteinScape from the original SEQUEST scores.", false}, {MS_ProteinExtractor_Score, "MS:1001507", "ProteinExtractor:Score", "The score calculated by ProteinExtractor.", false}, {MS_Agilent_MassHunter_nativeID_format, "MS:1001508", "Agilent MassHunter nativeID format", "Native format defined by scanId=xsd:nonNegativeInteger.", false}, {MS_Agilent_MassHunter_format, "MS:1001509", "Agilent MassHunter format", "A data file format found in an Agilent MassHunter directory which contains raw data acquired by an Agilent mass spectrometer.", false}, {MS_TSQ_Vantage, "MS:1001510", "TSQ Vantage", "TSQ Vantage.", false}, {MS_Sequence_database_filter_types, "MS:1001511", "Sequence database filter types", "Filter types which are used to filter a sequence database.", false}, {MS_Sequence_database_filters, "MS:1001512", "Sequence database filters", "Sequence database filters which actually can contains values, e.g. to limit PI value of the sequences used to search.", false}, {MS_DB_sequence_filter_pattern, "MS:1001513", "DB sequence filter pattern", "DB sequence filter pattern.", false}, {MS_DB_accession_filter_string, "MS:1001514", "DB accession filter string", "DB accession filter string.", false}, {MS_frag__c_ion___H2O, "MS:1001515", "frag: c ion - H2O", "Fragmentation information, type of product: c ion without water.", false}, {MS_frag__c_ion___NH3, "MS:1001516", "frag: c ion - NH3", "Fragmentation information, type of product: c ion without ammonia.", false}, {MS_frag__z_ion___H2O, "MS:1001517", "frag: z ion - H2O", "Fragmentation information, type of product: z ion without water.", false}, {MS_frag__z_ion___NH3, "MS:1001518", "frag: z ion - NH3", "Fragmentation information, type of product: z ion without ammonia.", false}, {MS_frag__x_ion___H2O, "MS:1001519", "frag: x ion - H2O", "Fragmentation information, type of product: x ion without water.", false}, {MS_frag__x_ion___NH3, "MS:1001520", "frag: x ion - NH3", "Fragmentation information, type of product: x ion without ammonia.", false}, {MS_frag__precursor_ion___H2O, "MS:1001521", "frag: precursor ion - H2O", "Fragmentation information, type of product: precursor ion without water.", false}, {MS_frag__precursor_ion___NH3, "MS:1001522", "frag: precursor ion - NH3", "Fragmentation information, type of product: precursor ion without ammonia.", false}, {MS_frag__precursor_ion, "MS:1001523", "frag: precursor ion", "Fragmentation information, type of product: precursor ion.", false}, {MS_fragment_neutral_loss, "MS:1001524", "fragment neutral loss", "This term can describe a neutral loss m/z value that is lost from an ion.", false}, {MS_precursor_neutral_loss, "MS:1001525", "precursor neutral loss", "This term can describe a neutral loss m/z value that is lost from an ion.", false}, {MS_spectrum_from_database_integer_nativeID_format, "MS:1001526", "spectrum from database integer nativeID format", "Native format defined by databasekey=xsd:long.", false}, {MS_Proteinscape_spectra, "MS:1001527", "Proteinscape spectra", "Spectra from Bruker/Protagen Proteinscape database.", false}, {MS_Mascot_query_number, "MS:1001528", "Mascot query number", "Native format defined by query=xsd:nonNegativeInteger.", false}, {MS_spectra_data_details, "MS:1001529", "spectra data details", "Child-terms contain information to map the results back to spectra.", false}, {MS_mzML_unique_identifier, "MS:1001530", "mzML unique identifier", "Native format defined by mzMLid=xsd:IDREF.", false}, {MS_spectrum_from_ProteinScape_database_nativeID_format, "MS:1001531", "spectrum from ProteinScape database nativeID format", "Native format defined by databasekey=xsd:long.", false}, {MS_spectrum_from_database_string_nativeID_format, "MS:1001532", "spectrum from database string nativeID format", "Native format defined by databasekey=xsd:string.", false}, {MS_Bruker_Daltonics_esquire_series, "MS:1001533", "Bruker Daltonics esquire series", "Bruker Daltonics' esquire series.", false}, {MS_Bruker_Daltonics_flex_series, "MS:1001534", "Bruker Daltonics flex series", "Bruker Daltonics' flex series.", false}, {MS_Bruker_Daltonics_BioTOF_series, "MS:1001535", "Bruker Daltonics BioTOF series", "Bruker Daltonics' BioTOF series.", false}, {MS_Bruker_Daltonics_micrOTOF_series, "MS:1001536", "Bruker Daltonics micrOTOF series", "Bruker Daltonics' micrOTOF series.", false}, {MS_BioTOF, "MS:1001537", "BioTOF", "Bruker Daltonics' BioTOF: ESI TOF.", false}, {MS_BioTOF_III, "MS:1001538", "BioTOF III", "Bruker Daltonics' BioTOF III: ESI TOF.", false}, {MS_UltroTOF_Q, "MS:1001539", "UltroTOF-Q", "Bruker Daltonics' UltroTOF-Q: ESI Q-TOF (MALDI optional).", false}, {MS_micrOTOF_II, "MS:1001540", "micrOTOF II", "Bruker Daltonics' micrOTOF II: ESI TOF, Nanospray, APCI, APPI.", false}, {MS_maXis, "MS:1001541", "maXis", "Bruker Daltonics' maXis: ESI Q-TOF, Nanospray, APCI, APPI.", false}, {MS_amaZon_ETD, "MS:1001542", "amaZon ETD", "Bruker Daltonics' amaZon ETD: ESI quadrupole ion trap, Nanospray, APCI, APPI, ETD, PTR.", false}, {MS_microflex_LRF, "MS:1001543", "microflex LRF", "Bruker Daltonics' microflex LRF: MALDI TOF.", false}, {MS_ultrafleXtreme, "MS:1001544", "ultrafleXtreme", "Bruker Daltonics' ultrafleXtreme: MALDI TOF.", false}, {MS_Bruker_Daltonics_amaZon_series, "MS:1001545", "Bruker Daltonics amaZon series", "Bruker Daltonics' amaZon series.", false}, {MS_amaZon_X, "MS:1001546", "amaZon X", "Bruker Daltonics' amaZon X: ESI quadrupole ion trap, APCI, APPI, ETD, PTR.", false}, {MS_Bruker_Daltonics_maXis_series, "MS:1001547", "Bruker Daltonics maXis series", "Bruker Daltonics' maXis series.", false}, {MS_Bruker_Daltonics_solarix_series, "MS:1001548", "Bruker Daltonics solarix series", "Bruker Daltonics' solarix: ESI quadrupole ion trap, APCI, APPI, ETD, PTR.", false}, {MS_solariX, "MS:1001549", "solariX", "Bruker Daltonics' solariX: ESI, MALDI, Qh-FT_ICR.", false}, {MS_microflex_II, "MS:1001550", "microflex II", "Bruker Daltonics' microflex II: MALDI TOF.", false}, {MS_autoflex_II_TOF_TOF, "MS:1001553", "autoflex II TOF/TOF", "Bruker Daltonics' autoflex II TOF/TOF: MALDI TOF.", false}, {MS_autoflex_III_TOF_TOF_smartbeam, "MS:1001554", "autoflex III TOF/TOF smartbeam", "Bruker Daltonics' autoflex III TOF/TOF smartbeam: MALDI TOF.", false}, {MS_autoflex, "MS:1001555", "autoflex", "Bruker Daltonics' autoflex: MALDI TOF.", false}, {MS_Bruker_Daltonics_apex_series, "MS:1001556", "Bruker Daltonics apex series", "Bruker Daltonics' apex series.", false}, {MS_Shimadzu_Corporation_software, "MS:1001557", "Shimadzu Corporation software", "Shimadzu Corporation software.", false}, {MS_MALDI_Solutions, "MS:1001558", "MALDI Solutions", "Shimadzu Biotech software for data acquisition, processing, and analysis.", false}, {MS_SCIEX_TOF_TOF_T2D_nativeID_format, "MS:1001559", "SCIEX TOF/TOF T2D nativeID format", "Native format defined by file=xsd:IDREF.", false}, {MS_SCIEX_TOF_TOF_T2D_format, "MS:1001560", "SCIEX TOF/TOF T2D format", "Applied Biosystems/MDS Analytical Technologies TOF/TOF instrument export format.", false}, {MS_Scaffold, "MS:1001561", "Scaffold", "Scaffold analysis software.", false}, {MS_Scaffold_nativeID_format, "MS:1001562", "Scaffold nativeID format", "Scaffold native ID format.", false}, {MS_SEQUEST_SQT_format, "MS:1001563", "SEQUEST SQT format", "Source file for this mzIdentML was in SEQUEST SQT format.", false}, {MS_Discoverer_MSF_format, "MS:1001564", "Discoverer MSF format", "Source file for this mzIdentML was in Thermo Scientific Discoverer MSF format.", false}, {MS_IdentityE_XML_format, "MS:1001565", "IdentityE XML format", "Source file for this mzIdentML was in Waters IdentityE XML format.", false}, {MS_ProteinLynx_XML_format, "MS:1001566", "ProteinLynx XML format", "Source file for this mzIdentML was in Waters ProteinLynx XML format.", false}, {MS_SpectrumMill_directories, "MS:1001567", "SpectrumMill directories", "Source file for this mzIdentML was in Agilent SpectrumMill directory format.", false}, {MS_Scaffold_Peptide_Probability, "MS:1001568", "Scaffold:Peptide Probability", "Scaffold peptide probability score.", false}, {MS_IdentityE_Score, "MS:1001569", "IdentityE Score", "Waters IdentityE peptide score.", false}, {MS_ProteinLynx_Log_Likelihood, "MS:1001570", "ProteinLynx:Log Likelihood", "ProteinLynx log likelihood score.", false}, {MS_ProteinLynx_Ladder_Score, "MS:1001571", "ProteinLynx:Ladder Score", "Waters ProteinLynx Ladder score.", false}, {MS_SpectrumMill_Score, "MS:1001572", "SpectrumMill:Score", "Spectrum mill peptide score.", false}, {MS_SpectrumMill_SPI, "MS:1001573", "SpectrumMill:SPI", "SpectrumMill SPI score (%).", false}, {MS_report_only_spectra_assigned_to_identified_proteins, "MS:1001574", "report only spectra assigned to identified proteins", "Flag indicating to report only the spectra assigned to identified proteins.", false}, {MS_Scaffold__Minimum_Peptide_Count, "MS:1001575", "Scaffold: Minimum Peptide Count", "Minimum number of peptides a protein must have to be accepted.", false}, {MS_Scaffold__Minimum_Protein_Probability, "MS:1001576", "Scaffold: Minimum Protein Probability", "Minimum protein probability a protein must have to be accepted.", false}, {MS_Scaffold__Minimum_Peptide_Probability, "MS:1001577", "Scaffold: Minimum Peptide Probability", "Minimum probability a peptide must have to be accepted for protein scoring.", false}, {MS_minimum_number_of_enzymatic_termini, "MS:1001578", "minimum number of enzymatic termini", "Minimum number of enzymatic termini a peptide must have to be accepted.", false}, {MS_Scaffold_Protein_Probability, "MS:1001579", "Scaffold:Protein Probability", "Scaffold protein probability score.", false}, {MS_SpectrumMill_Discriminant_Score, "MS:1001580", "SpectrumMill:Discriminant Score", "Discriminant score from Agilent SpectrumMill software.", false}, {MS_FAIMS_compensation_voltage, "MS:1001581", "FAIMS compensation voltage", "The DC potential applied to the asymmetric waveform in FAIMS that compensates for the difference between high and low field mobility of an ion.", false}, {MS_XCMS, "MS:1001582", "XCMS", "Bioconductor package XCMS for preprocessing high-throughput, untargeted analyte profiling data.", false}, {MS_MaxQuant, "MS:1001583", "MaxQuant", "MaxQuant is a quantitative proteomics software package designed for analyzing large mass spectrometric data sets. It is specifically aimed at high resolution MS data.", false}, {MS_combined_pmf___ms_ms_search, "MS:1001584", "combined pmf + ms-ms search", "Search that includes data from Peptide Mass Fingerprint (PMF) and MS2 (aka Peptide Fragment Fingerprint - PFF).", false}, {MS_MyriMatch, "MS:1001585", "MyriMatch", "Tabb Lab software for directly comparing peptides in a database to tandem mass spectra.", false}, {MS_DirecTag, "MS:1001586", "DirecTag", "Tabb Lab software for generating sequence tags from tandem mass spectra.", false}, {MS_TagRecon, "MS:1001587", "TagRecon", "Tabb Lab software for reconciling sequence tags to a protein database.", false}, {MS_Pepitome, "MS:1001588", "Pepitome", "Tabb Lab software for spectral library searches on tandem mass spectra.", false}, {MS_MyriMatch_MVH, "MS:1001589", "MyriMatch:MVH", "Using the multivariate hypergeometric distribution and a peak list divided into several intensity classes, this score is the negative natural log probability that the predicted peaks matched to experimental peaks by random chance.", false}, {MS_MyriMatch_mzFidelity, "MS:1001590", "MyriMatch:mzFidelity", "The negative natural log probability that predicted peaks match to experimental peaks by random chance by scoring the m/z delta of the matches in a multinomial distribution.", false}, {MS_anchor_protein, "MS:1001591", "anchor protein", "A representative protein selected from a set of sequence same-set or spectrum same-set proteins.", false}, {MS_family_member_protein, "MS:1001592", "family member protein", "A protein with significant homology to another protein, but some distinguishing peptide matches.", false}, {MS_group_member_with_undefined_relationship_OR_ortholog_protein, "MS:1001593", "group member with undefined relationship OR ortholog protein", "TO ENDETAIL: a really generic relationship OR ortholog protein.", false}, {MS_sequence_same_set_protein, "MS:1001594", "sequence same-set protein", "A protein which is indistinguishable or equivalent to another protein, having matches to an identical set of peptide sequences.", false}, {MS_spectrum_same_set_protein, "MS:1001595", "spectrum same-set protein", "A protein which is indistinguishable or equivalent to another protein, having matches to a set of peptide sequences that cannot be distinguished using the evidence in the mass spectra.", false}, {MS_sequence_sub_set_protein, "MS:1001596", "sequence sub-set protein", "A protein with a sub-set of the peptide sequence matches for another protein, and no distinguishing peptide matches.", false}, {MS_spectrum_sub_set_protein, "MS:1001597", "spectrum sub-set protein", "A protein with a sub-set of the matched spectra for another protein, where the matches cannot be distinguished using the evidence in the mass spectra, and no distinguishing peptide matches.", false}, {MS_sequence_subsumable_protein, "MS:1001598", "sequence subsumable protein", "A sequence same-set or sequence sub-set protein where the matches are distributed across two or more proteins.", false}, {MS_spectrum_subsumable_protein, "MS:1001599", "spectrum subsumable protein", "A spectrum same-set or spectrum sub-set protein where the matches are distributed across two or more proteins.", false}, {MS_protein_inference_confidence_category, "MS:1001600", "protein inference confidence category", "Confidence category of inferred protein (conclusive, non conclusive, ambiguous group or indistinguishable).", false}, {MS_ProteomeDiscoverer_Spectrum_Files_Raw_File_names_OBSOLETE, "MS:1001601", "ProteomeDiscoverer:Spectrum Files:Raw File names", "Name and location of the .raw file or files.", true}, {MS_ProteomeDiscoverer_SRF_File_Selector_SRF_File_Path_OBSOLETE, "MS:1001602", "ProteomeDiscoverer:SRF File Selector:SRF File Path", "Path and name of the .srf (SEQUEST Result Format) file.", true}, {MS_ProteomeDiscoverer_Spectrum_Selector_Ionization_Source_OBSOLETE, "MS:1001603", "ProteomeDiscoverer:Spectrum Selector:Ionization Source", "Ionization source (electro-, nano-, thermospray, electron impact, APCI, MALDI, FAB etc).", true}, {MS_ProteomeDiscoverer_Activation_Type_OBSOLETE, "MS:1001604", "ProteomeDiscoverer:Activation Type", "Fragmentation method used (CID, MPD, ECD, PQD, ETD, HCD, Any).", true}, {MS_ProteomeDiscoverer_Spectrum_Selector_Lower_RT_Limit, "MS:1001605", "ProteomeDiscoverer:Spectrum Selector:Lower RT Limit", "Lower retention-time limit.", false}, {MS_ProteomeDiscoverer_Mass_Analyzer_OBSOLETE, "MS:1001606", "ProteomeDiscoverer:Mass Analyzer", "Type of mass spectrometer used (ITMS, FTMS, TOFMS, SQMS, TQMS, SectorMS).", true}, {MS_ProteomeDiscoverer_Max_Precursor_Mass, "MS:1001607", "ProteomeDiscoverer:Max Precursor Mass", "Maximum mass limit of a singly charged precursor ion.", false}, {MS_ProteomeDiscoverer_Min_Precursor_Mass, "MS:1001608", "ProteomeDiscoverer:Min Precursor Mass", "Minimum mass limit of a singly charged precursor ion.", false}, {MS_ProteomeDiscoverer_Spectrum_Selector_Minimum_Peak_Count, "MS:1001609", "ProteomeDiscoverer:Spectrum Selector:Minimum Peak Count", "Minimum number of peaks in a tandem mass spectrum that is allowed to pass the filter and to be subjected to further processing in the workflow.", false}, {MS_ProteomeDiscoverer_MS_Order_OBSOLETE, "MS:1001610", "ProteomeDiscoverer:MS Order", "Level of the mass spectrum (MS2 ... MS10).", true}, {MS_ProteomeDiscoverer_Polarity_Mode_OBSOLETE, "MS:1001611", "ProteomeDiscoverer:Polarity Mode", "Polarity mode (positive or negative).", true}, {MS_ProteomeDiscoverer_Spectrum_Selector_Precursor_Selection, "MS:1001612", "ProteomeDiscoverer:Spectrum Selector:Precursor Selection", "Determines which precursor mass to use for a given MSn scan. This option applies only to higher-order MSn scans (n >= 3).", false}, {MS_ProteomeDiscoverer_SN_Threshold, "MS:1001613", "ProteomeDiscoverer:SN Threshold", "Signal-to-Noise ratio below which peaks are removed.", false}, {MS_ProteomeDiscoverer_Scan_Type_OBSOLETE, "MS:1001614", "ProteomeDiscoverer:Scan Type", "Scan type for the precursor ion (full, Single Ion Monitoring (SIM), Single Reaction Monitoring (SRM)).", true}, {MS_ProteomeDiscoverer_Spectrum_Selector_Total_Intensity_Threshold, "MS:1001615", "ProteomeDiscoverer:Spectrum Selector:Total Intensity Threshold", "Used to filter out tandem mass spectra that have a total intensity current(sum of the intensities of all peaks in a spectrum) below the specified value.", false}, {MS_ProteomeDiscoverer_Spectrum_Selector_Unrecognized_Activation_Type_Replacements, "MS:1001616", "ProteomeDiscoverer:Spectrum Selector:Unrecognized Activation Type Replacements", "Specifies the fragmentation method to use in the search algorithm if it is not included in the scan header.", false}, {MS_ProteomeDiscoverer_Spectrum_Selector_Unrecognized_Charge_Replacements, "MS:1001617", "ProteomeDiscoverer:Spectrum Selector:Unrecognized Charge Replacements", "Specifies the charge state of the precursor ions, if it is not defined in the scan header.", false}, {MS_ProteomeDiscoverer_Spectrum_Selector_Unrecognized_Mass_Analyzer_Replacements, "MS:1001618", "ProteomeDiscoverer:Spectrum Selector:Unrecognized Mass Analyzer Replacements", "Specifies the mass spectrometer to use to produce the spectra, if it is not included in the scan header.", false}, {MS_ProteomeDiscoverer_Spectrum_Selector_Unrecognized_MS_Order_Replacements, "MS:1001619", "ProteomeDiscoverer:Spectrum Selector:Unrecognized MS Order Replacements", "Specifies the MS scan order used to produce the product spectra, if it is not included in the scan header.", false}, {MS_ProteomeDiscoverer_Spectrum_Selector_Unrecognized_Polarity_Replacements, "MS:1001620", "ProteomeDiscoverer:Spectrum Selector:Unrecognized Polarity Replacements", "Specifies the polarity of the ions monitored if it is not included in the scan header.", false}, {MS_ProteomeDiscoverer_Spectrum_Selector_Upper_RT_Limit, "MS:1001621", "ProteomeDiscoverer:Spectrum Selector:Upper RT Limit", "Upper retention-time limit.", false}, {MS_ProteomeDiscoverer_Non_Fragment_Filter_Mass_Window_Offset, "MS:1001622", "ProteomeDiscoverer:Non-Fragment Filter:Mass Window Offset", "Specifies the size of the mass-to-charge ratio (m/z) window in daltons used to remove precursors.", false}, {MS_ProteomeDiscoverer_Non_Fragment_Filter_Maximum_Neutral_Loss_Mass, "MS:1001623", "ProteomeDiscoverer:Non-Fragment Filter:Maximum Neutral Loss Mass", "Maximum allowed mass of a neutral loss.", false}, {MS_ProteomeDiscoverer_Non_Fragment_Filter_Remove_Charge_Reduced_Precursor, "MS:1001624", "ProteomeDiscoverer:Non-Fragment Filter:Remove Charge Reduced Precursor", "Determines whether the charge-reduced precursor peaks found in an ETD or ECD spectrum are removed.", false}, {MS_ProteomeDiscoverer_Non_Fragment_Filter_Remove_Neutral_Loss_Peaks, "MS:1001625", "ProteomeDiscoverer:Non-Fragment Filter:Remove Neutral Loss Peaks", "Determines whether neutral loss peaks are removed from ETD and ECD spectra.", false}, {MS_ProteomeDiscoverer_Non_Fragment_Filter_Remove_Only_Known_Masses, "MS:1001626", "ProteomeDiscoverer:Non-Fragment Filter:Remove Only Known Masses", "Determines whether overtone peaks are removed from LTQ FT or LTQ FT Ultra ECD spectra.", false}, {MS_ProteomeDiscoverer_Non_Fragment_Filter_Remove_Precursor_Overtones, "MS:1001627", "ProteomeDiscoverer:Non-Fragment Filter:Remove Precursor Overtones", "Determines whether precursor overtone peaks in the spectrum are removed from the input spectrum.", false}, {MS_ProteomeDiscoverer_Non_Fragment_Filter_Remove_Precursor_Peak, "MS:1001628", "ProteomeDiscoverer:Non-Fragment Filter:Remove Precursor Peak", "Determines whether precursor artifact peaks from the MS2 input spectra are removed.", false}, {MS_ProteomeDiscoverer_Spectrum_Grouper_Allow_Mass_Analyzer_Mismatch, "MS:1001629", "ProteomeDiscoverer:Spectrum Grouper:Allow Mass Analyzer Mismatch", "Determines whether the fragment spectrum for scans with the same precursor mass is grouped, regardless of mass analyzer and activation type.", false}, {MS_ProteomeDiscoverer_Spectrum_Grouper_Allow_MS_Order_Mismatch, "MS:1001630", "ProteomeDiscoverer:Spectrum Grouper:Allow MS Order Mismatch", "Determines whether spectra from different MS order scans can be grouped together.", false}, {MS_ProteomeDiscoverer_Spectrum_Grouper_Max_RT_Difference_OBSOLETE, "MS:1001631", "ProteomeDiscoverer:Spectrum Grouper:Max RT Difference", "Chromatographic window where precursors to be grouped must reside to be considered the same species.", true}, {MS_ProteomeDiscoverer_Spectrum_Grouper_Precursor_Mass_Criterion, "MS:1001632", "ProteomeDiscoverer:Spectrum Grouper:Precursor Mass Criterion", "Groups spectra measured within the given mass and retention-time tolerances into a single spectrum for analysis.", false}, {MS_ProteomeDiscoverer_Xtract_Highest_Charge, "MS:1001633", "ProteomeDiscoverer:Xtract:Highest Charge", "Highest charge state that is allowed for the deconvolution of multiply charged data.", false}, {MS_ProteomeDiscoverer_Xtract_Highest_MZ_OBSOLETE, "MS:1001634", "ProteomeDiscoverer:Xtract:Highest MZ", "Highest mass-to-charge (mz) value for spectral peaks in the measured spectrum that are considered for Xtract.", true}, {MS_ProteomeDiscoverer_Xtract_Lowest_Charge, "MS:1001635", "ProteomeDiscoverer:Xtract:Lowest Charge", "Lowest charge state that is allowed for the deconvolution of multiply charged data.", false}, {MS_ProteomeDiscoverer_Xtract_Lowest_MZ_OBSOLETE, "MS:1001636", "ProteomeDiscoverer:Xtract:Lowest MZ", "Lowest mass-to-charge (mz) value for spectral peaks in the measured spectrum that are considered for Xtract.", true}, {MS_ProteomeDiscoverer_Xtract_Monoisotopic_Mass_Only, "MS:1001637", "ProteomeDiscoverer:Xtract:Monoisotopic Mass Only", "Determines whether the isotopic pattern, i.e. all isotopes of a mass are removed from the spectrum.", false}, {MS_ProteomeDiscoverer_Xtract_Overlapping_Remainder, "MS:1001638", "ProteomeDiscoverer:Xtract:Overlapping Remainder", "Fraction of the more abundant peak that an overlapping multiplet must exceed in order to be processed (deconvoluted).", false}, {MS_ProteomeDiscoverer_Xtract_Required_Fitting_Accuracy, "MS:1001639", "ProteomeDiscoverer:Xtract:Required Fitting Accuracy", "Accuracy required for a pattern fit to be considered valid.", false}, {MS_ProteomeDiscoverer_Xtract_Resolution_At_400, "MS:1001640", "ProteomeDiscoverer:Xtract:Resolution At 400", "Resolution at mass 400.", false}, {MS_ProteomeDiscoverer_Lowest_Charge_State, "MS:1001641", "ProteomeDiscoverer:Lowest Charge State", "Minimum charge state below which peptides are filtered out.", false}, {MS_ProteomeDiscoverer_Highest_Charge_State, "MS:1001642", "ProteomeDiscoverer:Highest Charge State", "Maximum charge above which peptides are filtered out.", false}, {MS_ProteomeDiscoverer_Spectrum_Score_Filter_Let_Pass_Above_Scores, "MS:1001643", "ProteomeDiscoverer:Spectrum Score Filter:Let Pass Above Scores", "Determines whether spectra with scores above the threshold score are retained rather than filtered out.", false}, {MS_ProteomeDiscoverer_Dynamic_Modification, "MS:1001644", "ProteomeDiscoverer:Dynamic Modification", "Determine dynamic post-translational modifications (PTMs).", false}, {MS_ProteomeDiscoverer_Static_Modification, "MS:1001645", "ProteomeDiscoverer:Static Modification", "Static Modification to all occurrences of a named amino acid.", false}, {MS_ProteomeDiscoverer_Mascot_Decoy_Search_OBSOLETE, "MS:1001646", "ProteomeDiscoverer:Mascot:Decoy Search", "Determines whether the Proteome Discoverer application searches an additional decoy database.", true}, {MS_ProteomeDiscoverer_Mascot_Error_tolerant_Search, "MS:1001647", "ProteomeDiscoverer:Mascot:Error tolerant Search", "Determines whether to search error-tolerant.", false}, {MS_ProteomeDiscoverer_Mascot_Max_MGF_File_Size, "MS:1001648", "ProteomeDiscoverer:Mascot:Max MGF File Size", "Maximum size of the .mgf (Mascot Generic Format) file in MByte.", false}, {MS_ProteomeDiscoverer_Mascot_Mascot_Server_URL, "MS:1001649", "ProteomeDiscoverer:Mascot:Mascot Server URL", "URL (Uniform resource Locator) of the Mascot server.", false}, {MS_ProteomeDiscoverer_Mascot_Number_of_attempts_to_submit_the_search, "MS:1001650", "ProteomeDiscoverer:Mascot:Number of attempts to submit the search", "Number of attempts to submit the Mascot search.", false}, {MS_ProteomeDiscoverer_Mascot_X_Static_Modification, "MS:1001651", "ProteomeDiscoverer:Mascot:X Static Modification", "Number of attempts to submit the Mascot search.", false}, {MS_ProteomeDiscoverer_Mascot_User_Name_OBSOLETE, "MS:1001652", "ProteomeDiscoverer:Mascot:User Name", "Name of the user submitting the Mascot search.", true}, {MS_ProteomeDiscoverer_Mascot_Time_interval_between_attempts_to_submit_a_search, "MS:1001653", "ProteomeDiscoverer:Mascot:Time interval between attempts to submit a search", "Time interval between attempts to submit a search in seconds.", false}, {MS_ProteomeDiscoverer_Enzyme_Name_OBSOLETE, "MS:1001654", "ProteomeDiscoverer:Enzyme Name", "Specifies the enzyme reagent used for protein digestion.", true}, {MS_ProteomeDiscoverer_Fragment_Mass_Tolerance_OBSOLETE, "MS:1001655", "ProteomeDiscoverer:Fragment Mass Tolerance", "Mass tolerance used for matching fragment peaks in Da or mmu.", true}, {MS_Mascot_Instrument, "MS:1001656", "Mascot:Instrument", "Type of instrument used to acquire the data in the raw file.", false}, {MS_ProteomeDiscoverer_Maximum_Missed_Cleavage_Sites, "MS:1001657", "ProteomeDiscoverer:Maximum Missed Cleavage Sites", "Maximum number of missed cleavage sites to consider during the digest.", false}, {MS_ProteomeDiscoverer_Mascot_Peptide_CutOff_Score, "MS:1001658", "ProteomeDiscoverer:Mascot:Peptide CutOff Score", "Minimum score in the IonScore column that each peptide must exceed in order to be reported.", false}, {MS_ProteomeDiscoverer_Precursor_Mass_Tolerance_OBSOLETE, "MS:1001659", "ProteomeDiscoverer:Precursor Mass Tolerance", "Mass window for which precursor ions are considered to be the same species.", true}, {MS_ProteomeDiscoverer_Mascot_Protein_CutOff_Score, "MS:1001660", "ProteomeDiscoverer:Mascot:Protein CutOff Score", "Minimum protein score in the IonScore column that each protein must exceed in order to be reported.", false}, {MS_ProteomeDiscoverer_Protein_Database_OBSOLETE, "MS:1001661", "ProteomeDiscoverer:Protein Database", "Database to use in the search (configured on the Mascot server).", true}, {MS_ProteomeDiscoverer_Mascot_Protein_Relevance_Factor, "MS:1001662", "ProteomeDiscoverer:Mascot:Protein Relevance Factor", "Specifies a factor that is used in calculating a threshold that determines whether a protein appears in the results report.", false}, {MS_ProteomeDiscoverer_Target_FDR_Relaxed, "MS:1001663", "ProteomeDiscoverer:Target FDR Relaxed", "Specifies the relaxed target false discovery rate (FDR, 0.0 - 1.0) for peptide hits with moderate confidence.", false}, {MS_ProteomeDiscoverer_Target_FDR_Strict, "MS:1001664", "ProteomeDiscoverer:Target FDR Strict", "Specifies the strict target false discovery rate (FDR, 0.0 - 1.0) for peptide hits with high confidence.", false}, {MS_ProteomeDiscoverer_Mascot_Taxonomy_OBSOLETE, "MS:1001665", "ProteomeDiscoverer:Mascot:Taxonomy", "Limits searches to entries from a particular species or group of species.", true}, {MS_ProteomeDiscoverer_Use_Average_Precursor_Mass_OBSOLETE, "MS:1001666", "ProteomeDiscoverer:Use Average Precursor Mass", "Use average mass for the precursor.", true}, {MS_Mascot_use_MudPIT_scoring_OBSOLETE, "MS:1001667", "Mascot:use MudPIT scoring", "Determines whether to use MudPIT or normal scoring.", true}, {MS_ProteomeDiscoverer_Absolute_XCorr_Threshold, "MS:1001668", "ProteomeDiscoverer:Absolute XCorr Threshold", "Minimum cross-correlation threshold that determines whether peptides in an .srf file are imported.", false}, {MS_ProteomeDiscoverer_SEQUEST_Calculate_Probability_Score, "MS:1001669", "ProteomeDiscoverer:SEQUEST:Calculate Probability Score", "Determines whether to calculate a probability score for every peptide match.", false}, {MS_ProteomeDiscoverer_SEQUEST_CTerminal_Modification, "MS:1001670", "ProteomeDiscoverer:SEQUEST:CTerminal Modification", "Dynamic C-terminal modification that is used during the search.", false}, {MS_ProteomeDiscoverer_SEQUEST_Fragment_Ion_Cutoff_Percentage, "MS:1001671", "ProteomeDiscoverer:SEQUEST:Fragment Ion Cutoff Percentage", "Percentage of the theoretical ions that must be found in order for a peptide to be scored and retained.", false}, {MS_ProteomeDiscoverer_SEQUEST_Max_Identical_Modifications_Per_Peptide, "MS:1001672", "ProteomeDiscoverer:SEQUEST:Max Identical Modifications Per Peptide", "Maximum number of identical modifications that a single peptide can have.", false}, {MS_ProteomeDiscoverer_Max_Modifications_Per_Peptide, "MS:1001673", "ProteomeDiscoverer:Max Modifications Per Peptide", "Maximum number of different modifications that a peptide can have, e.g. because of steric hindrance.", false}, {MS_ProteomeDiscoverer_SEQUEST_Maximum_Peptides_Considered, "MS:1001674", "ProteomeDiscoverer:SEQUEST:Maximum Peptides Considered", "Maximum number of peptides that are searched and scored per spectrum.", false}, {MS_ProteomeDiscoverer_Maximum_Peptides_Output, "MS:1001675", "ProteomeDiscoverer:Maximum Peptides Output", "Maximum number of peptide matches reported per spectrum.", false}, {MS_ProteomeDiscoverer_Maximum_Protein_References_Per_Peptide, "MS:1001676", "ProteomeDiscoverer:Maximum Protein References Per Peptide", "Maximum number of proteins that a single identified peptide can be associated with during protein assembly.", false}, {MS_ProteomeDiscoverer_SEQUEST_NTerminal_Modification, "MS:1001677", "ProteomeDiscoverer:SEQUEST:NTerminal Modification", "Dynamic N-terminal modification that is used during the search.", false}, {MS_ProteomeDiscoverer_Peptide_CTerminus, "MS:1001678", "ProteomeDiscoverer:Peptide CTerminus", "Static modification for the C terminal of the peptide used during the search.", false}, {MS_ProteomeDiscoverer_Peptide_NTerminus, "MS:1001679", "ProteomeDiscoverer:Peptide NTerminus", "Static modification for the N terminal of the peptide used during the search.", false}, {MS_ProteomeDiscoverer_SEQUEST_Peptide_Relevance_Factor, "MS:1001680", "ProteomeDiscoverer:SEQUEST:Peptide Relevance Factor", "Specifies a factor to apply to the protein score.", false}, {MS_ProteomeDiscoverer_Protein_Relevance_Threshold, "MS:1001681", "ProteomeDiscoverer:Protein Relevance Threshold", "Specifies a peptide threshold that determines whether the protein that it is a part of is scored and retained in the report.", false}, {MS_ProteomeDiscoverer_Search_Against_Decoy_Database_OBSOLETE, "MS:1001682", "ProteomeDiscoverer:Search Against Decoy Database", "Determines whether the Proteome Discoverer application searches against a decoy database.", true}, {MS_ProteomeDiscoverer_SEQUEST_Use_Average_Fragment_Masses, "MS:1001683", "ProteomeDiscoverer:SEQUEST:Use Average Fragment Masses", "Use average masses for the fragments.", false}, {MS_ProteomeDiscoverer_Use_Neutral_Loss_a_Ions, "MS:1001684", "ProteomeDiscoverer:Use Neutral Loss a Ions", "Determines whether a ions with neutral loss are used for spectrum matching.", false}, {MS_ProteomeDiscoverer_Use_Neutral_Loss_b_Ions, "MS:1001685", "ProteomeDiscoverer:Use Neutral Loss b Ions", "Determines whether b ions with neutral loss are used for spectrum matching.", false}, {MS_ProteomeDiscoverer_Use_Neutral_Loss_y_Ions, "MS:1001686", "ProteomeDiscoverer:Use Neutral Loss y Ions", "Determines whether y ions with neutral loss are used for spectrum matching.", false}, {MS_ProteomeDiscoverer_Use_Neutral_Loss_z_Ions, "MS:1001687", "ProteomeDiscoverer:Use Neutral Loss z Ions", "Determines whether z ions with neutral loss are used for spectrum matching.", false}, {MS_ProteomeDiscoverer_SEQUEST_Weight_of_a_Ions, "MS:1001688", "ProteomeDiscoverer:SEQUEST:Weight of a Ions", "Uses a ions for spectrum matching with this relative factor.", false}, {MS_ProteomeDiscoverer_SEQUEST_Weight_of_b_Ions, "MS:1001689", "ProteomeDiscoverer:SEQUEST:Weight of b Ions", "Uses b ions for spectrum matching with this relative factor.", false}, {MS_ProteomeDiscoverer_SEQUEST_Weight_of_c_Ions, "MS:1001690", "ProteomeDiscoverer:SEQUEST:Weight of c Ions", "Uses c ions for spectrum matching with this relative factor.", false}, {MS_ProteomeDiscoverer_SEQUEST_Weight_of_d_Ions, "MS:1001691", "ProteomeDiscoverer:SEQUEST:Weight of d Ions", "Uses c ions for spectrum matching with this relative factor.", false}, {MS_ProteomeDiscoverer_SEQUEST_Weight_of_v_Ions, "MS:1001692", "ProteomeDiscoverer:SEQUEST:Weight of v Ions", "Uses c ions for spectrum matching with this relative factor.", false}, {MS_ProteomeDiscoverer_SEQUEST_Weight_of_w_Ions, "MS:1001693", "ProteomeDiscoverer:SEQUEST:Weight of w Ions", "Uses c ions for spectrum matching with this relative factor.", false}, {MS_ProteomeDiscoverer_SEQUEST_Weight_of_x_Ions, "MS:1001694", "ProteomeDiscoverer:SEQUEST:Weight of x Ions", "Uses x ions for spectrum matching with this relative factor.", false}, {MS_ProteomeDiscoverer_SEQUEST_Weight_of_y_Ions, "MS:1001695", "ProteomeDiscoverer:SEQUEST:Weight of y Ions", "Uses y ions for spectrum matching with this relative factor.", false}, {MS_ProteomeDiscoverer_SEQUEST_Weight_of_z_Ions, "MS:1001696", "ProteomeDiscoverer:SEQUEST:Weight of z Ions", "Uses z ions for spectrum matching with this relative factor.", false}, {MS_ProteomeDiscoverer_ZCore_Protein_Score_Cutoff, "MS:1001697", "ProteomeDiscoverer:ZCore:Protein Score Cutoff", "Sets a minimum protein score that each protein must exceed in order to be reported.", false}, {MS_ProteomeDiscoverer_Reporter_Ions_Quantizer_Integration_Method, "MS:1001698", "ProteomeDiscoverer:Reporter Ions Quantizer:Integration Method", "Specifies which peak to select if more than one peak is found inside the integration window.", false}, {MS_ProteomeDiscoverer_Reporter_Ions_Quantizer_Integration_Window_Tolerance, "MS:1001699", "ProteomeDiscoverer:Reporter Ions Quantizer:Integration Window Tolerance", "Specifies the mass-to-charge window that enables one to look for the reporter peaks.", false}, {MS_ProteomeDiscoverer_Reporter_Ions_Quantizer_Quantitation_Method, "MS:1001700", "ProteomeDiscoverer:Reporter Ions Quantizer:Quantitation Method", "Quantitation method for isobarically labeled quantitation.", false}, {MS_ProteomeDiscoverer_Spectrum_Exporter_Export_Format_OBSOLETE, "MS:1001701", "ProteomeDiscoverer:Spectrum Exporter:Export Format", "Format of the exported spectra (dta, mgf or mzData).", true}, {MS_ProteomeDiscoverer_Spectrum_Exporter_File_name, "MS:1001702", "ProteomeDiscoverer:Spectrum Exporter:File name", "Name of the output file that contains the exported data.", false}, {MS_ProteomeDiscoverer_Search_Modifications_Only_For_Identified_Proteins, "MS:1001703", "ProteomeDiscoverer:Search Modifications Only For Identified Proteins", "Influences the modifications search.", false}, {MS_ProteomeDiscoverer_SEQUEST_Std_High_Confidence_XCorr_Charge1, "MS:1001704", "ProteomeDiscoverer:SEQUEST:Std High Confidence XCorr Charge1", "Standard high confidence XCorr parameter for charge = 1.", false}, {MS_ProteomeDiscoverer_SEQUEST_Std_High_Confidence_XCorr_Charge2, "MS:1001705", "ProteomeDiscoverer:SEQUEST:Std High Confidence XCorr Charge2", "Standard high confidence XCorr parameter for charge = 2.", false}, {MS_ProteomeDiscoverer_SEQUEST_Std_High_Confidence_XCorr_Charge3, "MS:1001706", "ProteomeDiscoverer:SEQUEST:Std High Confidence XCorr Charge3", "Standard high confidence XCorr parameter for charge = 3.", false}, {MS_ProteomeDiscoverer_SEQUEST_Std_High_Confidence_XCorr_Charge4, "MS:1001707", "ProteomeDiscoverer:SEQUEST:Std High Confidence XCorr Charge4", "Standard high confidence XCorr parameter for charge >= 4.", false}, {MS_ProteomeDiscoverer_SEQUEST_Std_Medium_Confidence_XCorr_Charge1, "MS:1001708", "ProteomeDiscoverer:SEQUEST:Std Medium Confidence XCorr Charge1", "Standard medium confidence XCorr parameter for charge = 1.", false}, {MS_ProteomeDiscoverer_SEQUEST_Std_Medium_Confidence_XCorr_Charge2, "MS:1001709", "ProteomeDiscoverer:SEQUEST:Std Medium Confidence XCorr Charge2", "Standard medium confidence XCorr parameter for charge = 2.", false}, {MS_ProteomeDiscoverer_SEQUEST_Std_Medium_Confidence_XCorr_Charge3, "MS:1001710", "ProteomeDiscoverer:SEQUEST:Std Medium Confidence XCorr Charge3", "Standard medium confidence XCorr parameter for charge = 3.", false}, {MS_ProteomeDiscoverer_SEQUEST_Std_Medium_Confidence_XCorr_Charge4, "MS:1001711", "ProteomeDiscoverer:SEQUEST:Std Medium Confidence XCorr Charge4", "Standard medium confidence XCorr parameter for charge >= 4.", false}, {MS_ProteomeDiscoverer_SEQUEST_FT_High_Confidence_XCorr_Charge1, "MS:1001712", "ProteomeDiscoverer:SEQUEST:FT High Confidence XCorr Charge1", "FT high confidence XCorr parameter for charge = 1.", false}, {MS_ProteomeDiscoverer_SEQUEST_FT_High_Confidence_XCorr_Charge2, "MS:1001713", "ProteomeDiscoverer:SEQUEST:FT High Confidence XCorr Charge2", "FT high confidence XCorr parameter for charge = 2.", false}, {MS_ProteomeDiscoverer_SEQUEST_FT_High_Confidence_XCorr_Charge3, "MS:1001714", "ProteomeDiscoverer:SEQUEST:FT High Confidence XCorr Charge3", "FT high confidence XCorr parameter for charge = 3.", false}, {MS_ProteomeDiscoverer_SEQUEST_FT_High_Confidence_XCorr_Charge4, "MS:1001715", "ProteomeDiscoverer:SEQUEST:FT High Confidence XCorr Charge4", "FT high confidence XCorr parameter for charge >= 4.", false}, {MS_ProteomeDiscoverer_SEQUEST_FT_Medium_Confidence_XCorr_Charge1, "MS:1001716", "ProteomeDiscoverer:SEQUEST:FT Medium Confidence XCorr Charge1", "FT medium confidence XCorr parameter for charge = 1.", false}, {MS_ProteomeDiscoverer_SEQUEST_FT_Medium_Confidence_XCorr_Charge2, "MS:1001717", "ProteomeDiscoverer:SEQUEST:FT Medium Confidence XCorr Charge2", "FT medium confidence XCorr parameter for charge = 2.", false}, {MS_ProteomeDiscoverer_SEQUEST_FT_Medium_Confidence_XCorr_Charge3, "MS:1001718", "ProteomeDiscoverer:SEQUEST:FT Medium Confidence XCorr Charge3", "FT medium confidence XCorr parameter for charge = 3.", false}, {MS_ProteomeDiscoverer_SEQUEST_FT_Medium_Confidence_XCorr_Charge4, "MS:1001719", "ProteomeDiscoverer:SEQUEST:FT Medium Confidence XCorr Charge4", "FT medium confidence XCorr parameter for charge >= 4.", false}, {MS_ProteomeDiscoverer_1__Dynamic_Modification_OBSOLETE, "MS:1001720", "ProteomeDiscoverer:1. Dynamic Modification", "ProteomeDiscoverer's 1st dynamic post-translational modification (PTM) input parameter.", true}, {MS_ProteomeDiscoverer_2__Dynamic_Modification_OBSOLETE, "MS:1001721", "ProteomeDiscoverer:2. Dynamic Modification", "ProteomeDiscoverer's 2nd dynamic post-translational modification (PTM) input parameter.", true}, {MS_ProteomeDiscoverer_3__Dynamic_Modification_OBSOLETE, "MS:1001722", "ProteomeDiscoverer:3. Dynamic Modification", "ProteomeDiscoverer's 3rd dynamic post-translational modification (PTM) input parameter.", true}, {MS_ProteomeDiscoverer_4__Dynamic_Modification_OBSOLETE, "MS:1001723", "ProteomeDiscoverer:4. Dynamic Modification", "ProteomeDiscoverer's 4th dynamic post-translational modification (PTM) input parameter.", true}, {MS_ProteomeDiscoverer_Static_Modification_for_X, "MS:1001724", "ProteomeDiscoverer:Static Modification for X", "Static Modification for X.", false}, {MS_ProteomeDiscoverer_Initial_minimal_peptide_probability, "MS:1001725", "ProteomeDiscoverer:Initial minimal peptide probability", "Minimal initial peptide probability to contribute to analysis.", false}, {MS_ProteomeDiscoverer_Minimal_peptide_probability, "MS:1001726", "ProteomeDiscoverer:Minimal peptide probability", "Minimum adjusted peptide probability contributing to protein probability.", false}, {MS_ProteomeDiscoverer_Minimal_peptide_weight, "MS:1001727", "ProteomeDiscoverer:Minimal peptide weight", "Minimum peptide weight contributing to protein probability.", false}, {MS_ProteomeDiscoverer_Number_of_input1_spectra, "MS:1001728", "ProteomeDiscoverer:Number of input1 spectra", "Number of spectra from 1+ precursor ions.", false}, {MS_ProteomeDiscoverer_Number_of_input2_spectra, "MS:1001729", "ProteomeDiscoverer:Number of input2 spectra", "Number of spectra from 2+ precursor ions.", false}, {MS_ProteomeDiscoverer_Number_of_input3_spectra, "MS:1001730", "ProteomeDiscoverer:Number of input3 spectra", "Number of spectra from 3+ precursor ions.", false}, {MS_ProteomeDiscoverer_Number_of_input4_spectra, "MS:1001731", "ProteomeDiscoverer:Number of input4 spectra", "Number of spectra from 4+ precursor ions.", false}, {MS_ProteomeDiscoverer_Number_of_input5_spectra, "MS:1001732", "ProteomeDiscoverer:Number of input5 spectra", "Number of spectra from 5+ precursor ions.", false}, {MS_ProteomeDiscoverer_Number_of_predicted_correct_proteins, "MS:1001733", "ProteomeDiscoverer:Number of predicted correct proteins", "Total number of predicted correct protein ids (sum of probabilities).", false}, {MS_ProteomeDiscoverer_Organism_OBSOLETE, "MS:1001734", "ProteomeDiscoverer:Organism", "Sample organism (used for annotation purposes).", true}, {MS_ProteomeDiscoverer_Reference_Database_OBSOLETE, "MS:1001735", "ProteomeDiscoverer:Reference Database", "Full path database name.", true}, {MS_ProteomeDiscoverer_Residue_substitution_list, "MS:1001736", "ProteomeDiscoverer:Residue substitution list", "Residues considered equivalent when comparing peptides.", false}, {MS_ProteomeDiscoverer_Source_file_extension_OBSOLETE, "MS:1001737", "ProteomeDiscoverer:Source file extension", "File type (if not pepXML).", true}, {MS_ProteomeDiscoverer_Source_Files_OBSOLETE, "MS:1001738", "ProteomeDiscoverer:Source Files", "Input pepXML files.", true}, {MS_ProteomeDiscoverer_Source_Files_old_OBSOLETE, "MS:1001739", "ProteomeDiscoverer:Source Files old", "Input pepXML files (old).", true}, {MS_ProteomeDiscoverer_WinCyg_reference_database, "MS:1001740", "ProteomeDiscoverer:WinCyg reference database", "Windows full path for database.", false}, {MS_ProteomeDiscoverer_WinCyg_source_files, "MS:1001741", "ProteomeDiscoverer:WinCyg source files", "Windows pepXML file names.", false}, {MS_LTQ_Orbitrap_Velos, "MS:1001742", "LTQ Orbitrap Velos", "Finnigan LTQ Orbitrap Velos MS.", false}, {MS_ProteomeDiscoverer_Mascot_Weight_of_A_Ions, "MS:1001743", "ProteomeDiscoverer:Mascot:Weight of A Ions", "Determines if to use A ions for spectrum matching.", false}, {MS_ProteomeDiscoverer_Mascot_Weight_of_B_Ions, "MS:1001744", "ProteomeDiscoverer:Mascot:Weight of B Ions", "Determines if to use B ions for spectrum matching.", false}, {MS_ProteomeDiscoverer_Mascot_Weight_of_C_Ions, "MS:1001745", "ProteomeDiscoverer:Mascot:Weight of C Ions", "Determines if to use C ions for spectrum matching.", false}, {MS_ProteomeDiscoverer_Mascot_Weight_of_D_Ions, "MS:1001746", "ProteomeDiscoverer:Mascot:Weight of D Ions", "Determines if to use D ions for spectrum matching.", false}, {MS_ProteomeDiscoverer_Mascot_Weight_of_V_Ions, "MS:1001747", "ProteomeDiscoverer:Mascot:Weight of V Ions", "Determines if to use V ions for spectrum matching.", false}, {MS_ProteomeDiscoverer_Mascot_Weight_of_W_Ions, "MS:1001748", "ProteomeDiscoverer:Mascot:Weight of W Ions", "Determines if to use W ions for spectrum matching.", false}, {MS_ProteomeDiscoverer_Mascot_Weight_of_X_Ions, "MS:1001749", "ProteomeDiscoverer:Mascot:Weight of X Ions", "Determines if to use X ions for spectrum matching.", false}, {MS_ProteomeDiscoverer_Mascot_Weight_of_Y_Ions, "MS:1001750", "ProteomeDiscoverer:Mascot:Weight of Y Ions", "Determines if to use Y ions for spectrum matching.", false}, {MS_ProteomeDiscoverer_Mascot_Weight_of_Z_Ions, "MS:1001751", "ProteomeDiscoverer:Mascot:Weight of Z Ions", "Determines if to use z ions for spectrum matching.", false}, {MS_ProteomeDiscoverer_Spectrum_Selector_Use_New_Precursor_Reevaluation, "MS:1001752", "ProteomeDiscoverer:Spectrum Selector:Use New Precursor Reevaluation", "Determines if to use precursor reevaluation.", false}, {MS_ProteomeDiscoverer_Spectrum_Selector_SN_Threshold_FTonly, "MS:1001753", "ProteomeDiscoverer:Spectrum Selector:SN Threshold FTonly", "Signal-to-Noise ratio below which peaks are removed (in FT mode only).", false}, {MS_ProteomeDiscoverer_Mascot_Please_Do_not_Touch_this, "MS:1001754", "ProteomeDiscoverer:Mascot:Please Do not Touch this", "Unknown Mascot parameter which ProteomeDiscoverer uses for mascot searches.", false}, {MS_contact_phone_number, "MS:1001755", "contact phone number", "Phone number of the contact person or organization.", false}, {MS_contact_fax_number, "MS:1001756", "contact fax number", "Fax number for the contact person or organization.", false}, {MS_contact_toll_free_phone_number, "MS:1001757", "contact toll-free phone number", "Toll-free phone number of the contact person or organization.", false}, {MS_Mascot_SigThresholdType, "MS:1001758", "Mascot:SigThresholdType", "Significance threshold type used in Mascot reporting (either 'identity' or 'homology').", false}, {MS_Mascot_ProteinGrouping, "MS:1001759", "Mascot:ProteinGrouping", "Strategy used by Mascot to group proteins with same peptide matches (one of 'none', 'Occam's razor' or 'family clustering').", false}, {MS_Percolator_features, "MS:1001760", "Percolator:features", "List of Percolator features that were used in processing the peptide matches. Typical Percolator features are 'retentionTime', 'dM', 'mScore', 'lgDScore', 'mrCalc', 'charge' and 'dMppm'.", false}, {MS_ACQUITY_UPLC, "MS:1001761", "ACQUITY UPLC", "Waters LC-system ACQUITY UPLC.", false}, {MS_ACQUITY_UPLC_H_Class, "MS:1001762", "ACQUITY UPLC H-Class", "Waters LC-system ACQUITY UPLC H-Class.", false}, {MS_ACQUITY_UPLC_H_Class_Bio, "MS:1001763", "ACQUITY UPLC H-Class Bio", "Waters LC-system ACQUITY UPLC H-Class Bio.", false}, {MS_ACQUITY_UPLC_I_Class, "MS:1001764", "ACQUITY UPLC I-Class", "Waters LC-system ACQUITY UPLC I-Class.", false}, {MS_ACQUITY_UPLC_Systems_with_2D_Technology, "MS:1001765", "ACQUITY UPLC Systems with 2D Technology", "Waters LC-system ACQUITY UPLC Systems with 2D Technology.", false}, {MS_nanoACQUITY_UPLC, "MS:1001766", "nanoACQUITY UPLC", "Waters LC-system nanoACQUITY UPLC.", false}, {MS_nanoACQUITY_UPLC_System_with_Technology, "MS:1001767", "nanoACQUITY UPLC System with Technology", "Waters LC-system nanoACQUITY UPLC System with Technology.", false}, {MS_nanoACQUITY_UPLC_with_HDX_Technology, "MS:1001768", "nanoACQUITY UPLC with HDX Technology", "Waters LC-system nanoACQUITY UPLC with HDX Technology.", false}, {MS_TRIZAIC_UPLC_nanoTile, "MS:1001769", "TRIZAIC UPLC nanoTile", "Waters LC-system TRIZAIC UPLC nanoTile.", false}, {MS_GCT_Premier, "MS:1001770", "GCT Premier", "Waters oa-ToF based GCT Premier.", false}, {MS_MALDI_Synapt_G2_HDMS, "MS:1001771", "MALDI Synapt G2 HDMS", "Waters oa-ToF based MALDI Synapt G2 HDMS.", false}, {MS_MALDI_Synapt_G2_MS, "MS:1001772", "MALDI Synapt G2 MS", "Waters oa-ToF based MALDI Synapt G2 MS.", false}, {MS_MALDI_Synapt_G2_S_HDMS, "MS:1001773", "MALDI Synapt G2-S HDMS", "Waters oa-ToF based MALDI Synapt G2 MS.", false}, {MS_MALDI_Synapt_G2_S_MS, "MS:1001774", "MALDI Synapt G2-S MS", "Waters oa-ToF based MALDI Synapt G2-S MS.", false}, {MS_MALDI_Synapt_HDMS, "MS:1001775", "MALDI Synapt HDMS", "Waters oa-ToF based MALDI Synapt HDMS.", false}, {MS_MALDI_Synapt_MS, "MS:1001776", "MALDI Synapt MS", "Waters oa-ToF based MALDI Synapt MS.", false}, {MS_Synapt_G2_HDMS, "MS:1001777", "Synapt G2 HDMS", "Waters oa-ToF based Synapt G2 HDMS.", false}, {MS_Synapt_G2_MS, "MS:1001778", "Synapt G2 MS", "Waters oa-ToF based Synapt G2 MS.", false}, {MS_Synapt_G2_S_HDMS, "MS:1001779", "Synapt G2-S HDMS", "Waters oa-ToF based Synapt G2-S HDMS.", false}, {MS_Synapt_G2_S_MS, "MS:1001780", "Synapt G2-S MS", "Waters oa-ToF based Synapt G2-S MS.", false}, {MS_Synapt_HDMS, "MS:1001781", "Synapt HDMS", "Waters oa-ToF based Synapt HDMS.", false}, {MS_Synapt_MS, "MS:1001782", "Synapt MS", "Waters oa-ToF based Synapt MS.", false}, {MS_Xevo_G2_Q_Tof, "MS:1001783", "Xevo G2 Q-Tof", "Waters oa-ToF based Xevo G2 Q-Tof.", false}, {MS_Xevo_G2_Tof, "MS:1001784", "Xevo G2 Tof", "Waters oa-ToF based Xevo G2 Tof.", false}, {MS_Xevo_Q_Tof, "MS:1001785", "Xevo Q-Tof", "Waters oa-ToF based Xevo Q-Tof.", false}, {MS_3100, "MS:1001786", "3100", "Waters quadrupole based 3100.", false}, {MS_Acquity_SQD, "MS:1001787", "Acquity SQD", "Waters quadrupole based Acquity SQD.", false}, {MS_Acquity_TQD, "MS:1001788", "Acquity TQD", "Waters quadrupole based Acquity TQD.", false}, {MS_Quattro_micro_GC, "MS:1001789", "Quattro micro GC", "Waters quadrupole based Quattro micro GC.", false}, {MS_Xevo_TQ_MS, "MS:1001790", "Xevo TQ MS", "Waters quadrupole based Xevo TQ MS.", false}, {MS_Xevo_TQD, "MS:1001791", "Xevo TQD", "Waters quadrupole based Xevo TQD.", false}, {MS_Xevo_TQ_S, "MS:1001792", "Xevo TQ-S", "Waters quadrupole based Xevo TQ-S.", false}, {MS_Mascot_PreferredTaxonomy, "MS:1001793", "Mascot:PreferredTaxonomy", "NCBI TaxID taxonomy ID to prefer when two or more proteins match the same set of peptides or when protein entry in database represents multiple sequences.", false}, {MS_Empower, "MS:1001795", "Empower", "Waters Empower software for liquid chromatography and mass spectrometry acquisition.", false}, {MS_Unify, "MS:1001796", "Unify", "Waters Unify software for liquid chromatography and mass spectrometry acquisition.", false}, {MS_travelling_wave_ion_mobility_mass_spectrometer_OBSOLETE, "MS:1001797", "travelling wave ion mobility mass spectrometer", "An ion mobility mass spectrometry technique based on the superimposition of travelling voltage waves on a radially-confining RF voltage in a gas-filled, stacked-ring ion guide.", true}, {MS_LECO_software, "MS:1001798", "LECO software", "LECO software for data acquisition and analysis.", false}, {MS_ChromaTOF_software, "MS:1001799", "ChromaTOF software", "Software for acquisition, processing and analysis of data for LECO instruments.", false}, {MS_LECO_instrument_model, "MS:1001800", "LECO instrument model", "LECO instrument model.", false}, {MS_Pegasus_HRT, "MS:1001801", "Pegasus HRT", "LECO high resolution time-of-flight GC mass spectrometer.", false}, {MS_Citius_HRT, "MS:1001802", "Citius HRT", "LECO high resolution time-of-flight LC mass spectrometer.", false}, {MS_Pegasus, "MS:1001803", "Pegasus", "LECO GC time-of-flight mass spectrometer.", false}, {MS_TruTOF, "MS:1001804", "TruTOF", "LECO bench-top GC time-of-flight mass spectrometer.", false}, {MS_quantification_datatype, "MS:1001805", "quantification datatype", "The data type of the value reported in a QuantLayer for a feature, peptide, protein, protein group.", false}, {MS_quantification_object_attribute, "MS:1001806", "quantification object attribute", "Attributes describing the details of an object relevant for reporting quantification workflows or values.", false}, {MS_study_variable_attribute, "MS:1001807", "study variable attribute", "Attribute describing a study variable.", false}, {MS_technical_replicate, "MS:1001808", "technical replicate", "The study variable is 'technical replicate'. The string value denotes the category of technical replicate, e.g. 'run generated from same sample'.", false}, {MS_biological_replicate, "MS:1001809", "biological replicate", "The study variable is 'biological replicate'. This means, the run was generated from another individual or sample.", false}, {MS_experimental_condition__case_, "MS:1001810", "experimental condition 'case'", "The experimental condition is 'case' in contrast to 'control'.", false}, {MS_experimental_condition__control_, "MS:1001811", "experimental condition 'control'", "The experimental condition is 'control' in contrast to 'case'.", false}, {MS_experimental_condition__disease_, "MS:1001812", "experimental condition 'disease'", "The experimental condition is 'disease' in contrast to 'healthy'.", false}, {MS_experimental_condition__healthy_, "MS:1001813", "experimental condition 'healthy'", "The experimental condition is 'healthy' in contrast to 'disease'.", false}, {MS_generic_experimental_condition, "MS:1001814", "generic experimental condition", "The experimental condition is given in the value of this term.", false}, {MS_time_series__time_point_X, "MS:1001815", "time series, time point X", "The experimental design followed a time series design. The time point of this run is given in the value of this term.", false}, {MS_dilution_series__concentration_X, "MS:1001816", "dilution series, concentration X", "The experimental design followed a dilution series design. The concentration of this run is given in the value of this term.", false}, {MS_raw_file_attribute, "MS:1001817", "raw file attribute", "Attribute describing a raw file.", false}, {MS_one_sample_run, "MS:1001818", "one sample run", "The raw file contains the run of one sample (e.g. spectral counting, LC-MS label-free).", false}, {MS_two_sample_run, "MS:1001819", "two sample run", "The raw file contains the run of two samples (e.g. SILAC, metabolic labelling).", false}, {MS_three_sample_run, "MS:1001820", "three sample run", "The raw file contains the run of three samples (e.g. 3-plex SILAC).", false}, {MS_four_sample_run, "MS:1001821", "four sample run", "The raw file contains the run of four samples (e.g. 4-plex iTraq).", false}, {MS_eight_sample_run, "MS:1001822", "eight sample run", "The raw file contains the run of eight samples (e.g. 8-plex iTraq).", false}, {MS_raw_files_group_attribute, "MS:1001823", "raw files group attribute", "Attribute describing, how raw files build a raw file group.", false}, {MS_merge_of_runs_of_1D_gel_bands, "MS:1001824", "merge of runs of 1D gel bands", "Attribute describing, how raw files build a raw file group.", false}, {MS_feature_list_attribute, "MS:1001825", "feature list attribute", "Attribute describing a feature list.", false}, {MS_mass_trace_reporting__rectangles, "MS:1001826", "mass trace reporting: rectangles", "The mass trace of the features of this feature list specifies rectangles. Each mass trace has the syntax (RT_start,MZ_start,RT_end,MZ_end), i.e. opposite corners are given.", false}, {MS_mass_trace_reporting__polygons, "MS:1001827", "mass trace reporting: polygons", "The mass trace of the features of this feature list specifies polygons. Each mass trace has the syntax (RT_1, MZ_1, RT_2, MZ_2, ... , RT_i, MZ_i, ... , RT_n, MZ_n), where the line (RT_n, MZ_n)->(RT_1, MZ_1) is implicit.", false}, {MS_feature_attribute, "MS:1001828", "feature attribute", "Attribute describing a feature.", false}, {MS_SRM_transition_ID, "MS:1001829", "SRM transition ID", "Identifier for an SRM transition in an external document describing additional information about the transition.", false}, {MS_Progenesis_LC_MS, "MS:1001830", "Progenesis LC-MS", "Software from Nonlinear Dynamics for LC-MS label-free workflow.", false}, {MS_SILACAnalyzer, "MS:1001831", "SILACAnalyzer", "Software for SILAC workflow.", false}, {MS_quantitation_software_comment_or_customizations, "MS:1001832", "quantitation software comment or customizations", "Quantitation software comment or any customizations to the default setup of the software.", false}, {MS_quantitation_analysis_summary, "MS:1001833", "quantitation analysis summary", "The overall workflow of this quantitation report.", false}, {MS_LC_MS_label_free_quantitation_analysis, "MS:1001834", "LC-MS label-free quantitation analysis", "LC-MS label-free workflow (RT m/z map).", false}, {MS_SILAC_quantitation_analysis, "MS:1001835", "SILAC quantitation analysis", "SILAC workflow (heavy, light, and sometimes medium peak).", false}, {MS_spectral_counting_quantitation_analysis, "MS:1001836", "spectral counting quantitation analysis", "Spectral counting workflow (number of identified MS2 spectra as approximation of peptide / protein quant).", false}, {MS_iTRAQ_quantitation_analysis, "MS:1001837", "iTRAQ quantitation analysis", "Quantification analysis using the SCIEX iTRAQ isobaric labelling workflow, wherein 2-8 reporter ions are measured in MS2 spectra near 114 m/z.", false}, {MS_SRM_quantitation_analysis, "MS:1001838", "SRM quantitation analysis", "Selected Reaction Monitoring workflow (XIC quantitation of precursor / fragment mass pair).", false}, {MS_metabolic_labeling_14N___15N_quantitation_analysis, "MS:1001839", "metabolic labeling 14N / 15N quantitation analysis", "Metabolic labeling workflow (heavy and light versions of peptides, depending on number of nitrogens).", false}, {MS_LC_MS_feature_intensity, "MS:1001840", "LC-MS feature intensity", "Maximum peak intensity of the LC-MS feature.", false}, {MS_LC_MS_feature_volume, "MS:1001841", "LC-MS feature volume", "Real (intensity times area) volume of the LC-MS feature.", false}, {MS_peptide_PSM_count, "MS:1001842", "peptide PSM count", "The number of MS2 spectra identified for this peptide in spectral counting.", false}, {MS_MS1_feature_maximum_intensity, "MS:1001843", "MS1 feature maximum intensity", "Maximum intensity of MS1 feature.", false}, {MS_MS1_feature_area, "MS:1001844", "MS1 feature area", "Area of MS1 feature.", false}, {MS_peak_area_OBSOLETE, "MS:1001845", "peak area", "Area of MS1 peak (e.g. SILAC, 15N).", true}, {MS_isotopic_pattern_area, "MS:1001846", "isotopic pattern area", "Area of all peaks belonging to the isotopic pattern of light or heavy peak (e.g. 15N).", false}, {MS_reporter_ion_intensity, "MS:1001847", "reporter ion intensity", "Intensity of MS2 reporter ion (e.g. iTraq).", false}, {MS_simple_ratio_of_two_values, "MS:1001848", "simple ratio of two values", "Simple ratio of two values (enumerator and denominator).", false}, {MS_sum_of_MatchedFeature_values_OBSOLETE, "MS:1001849", "sum of MatchedFeature values", "Peptide quantification value calculated as sum of MatchedFeature quantification values.", true}, {MS_normalized_peptide_value, "MS:1001850", "normalized peptide value", "Normalized peptide value.", false}, {MS_protein_value__sum_of_peptide_values, "MS:1001851", "protein value: sum of peptide values", "Protein quantification value calculated as sum of peptide values.", false}, {MS_normalized_protein_value, "MS:1001852", "normalized protein value", "Normalized protein value.", false}, {MS_max_fold_change, "MS:1001853", "max fold change", "Global datatype: Maximum of all pair-wise fold changes of group means (e.g. Progenesis).", false}, {MS_ANOVA_p_value, "MS:1001854", "ANOVA p-value", "Global datatype: p-value of ANOVA of group means (e.g. Progenesis).", false}, {MS_t_test_p_value, "MS:1001855", "t-test p-value", "P-value of t-Test of two groups.", false}, {MS_reporter_ion_raw_value, "MS:1001856", "reporter ion raw value", "Intensity (or area) of MS2 reporter ion (e.g. iTraq).", false}, {MS_reporter_ion_normalized_value, "MS:1001857", "reporter ion normalized value", "Normalized value of MS2 reporter ion (e.g. iTraq).", false}, {MS_XIC_area, "MS:1001858", "XIC area", "Area of the extracted ion chromatogram (e.g. of a transition in SRM).", false}, {MS_normalized_XIC_area, "MS:1001859", "normalized XIC area", "Normalized area of the extracted ion chromatogram (e.g. of a transition in SRM).", false}, {MS_protein_value__mean_of_peptide_ratios, "MS:1001860", "protein value: mean of peptide ratios", "Protein quantification value calculated as mean of peptide ratios.", false}, {MS_quantification_data_processing, "MS:1001861", "quantification data processing", "Terms used to describe types of quantification data processing.", false}, {MS_normalization_to_mean_of_sum_of_all_proteins, "MS:1001862", "normalization to mean of sum of all proteins", "Normalization of protein values to the mean of the sum of all protein PSM counts (e.g. spectral counting).", false}, {MS_quantile_normalization__proteins, "MS:1001863", "quantile normalization, proteins", "Normalization of protein values to approach the same distribution.", false}, {MS_quantile_normalization__peptides, "MS:1001864", "quantile normalization, peptides", "Normalization of peptide values to approach the same distribution.", false}, {MS_Progenesis_automatic_alignment, "MS:1001865", "Progenesis automatic alignment", "Automatic RT alignment of Progenesis software.", false}, {MS_Progenesis_manual_alignment, "MS:1001866", "Progenesis manual alignment", "RT alignment of Progenesis software using automatic and manual vectors.", false}, {MS_Progenesis_normalization, "MS:1001867", "Progenesis normalization", "Normalization as performed by Progenesis LC-MS.", false}, {MS_distinct_peptide_level_q_value, "MS:1001868", "distinct peptide-level q-value", "Estimation of the q-value for distinct peptides once redundant identifications of the same peptide have been removed (id est multiple PSMs, possibly with different mass modifications, mapping to the same sequence have been collapsed to one entry).", false}, {MS_protein_level_q_value, "MS:1001869", "protein-level q-value", "Estimation of the q-value for proteins.", false}, {MS_distinct_peptide_level_p_value, "MS:1001870", "distinct peptide-level p-value", "Estimation of the p-value for distinct peptides once redundant identifications of the same peptide have been removed (id est multiple PSMs have been collapsed to one entry).", false}, {MS_protein_level_p_value, "MS:1001871", "protein-level p-value", "Estimation of the p-value for proteins.", false}, {MS_distinct_peptide_level_e_value, "MS:1001872", "distinct peptide-level e-value", "Estimation of the e-value for distinct peptides once redundant identifications of the same peptide have been removed (id est multiple PSMs have been collapsed to one entry).", false}, {MS_protein_level_e_value, "MS:1001873", "protein-level e-value", "Estimation of the e-value for proteins.", false}, {MS_FDRScore_OBSOLETE, "MS:1001874", "FDRScore", "A smoothing of the distribution of q-values calculated for PSMs from individual search engines, such that ordering of result quality is maintained and all FDRScore values are guaranteed to have a value > 0.", true}, {MS_modification_motif, "MS:1001875", "modification motif", "The regular expression describing the sequence motif for a modification.", false}, {MS_modification_probability, "MS:1001876", "modification probability", "The a priori probability of a modification.", false}, {MS_ChromaTOF_HRT_software, "MS:1001877", "ChromaTOF HRT software", "Software for acquisition, processing and analysis of data for LECO instruments.", false}, {MS_MALDI_Solutions_Microbial_Identification, "MS:1001878", "MALDI Solutions Microbial Identification", "Shimadzu Biotech software for data acquisition, processing, and analysis.", false}, {MS_offset_voltage, "MS:1001879", "offset voltage", "The potential difference between two adjacent interface voltages affecting in-source collision induced dissociation.", false}, {MS_in_source_collision_induced_dissociation, "MS:1001880", "in-source collision-induced dissociation", "The dissociation of an ion as a result of collisional excitation during ion transfer from an atmospheric pressure ion source and the mass spectrometer vacuum.", false}, {MS_mz5_format, "MS:1001881", "mz5 format", "mz5 file format, modelled after mzML.", false}, {MS_transition_validation_attribute, "MS:1001882", "transition validation attribute", "Attributes of the quality of a transition that affect its selection as appropriate.", false}, {MS_coefficient_of_variation, "MS:1001883", "coefficient of variation", "Variation of a set of signal measurements calculated as the standard deviation relative to the mean.", false}, {MS_signal_to_noise_ratio, "MS:1001884", "signal-to-noise ratio", "Unitless number providing the ratio of the total measured intensity of a signal relative to the estimated noise level for that signal.", false}, {MS_command_line_parameters, "MS:1001885", "command-line parameters", "Parameters string passed to a command-line interface software application, omitting the executable name.", false}, {MS_SQID, "MS:1001886", "SQID", "Software for data analysis of peptides and proteins.", false}, {MS_SQID_score, "MS:1001887", "SQID:score", "The SQID result 'Score'.", false}, {MS_SQID_deltaScore, "MS:1001888", "SQID:deltaScore", "The SQID result 'deltaScore'.", false}, {MS_SQID_protein_score, "MS:1001889", "SQID:protein score", "The SQID result 'protein score'.", false}, {MS_Progenesis_protein_normalised_abundance, "MS:1001890", "Progenesis:protein normalised abundance", "The data type normalised abundance for proteins produced by Progenesis LC-MS.", false}, {MS_Progenesis_peptide_normalised_abundance, "MS:1001891", "Progenesis:peptide normalised abundance", "The data type normalised abundance for peptides produced by Progenesis LC-MS.", false}, {MS_Progenesis_protein_raw_abundance, "MS:1001892", "Progenesis:protein raw abundance", "The data type raw abundance for proteins produced by Progenesis LC-MS.", false}, {MS_Progenesis_peptide_raw_abundance, "MS:1001893", "Progenesis:peptide raw abundance", "The data type raw abundance for peptide produced by Progenesis LC-MS.", false}, {MS_Progenesis_confidence_score, "MS:1001894", "Progenesis:confidence score", "The data type confidence score produced by Progenesis LC-MS.", false}, {MS_Progenesis_peptide_count, "MS:1001895", "Progenesis:peptide count", "The data type peptide count produced by Progenesis LC-MS.", false}, {MS_Progenesis_feature_intensity, "MS:1001896", "Progenesis:feature intensity", "The data type feature intensity produced by Progenesis LC-MS.", false}, {MS_MaxQuant_peptide_counts__unique_, "MS:1001897", "MaxQuant:peptide counts (unique)", "The data type peptide counts (unique) produced by MaxQuant.", false}, {MS_MaxQuant_peptide_counts__all_, "MS:1001898", "MaxQuant:peptide counts (all)", "The data type peptide counts (all) produced by MaxQuant.", false}, {MS_MaxQuant_peptide_counts__razor_unique_, "MS:1001899", "MaxQuant:peptide counts (razor+unique)", "The data type peptide counts (razor+unique) produced by MaxQuant.", false}, {MS_MaxQuant_sequence_length, "MS:1001900", "MaxQuant:sequence length", "The data type sequence length produced by MaxQuant.", false}, {MS_MaxQuant_PEP, "MS:1001901", "MaxQuant:PEP", "The data type PEP (posterior error probability) produced by MaxQuant.", false}, {MS_MaxQuant_LFQ_intensity, "MS:1001902", "MaxQuant:LFQ intensity", "The data type LFQ intensity produced by MaxQuant.", false}, {MS_MaxQuant_feature_intensity, "MS:1001903", "MaxQuant:feature intensity", "The data type feature intensity produced by MaxQuant.", false}, {MS_MaxQuant_MS_MS_count, "MS:1001904", "MaxQuant:MS/MS count", "The data type MS2 count produced by MaxQuant.", false}, {MS_emPAI_value, "MS:1001905", "emPAI value", "The emPAI value of protein abundance, produced from the emPAI algorithm.", false}, {MS_APEX_value, "MS:1001906", "APEX value", "The APEX value of protein abundance, produced from the APEX software.", false}, {MS_retention_time_window_width, "MS:1001907", "retention time window width", "The full width of a retention time window for a chromatographic peak.", false}, {MS_ISQ, "MS:1001908", "ISQ", "Thermo Scientific ISQ single quadrupole MS with the ExtractraBrite source.", false}, {MS_Velos_Plus, "MS:1001909", "Velos Plus", "Thermo Scientific second generation Velos.", false}, {MS_LTQ_Orbitrap_Elite, "MS:1001910", "LTQ Orbitrap Elite", "Thermo Scientific second generation Velos and Orbitrap.", false}, {MS_Q_Exactive, "MS:1001911", "Q Exactive", "Thermo Scientific Q Exactive.", false}, {MS_PinPoint, "MS:1001912", "PinPoint", "Thermo Scientific PinPoint SRM analysis software.", false}, {MS_S_lens_voltage, "MS:1001913", "S-lens voltage", "Potential difference setting of the Thermo Scientific S-lens stacked-ring ion guide in volts.", false}, {MS_pymzML, "MS:1001914", "pymzML", "Python module to interface mzML Data.", false}, {MS_leukocyte_elastase, "MS:1001915", "leukocyte elastase", "Enzyme leukocyte elastase (EC 3.4.21.37).", false}, {MS_proline_endopeptidase, "MS:1001916", "proline endopeptidase", "Enzyme proline endopeptidase (EC 3.4.21.26).", false}, {MS_glutamyl_endopeptidase, "MS:1001917", "glutamyl endopeptidase", "Enzyme glutamyl endopeptidase (EC 3.4.21.19).", false}, {MS_2_iodobenzoate, "MS:1001918", "2-iodobenzoate", "Chemical iodobenzoate. Cleaves after W.", false}, {MS_ProteomeXchange_accession_number, "MS:1001919", "ProteomeXchange accession number", "Main identifier of a ProteomeXchange dataset.", false}, {MS_ProteomeXchange_accession_number_version_number, "MS:1001921", "ProteomeXchange accession number version number", "Version number of a ProteomeXchange accession number.", false}, {MS_Digital_Object_Identifier__DOI_, "MS:1001922", "Digital Object Identifier (DOI)", "DOI unique identifier of a publication.", false}, {MS_external_reference_keyword, "MS:1001923", "external reference keyword", "Free text attribute that can enrich the information about an entity.", false}, {MS_journal_article_keyword, "MS:1001924", "journal article keyword", "Keyword present in a scientific publication.", false}, {MS_submitter_keyword, "MS:1001925", "submitter keyword", "Keyword assigned by the data submitter.", false}, {MS_curator_keyword, "MS:1001926", "curator keyword", "Keyword assigned by a data curator.", false}, {MS_Tranche_file_hash, "MS:1001927", "Tranche file hash", "Hash assigned by the Tranche resource to an individual file.", false}, {MS_Tranche_project_hash, "MS:1001928", "Tranche project hash", "Hash assigned by the Tranche resource to a whole project.", false}, {MS_PRIDE_experiment_URI, "MS:1001929", "PRIDE experiment URI", "URI that allows the access to one experiment in the PRIDE database.", false}, {MS_PRIDE_project_URI, "MS:1001930", "PRIDE project URI", "URI that allows the access to one project in the PRIDE database.", false}, {MS_source_interface, "MS:1001931", "source interface", "The source interface.", false}, {MS_source_interface_model, "MS:1001932", "source interface model", "The source interface model.", false}, {MS_source_sprayer, "MS:1001933", "source sprayer", "The source sprayer.", false}, {MS_source_sprayer_type, "MS:1001934", "source sprayer type", "The source sprayer type.", false}, {MS_source_sprayer_manufacturer, "MS:1001935", "source sprayer manufacturer", "The source sprayer manufacturer.", false}, {MS_source_sprayer_model, "MS:1001936", "source sprayer model", "The source sprayer model.", false}, {MS_sample_plate, "MS:1001937", "sample plate", "Plate where the sample solution is spotted in a MALDI or similar instrument.", false}, {MS_sample_plate_type, "MS:1001938", "sample plate type", "The sample plate type.", false}, {MS_stainless_steel_plate, "MS:1001939", "stainless steel plate", "Stainless steel plate.", false}, {MS_coated_glass_plate, "MS:1001940", "coated glass plate", "Coated glass plate.", false}, {MS_electrospray_supply_type, "MS:1001941", "electrospray supply type", "Whether the sprayer is fed or is loaded with sample once.", false}, {MS_static_supply_electrospray, "MS:1001942", "static supply electrospray", "The sprayer is loaded with sample once.", false}, {MS_fed_supply_electrospray, "MS:1001943", "fed supply electrospray", "The sprayer is continuously fed with sample.", false}, {MS_Collision_cell_exit_potential, "MS:1001944", "Collision cell exit potential", "Potential difference between Q2 and Q3 in a triple quadrupole instrument in volts.", false}, {MS_Pegasus_4D, "MS:1001945", "Pegasus 4D", "LECO nominal mass resolution time-of-flight GCxGC mass spectrometer.", false}, {MS_PEAKS_Studio, "MS:1001946", "PEAKS Studio", "PEAKS Studio software for data analysis.", false}, {MS_PEAKS_Online, "MS:1001947", "PEAKS Online", "PEAKS Online software for high throughput data analysis.", false}, {MS_PEAKS_Node, "MS:1001948", "PEAKS Node", "PEAKS Node software for high throughput data analysis.", false}, {MS_BSI_software, "MS:1001949", "BSI software", "Bioinformatics Solutions Inc. Software for data processing and analysis.", false}, {MS_PEAKS_peptideScore, "MS:1001950", "PEAKS:peptideScore", "The PEAKS peptide '-10lgP Score'.", false}, {MS_PEAKS_proteinScore, "MS:1001951", "PEAKS:proteinScore", "The PEAKS protein '-10lgP Score'.", false}, {MS_ZCore_probScore, "MS:1001952", "ZCore:probScore", "The ZCore probability score.", false}, {MS_source_interface_manufacturer, "MS:1001953", "source interface manufacturer", "The source interface manufacturer.", false}, {MS_acquisition_parameter, "MS:1001954", "acquisition parameter", "Parameters used in the mass spectrometry acquisition.", false}, {MS_no_cleavage, "MS:1001955", "no cleavage", "No cleavage.", false}, {MS_unspecific_cleavage, "MS:1001956", "unspecific cleavage", "Unspecific cleavage.", false}, {MS______ALIV_____P_, "MS:1001957", "(?<=[ALIV])(?!P)", "Regular expression for leukocyte elastase.", false}, {MS______HKR_P____P_, "MS:1001958", "(?<=[HKR]P)(?!P)", "Regular expression for proline endopeptidase.", false}, {MS_______E_E_, "MS:1001959", "(?<=[^E]E)", "Regular expression for glutamyl endopeptidase.", false}, {MS_____W_, "MS:1001960", "(?<=W)", "Regular expression for 2-iodobenzoate.", false}, {MS_peptide_spectrum_match_scoring_algorithm, "MS:1001961", "peptide spectrum match scoring algorithm", "Algorithm used to score the match between a spectrum and a peptide ion.", false}, {MS_Mascot_C13_counts, "MS:1001962", "Mascot:C13 counts", "C13 peaks to use in peak detection.", false}, {MS_ProteinExtractor_Weighting, "MS:1001963", "ProteinExtractor:Weighting", "Weighting factor for protein list compilation by ProteinExtractor.", false}, {MS_ProteinScape_second_round_Mascot, "MS:1001964", "ProteinScape:second round Mascot", "Flag indicating a second round search with Mascot.", false}, {MS_ProteinScape_second_round_Phenyx, "MS:1001965", "ProteinScape:second round Phenyx", "Flag indicating a second round search with Phenyx.", false}, {MS_product_ion_mobility, "MS:1001966", "product ion mobility", "The mobility of an MS2 product ion, as measured by ion mobility mass spectrometry.", false}, {MS_product_ion_drift_time_OBSOLETE, "MS:1001967", "product ion drift time", "The ion drift time of an MS2 product ion.", true}, {MS_PSM_level_PTM_localization_score, "MS:1001968", "PSM-level PTM localization score", "A score that assign confidence to the localization of an amino acid modification on a peptide sequence at the PSM-level.", false}, {MS_phosphoRS_score, "MS:1001969", "phosphoRS score", "phosphoRS score for PTM site location at the PSM-level.", false}, {MS_phosphoRS_sequence_probability, "MS:1001970", "phosphoRS sequence probability", "Probability that the respective isoform is correct.", false}, {MS_phosphoRS_site_probability, "MS:1001971", "phosphoRS site probability", "Estimate of the probability that the respective site is truly phosphorylated.", false}, {MS_PTM_scoring_algorithm_version, "MS:1001972", "PTM scoring algorithm version", "Version of the post-translational modification scoring algorithm.", false}, {MS_DeBunker, "MS:1001973", "DeBunker", "DeBunker software.", false}, {MS_DeBunker_score, "MS:1001974", "DeBunker:score", "Score specific to DeBunker.", false}, {MS_delta_m_z, "MS:1001975", "delta m/z", "The difference between a theoretically calculated m/z and the corresponding experimentally measured m/z. It can be expressed as absolute or relative value.", false}, {MS_delta_M, "MS:1001976", "delta M", "The difference between a theoretically calculated molecular mass M and the corresponding experimentally measured M. It can be expressed as absolute or relative value.", false}, {MS_MSQuant, "MS:1001977", "MSQuant", "MSQuant software.", false}, {MS_MSQuant_PTM_score, "MS:1001978", "MSQuant:PTM-score", "The PTM score from MSQuant software.", false}, {MS_MaxQuant_PTM_Score, "MS:1001979", "MaxQuant:PTM Score", "The PTM score from MaxQuant software.", false}, {MS_MaxQuant_Phospho__STY__Probabilities, "MS:1001980", "MaxQuant:Phospho (STY) Probabilities", "The Phospho (STY) Probabilities from MaxQuant software.", false}, {MS_MaxQuant_Phospho__STY__Score_Diffs, "MS:1001981", "MaxQuant:Phospho (STY) Score Diffs", "The Phospho (STY) Score Diffs from MaxQuant software.", false}, {MS_MaxQuant_P_site_localization_probability, "MS:1001982", "MaxQuant:P-site localization probability", "The P-site localization probability value from MaxQuant software.", false}, {MS_MaxQuant_PTM_Delta_Score, "MS:1001983", "MaxQuant:PTM Delta Score", "The PTM Delta Score value from MaxQuant software (Difference between highest scoring site and second highest).", false}, {MS_Ascore_1001984, "MS:1001984", "Ascore (MS:1001984)", "Ascore software.", false}, {MS_Ascore_1001985, "MS:1001985", "Ascore (MS:1001985)", "A-score for PTM site location at the PSM-level.", false}, {MS_H_Score, "MS:1001986", "H-Score", "H-Score for peptide phosphorylation site location.", false}, {MS_vacuum_drying_MALDI_sample_preparation, "MS:1001987", "vacuum drying MALDI sample preparation", "Vacuum-drying MALDI sample preparation crystallization method.", false}, {MS_crushed_crystal_MALDI_sample_preparation, "MS:1001988", "crushed crystal MALDI sample preparation", "Crushed-crystal MALDI sample preparation method.", false}, {MS_fast_evaporation_MALDI_sample_preparation, "MS:1001989", "fast evaporation MALDI sample preparation", "Fast-evaporation MALDI sample preparation method.", false}, {MS_overlayer_MALDI_sample_preparation, "MS:1001990", "overlayer MALDI sample preparation", "Overlayer method combining features of the crushed-crystal method and the fast-evaporation method.", false}, {MS_sandwich_MALDI_sample_preparation, "MS:1001991", "sandwich MALDI sample preparation", "Sandwich MALDI sample preparation method.", false}, {MS_spin_coating_MALDI_sample_preparation, "MS:1001992", "spin coating MALDI sample preparation", "Spin coating MALDI sample preparation method.", false}, {MS_quick_and_dirty_MALDI_sample_preparation, "MS:1001993", "quick and dirty MALDI sample preparation", "Quick & dirty (Q&D) sample preparation separating matrix handling from sample handling.", false}, {MS_top_hat_baseline_reduction, "MS:1001994", "top hat baseline reduction", "Top-hat morphological filter based on the basic morphological operations 'erosion' and 'dilatation'.", false}, {MS_convex_hull_baseline_reduction, "MS:1001995", "convex hull baseline reduction", "Constructs the baseline by fitting multiple parabolas to the spectrum starting with the large scale structures.", false}, {MS_median_baseline_reduction, "MS:1001996", "median baseline reduction", "The spectrum that will be baseline subtracted is divided into a number of segments.", false}, {MS_wavelet_transformation_smoothing, "MS:1001997", "wavelet transformation smoothing", "The random noise is removed by using the undecimated wavelet transform.", false}, {MS_sophisticated_numerical_annotation_procedure, "MS:1001998", "sophisticated numerical annotation procedure", "It searches for known patterns in the measured spectrum.", false}, {MS_area_normalization, "MS:1001999", "area normalization", "Normalization of areas below the curves.", false}, {MS_LIFT, "MS:1002000", "LIFT", "A Bruker's proprietary technique where molecular ions are initially accelerated at lower energy, then collide with inert gas in a collision cell that is then 'lifted' to high potential. The use of inert gas is optional, as it could lift also fragments provided by LID.", false}, {MS_MS1_label_based_raw_feature_quantitation, "MS:1002001", "MS1 label-based raw feature quantitation", "MS1 label-based raw feature quantitation.", false}, {MS_MS1_label_based_peptide_level_quantitation, "MS:1002002", "MS1 label-based peptide level quantitation", "MS1 label-based peptide level quantitation.", false}, {MS_MS1_label_based_protein_level_quantitation, "MS:1002003", "MS1 label-based protein level quantitation", "MS1 label-based protein level quantitation.", false}, {MS_MS1_label_based_proteingroup_level_quantitation, "MS:1002004", "MS1 label-based proteingroup level quantitation", "MS1 label-based proteingroup level quantitation.", false}, {MS_iRT_retention_time_normalization_standard, "MS:1002005", "iRT retention time normalization standard", "A de facto standard providing the retention times at which a specific set of 10 reference peptides exit the reference chromatographic column. The kit may be obtain from Biognosys.", false}, {MS_SRM_transition_type, "MS:1002006", "SRM transition type", "The type of the transitions, e.g. target or decoy.", false}, {MS_target_SRM_transition, "MS:1002007", "target SRM transition", "A transition used to target a specific compound that may be in the sample.", false}, {MS_decoy_SRM_transition, "MS:1002008", "decoy SRM transition", "A transition not expected to be present in the sample and used to calculate statistical confidence of target transition detections in some workflows.", false}, {MS_isobaric_label_quantitation_analysis, "MS:1002009", "isobaric label quantitation analysis", "Quantitation analysis using an isobaric labelling workflow.", false}, {MS_TMT_quantitation_analysis, "MS:1002010", "TMT quantitation analysis", "Quantitation analysis using the Thermo Fisher tandem mass tag (TMT) labelling workflow.", false}, {MS_desorption_electrospray_ionization, "MS:1002011", "desorption electrospray ionization", "Combination of electrospray and desorption ionization method that ionizes gases, liquids and solids in open air under atmospheric pressure.", false}, {MS_Mascot_PTM_site_assignment_confidence, "MS:1002012", "Mascot:PTM site assignment confidence", "Relative probability that PTM site assignment is correct, derived from the Mascot score difference between matches to the same spectrum (Mascot Delta Score).", false}, {MS_collision_energy_ramp_start, "MS:1002013", "collision energy ramp start", "Collision energy at the start of the collision energy ramp.", false}, {MS_collision_energy_ramp_end, "MS:1002014", "collision energy ramp end", "Collision energy at the end of the collision energy ramp.", false}, {MS_spectral_count_peptide_level_quantitation, "MS:1002015", "spectral count peptide level quantitation", "Spectral count peptide level quantitation.", false}, {MS_spectral_count_protein_level_quantitation, "MS:1002016", "spectral count protein level quantitation", "Spectral count protein level quantitation.", false}, {MS_spectral_count_proteingroup_level_quantitation, "MS:1002017", "spectral count proteingroup level quantitation", "Spectral count proteingroup level quantitation.", false}, {MS_MS1_label_based_analysis, "MS:1002018", "MS1 label-based analysis", "MS1 label-based analysis.", false}, {MS_label_free_raw_feature_quantitation, "MS:1002019", "label-free raw feature quantitation", "Label-free raw feature quantitation.", false}, {MS_label_free_peptide_level_quantitation, "MS:1002020", "label-free peptide level quantitation", "Label-free peptide level quantitation.", false}, {MS_label_free_protein_level_quantitation, "MS:1002021", "label-free protein level quantitation", "Label-free protein level quantitation.", false}, {MS_label_free_proteingroup_level_quantitation, "MS:1002022", "label-free proteingroup level quantitation", "Label-free proteingroup level quantitation.", false}, {MS_MS2_tag_based_analysis, "MS:1002023", "MS2 tag-based analysis", "MS2 tag-based analysis.", false}, {MS_MS2_tag_based_feature_level_quantitation, "MS:1002024", "MS2 tag-based feature level quantitation", "MS2 tag-based feature level quantitation.", false}, {MS_MS2_tag_based_peptide_level_quantitation, "MS:1002025", "MS2 tag-based peptide level quantitation", "MS2 tag-based peptide level quantitation.", false}, {MS_MS2_tag_based_protein_level_quantitation, "MS:1002026", "MS2 tag-based protein level quantitation", "MS2 tag-based protein level quantitation.", false}, {MS_MS2_tag_based_proteingroup_level_quantitation, "MS:1002027", "MS2 tag-based proteingroup level quantitation", "MS2 tag-based proteingroup level quantitation.", false}, {MS_nucleic_acid_base_modification, "MS:1002028", "nucleic acid base modification", "Nucleic acid base modification (substitution, insertion or deletion).", false}, {MS_original_nucleic_acid_sequence, "MS:1002029", "original nucleic acid sequence", "Specification of the original nucleic acid sequence, prior to a modification. The value slot should hold the DNA or RNA sequence.", false}, {MS_modified_nucleic_acid_sequence, "MS:1002030", "modified nucleic acid sequence", "Specification of the modified nucleic acid sequence. The value slot should hold the DNA or RNA sequence.", false}, {MS_PASSEL_transition_group_browser_URI, "MS:1002031", "PASSEL transition group browser URI", "URI to retrieve transition group data for a PASSEL (PeptideAtlas SRM Experiment Library) experiment.", false}, {MS_PeptideAtlas_dataset_URI, "MS:1002032", "PeptideAtlas dataset URI", "URI that allows access to a PeptideAtlas dataset.", false}, {MS_contact_role, "MS:1002033", "contact role", "Role of the contact person.", false}, {MS_first_author, "MS:1002034", "first author", "The first of a set of authors associated with a publication or release. There may be more than one first author in cases where several authors share primary attribution.", false}, {MS_senior_author, "MS:1002035", "senior author", "The last of a set of authors associated with a publication or release. There may be more than one senior author in cases where several authors share senior attribution.", false}, {MS_co_author, "MS:1002036", "co-author", "One of a set of authors associated with a publication or release.", false}, {MS_dataset_submitter, "MS:1002037", "dataset submitter", "A person who submits a dataset to a repository.", false}, {MS_unlabeled_sample, "MS:1002038", "unlabeled sample", "A sample that has not been labelled or modified. This is often referred to as \\\"light\\\" to distinguish from \\\"heavy\\\".", false}, {MS_inlet_attribute, "MS:1002039", "inlet attribute", "Inlet properties that are associated with a value.", false}, {MS_inlet_temperature, "MS:1002040", "inlet temperature", "The temperature of the inlet of a mass spectrometer.", false}, {MS_source_temperature, "MS:1002041", "source temperature", "The temperature of the source of a mass spectrometer.", false}, {MS_modulation_time, "MS:1002042", "modulation time", "The duration of a complete cycle of modulation in a comprehensive two-dimensional separation system, equals the length of a second dimension chromatogram, i.e., the time between two successive injections into the second column.", false}, {MS_ProteinProspector, "MS:1002043", "ProteinProspector", "ProteinProspector software for data acquisition and analysis.", false}, {MS_ProteinProspector_score, "MS:1002044", "ProteinProspector:score", "The ProteinProspector result 'Score'.", false}, {MS_ProteinProspector_expectation_value, "MS:1002045", "ProteinProspector:expectation value", "The ProteinProspector result 'Expectation value'.", false}, {MS_native_source_path, "MS:1002046", "native source path", "The original source path used for directory-based sources.", false}, {MS_MS_GF, "MS:1002047", "MS-GF", "MS-GF software used to re-score the peptide-spectrum matches.", false}, {MS_MS_GF_, "MS:1002048", "MS-GF+", "MS-GF+ software used to analyze the spectra.", false}, {MS_MS_GF_RawScore, "MS:1002049", "MS-GF:RawScore", "MS-GF raw score.", false}, {MS_MS_GF_DeNovoScore, "MS:1002050", "MS-GF:DeNovoScore", "MS-GF de novo score.", false}, {MS_MS_GF_Energy, "MS:1002051", "MS-GF:Energy", "MS-GF energy score.", false}, {MS_MS_GF_SpecEValue, "MS:1002052", "MS-GF:SpecEValue", "MS-GF spectral E-value.", false}, {MS_MS_GF_EValue, "MS:1002053", "MS-GF:EValue", "MS-GF E-value.", false}, {MS_MS_GF_QValue, "MS:1002054", "MS-GF:QValue", "MS-GF Q-value.", false}, {MS_MS_GF_PepQValue, "MS:1002055", "MS-GF:PepQValue", "MS-GF peptide-level Q-value.", false}, {MS_MS_GF_PEP, "MS:1002056", "MS-GF:PEP", "MS-GF posterior error probability.", false}, {MS_modification_specificity_protein_N_term, "MS:1002057", "modification specificity protein N-term", "As parameter for search engine: apply the modification only at the N-terminus of a protein.", false}, {MS_modification_specificity_protein_C_term, "MS:1002058", "modification specificity protein C-term", "As parameter for search engine: apply the modification only at the C-terminus of a protein.", false}, {MS_Microsoft_Excel, "MS:1002059", "Microsoft Excel", "Microsoft Excel (can be used for spectral counting).", false}, {MS_database_UniProtKB_TrEMBL, "MS:1002060", "database UniProtKB/TrEMBL", "The name of the UniProtKB/TrEMBL database.", false}, {MS_decoy_DB_from_UniProtKB_TrEMBL_OBSOLETE, "MS:1002061", "decoy DB from UniProtKB/TrEMBL", "Decoy database from a TrEMBL protein sequence database.", true}, {MS_metabolic_labelling__natural_N__mainly_14N_, "MS:1002062", "metabolic labelling: natural N (mainly 14N)", "Metabolic labelling: natural N (mainly 14N).", false}, {MS_FindPairs, "MS:1002063", "FindPairs", "Software e.g. for SILAC and 14N/15N workflow, part of the PeakQuant suite.", false}, {MS_peptide_consensus_RT, "MS:1002064", "peptide consensus RT", "Peptide consensus retention time.", false}, {MS_peptide_consensus_m_z, "MS:1002065", "peptide consensus m/z", "Peptide consensus mass/charge ratio.", false}, {MS_ratio_calculation_method, "MS:1002066", "ratio calculation method", "Method used to calculate the ratio.", false}, {MS_protein_value__median_of_peptide_ratios, "MS:1002067", "protein value: median of peptide ratios", "Protein quantification value calculated as median of peptide ratios.", false}, {MS_metabolic_labelling__heavy_N__mainly_15N_, "MS:1002068", "metabolic labelling: heavy N (mainly 15N)", "Metabolic labelling: heavy N (mainly 15N).", false}, {MS_metabolic_labelling__labelling_purity, "MS:1002069", "metabolic labelling: labelling purity", "Metabolic labelling: Description of labelling purity. Usually the purity of feeding material (e.g. 95%), or the inclusion rate derived from isotopic peak pattern shape.", false}, {MS_t_test, "MS:1002070", "t-test", "Perform a t-test (two groups). Specify in string value, whether paired / unpaired, variance equal / different, one- / two-sided version is performed.", false}, {MS_ANOVA_test, "MS:1002071", "ANOVA-test", "Perform an ANOVA-test (more than two groups). Specify in string value, which version is performed.", false}, {MS_p_value, "MS:1002072", "p-value", "P-value as result of one of the processing steps described. Specify in the description, which processing step it was.", false}, {MS_mzIdentML_format, "MS:1002073", "mzIdentML format", "The mzIdentML format for peptide and protein identification data from the PSI. File extension '.mzid'.", false}, {MS_quantification_file_format, "MS:1002074", "quantification file format", "File format containing quantification results.", false}, {MS_mzQuantML_format, "MS:1002075", "mzQuantML format", "The mzQuantML format for quantification data from the PSI. File extension '.mzq'.", false}, {MS_PAnalyzer, "MS:1002076", "PAnalyzer", "PAnalyzer software for getting protein evidence categories.", false}, {MS_impact, "MS:1002077", "impact", "Bruker Daltonics' impact: ESI Q-TOF, Nanospray, APCI, APPI, GC-APCI, CaptiveSpray.", false}, {MS_ProteomeDiscoverer_1__Static_Modification_OBSOLETE, "MS:1002078", "ProteomeDiscoverer:1. Static Modification", "ProteomeDiscoverer's 1st static post-translational modification (PTM) input parameter.", true}, {MS_ProteomeDiscoverer_2__Static_Modification_OBSOLETE, "MS:1002079", "ProteomeDiscoverer:2. Static Modification", "ProteomeDiscoverer's 2nd static post-translational modification (PTM) input parameter.", true}, {MS_ProteomeDiscoverer_Spectrum_Selector_Precursor_Clipping_Range_Before, "MS:1002080", "ProteomeDiscoverer:Spectrum Selector:Precursor Clipping Range Before", "Precursor clipping range before.", false}, {MS_ProteomeDiscoverer_Spectrum_Selector_Precursor_Clipping_Range_After, "MS:1002081", "ProteomeDiscoverer:Spectrum Selector:Precursor Clipping Range After", "Precursor clipping range after.", false}, {MS_first_column_elution_time, "MS:1002082", "first column elution time", "The time of elution from the first chromatographic column in the chromatographic separation step, relative to the start of chromatography on the first column.", false}, {MS_second_column_elution_time, "MS:1002083", "second column elution time", "The time of elution from the second chromatographic column in the chromatographic separation step, relative to the start of the chromatography on the second column.", false}, {MS_multidimensional_chromatography_modulation_description, "MS:1002084", "multidimensional chromatography modulation description", "Multidimensional chromatography modulation description.", false}, {MS_two_dimensional_gas_chromatography_with_fixed_modulation_time, "MS:1002085", "two-dimensional gas chromatography with fixed modulation time", "Two-dimensional gas chromatography where a single modulation time is used throughout the acquisition.", false}, {MS_two_dimensional_gas_chromatography_with_discrete_modulation_time_steps, "MS:1002086", "two-dimensional gas chromatography with discrete modulation time steps", "Two-dimensional gas chromatography where the acquisition is divided into steps, each with a different modulation time.", false}, {MS_two_dimensional_liquid_chromatography_with_fixed_modulation_time, "MS:1002087", "two-dimensional liquid chromatography with fixed modulation time", "Two-dimensional liquid chromatography where a single modulation time is used throughout the acquisition.", false}, {MS_two_dimensional_liquid_chromatography_with_discrete_modulation_time_steps, "MS:1002088", "two-dimensional liquid chromatography with discrete modulation time steps", "Two-dimensional liquid chromatography where the acquisition is divided into steps, each with a different modulation time.", false}, {MS_ProteomeDiscoverer_Peptide_Without_Protein_XCorr_Threshold, "MS:1002089", "ProteomeDiscoverer:Peptide Without Protein XCorr Threshold", "XCorr threshold for storing peptides that do not belong to a protein.", false}, {MS_Calculate_Probability_Scores, "MS:1002090", "Calculate Probability Scores", "Flag indicating that a probability score for the assessment that a reported peptide match is a random occurrence is calculated.", false}, {MS_ProteomeDiscoverer_Maximum_Delta_Cn, "MS:1002091", "ProteomeDiscoverer:Maximum Delta Cn", "Delta Cn threshold for filtering out PSM's.", false}, {MS_Percolator_Validation_based_on, "MS:1002092", "Percolator:Validation based on", "Algorithm (e.g. q-value or PEP) used for calculation of the validation score using Percolator.", false}, {MS_search_engine_input_parameter, "MS:1002093", "search engine input parameter", "Search engine input parameter.", false}, {MS_common_search_engine_input_parameter, "MS:1002094", "common search engine input parameter", "Search engine input parameter that is shared by more than one search engine.", false}, {MS_Mascot_input_parameter, "MS:1002095", "Mascot input parameter", "Search engine input parameters specific to Mascot.", false}, {MS_SEQUEST_input_parameter, "MS:1002096", "SEQUEST input parameter", "Search engine input parameters specific to SEQUEST.", false}, {MS_Phenyx_input_parameter, "MS:1002097", "Phenyx input parameter", "Search engine input parameters specific to Phenyx.", false}, {MS_ProteinExtractor_input_parameter, "MS:1002098", "ProteinExtractor input parameter", "Search engine input parameters specific to ProteinExtractor.", false}, {MS_OMSSA_input_parameter, "MS:1002099", "OMSSA input parameter", "Search engine input parameters specific to OMSSA.", false}, {MS_ProteinScape_input_parameter, "MS:1002100", "ProteinScape input parameter", "Search engine input parameters specific to ProteinScape.", false}, {MS_ProteomeDiscoverer_input_parameter, "MS:1002101", "ProteomeDiscoverer input parameter", "Search engine input parameters specific to ProteomeDiscoverer.", false}, {MS_software_input_parameter, "MS:1002103", "software input parameter", "Software input parameters.", false}, {MS_common_software_input_parameter, "MS:1002104", "common software input parameter", "Software input parameter that is shared by more than one software.", false}, {MS_software_specific_input_parameter, "MS:1002105", "software specific input parameter", "Software specific input parameter.", false}, {MS_Scaffold_input_parameter, "MS:1002106", "Scaffold input parameter", "Search engine input parameters specific to Scaffold.", false}, {MS_Percolator_input_parameter, "MS:1002107", "Percolator input parameter", "Search engine input parameters specific to Percolator.", false}, {MS_higher_score_better, "MS:1002108", "higher score better", "Indicates that a higher score is better.", false}, {MS_lower_score_better, "MS:1002109", "lower score better", "Indicates that a lower score is better.", false}, {MS_assay_attribute, "MS:1002110", "assay attribute", "Attribute describing an assay.", false}, {MS_assay_label_attribute, "MS:1002111", "assay label attribute", "Attribute describing an assay label.", false}, {MS_protein_group_list_attribute, "MS:1002112", "protein group list attribute", "Attribute describing a protein group list.", false}, {MS_protein_group_attribute, "MS:1002113", "protein group attribute", "Attribute describing a protein group.", false}, {MS_protein_list_attribute, "MS:1002114", "protein list attribute", "Attribute describing a protein list.", false}, {MS_peptide_consensus_list_attribute, "MS:1002115", "peptide consensus list attribute", "Attribute describing a peptide consensus list.", false}, {MS_peptide_consensus_attribute, "MS:1002116", "peptide consensus attribute", "Attribute describing a peptide consensus.", false}, {MS_small_molecule_list_attribute, "MS:1002117", "small molecule list attribute", "Attribute describing a small molecule list.", false}, {MS_small_molecule_attribute, "MS:1002118", "small molecule attribute", "Attribute describing a small molecule.", false}, {MS_small_molecule_modification_attribute, "MS:1002119", "small molecule modification attribute", "Attribute describing a small molecule modification.", false}, {MS_experiment_name, "MS:1002120", "experiment name", "The name for identifying an experiment.", false}, {MS_spectral_count_feature, "MS:1002121", "spectral count feature", "Dummy decribing a spectral count feature.", false}, {MS_counts_reporting, "MS:1002122", "counts reporting", "FeatureList of spectral counts.", false}, {MS_x_Tracker, "MS:1002123", "x-Tracker", "x-Tracker generic tool for quantitative proteomics.", false}, {MS_ProteoSuite, "MS:1002124", "ProteoSuite", "ProteoSuite software for the analysis of quantitative proteomics data.", false}, {MS_combined_FDRScore_OBSOLETE, "MS:1002125", "combined FDRScore", "FDRScore values specifically obtained for distinct combinations of single, pairs or triplets of search engines making a given PSM, used for integrating results from these distinct pools.", true}, {MS_database_UniProtKB, "MS:1002126", "database UniProtKB", "The name of the UniProtKB knowledgebase.", false}, {MS_identification_file_attribute, "MS:1002127", "identification file attribute", "Attribute describing an identification file.", false}, {MS_method_file_format, "MS:1002128", "method file format", "Attribute describing a method file format.", false}, {MS_ITRAQAnalyzer, "MS:1002129", "ITRAQAnalyzer", "Software for iTRAQ workflow. Extracts and normalizes iTRAQ information from an MS experiment.", false}, {MS_identification_file_format, "MS:1002130", "identification file format", "Attribute describing an identification file format.", false}, {MS_TOPP_noise_filter, "MS:1002131", "TOPP noise filter", "Noise filter component of the TOPP software.", false}, {MS_TOPP_NoiseFilterGaussian, "MS:1002132", "TOPP NoiseFilterGaussian", "Removes noise from profile spectra by using a gaussian smoothing.", false}, {MS_TOPP_NoiseFilterSGolay, "MS:1002133", "TOPP NoiseFilterSGolay", "Removes noise from profile spectra by using a Savitzky-Golay smoothing.", false}, {MS_TOPP_peak_picker, "MS:1002134", "TOPP peak picker", "Peak picker component of the TOPP software.", false}, {MS_TOPP_PeakPickerHiRes, "MS:1002135", "TOPP PeakPickerHiRes", "Finds mass spectrometric peaks in high-resoluted profile mass spectra.", false}, {MS_TOPP_PeakPickerWavelet, "MS:1002136", "TOPP PeakPickerWavelet", "Finds mass spectrometric peaks with a wavelet algorithm in low-resoluted profile mass spectra.", false}, {MS_TOPP_spectra_filter, "MS:1002137", "TOPP spectra filter", "Spectra filter component of the TOPP software.", false}, {MS_TOPP_SpectraFilterBernNorm, "MS:1002138", "TOPP SpectraFilterBernNorm", "Applies a Bern et al normalization to peak spectra.", false}, {MS_TOPP_SpectraFilterMarkerMower, "MS:1002139", "TOPP SpectraFilterMarkerMower", "Applies a filter to peak spectra for marked peaks.", false}, {MS_TOPP_SpectraFilterNLargest, "MS:1002140", "TOPP SpectraFilterNLargest", "Retains the n largest peaks of a peak spectra.", false}, {MS_TOPP_SpectraFilterNormalizer, "MS:1002141", "TOPP SpectraFilterNormalizer", "Applies a TIC/maximal intensity normalization to peak spectra.", false}, {MS_TOPP_SpectraFilterParentPeakMower, "MS:1002142", "TOPP SpectraFilterParentPeakMower", "Filters putative unfragmented precursor ions from tandem spectra.", false}, {MS_TOPP_SpectraFilterScaler, "MS:1002143", "TOPP SpectraFilterScaler", "Applies a filter to peak spectra after intensity scaling according to rank.", false}, {MS_TOPP_SpectraFilterSqrtMower, "MS:1002144", "TOPP SpectraFilterSqrtMower", "Applies a filter to peak spectra after intensity scaling to the square root.", false}, {MS_TOPP_SpectraFilterThresholdMower, "MS:1002145", "TOPP SpectraFilterThresholdMower", "Applies a filter of peaks below a given threshold to peak spectra.", false}, {MS_TOPP_SpectraFilterWindowMower, "MS:1002146", "TOPP SpectraFilterWindowMower", "Applies a filter of the largest peaks in a sliding window over a peak spectrum.", false}, {MS_TOPP_map_aligner, "MS:1002147", "TOPP map aligner", "Map aligner component of the TOPP software.", false}, {MS_TOPP_MapAlignerIdentification, "MS:1002148", "TOPP MapAlignerIdentification", "Corrects retention time distortions between maps based on common peptide identifications.", false}, {MS_TOPP_MapAlignerPoseClustering, "MS:1002149", "TOPP MapAlignerPoseClustering", "Corrects retention time distortions between maps using a pose clustering approach.", false}, {MS_TOPP_MapAlignerSpectrum, "MS:1002150", "TOPP MapAlignerSpectrum", "Corrects retention time distortions between maps by spectrum alignment.", false}, {MS_numerator_data_type_attribute, "MS:1002151", "numerator data type attribute", "Attribute describing the data type of the numerator of a ratio.", false}, {MS_denominator_data_type_attribute, "MS:1002152", "denominator data type attribute", "Attribute describing the data type of the denominator of a ratio.", false}, {MS_protein_level_PSM_counts, "MS:1002153", "protein level PSM counts", "The number of spectra identified for this protein in spectral counting.", false}, {MS_TOPP_DTAExtractor, "MS:1002154", "TOPP DTAExtractor", "Extracts spectra of an MS run file to several files in DTA format.", false}, {MS_TOPP_IDMerger, "MS:1002155", "TOPP IDMerger", "Merges several protein/peptide identification files into one file.", false}, {MS_TOPP_IDFileConverter, "MS:1002156", "TOPP IDFileConverter", "Converts identification engine file formats.", false}, {MS_TOPP_SpectraMerger, "MS:1002157", "TOPP SpectraMerger", "Merges spectra from an LC/MS map, either by precursor or by RT blocks.", false}, {MS_TOPP_MzTabExporter, "MS:1002158", "TOPP MzTabExporter", "Exports various XML formats to an mzTab file.", false}, {MS_TOPP_MassTraceExtractor, "MS:1002159", "TOPP MassTraceExtractor", "Annotates mass traces in centroided LC/MS maps.", false}, {MS_TOPP_PrecursorMassCorrector, "MS:1002160", "TOPP PrecursorMassCorrector", "Correct the precursor entries of tandem MS scans.", false}, {MS_TOPP_HighResPrecursorMassCorrector, "MS:1002161", "TOPP HighResPrecursorMassCorrector", "Performs precursor mz correction on centroided high resolution data.", false}, {MS_TOPP_AdditiveSeries, "MS:1002162", "TOPP AdditiveSeries", "Computes an additive series to quantify a peptide in a set of samples.", false}, {MS_TOPP_Decharger, "MS:1002163", "TOPP Decharger", "Decharges and merges different feature charge variants of the same chemical entity.", false}, {MS_TOPP_EICExtractor, "MS:1002164", "TOPP EICExtractor", "Quantifies signals at given positions in (raw or picked) LC/MS maps.", false}, {MS_TOPP_feature_finder, "MS:1002165", "TOPP feature finder", "Feature finder component of the TOPP software.", false}, {MS_TOPP_FeatureFinderCentroided, "MS:1002166", "TOPP FeatureFinderCentroided", "Detects two-dimensional features in centroided LC-MS data.", false}, {MS_TOPP_FeatureFinderRaw, "MS:1002167", "TOPP FeatureFinderRaw", "Detects two-dimensional features in uncentroided LC-MS data.", false}, {MS_TOPP_FeatureFinderIsotopeWavelet, "MS:1002168", "TOPP FeatureFinderIsotopeWavelet", "Detects two-dimensional features in uncentroided LC-MS data with a wavelet algorithm.", false}, {MS_TOPP_FeatureFinderMetabo, "MS:1002169", "TOPP FeatureFinderMetabo", "Detects two-dimensional features in centroided LC-MS data of metabolites.", false}, {MS_TOPP_FeatureFinderMRM, "MS:1002170", "TOPP FeatureFinderMRM", "Quantifies features LC-MS/MS MRM data.", false}, {MS_TOPP_ProteinQuantifier, "MS:1002171", "TOPP ProteinQuantifier", "Computes protein abundances from annotated feature/consensus maps.", false}, {MS_TOPP_ConsensusMapNormalizer, "MS:1002172", "TOPP ConsensusMapNormalizer", "Normalizes maps of one consensus XML file (after linking).", false}, {MS_TOPP_MapRTTransformer, "MS:1002173", "TOPP MapRTTransformer", "Applies retention time transformations to maps.", false}, {MS_TOPP_feature_linker, "MS:1002174", "TOPP feature linker", "Feature linker component of the TOPP software.", false}, {MS_TOPP_FeatureLinkerLabeled, "MS:1002175", "TOPP FeatureLinkerLabeled", "Groups corresponding isotope-labeled features in a feature map.", false}, {MS_TOPP_FeatureLinkerUnlabeled, "MS:1002176", "TOPP FeatureLinkerUnlabeled", "Groups corresponding features from multiple maps.", false}, {MS_TOPP_FeatureLinkerUnlabeledQT, "MS:1002177", "TOPP FeatureLinkerUnlabeledQT", "Groups corresponding features from multiple maps using a quality threshold clustering approach.", false}, {MS_TOPP_CompNovo, "MS:1002178", "TOPP CompNovo", "Performs a peptide/protein identification with the CompNovo engine.", false}, {MS_TOPP_CompNovoCID, "MS:1002179", "TOPP CompNovoCID", "Performs a peptide/protein identification with the CompNovo engine in collision-induced dissociation (CID) mode.", false}, {MS_TOPP_software_adaptor, "MS:1002180", "TOPP software adaptor", "Software adaptor to an external program in the TOPP software.", false}, {MS_TOPP_InspectAdapter, "MS:1002181", "TOPP InspectAdapter", "Identifies MS2 spectra using the external program Inspect.", false}, {MS_TOPP_MascotAdapter, "MS:1002182", "TOPP MascotAdapter", "Identifies MS2 spectra using the external program Mascot.", false}, {MS_TOPP_MascotAdapterOnline, "MS:1002183", "TOPP MascotAdapterOnline", "Identifies MS2 spectra using the online version of the external program Mascot.", false}, {MS_TOPP_OMSSAAdapter, "MS:1002184", "TOPP OMSSAAdapter", "Identifies MS2 spectra using the external program OMSSA.", false}, {MS_TOPP_PepNovoAdapter, "MS:1002185", "TOPP PepNovoAdapter", "Identifies MS2 spectra using the external program PepNovo.", false}, {MS_TOPP_XTandemAdapter, "MS:1002186", "TOPP XTandemAdapter", "Identifies MS2 spectra using the external program XTandem.", false}, {MS_TOPP_SpecLibSearcher, "MS:1002187", "TOPP SpecLibSearcher", "Identifies peptide MS2 spectra by spectral matching with a searchable spectral library.", false}, {MS_TOPP_ConsensusID, "MS:1002188", "TOPP ConsensusID", "Computes a consensus identification from peptide identifications of several identification engines.", false}, {MS_TOPP_IDConflictResolver, "MS:1002189", "TOPP IDConflictResolver", "Resolves ambiguous annotations of features with peptide identifications.", false}, {MS_TOPP_IDFilter, "MS:1002190", "TOPP IDFilter", "Filters results from protein or peptide identification engines based on different criteria.", false}, {MS_TOPP_IDMapper, "MS:1002191", "TOPP IDMapper", "Assigns protein/peptide identifications to feature or consensus features.", false}, {MS_TOPP_IDPosteriorErrorProbability, "MS:1002192", "TOPP IDPosteriorErrorProbability", "Estimates posterior error probabilities using a mixture model.", false}, {MS_TOPP_IDRTCalibration, "MS:1002193", "TOPP IDRTCalibration", "Calibrate Retention times of peptide hits to standards.", false}, {MS_TOPP_PeptideIndexer, "MS:1002194", "TOPP PeptideIndexer", "Refreshes the protein references for all peptide hits.", false}, {MS_TOPP_PrecursorIonSelector, "MS:1002195", "TOPP PrecursorIonSelector", "A tool for precursor ion selection based on identification results.", false}, {MS_TOPP_MRMMapper, "MS:1002196", "TOPP MRMMapper", "MRMMapper maps measured chromatograms (mzML) and the transitions used (TraML).", false}, {MS_TOPP_OpenSwath_component, "MS:1002197", "TOPP OpenSwath component", "OpenSwath component of the TOPP software.", false}, {MS_TOPP_OpenSwathAnalyzer, "MS:1002198", "TOPP OpenSwathAnalyzer", "Picks peaks and finds features in an SRM experiment.", false}, {MS_TOPP_OpenSwathChromatogramExtractor, "MS:1002199", "TOPP OpenSwathChromatogramExtractor", "Extract chromatograms (XIC) from a MS2 map file.", false}, {MS_TOPP_OpenSwathDecoyGenerator, "MS:1002200", "TOPP OpenSwathDecoyGenerator", "Generates decoys according to different models for a specific TraML.", false}, {MS_TOPP_OpenSwathFeatureXMLToTSV, "MS:1002201", "TOPP OpenSwathFeatureXMLToTSV", "Converts a featureXML to a mProphet tsv (tab separated values).", false}, {MS_TOPP_OpenSwathRTNormalizer, "MS:1002202", "TOPP OpenSwathRTNormalizer", "Generates a transformation file for retention time space into normalized space.", false}, {MS_TOPP_ProteinInference, "MS:1002203", "TOPP ProteinInference", "Infer proteins from a list of (high-confidence) peptides.", false}, {MS_TOPP_FalseDiscoveryRate, "MS:1002204", "TOPP FalseDiscoveryRate", "Estimates the false discovery rate on peptide and protein level using decoy searches.", false}, {MS_ProteoWizard_msconvert, "MS:1002205", "ProteoWizard msconvert", "Converts, filters, and processes mass spectrometry data in variety of formats.", false}, {MS_ProteoWizard_idconvert, "MS:1002206", "ProteoWizard idconvert", "Converts, filters, and processes identifications from shotgun proteomics experiments.", false}, {MS_ProteoWizard_chainsaw, "MS:1002207", "ProteoWizard chainsaw", "Filters and processes protein sequence databases.", false}, {MS_ProteoWizard_msaccess, "MS:1002208", "ProteoWizard msaccess", "Filters, processes, and displays mass spectrometry data in a variety of ways.", false}, {MS_ProteoWizard_SeeMS, "MS:1002209", "ProteoWizard SeeMS", "An interactive GUI application to view and filter mass spectrometry data in a variety of formats.", false}, {MS_IsobariQ, "MS:1002210", "IsobariQ", "A quantitative software package designed for analysis of IPTL, TMT and iTRAQ data.", false}, {MS_Variance_stabilizing_normalization, "MS:1002211", "Variance stabilizing normalization", "The model incorporates data calibration (normalization), a model for the dependence of the variance on the mean intensity, and a variance stabilizing data transformation.", false}, {MS_IPTL_quantitation_analysis, "MS:1002212", "IPTL quantitation analysis", "Quantification analysis using a labelling strategy where both peptide termini are labelled so that the peptides from different labelling schema are isobaric.", false}, {MS_PAnalyzer_conclusive_protein, "MS:1002213", "PAnalyzer:conclusive protein", "A protein identified by at least one unique (distinct, discrete) peptide (peptides are considered different only if they can be distinguished by evidence in mass spectrum).", false}, {MS_PAnalyzer_indistinguishable_protein, "MS:1002214", "PAnalyzer:indistinguishable protein", "A member of a group of proteins sharing all peptides that are exclusive to the group (peptides are considered different only if they can be distinguished by evidence in mass spectrum).", false}, {MS_PAnalyzer_non_conclusive_protein, "MS:1002215", "PAnalyzer:non-conclusive protein", "A protein sharing all its matched peptides with either conclusive or indistinguishable proteins (peptides are considered different only if they can be distinguished by evidence in mass spectrum).", false}, {MS_PAnalyzer_ambiguous_group_member, "MS:1002216", "PAnalyzer:ambiguous group member", "A protein sharing at least one peptide not matched to either conclusive or indistinguishable proteins (peptides are considered different only if they can be distinguished by evidence in mass spectrum).", false}, {MS_decoy_peptide, "MS:1002217", "decoy peptide", "A putative identified peptide issued from a decoy sequence database.", false}, {MS_percent_collision_energy_ramp_start, "MS:1002218", "percent collision energy ramp start", "Collision energy at the start of the collision energy ramp in percent, normalized to the mass of the ion.", false}, {MS_percent_collision_energy_ramp_end, "MS:1002219", "percent collision energy ramp end", "Collision energy at the end of the collision energy ramp in percent, normalized to the mass of the ion.", false}, {MS_MRMaid, "MS:1002220", "MRMaid", "A web-based SRM assay design tool whose transitions are generated by mining the millions of identified peptide spectra held in the EBI's PRIDE database.", false}, {MS_MRMaid_peptide_score, "MS:1002221", "MRMaid:peptide score", "Score in MRMaid to indicate the expected performance of the peptide in SRM.", false}, {MS_SRM_transition_attribute, "MS:1002222", "SRM transition attribute", "Attribute associated with a SRM transition.", false}, {MS_precursor_ion_detection_probability, "MS:1002223", "precursor ion detection probability", "Probability of detecting precursor when parent protein is present.", false}, {MS_product_ion_detection_probability, "MS:1002224", "product ion detection probability", "Probability of detecting product ion when precursor ion is present.", false}, {MS_average_product_ion_intensity, "MS:1002225", "average product ion intensity", "Average value of product ion intensity in a collection of identified spectra.", false}, {MS_product_ion_intensity_standard_deviation, "MS:1002226", "product ion intensity standard deviation", "Standard deviation of product ion intensity in a collection of identified spectra.", false}, {MS_number_of_product_ion_observations, "MS:1002227", "number of product ion observations", "The number of times the specific product ion has been observed in a series of SRM experiments.", false}, {MS_number_of_precursor_ion_observations, "MS:1002228", "number of precursor ion observations", "The number of times the specific precursor ion has been observed in a series of SRM experiments.", false}, {MS_ProteomeDiscoverer_Mascot_Significance_Middle, "MS:1002229", "ProteomeDiscoverer:Mascot:Significance Middle", "Calculated relaxed significance when performing a decoy search for high-confidence peptides.", false}, {MS_ProteomeDiscoverer_Mascot_Significance_High, "MS:1002230", "ProteomeDiscoverer:Mascot:Significance High", "Calculated relaxed significance when performing a decoy search for medium-confidence peptides.", false}, {MS_regular_expressions_for_a_GUID, "MS:1002231", "regular expressions for a GUID", "([A-Fa-f0-9]\\{8\\}-([A-Fa-f0-9]\\{4\\}-)\\{3\\}[A-Fa-f0-9]\\{12\\}).", false}, {MS_ProteomeDiscoverer_Default_FDR_calculator, "MS:1002232", "ProteomeDiscoverer:Default FDR calculator", "The default FDR calculator as globally unique identifier (GUID).", false}, {MS_ProteomeDiscoverer_SEQUEST_Low_resolution_spectra_contained, "MS:1002233", "ProteomeDiscoverer:SEQUEST:Low resolution spectra contained", "Flag indicating if low-resolution spectra are taken into consideration.", false}, {MS_selected_precursor_m_z, "MS:1002234", "selected precursor m/z", "Mass-to-charge ratio of a precursor ion selected for fragmentation.", false}, {MS_ProteoGrouper_PDH_score, "MS:1002235", "ProteoGrouper:PDH score", "A score assigned to a single protein accession (modelled as ProteinDetectionHypothesis in mzIdentML), based on summed peptide level scores.", false}, {MS_ProteoGrouper_PAG_score, "MS:1002236", "ProteoGrouper:PAG score", "A score assigned to a protein group (modelled as ProteinAmbiguityGroup in mzIdentML), based on all summed peptide level scores that have been assigned to the group as unique or razor peptides.", false}, {MS_mzidLib, "MS:1002237", "mzidLib", "A library of Java routines for manipulating mzIdentML files.", false}, {MS_mzidLib_Omssa2Mzid, "MS:1002238", "mzidLib:Omssa2Mzid", "A converter for OMSSA OMX to mzIdentML.", false}, {MS_mzidLib_Tandem2Mzid, "MS:1002239", "mzidLib:Tandem2Mzid", "A converter for Tandem XML to mzIdentML.", false}, {MS_mzidLib_Csv2Mzid, "MS:1002240", "mzidLib:Csv2Mzid", "A converter for CSV files (following OMSSA CSV style) to mzIdentML.", false}, {MS_mzidLib_ProteoGrouper, "MS:1002241", "mzidLib:ProteoGrouper", "A generic and parameterizable protein inference algorithm for mzIdentML files.", false}, {MS_mzidLib_Thresholder, "MS:1002242", "mzidLib:Thresholder", "A routine for keeping only identifications passing a given threshold or setting passThreshold to true or false for SpectrumIdentificationItem or ProteinDetectionHypothesis in mzIdentML files.", false}, {MS_mzidLib_Perform_emPAI_on_mzid, "MS:1002243", "mzidLib:Perform emPAI on mzid", "A routine for adding emPAI quantitative values to an mzIdentML file.", false}, {MS_mzidLib_FalseDiscoveryRate, "MS:1002244", "mzidLib:FalseDiscoveryRate", "A routine for calculating local FDR, q-value and FDRScore for mzIdentML files, based on a decoy search.", false}, {MS_mzidLib_Mzidentml2Csv, "MS:1002245", "mzidLib:Mzidentml2Csv", "A tool for converting mzIdentML files to CSV format.", false}, {MS_mzidLib_CombineSearchEngines, "MS:1002246", "mzidLib:CombineSearchEngines", "A tool for combining results analysed in parallel in two or three search engines into a single mzIdentML file.", false}, {MS_mzidLib_InsertMetaDataFromFasta, "MS:1002247", "mzidLib:InsertMetaDataFromFasta", "A tool for adding additional meta data from a FASTA file to DBSequence entries (sequence and description) in mzIdentML files.", false}, {MS_SEQUEST_spscore, "MS:1002248", "SEQUEST:spscore", "The SEQUEST result 'SpScore'.", false}, {MS_SEQUEST_sprank, "MS:1002249", "SEQUEST:sprank", "The SEQUEST result 'SpRank'.", false}, {MS_SEQUEST_deltacnstar, "MS:1002250", "SEQUEST:deltacnstar", "The SEQUEST result 'DeltaCnStar'.", false}, {MS_Comet, "MS:1002251", "Comet", "Comet open-source sequence search engine developed at the University of Washington.", false}, {MS_Comet_xcorr, "MS:1002252", "Comet:xcorr", "The Comet result 'XCorr'.", false}, {MS_Comet_deltacn, "MS:1002253", "Comet:deltacn", "The Comet result 'DeltaCn'.", false}, {MS_Comet_deltacnstar, "MS:1002254", "Comet:deltacnstar", "The Comet result 'DeltaCnStar'.", false}, {MS_Comet_spscore, "MS:1002255", "Comet:spscore", "The Comet result 'SpScore'.", false}, {MS_Comet_sprank, "MS:1002256", "Comet:sprank", "The Comet result 'SpRank'.", false}, {MS_Comet_expectation_value, "MS:1002257", "Comet:expectation value", "The Comet result 'Expectation value'.", false}, {MS_Comet_matched_ions, "MS:1002258", "Comet:matched ions", "The Comet result 'Matched Ions'.", false}, {MS_Comet_total_ions, "MS:1002259", "Comet:total ions", "The Comet result 'Total Ions'.", false}, {MS_PSM_FDR_threshold, "MS:1002260", "PSM:FDR threshold", "False-discovery rate threshold for peptide-spectrum matches.", false}, {MS_Byonic, "MS:1002261", "Byonic", "Byonic search engine from Protein Metrics.", false}, {MS_Byonic_Score, "MS:1002262", "Byonic:Score", "The Byonic score is the primary indicator of PSM correctness. The Byonic score reflects the absolute quality of the peptide-spectrum match, not the relative quality compared to other candidate peptides. Byonic scores range from 0 to about 1000, with 300 a good score, 400 a very good score, and PSMs with scores over 500 almost sure to be correct.", false}, {MS_Byonic_Delta_Score, "MS:1002263", "Byonic:Delta Score", "The drop in Byonic score from the top-scoring peptide to the next peptide with distinct sequence. In this computation, the same peptide with different modifications is not considered distinct.", false}, {MS_Byonic_DeltaMod_Score, "MS:1002264", "Byonic:DeltaMod Score", "The drop in Byonic score from the top-scoring peptide to the next peptide different in any way, including placement of modifications. DeltaMod gives an indication of whether modifications are confidently localized; DeltaMod over 10.0 means that there is high likelihood that all modification placements are correct.", false}, {MS_Byonic_PEP, "MS:1002265", "Byonic:PEP", "Byonic posterior error probability.", false}, {MS_Byonic_Peptide_LogProb, "MS:1002266", "Byonic:Peptide LogProb", "The log p-value of the PSM. This is the log of the probability that the PSM with such a score and delta would arise by chance in a search of this size (size of the protein database, as expanded by the modification rules). A log p-value of -3.0 should happen by chance on only one of a thousand spectra. Caveat: it is very hard to compute a p-value that works for all searches and all spectra, so read Byonic p-values with a certain amount of skepticism.", false}, {MS_Byonic_Protein_LogProb, "MS:1002267", "Byonic:Protein LogProb", "The log p-value of the protein.", false}, {MS_Byonic_Best_LogProb, "MS:1002268", "Byonic:Best LogProb", "Best (most negative) log p-value of an individual PSM.", false}, {MS_Byonic_Best_Score, "MS:1002269", "Byonic:Best Score", "Best (largest) Byonic score of a PSM.", false}, {MS_chromatography_separation, "MS:1002270", "chromatography separation", "A technique by which molecules are separated by chemical and physical properties such as hydrophobicity or vapour pressure.", false}, {MS_liquid_chromatography_separation, "MS:1002271", "liquid chromatography separation", "Liquid chromatography (LC) is a separation technique in which the mobile phase is a liquid.", false}, {MS_gas_chromatography_separation, "MS:1002272", "gas chromatography separation", "Gas chromatography (GC) is a separation technique in which the mobile phase is a gas.", false}, {MS_detector_potential, "MS:1002273", "detector potential", "Detector potential difference in volts.", false}, {MS_SQ_Detector_2, "MS:1002274", "SQ Detector 2", "Waters quadrupole based SQ Detector 2.", false}, {MS_Xevo_G2_S_Tof, "MS:1002275", "Xevo G2-S Tof", "Waters oa-ToF based Xevo G2-S Tof.", false}, {MS_Xevo_G2_S_QTof, "MS:1002276", "Xevo G2-S QTof", "Waters oa-ToF based Xevo G2-S QTof.", false}, {MS_AutoSpec_Premier, "MS:1002277", "AutoSpec Premier", "Waters AutoSpec Premier.", false}, {MS_Pegasus_III, "MS:1002278", "Pegasus III", "LECO nominal mass resolution time-of-flight GC mass spectrometer.", false}, {MS_maXis_4G, "MS:1002279", "maXis 4G", "Bruker Daltonics' maXis 4G: ESI Q-TOF, Nanospray, APCI, APPI, GC-APCI, CaptiveSpray.", false}, {MS_compact, "MS:1002280", "compact", "Bruker Daltonics' compact: ESI Q-TOF, Nanospray, APCI, APPI, GC-APCI, CaptiveSpray.", false}, {MS_SRM_feature_level_quantitation, "MS:1002281", "SRM feature level quantitation", "Selected Reaction Monitoring feature level quantitation.", false}, {MS_SRM_peptide_level_quantitation, "MS:1002282", "SRM peptide level quantitation", "Selected Reaction Monitoring peptide level quantitation.", false}, {MS_SRM_protein_level_quantitation, "MS:1002283", "SRM protein level quantitation", "Selected Reaction Monitoring protein level quantitation.", false}, {MS_SRM_proteingroup_level_quantitation, "MS:1002284", "SRM proteingroup level quantitation", "Selected Reaction Monitoring proteingroup level quantitation.", false}, {MS_Trans_Proteomic_Pipeline, "MS:1002285", "Trans-Proteomic Pipeline", "A suite of open source tools for the processing of MS2 proteomics data developed by the Seattle Proteome Center at the Institute for Systems Biology.", false}, {MS_Trans_Proteomic_Pipeline_software, "MS:1002286", "Trans-Proteomic Pipeline software", "A software program that is a component of the Trans-Proteomic Pipeline.", false}, {MS_PeptideProphet, "MS:1002287", "PeptideProphet", "A program in the TPP that calculates PSM probabilities for MS2 proteomics data searched with any of the supported sequence or spectral library search engines via the pepXML format.", false}, {MS_iProphet, "MS:1002288", "iProphet", "A program in the TPP that calculates distinct peptide probabilities based on several lines of corroborating evidence including search results from multiple search engines via the pepXML format.", false}, {MS_ProteinProphet, "MS:1002289", "ProteinProphet", "A program in the TPP that calculates protein-level probabilities based on input PSM or peptide-level probabilities from PeptideProphet or iProphet. The output is written in the protXML format.", false}, {MS_XPRESS, "MS:1002290", "XPRESS", "A program in the TPP that calculates PSM-level abundances based on 2-channel isotope-labelled data such as ICAT, SILAC, etc.", false}, {MS_Libra, "MS:1002291", "Libra", "A program in the TPP that calculates PSM, peptide, and protein-level abundances based on N-channel isobaric label peptide data such as iTRAQ, TMT, etc.", false}, {MS_PTMProphet, "MS:1002292", "PTMProphet", "A program in the TPP that calculates PTM localization probabilities by re-analyzing the peaks that are available to distinguish between possible modification sites.", false}, {MS_Bruker_Daltonics_SCION_series, "MS:1002293", "Bruker Daltonics SCION series", "Bruker Daltonics' SCION series.", false}, {MS_Bruker_Daltonics_EVOQ_series, "MS:1002294", "Bruker Daltonics EVOQ series", "Bruker Daltonics' EVOQ series.", false}, {MS_SCION_SQ, "MS:1002295", "SCION SQ", "Bruker Daltonics' SCION SQ: GC-single quadrupole.", false}, {MS_SCION_TQ, "MS:1002296", "SCION TQ", "Bruker Daltonics' SCION TQ: GC-triple quadrupole.", false}, {MS_EVOQ_Elite, "MS:1002297", "EVOQ Elite", "Bruker Daltonics' EVOQ Elite: LC-triple quadrupole.", false}, {MS_EVOQ_Qube, "MS:1002298", "EVOQ Qube", "Bruker Daltonics' EVOQ Qube: LC-triple quadrupole.", false}, {MS_micrOTOF_Q_III, "MS:1002299", "micrOTOF-Q III", "Bruker Daltonics' micrOTOF-Q III: ESI Q-TOF, Nanospray, APCI, APPI, GC-APCI, CaptiveSpray.", false}, {MS_amaZon_Speed_ETD, "MS:1002300", "amaZon Speed ETD", "Bruker Daltonics' amaZon Speed ETD: ESI quadrupole ion trap, Nanospray, APCI, APPI, ETD, PTR, GC-APCI, CaptiveSpray.", false}, {MS_amaZon_Speed, "MS:1002301", "amaZon Speed", "Bruker Daltonics' amaZon ETD: ESI quadrupole ion trap, Nanospray, APCI, APPI, GC-APCI, CaptiveSpray.", false}, {MS_Bruker_Container_format, "MS:1002302", "Bruker Container format", "Bruker Container raw file format.", false}, {MS_Bruker_Container_nativeID_format, "MS:1002303", "Bruker Container nativeID format", "Native identifier (UUID).", false}, {MS_domain_range, "MS:1002304", "domain range", "Domain range of a numerical value.", false}, {MS_value_between_0_and_1_inclusive, "MS:1002305", "value between 0 and 1 inclusive", "Value range for probabilities.", false}, {MS_value_greater_than_zero, "MS:1002306", "value greater than zero", "Positive value range.", false}, {MS_fragmentation_ion_type, "MS:1002307", "fragmentation ion type", "Type of fragment ion based on where the backbone breaks, such as a y ion or a c ion.", false}, {MS_fluorescence_detector, "MS:1002308", "fluorescence detector", "A detector using a fluorescent signal after excitation with light.", false}, {MS_Byonic__Peptide_AbsLogProb, "MS:1002309", "Byonic: Peptide AbsLogProb", "The absolute value of the log-base10 of the Byonic posterior error probability (PEP) of the PSM.", false}, {MS_Byonic__Protein_AbsLogProb, "MS:1002310", "Byonic: Protein AbsLogProb", "The absolute value of the log-base10 of the Byonic posterior error probability (PEP) of the protein.", false}, {MS_Byonic__Peptide_AbsLogProb2D, "MS:1002311", "Byonic: Peptide AbsLogProb2D", "The absolute value of the log-base10 Byonic two-dimensional posterior error probability (PEP) of the PSM. The two-dimensional PEP takes into account protein ranking information as well as PSM information.", false}, {MS_MS_Numpress_linear_prediction_compression, "MS:1002312", "MS-Numpress linear prediction compression", "Compression using MS-Numpress linear prediction compression.", false}, {MS_MS_Numpress_positive_integer_compression, "MS:1002313", "MS-Numpress positive integer compression", "Compression using MS-Numpress positive integer compression.", false}, {MS_MS_Numpress_short_logged_float_compression, "MS:1002314", "MS-Numpress short logged float compression", "Compression using MS-Numpress short logged float compression.", false}, {MS_consensus_result, "MS:1002315", "consensus result", "Indicates a consensus result from several search engine runs.", false}, {MS_ProteomeDiscoverer_Amanda_high_confidence_threshold, "MS:1002316", "ProteomeDiscoverer:Amanda:high confidence threshold", "Strict confidence probability score.", false}, {MS_ProteomeDiscoverer_Amanda_middle_confidence_threshold, "MS:1002317", "ProteomeDiscoverer:Amanda:middle confidence threshold", "Relaxed confidence probability score.", false}, {MS_ProteomeDiscoverer_automatic_workload, "MS:1002318", "ProteomeDiscoverer:automatic workload", "Flag indicating automatic estimation of the workload level.", false}, {MS_Amanda_AmandaScore, "MS:1002319", "Amanda:AmandaScore", "The Amanda score of the scoring function for a PSM.", false}, {MS_ProteomeDiscoverer_max_differential_modifications, "MS:1002320", "ProteomeDiscoverer:max differential modifications", "Maximum dynamic modifications per PSM.", false}, {MS_ProteomeDiscoverer_max_equal_modifications, "MS:1002321", "ProteomeDiscoverer:max equal modifications", "Maximum equal modifications per PSM.", false}, {MS_ProteomeDiscoverer_min_peptide_length, "MS:1002322", "ProteomeDiscoverer:min peptide length", "Minimum peptide length.", false}, {MS_ProteomeDiscoverer_max_peptide_length, "MS:1002323", "ProteomeDiscoverer:max peptide length", "Maximum peptide length.", false}, {MS_ProteomeDiscoverer_max_number_neutral_loss, "MS:1002324", "ProteomeDiscoverer:max number neutral loss", "Maximum number of same neutral losses.", false}, {MS_ProteomeDiscoverer_max_number_neutral_loss_modifications, "MS:1002325", "ProteomeDiscoverer:max number neutral loss modifications", "Max number of same neutral losses of modifications.", false}, {MS_ProteomeDiscoverer_use_flanking_ions, "MS:1002326", "ProteomeDiscoverer:use flanking ions", "Flag for usage of flanking ions.", false}, {MS_ProteomeDiscoverer_max_number_of_same_modifs, "MS:1002327", "ProteomeDiscoverer:max number of same modifs", "The maximum number of possible equal modifications per PSM.", false}, {MS_ProteomeDiscoverer_perform_deisotoping, "MS:1002328", "ProteomeDiscoverer:perform deisotoping", "Defines whether a simple deisotoping shall be performed.", false}, {MS_ProteomeDiscoverer_ion_settings, "MS:1002329", "ProteomeDiscoverer:ion settings", "Specifies the fragment ions and neutral losses that are calculated.", false}, {MS_ProteomeDiscoverer_3__Static_Modification_OBSOLETE, "MS:1002330", "ProteomeDiscoverer:3. Static Modification", "ProteomeDiscoverer's 3rd static post-translational modification (PTM) input parameter.", true}, {MS_ProteomeDiscoverer_5__Dynamic_Modification_OBSOLETE, "MS:1002331", "ProteomeDiscoverer:5. Dynamic Modification", "ProteomeDiscoverer's 5th dynamic post-translational modification (PTM) input parameter.", true}, {MS_lab_head, "MS:1002332", "lab head", "The scientist responsible for personnel, grants, and instrumentation in a functional laboratory group.", false}, {MS_conversion_software, "MS:1002333", "conversion software", "Computer software primarily designed to convert data represented in one format to another format, sometimes with minor data alterations in the process.", false}, {MS_ProCon, "MS:1002334", "ProCon", "Java software designed to convert one of several proteomics identification results formats into mzIdentML or PRIDE XML.", false}, {MS_PRIDE_Converter2, "MS:1002335", "PRIDE Converter2", "Java software designed to convert one of several proteomics identification results formats into PRIDE XML.", false}, {MS_Amanda, "MS:1002336", "Amanda", "Amanda scoring system for PSM identification.", false}, {MS_Andromeda, "MS:1002337", "Andromeda", "Andromeda is a peptide search engine.", false}, {MS_Andromeda_score, "MS:1002338", "Andromeda:score", "The probability based score of the Andromeda search engine.", false}, {MS_site_global_FDR, "MS:1002339", "site:global FDR", "Estimation of global false discovery rate of peptides with a post-translational modification.", false}, {MS_ProteomeXchange_project_tag, "MS:1002340", "ProteomeXchange project tag", "Tag that can be added to a ProteomeXchange dataset, to enable the grouping of datasets. One tag can be used for indicating that a given dataset is part of a bigger project, like e.g. the Human Proteome Project.", false}, {MS_second_pass_peptide_identification, "MS:1002341", "second-pass peptide identification", "A putative identified peptide found in a second-pass search of protein sequences selected from a first-pass search.", false}, {MS_MZmine, "MS:1002342", "MZmine", "A framework for differential analysis of mass spectrometry data.", false}, {MS_ion_stability_type_OBSOLETE, "MS:1002343", "ion stability type", "Stability type of the ion.", true}, {MS_Maltcms, "MS:1002344", "Maltcms", "Modular Application Toolkit for Chromatography Mass-Spectrometry is an application framework mainly for developers.", false}, {MS_PSM_level_result_details, "MS:1002345", "PSM-level result details", "Peptide spectrum match level information.", false}, {MS_protein_group_level_result_details, "MS:1002346", "protein group-level result details", "Protein group level information.", false}, {MS_PSM_level_identification_confidence_metric, "MS:1002347", "PSM-level identification confidence metric", "Identification confidence metric for a peptide spectrum match.", false}, {MS_protein_group_level_identification_confidence_metric, "MS:1002348", "protein group-level identification confidence metric", "Identification confidence metric for a protein group.", false}, {MS_value_greater_than_zero_but_less_than_or_equal_to_one, "MS:1002349", "value greater than zero but less than or equal to one", "Positive value range less than or equal to 1.", false}, {MS_PSM_level_global_FDR, "MS:1002350", "PSM-level global FDR", "Estimation of the global false discovery rate of peptide spectrum matches.", false}, {MS_PSM_level_local_FDR, "MS:1002351", "PSM-level local FDR", "Estimation of the local false discovery rate of peptide spectrum matches.", false}, {MS_PSM_level_p_value, "MS:1002352", "PSM-level p-value", "Estimation of the p-value for peptide spectrum matches.", false}, {MS_PSM_level_e_value, "MS:1002353", "PSM-level e-value", "Estimation of the e-value for peptide spectrum matches.", false}, {MS_PSM_level_q_value, "MS:1002354", "PSM-level q-value", "Estimation of the q-value for peptide spectrum matches.", false}, {MS_PSM_level_FDRScore, "MS:1002355", "PSM-level FDRScore", "FDRScore for peptide spectrum matches.", false}, {MS_PSM_level_combined_FDRScore, "MS:1002356", "PSM-level combined FDRScore", "Combined FDRScore for peptide spectrum matches specifically obtained for distinct combinations of single, pairs or triplets of search engines making a given PSM, used for integrating results from these distinct pools.", false}, {MS_PSM_level_probability, "MS:1002357", "PSM-level probability", "Probability that the reported peptide ion is truly responsible for some or all of the components of the specified mass spectrum.", false}, {MS_search_engine_specific_score_for_distinct_peptides, "MS:1002358", "search engine specific score for distinct peptides", "Search engine specific distinct peptide score.", false}, {MS_distinct_peptide_level_local_FDR, "MS:1002359", "distinct peptide-level local FDR", "Estimation of the local false discovery rate for distinct peptides once redundant identifications of the same peptide have been removed (id est multiple PSMs have been collapsed to one entry).", false}, {MS_distinct_peptide_level_FDRScore, "MS:1002360", "distinct peptide-level FDRScore", "FDRScore for distinct peptides once redundant identifications of the same peptide have been removed (id est multiple PSMs have been collapsed to one entry).", false}, {MS_distinct_peptide_level_combined_FDRScore, "MS:1002361", "distinct peptide-level combined FDRScore", "Combined FDRScore for peptides once redundant identifications of the same peptide have been removed (id est multiple PSMs have been collapsed to one entry) specifically obtained for distinct combinations of single, pairs or triplets of search engines making a given peptide, used for integrating results from these distinct pools.", false}, {MS_distinct_peptide_level_probability, "MS:1002362", "distinct peptide-level probability", "Probability that the reported distinct peptide sequence (irrespective of mass modifications) has been correctly identified via the referenced PSMs.", false}, {MS_search_engine_specific_score_for_proteins, "MS:1002363", "search engine specific score for proteins", "Search engine specific protein scores.", false}, {MS_protein_level_local_FDR, "MS:1002364", "protein-level local FDR", "Estimation of the local false discovery rate of proteins.", false}, {MS_FDRScore_for_proteins, "MS:1002365", "FDRScore for proteins", "FDRScore for proteins specifically obtained for distinct combinations of single, pairs or triplets of search engines making a given PSM, used for integrating results from these distinct pools.", false}, {MS_combined_FDRScore_for_proteins, "MS:1002366", "combined FDRScore for proteins", "Combined FDRScore for proteins.", false}, {MS_probability_for_proteins, "MS:1002367", "probability for proteins", "Probability that a specific protein sequence has been correctly identified from the PSM and distinct peptide evidence, and based on the available protein sequences presented to the analysis software.", false}, {MS_search_engine_specific_score_for_protein_groups, "MS:1002368", "search engine specific score for protein groups", "Search engine specific protein group scores.", false}, {MS_protein_group_level_global_FDR, "MS:1002369", "protein group-level global FDR", "Estimation of the global false discovery rate of protein groups.", false}, {MS_protein_group_level_local_FDR, "MS:1002370", "protein group-level local FDR", "Estimation of the local false discovery rate of protein groups.", false}, {MS_protein_group_level_p_value, "MS:1002371", "protein group-level p-value", "Estimation of the p-value for protein groups.", false}, {MS_protein_group_level_e_value, "MS:1002372", "protein group-level e-value", "Estimation of the e-value for protein groups.", false}, {MS_protein_group_level_q_value, "MS:1002373", "protein group-level q-value", "Estimation of the q-value for protein groups.", false}, {MS_protein_group_level_FDRScore, "MS:1002374", "protein group-level FDRScore", "FDRScore for protein groups.", false}, {MS_protein_group_level_combined_FDRScore, "MS:1002375", "protein group-level combined FDRScore", "Combined FDRScore for proteins specifically obtained for distinct combinations of single, pairs or triplets of search engines making a given PSM, used for integrating results from these distinct pools.", false}, {MS_protein_group_level_probability, "MS:1002376", "protein group-level probability", "Probability that at least one of the members of a group of protein sequences has been correctly identified from the PSM and distinct peptide evidence, and based on the available protein sequences presented to the analysis software.", false}, {MS_ProteomeDiscoverer_Relaxed_Score_Threshold, "MS:1002377", "ProteomeDiscoverer:Relaxed Score Threshold", "Specifies the threshold value for relaxed scoring.", false}, {MS_ProteomeDiscoverer_Strict_Score_Threshold, "MS:1002378", "ProteomeDiscoverer:Strict Score Threshold", "Specifies the threshold value for strict scoring.", false}, {MS_ProteomeDiscoverer_Peptide_Without_Protein_Cut_Off_Score, "MS:1002379", "ProteomeDiscoverer:Peptide Without Protein Cut Off Score", "Cut off score for storing peptides that do not belong to a protein.", false}, {MS_false_localization_rate, "MS:1002380", "false localization rate", "Estimation of the false localization rate for modification site assignment.", false}, {MS_MALDI_Solutions_LC_MALDI, "MS:1002381", "MALDI Solutions LC-MALDI", "Software for automated LC-MALDI analysis and reporting.", false}, {MS_Shimadzu_MALDI_7090, "MS:1002382", "Shimadzu MALDI-7090", "Shimadzu MALDI-7090: MALDI-TOF-TOF.", false}, {MS_SCiLS_software, "MS:1002383", "SCiLS software", "SCiLS software for data acquisition and analysis.", false}, {MS_SCiLS_Lab, "MS:1002384", "SCiLS Lab", "SCiLS Lab software.", false}, {MS_SCiLS_Lab_format, "MS:1002385", "SCiLS Lab format", "SCiLS Lab file format.", false}, {MS_preprocessing_software, "MS:1002386", "preprocessing software", "Preprocessing software.", false}, {MS_PIA, "MS:1002387", "PIA", "PIA - Protein Inference Algorithms, a toolbox for protein inference and identification analysis.", false}, {MS_PIA_XML_format, "MS:1002388", "PIA XML format", "A compilation of search engine results in the PIA XML format.", false}, {MS_PIA_workflow_parameter, "MS:1002389", "PIA workflow parameter", "A parameter set for a single PIA analysis.", false}, {MS_PIA_FDRScore_calculated, "MS:1002390", "PIA:FDRScore calculated", "Indicates whether the FDR score was calculated for the input file.", false}, {MS_PIA_Combined_FDRScore_calculated, "MS:1002391", "PIA:Combined FDRScore calculated", "Indicates whether the combined FDR score was calculated for the PIA compilation.", false}, {MS_PIA_PSM_sets_created, "MS:1002392", "PIA:PSM sets created", "Indicates whether PSM sets were created.", false}, {MS_PIA_used_top_identifications_for_FDR, "MS:1002393", "PIA:used top identifications for FDR", "The number of top identifications per spectrum used for the FDR calculation, 0 means all.", false}, {MS_PIA_protein_score, "MS:1002394", "PIA:protein score", "The score given to a protein by any protein inference.", false}, {MS_PIA_protein_inference, "MS:1002395", "PIA:protein inference", "The used algorithm for the protein inference using PIA.", false}, {MS_PIA_protein_inference_filter, "MS:1002396", "PIA:protein inference filter", "A filter used by PIA for the protein inference.", false}, {MS_PIA_protein_inference_scoring, "MS:1002397", "PIA:protein inference scoring", "The used scoring method for the protein inference using PIA.", false}, {MS_PIA_protein_inference_used_score, "MS:1002398", "PIA:protein inference used score", "The used base score for the protein inference using PIA.", false}, {MS_PIA_protein_inference_used_PSMs, "MS:1002399", "PIA:protein inference used PSMs", "The method to determine the PSMs used for scoring by the protein inference.", false}, {MS_PIA_filter, "MS:1002400", "PIA:filter", "A filter used for the report generation.", false}, {MS_leading_protein, "MS:1002401", "leading protein", "At least one protein within each group should be annotated as a leading protein to indicate it has the strongest evidence, or approximately equal evidence as other group members.", false}, {MS_non_leading_protein, "MS:1002402", "non-leading protein", "Zero to many proteins within each group should be annotated as non-leading to indicate that other proteins have stronger evidence.", false}, {MS_group_representative, "MS:1002403", "group representative", "An arbitrary and optional flag applied to exactly one protein per group to indicate it can serve as the representative of the group, amongst leading proteins, in effect serving as a tiebreaker for approaches that require exactly one group representative.", false}, {MS_count_of_identified_proteins, "MS:1002404", "count of identified proteins", "The number of proteins that have been identified, which must match the number of groups that pass the threshold in the file.", false}, {MS_protein_cluster_details, "MS:1002405", "protein cluster details", "Details describing a protein cluster.", false}, {MS_count_of_identified_clusters, "MS:1002406", "count of identified clusters", "The number of protein clusters that have been identified, which must match the number of clusters that pass the threshold in the file.", false}, {MS_cluster_identifier, "MS:1002407", "cluster identifier", "An identifier applied to protein groups to indicate that they are linked by shared peptides.", false}, {MS_number_of_distinct_protein_sequences, "MS:1002408", "number of distinct protein sequences", "The number of protein clusters that have been identified, which must match the number of clusters that pass the threshold in the file.", false}, {MS_marginally_distinguished_protein, "MS:1002409", "marginally distinguished protein", "Assigned to a non-leading protein that has some independent evidence to support its presence relative to the leading protein(s), e.g. the protein may have a unique peptide but not sufficient to be promoted as a leading protein of another group.", false}, {MS_Anubis, "MS:1002410", "Anubis", "Anubis software for selected reaction monitoring data.", false}, {MS_TraML_format, "MS:1002411", "TraML format", "The TraML format for transitions in SRM from the PSI. File extension '.TraML'.", false}, {MS_total_XIC_area, "MS:1002412", "total XIC area", "Summed area of all the extracted ion chromatogram for the peptide (e.g. of all the transitions in SRM).", false}, {MS_product_background, "MS:1002413", "product background", "The background area for the quantified transition.", false}, {MS_postprocessing_software, "MS:1002414", "postprocessing software", "Postprocessing software.", false}, {MS_protein_group_passes_threshold, "MS:1002415", "protein group passes threshold", "A Boolean attribute to determine whether the protein group has passed the threshold indicated in the file.", false}, {MS_Orbitrap_Fusion, "MS:1002416", "Orbitrap Fusion", "Thermo Scientific Orbitrap Fusion.", false}, {MS_Orbitrap_Fusion_ETD, "MS:1002417", "Orbitrap Fusion ETD", "Thermo Scientific Orbitrap Fusion with ETD.", false}, {MS_TSQ_Quantiva, "MS:1002418", "TSQ Quantiva", "Thermo Scientific TSQ Quantiva MS.", false}, {MS_TSQ_Endura, "MS:1002419", "TSQ Endura", "Thermo Scientific TSQ Endura MS.", false}, {MS_PASSEL_experiment_URI, "MS:1002420", "PASSEL experiment URI", "URI that allows access to a PASSEL experiment.", false}, {MS_Paragon_input_parameter, "MS:1002421", "Paragon input parameter", "Search engine input parameters specific to Paragon.", false}, {MS_Paragon__sample_type, "MS:1002422", "Paragon: sample type", "The Paragon method setting indicating the type of sample at the high level, generally meaning the type of quantitation labelling or lack thereof. 'Identification' is indicated for samples without any labels for quantitation.", false}, {MS_Paragon__cysteine_alkylation, "MS:1002423", "Paragon: cysteine alkylation", "The Paragon method setting indicating the actual cysteine alkylation agent; 'None' is indicated if there was no cysteine alkylation.", false}, {MS_Paragon__instrument_setting, "MS:1002424", "Paragon: instrument setting", "The Paragon method setting (translating to a large number of lower level settings) indicating the instrument used or a category of instrument.", false}, {MS_Paragon__search_effort, "MS:1002425", "Paragon: search effort", "The Paragon method setting that controls the two major modes of search effort of the Paragon algorithm: the Rapid mode uses a conventional database search, while the Thorough mode uses a hybrid search, starting with the same approach as the Rapid mode but then follows it with a separate tag-based approach enabling a more extensive search.", false}, {MS_Paragon__ID_focus, "MS:1002426", "Paragon: ID focus", "A Paragon method setting that allows the inclusion of large sets of features such as biological modification or substitutions.", false}, {MS_Paragon__FDR_analysis, "MS:1002427", "Paragon: FDR analysis", "The Paragon method setting that controls whether FDR analysis is conducted.", false}, {MS_Paragon__quantitation, "MS:1002428", "Paragon: quantitation", "The Paragon method setting that controls whether quantitation analysis is conducted.", false}, {MS_Paragon__background_correction, "MS:1002429", "Paragon: background correction", "The Paragon method setting that controls whether the 'Background Correction' analysis is conducted; this processing estimates a correction to the attenuation in extremity ratios that can occur in isobaric quantatitation workflows on complex samples.", false}, {MS_Paragon__bias_correction, "MS:1002430", "Paragon: bias correction", "The Paragon method setting that controls whether 'Bias Correction' is invoked in quantitation analysis; this correction is a normalization to set the central tendency of protein ratios to unity.", false}, {MS_Paragon__channel_to_use_as_denominator_in_ratios, "MS:1002431", "Paragon: channel to use as denominator in ratios", "The Paragon method setting that controls which label channel is used as the denominator in calculating relative expression ratios.", false}, {MS_search_engine_specific_input_metadata, "MS:1002432", "search engine specific input metadata", "Search engine specific metadata that are not user-controlled settings.", false}, {MS_Paragon__modified_data_dictionary_or_parameter_translation, "MS:1002433", "Paragon: modified data dictionary or parameter translation", "This metric detects if any changes have been made to the originally installed key control files for the software; if no changes have been made, then the software version and settings are sufficient to enable exact reproduction; if changes have been made, then the modified ParameterTranslation- and ProteinPilot DataDictionary-XML files much also be provided in order to exactly reproduce a result.", false}, {MS_number_of_spectra_searched, "MS:1002434", "number of spectra searched", "Number of spectra in a search.", false}, {MS_data_processing_start_time, "MS:1002435", "data processing start time", "The time that a data processing action was started.", false}, {MS_Paragon__digestion, "MS:1002436", "Paragon: digestion", "The Paragon method setting indicating the actual digestion agent - unlike other search tools, this setting does not include options that control partial specificity like 'semitrypsin'; if trypsin is used, trypsin is set, and partially conforming peptides are found in the Thorough mode of search; 'None' should be indicated only if there was really no digestion done.", false}, {MS_number_of_decoy_sequences, "MS:1002437", "number of decoy sequences", "The number of decoy sequences, if the concatenated target-decoy approach is used.", false}, {MS_spectrum_identification_list_result_details, "MS:1002438", "spectrum identification list result details", "Information about the list of PSMs (SpectrumIdentificationList).", false}, {MS_final_PSM_list, "MS:1002439", "final PSM list", "A flag on a list of PSMs (SpectrumIdentificationList) to indicate that this is the final set of identifications to be interpreted by consuming software. Amongst the set of SpectrumIdentificationList(s) that are flagged with the term, each spectrum must not be referenced from more than one SpectrumIdentificationResult.", false}, {MS_intermediate_PSM_list, "MS:1002440", "intermediate PSM list", "A flag on a list of PSMs (SpectrumIdentificationList) to indicate that this is not the final set of identifications to be interpreted by consuming software. This term should be used when results are provided from multiple search engines for the results from each search engine before they are combined to give consensus identifications. Amongst the set of SpectrumIdentificationList(s) that are flagged with the term, each spectrum may be referenced from more than one SpectrumIdentificationResult.", false}, {MS_Andi_MS_format, "MS:1002441", "Andi-MS format", "AIA Analytical Data Interchange file format for mass spectrometry data.", false}, {MS_chromatograph_file_format, "MS:1002442", "chromatograph file format", "The format of the chromatography file being used. This could be a instrument or vendor specific proprietary file format or a converted open file format.", false}, {MS_Andi_CHROM_format, "MS:1002443", "Andi-CHROM format", "AIA Analytical Data Interchange file format for chromatography data.", false}, {MS_6420_Triple_Quadrupole_LC_MS, "MS:1002444", "6420 Triple Quadrupole LC/MS", "The 6420 Quadrupole LC/MS system is a Agilent liquid chromatography instrument combined with a Agilent triple quadrupole mass spectrometer.", false}, {MS_6460_Triple_Quadrupole_LC_MS, "MS:1002445", "6460 Triple Quadrupole LC/MS", "The 6460 Quadrupole LC/MS system is a Agilent liquid chromatography instrument combined with a Agilent triple quadrupole mass spectrometer. It is similar to the 6420 but adds Agilent Jet Stream (AJS) technology to increase sensitivity.", false}, {MS_6490_Triple_Quadrupole_LC_MS, "MS:1002446", "6490 Triple Quadrupole LC/MS", "The 6490 Quadrupole LC/MS system is a Agilent liquid chromatography instrument combined with a Agilent triple quadrupole mass spectrometer. It is similar to the 6420 but adds the Agilent iFunnel technology to increase sensitivity.", false}, {MS_Paragon_special_factor, "MS:1002447", "Paragon:special factor", "The Paragon method setting indicating a list of one or more 'special factors', which generally capture secondary effects (relative to other settings) as a set of probabilities of modification features that override the assumed levels. For example the 'gel-based ID' special factor causes an increase probability of oxidation on several resides because of the air exposure impact on a gel, in addition to other effects.", false}, {MS_PEAKS_inChorusPeptideScore, "MS:1002448", "PEAKS:inChorusPeptideScore", "The PEAKS inChorus peptide score.", false}, {MS_PEAKS_inChorusProteinScore, "MS:1002449", "PEAKS:inChorusProteinScore", "The PEAKS inChorus protein score.", false}, {MS_param__b_ion_H3PO4_DEPRECATED, "MS:1002450", "param: b ion-H3PO4 DEPRECATED", "Ion b-H3PO4: b ion with lost phosphoric acid.", false}, {MS_param__y_ion_H3PO4_DEPRECATED, "MS:1002451", "param: y ion-H3PO4 DEPRECATED", "Ion y-H3PO4: y ion with lost phosphoric acid.", false}, {MS_Maui, "MS:1002452", "Maui", "The Maltcms Graphical User Interface.", false}, {MS_No_fixed_modifications_searched, "MS:1002453", "No fixed modifications searched", "No fixed modifications are included as a parameter for the search, and therefore they are not reported.", false}, {MS_No_variable_modifications_searched, "MS:1002454", "No variable modifications searched", "No variable modifications are included as a parameter for the search, and therefore they are not reported.", false}, {MS_H2O_neutral_loss, "MS:1002455", "H2O neutral loss", "Neutral loss of water.", false}, {MS_NH3_neutral_loss, "MS:1002456", "NH3 neutral loss", "Neutral loss of ammonia.", false}, {MS_H3PO4_neutral_loss, "MS:1002457", "H3PO4 neutral loss", "Neutral loss of phosphoric acid.", false}, {MS_PeptideShaker, "MS:1002458", "PeptideShaker", "PeptideShaker is a software for the interpretation of proteomics identification results.", false}, {MS_MS_Amanda_csv_format, "MS:1002459", "MS Amanda csv format", "MS Amanda csv output format.", false}, {MS_protein_group_level_global_FNR, "MS:1002460", "protein group-level global FNR", "Estimation of the global false negative rate of protein groups.", false}, {MS_protein_group_level_confidence, "MS:1002461", "protein group-level confidence", "Estimation of the global confidence of protein groups.", false}, {MS_distinct_peptide_level_global_FNR, "MS:1002462", "distinct peptide-level global FNR", "Estimation of the global false negative rate for distinct peptides once redundant identifications of the same peptide have been removed (id est multiple PSMs have been collapsed to one entry).", false}, {MS_distinct_peptide_level_global_confidence, "MS:1002463", "distinct peptide-level global confidence", "Estimation of the global confidence for distinct peptides once redundant identifications of the same peptide have been removed (id est multiple PSMs have been collapsed to one entry).", false}, {MS_PSM_level_global_FNR, "MS:1002464", "PSM-level global FNR", "Estimation of the global false negative rate of peptide spectrum matches.", false}, {MS_PSM_level_global_confidence, "MS:1002465", "PSM-level global confidence", "Estimation of the global confidence of peptide spectrum matches.", false}, {MS_PeptideShaker_PSM_score, "MS:1002466", "PeptideShaker PSM score", "The probability based PeptideShaker PSM score.", false}, {MS_PeptideShaker_PSM_confidence, "MS:1002467", "PeptideShaker PSM confidence", "The probability based PeptideShaker PSM confidence.", false}, {MS_PeptideShaker_peptide_score, "MS:1002468", "PeptideShaker peptide score", "The probability based PeptideShaker peptide score.", false}, {MS_PeptideShaker_peptide_confidence, "MS:1002469", "PeptideShaker peptide confidence", "The probability based PeptideShaker peptide confidence.", false}, {MS_PeptideShaker_protein_group_score, "MS:1002470", "PeptideShaker protein group score", "The probability based PeptideShaker protein group score.", false}, {MS_PeptideShaker_protein_group_confidence, "MS:1002471", "PeptideShaker protein group confidence", "The probability based PeptideShaker protein group confidence.", false}, {MS_trap_type_collision_induced_dissociation, "MS:1002472", "trap-type collision-induced dissociation", "A collision-induced dissociation process that occurs in a trap-type collision cell.", false}, {MS_ion_series_considered_in_search, "MS:1002473", "ion series considered in search", "The description of the ion fragment series (including charges and neutral losses) that are considered by the search engine.", false}, {MS_ProteoAnnotator_non_canonical_gene_model_score, "MS:1002474", "ProteoAnnotator:non-canonical gene model score", "The sum of peptide-level scores for peptides mapped only to non-canonical gene models within the group.", false}, {MS_ProteoAnnotator_count_alternative_peptides, "MS:1002475", "ProteoAnnotator:count alternative peptides", "The count of the number of peptide sequences mapped to non-canonical gene models only within the group.", false}, {MS_ion_mobility_drift_time, "MS:1002476", "ion mobility drift time", "Drift time of an ion or spectrum of ions as measured in an ion mobility mass spectrometer. This time might refer to the central value of a bin into which all ions within a narrow range of drift time have been aggregated.", false}, {MS_mean_drift_time_array, "MS:1002477", "mean drift time array", "Array of drift times, averaged from a matrix of binned m/z and drift time values, corresponding to spectrum of individual peaks encoded with an m/z array.", false}, {MS_mean_charge_array, "MS:1002478", "mean charge array", "Array of mean charge values where the mean charge is calculated as a weighted mean of the charges of individual peaks that are aggregated into a processed spectrum.", false}, {MS_regular_expression, "MS:1002479", "regular expression", "Regular expression.", false}, {MS_regular_expression_for_a_digital_object_identifier__DOI_, "MS:1002480", "regular expression for a digital object identifier (DOI)", "(10[.][0-9]\\{4,\\}(?:[.][0-9]+)*/(?:(?![\\\"&\\'<>])[^ \\t\\\\r\\n\\\\v\\\\f])+).", false}, {MS_higher_energy_beam_type_collision_induced_dissociation, "MS:1002481", "higher energy beam-type collision-induced dissociation", "A collision-induced dissociation process wherein the projectile ion has the translational energy higher than approximately 1000 eV.", false}, {MS_statistical_threshold, "MS:1002482", "statistical threshold", "Estimated statistical threshold.", false}, {MS_PSM_level_statistical_threshold, "MS:1002483", "PSM-level statistical threshold", "Estimated statistical threshold at PSM-level.", false}, {MS_peptide_level_statistical_threshold, "MS:1002484", "peptide-level statistical threshold", "Estimated statistical threshold at peptide-level.", false}, {MS_protein_level_statistical_threshold, "MS:1002485", "protein-level statistical threshold", "Estimated statistical threshold at protein-level.", false}, {MS_protein_group_level_statistical_threshold, "MS:1002486", "protein group-level statistical threshold", "Estimated statistical threshold at protein group-level.", false}, {MS_MassIVE_dataset_identifier, "MS:1002487", "MassIVE dataset identifier", "Dataset identifier issued by the MassIVE repository. A dataset can refer to either a single sample as part of a study, or all samples that are part of the study corresponding to a publication.", false}, {MS_MassIVE_dataset_URI, "MS:1002488", "MassIVE dataset URI", "URI that allows the access to one dataset in the MassIVE repository. A dataset can refer to either a single sample as part of a study, or all samples that are part of the study corresponding to a publication.", false}, {MS_special_processing, "MS:1002489", "special processing", "Details describing a special processing.", false}, {MS_peptide_level_scoring, "MS:1002490", "peptide-level scoring", "Peptide-level scoring performed.", false}, {MS_modification_localization_scoring, "MS:1002491", "modification localization scoring", "Modification localization scoring performed.", false}, {MS_consensus_scoring, "MS:1002492", "consensus scoring", "Consensus multiple search engine approach performed.", false}, {MS_sample_pre_fractionation, "MS:1002493", "sample pre-fractionation", "Sample pre-fractionation performed.", false}, {MS_cross_linking_search, "MS:1002494", "cross-linking search", "Cross-linking search performed.", false}, {MS_no_special_processing, "MS:1002495", "no special processing", "No special processing performed.", false}, {MS_group_PSMs_by_sequence, "MS:1002496", "group PSMs by sequence", "Group PSMs by distinct peptide sequence ignoring modifications.", false}, {MS_group_PSMs_by_sequence_with_modifications, "MS:1002497", "group PSMs by sequence with modifications", "Group PSMs by distinct peptide sequence with taking modifications into account.", false}, {MS_group_PSMs_by_sequence_with_modifications_and_charge, "MS:1002498", "group PSMs by sequence with modifications and charge", "Group PSMs by distinct peptide sequence with taking modifications and charge into account.", false}, {MS_peptide_level_score, "MS:1002499", "peptide level score", "Peptide level score.", false}, {MS_peptide_passes_threshold, "MS:1002500", "peptide passes threshold", "A Boolean attribute to determine whether the peptide has passed the threshold indicated in the file.", false}, {MS_no_PSM_threshold, "MS:1002501", "no PSM threshold", "Indicating that no PSM threshold was used.", false}, {MS_no_peptide_level_threshold, "MS:1002502", "no peptide-level threshold", "Indicating that no peptide-level threshold was used.", false}, {MS_PSM_is_used_for_peptide_level_scoring, "MS:1002503", "PSM is used for peptide-level scoring", "Flags a PSM that it is used for peptide-level scoring.", false}, {MS_modification_index, "MS:1002504", "modification index", "The order of modifications to be referenced elsewhere in the document.", false}, {MS_regular_expression_for_modification_localization_scoring, "MS:1002505", "regular expression for modification localization scoring", "([:digit:]+:[0|1]\\{1\\}.[:digit:]+:[:digit:]+[|]\\{1\\}[:digit:]+:(true|false)\\{1\\})", false}, {MS_modification_position_score, "MS:1002506", "modification position score", "Modification position score.", false}, {MS_modification_rescoring_false_localization_rate, "MS:1002507", "modification rescoring:false localization rate", "Mod position score: false localization rate.", false}, {MS_cross_linking_attribute, "MS:1002508", "cross-linking attribute", "Cross-linking attribute.", false}, {MS_cross_link_donor, "MS:1002509", "cross-link donor", "The Cross-linking donor, assigned according to the following rules: the export software SHOULD use the following rules to choose the cross-link donor as the: longer peptide, then higher peptide neutral mass, then alphabetical order.", false}, {MS_cross_link_receiver, "MS:1002510", "cross-link receiver", "Cross-linking receiver, assigned according to the following rules: the export software SHOULD use the following rules to choose the cross-link donor as the: longer peptide, then higher peptide neutral mass, then alphabetical order.", false}, {MS_cross_link_spectrum_identification_item, "MS:1002511", "cross-link spectrum identification item", "Cross-linked spectrum identification item.", false}, {MS_cross_linking_score, "MS:1002512", "cross-linking score", "Cross-linking scoring value.", false}, {MS_molecules_per_cell, "MS:1002513", "molecules per cell", "The absolute abundance of protein in a cell.", false}, {MS_absolute_quantitation_analysis, "MS:1002514", "absolute quantitation analysis", "Absolute quantitation analysis.", false}, {MS_internal_peptide_reference_used, "MS:1002515", "internal peptide reference used", "States whether an internal peptide reference is used or not in absolute quantitation analysis.", false}, {MS_internal_protein_reference_used, "MS:1002516", "internal protein reference used", "States whether an internal protein reference is used or not in absolute quantitation analysis.", false}, {MS_internal_reference_abundance, "MS:1002517", "internal reference abundance", "The absolute abundance of the spiked in reference peptide or protein used for absolute quantitation analysis.", false}, {MS_Progenesis_protein_group_normalised_abundance, "MS:1002518", "Progenesis:protein group normalised abundance", "The data type normalised abundance for protein groups produced by Progenesis LC-MS.", false}, {MS_Progenesis_protein_group_raw_abundance, "MS:1002519", "Progenesis:protein group raw abundance", "The data type raw abundance for protein groups produced by Progenesis LC-MS.", false}, {MS_peptide_group_ID, "MS:1002520", "peptide group ID", "Peptide group identifier for peptide-level stats.", false}, {MS_mass_spectrometry_imaging, "MS:1002521", "mass spectrometry imaging", "A technique in which mass spectra are acquired in a spatially resolved manner. This is typically achieved by scanning a laser or primary ion beam over a sample and acquiring a mass spectrum at each position.", false}, {MS_ProteomeDiscoverer_1__Static_Terminal_Modification, "MS:1002522", "ProteomeDiscoverer:1. Static Terminal Modification", "Determine 1st static terminal post-translational modifications (PTMs).", false}, {MS_Q_Exactive_HF, "MS:1002523", "Q Exactive HF", "Thermo Scientific Q Exactive.", false}, {MS_PepFinder, "MS:1002524", "PepFinder", "Thermo Scientific PepFinder BioPharma analysis software.", false}, {MS_TSQ_8000_Evo, "MS:1002525", "TSQ 8000 Evo", "Thermo Scientific TSQ 8000 Evo MS.", false}, {MS_Exactive_Plus, "MS:1002526", "Exactive Plus", "Thermo Scientific Exactive Plus MS.", false}, {MS_instrument_specific_scan_attribute, "MS:1002527", "instrument specific scan attribute", "Instrument specific scan properties that are associated with a value.", false}, {MS_synchronous_prefilter_selection, "MS:1002528", "synchronous prefilter selection", "Synchronous prefilter selection.", false}, {MS_resolution_array, "MS:1002529", "resolution array", "A data array of resolution values.", false}, {MS_baseline_array, "MS:1002530", "baseline array", "A data array of signal baseline values (the signal in the absence of analytes).", false}, {MS_UIMF_format, "MS:1002531", "UIMF format", "SQLite-based file format created at Pacific Northwest National Lab. It stores an intermediate analysis of ion-mobility mass spectrometry data.", false}, {MS_UIMF_nativeID_format, "MS:1002532", "UIMF nativeID format", "Native format defined by frame=xsd:nonNegativeInteger scan=xsd:nonNegativeInteger frameType=xsd:nonNegativeInteger.", false}, {MS_TripleTOF_6600, "MS:1002533", "TripleTOF 6600", "SCIEX TripleTOF 6600, a quadrupole - quadrupole - time-of-flight mass spectrometer.", false}, {MS_ProLuCID_xcorr, "MS:1002534", "ProLuCID:xcorr", "The ProLuCID result 'XCorr'.", false}, {MS_ProLuCID_deltacn, "MS:1002535", "ProLuCID:deltacn", "The ProLuCID result 'DeltaCn'.", false}, {MS_D_Score, "MS:1002536", "D-Score", "D-Score for PTM site location at the PSM-level.", false}, {MS_MD_Score, "MS:1002537", "MD-Score", "MD-Score for PTM site location at the PSM-level.", false}, {MS_PTM_localization_confidence_metric, "MS:1002538", "PTM localization confidence metric", "Localization confidence metric for a post translational modification (PTM).", false}, {MS_PeptideShaker_PTM_confidence_type, "MS:1002539", "PeptideShaker PTM confidence type", "PeptideShaker quality criteria for the confidence of PTM localizations.", false}, {MS_PeptideShaker_PSM_confidence_type, "MS:1002540", "PeptideShaker PSM confidence type", "PeptideShaker quality criteria for the confidence of PSM's.", false}, {MS_PeptideShaker_peptide_confidence_type, "MS:1002541", "PeptideShaker peptide confidence type", "PeptideShaker quality criteria for the confidence of peptide identifications.", false}, {MS_PeptideShaker_protein_confidence_type, "MS:1002542", "PeptideShaker protein confidence type", "PeptideShaker quality criteria for the confidence of protein identifications.", false}, {MS_xiFDR, "MS:1002543", "xiFDR", "Target/Decoy based FDR estimation for cross-linking peptide-identifications.", false}, {MS_xi, "MS:1002544", "xi", "Search engine for cross-linked peptides.", false}, {MS_xi_score, "MS:1002545", "xi:score", "The xi result 'Score'.", false}, {MS_Skyline_mzQuantML_converter, "MS:1002546", "Skyline mzQuantML converter", "A software package to convert Skyline report to mzQuantML.", false}, {MS_normalized_spectral_abundance_factor, "MS:1002547", "normalized spectral abundance factor", "A normalized spectral abundance factor (NSAF).", false}, {MS_distributed_normalized_spectral_abundance_factor, "MS:1002548", "distributed normalized spectral abundance factor", "A distributed normalized spectral abundance factor (dNSAF.", false}, {MS_peptide_level_PTM_localization_score, "MS:1002549", "peptide-level PTM localization score", "A score that assign confidence to the localization of an amino acid modification on a peptide sequence at the peptide-level.", false}, {MS_peptide_phosphoRS_score, "MS:1002550", "peptide:phosphoRS score", "phosphoRS score for PTM site location at the peptide-level.", false}, {MS_peptide_Ascore, "MS:1002551", "peptide:Ascore", "A-score for PTM site location at the peptide-level.", false}, {MS_peptide_H_Score, "MS:1002552", "peptide:H-Score", "H-Score for peptide phosphorylation site location at the peptide-level.", false}, {MS_peptide_D_Score, "MS:1002553", "peptide:D-Score", "D-Score for PTM site location at the peptide-level.", false}, {MS_peptide_MD_Score, "MS:1002554", "peptide:MD-Score", "MD-Score for PTM site location at the peptide-level.", false}, {MS_PTM_localization_score_threshold, "MS:1002555", "PTM localization score threshold", "Threshold for PTM site location score.", false}, {MS_Ascore_threshold, "MS:1002556", "Ascore threshold", "Threshold for Ascore PTM site location score.", false}, {MS_D_Score_threshold, "MS:1002557", "D-Score threshold", "Threshold for D-score PTM site location score.", false}, {MS_MD_Score_threshold, "MS:1002558", "MD-Score threshold", "Threshold for MD-score PTM site location score.", false}, {MS_H_Score_threshold, "MS:1002559", "H-Score threshold", "Threshold for H-score PTM site location score.", false}, {MS_Mascot_PTM_site_assignment_confidence_threshold, "MS:1002561", "Mascot:PTM site assignment confidence threshold", "Threshold for Mascot PTM site assignment confidence.", false}, {MS_MSQuant_PTM_score_threshold, "MS:1002562", "MSQuant:PTM-score threshold", "Threshold for MSQuant:PTM-score.", false}, {MS_MaxQuant_PTM_Score_threshold, "MS:1002563", "MaxQuant:PTM Score threshold", "Threshold for MaxQuant:PTM Score.", false}, {MS_MaxQuant_P_site_localization_probability_threshold, "MS:1002564", "MaxQuant:P-site localization probability threshold", "Threshold for MaxQuant:P-site localization probability.", false}, {MS_MaxQuant_PTM_Delta_Score_threshold, "MS:1002565", "MaxQuant:PTM Delta Score threshold", "Threshold for MaxQuant:PTM Delta Score.", false}, {MS_MaxQuant_Phospho__STY__Probabilities_threshold, "MS:1002566", "MaxQuant:Phospho (STY) Probabilities threshold", "Threshold for MaxQuant:Phospho (STY) Probabilities.", false}, {MS_phosphoRS_score_threshold, "MS:1002567", "phosphoRS score threshold", "Threshold for phosphoRS score.", false}, {MS_phosphoRS_site_probability_threshold, "MS:1002568", "phosphoRS site probability threshold", "Threshold for phosphoRS site probability.", false}, {MS_ProteomeDiscoverer_Number_of_Spectra_Processed_At_Once, "MS:1002569", "ProteomeDiscoverer:Number of Spectra Processed At Once", "Number of spectra processed at once in a ProteomeDiscoverer search.", false}, {MS_sequence_multiply_subsumable_protein, "MS:1002570", "sequence multiply subsumable protein", "A protein for which the matched peptide sequences are the same, or a subset of, the matched peptide sequences for two or more other proteins combined. These other proteins need not all be in the same group.", false}, {MS_spectrum_multiply_subsumable_protein, "MS:1002571", "spectrum multiply subsumable protein", "A protein for which the matched spectra are the same, or a subset of, the matched spectra for two or more other proteins combined. These other proteins need not all be in the same group.", false}, {MS_protein_detection_statistical_threshold, "MS:1002572", "protein detection statistical threshold", "Estimated statistical threshold used for protein detection.", false}, {MS_spectrum_identification_statistical_threshold, "MS:1002573", "spectrum identification statistical threshold", "Estimated statistical threshold used for spectrum identification.", false}, {MS_ASAPRatio, "MS:1002574", "ASAPRatio", "A program in the TPP that calculates PSM, peptide, and protein-level abundances based on 2-channel isotope-labelled data such as ICAT, SILAC, etc.", false}, {MS_Tide, "MS:1002575", "Tide", "Tide open-source sequence search program developed at the University of Washington.", false}, {MS_Andromeda_result_file, "MS:1002576", "Andromeda result file", "Andromeda result file output format.", false}, {MS_2000_QTRAP, "MS:1002577", "2000 QTRAP", "SCIEX 2000 QTRAP.", false}, {MS_2500_QTRAP, "MS:1002578", "2500 QTRAP", "SCIEX 2500 QTRAP.", false}, {MS_3500_QTRAP, "MS:1002579", "3500 QTRAP", "SCIEX 3500 QTRAP.", false}, {MS_QTRAP_4500, "MS:1002580", "QTRAP 4500", "SCIEX QTRAP 4500.", false}, {MS_QTRAP_6500, "MS:1002581", "QTRAP 6500", "SCIEX QTRAP 6500.", false}, {MS_QTRAP_6500_, "MS:1002582", "QTRAP 6500+", "SCIEX QTRAP 6500+.", false}, {MS_TripleTOF_4600, "MS:1002583", "TripleTOF 4600", "SCIEX TripleTOF 4600 time-of-flight mass spectrometer.", false}, {MS_TripleTOF_5600_, "MS:1002584", "TripleTOF 5600+", "SCIEX TripleTOF 5600+ time-of-flight mass spectrometer.", false}, {MS_API_100, "MS:1002585", "API 100", "Applied Biosystems/MDS SCIEX API 100 MS.", false}, {MS_API_100LC, "MS:1002586", "API 100LC", "Applied Biosystems/MDS SCIEX API 100LC MS.", false}, {MS_API_165, "MS:1002587", "API 165", "Applied Biosystems/MDS SCIEX API 165 MS.", false}, {MS_API_300, "MS:1002588", "API 300", "Applied Biosystems/MDS SCIEX API 300 MS.", false}, {MS_API_350, "MS:1002589", "API 350", "Applied Biosystems/MDS SCIEX API 350 MS.", false}, {MS_API_365, "MS:1002590", "API 365", "Applied Biosystems/MDS SCIEX API 365 MS.", false}, {MS_Triple_Quad_3500, "MS:1002591", "Triple Quad 3500", "SCIEX Triple Quad 3500.", false}, {MS_Triple_Quad_4500, "MS:1002592", "Triple Quad 4500", "SCIEX Triple Quad 4500.", false}, {MS_Triple_Quad_5500, "MS:1002593", "Triple Quad 5500", "SCIEX Triple Quad 5500.", false}, {MS_Triple_Quad_6500, "MS:1002594", "Triple Quad 6500", "SCIEX Triple Quad 6500.", false}, {MS_Triple_Quad_6500_, "MS:1002595", "Triple Quad 6500+", "SCIEX Triple Quad 6500+.", false}, {MS_DeBunker_score_threshold, "MS:10025560", "DeBunker:score threshold", "Threshold for DeBunker PTM site location score.", false}, {UNIMOD_unimod_root_node, "UNIMOD:0", "unimod root node", "The root node of the unimod modifications ontology.", false}, {UNIMOD_Acetyl, "UNIMOD:1", "Acetyl", "Acetylation.", false}, {UNIMOD_Amidated, "UNIMOD:2", "Amidated", "Amidation.", false}, {UNIMOD_Biotin, "UNIMOD:3", "Biotin", "Biotinylation.", false}, {UNIMOD_Carbamidomethyl, "UNIMOD:4", "Carbamidomethyl", "Iodoacetamide derivative.", false}, {UNIMOD_Carbamyl, "UNIMOD:5", "Carbamyl", "Carbamylation.", false}, {UNIMOD_Carboxymethyl, "UNIMOD:6", "Carboxymethyl", "Iodoacetic acid derivative.", false}, {UNIMOD_Deamidated, "UNIMOD:7", "Deamidated", "Deamidation.", false}, {UNIMOD_ICAT_G, "UNIMOD:8", "ICAT-G", "Gygi ICAT(TM) d0.", false}, {UNIMOD_ICAT_G_2H_8_, "UNIMOD:9", "ICAT-G:2H(8)", "Gygi ICAT(TM) d8.", false}, {UNIMOD_Met__Hse, "UNIMOD:10", "Met->Hse", "Homoserine.", false}, {UNIMOD_Met__Hsl, "UNIMOD:11", "Met->Hsl", "Homoserine lactone.", false}, {UNIMOD_ICAT_D_2H_8_, "UNIMOD:12", "ICAT-D:2H(8)", "Applied Biosystems original ICAT(TM) d8.", false}, {UNIMOD_ICAT_D, "UNIMOD:13", "ICAT-D", "Applied Biosystems original ICAT(TM) d0.", false}, {UNIMOD_NIPCAM, "UNIMOD:17", "NIPCAM", "N-isopropylcarboxamidomethyl.", false}, {UNIMOD_PEO_Iodoacetyl_LC_Biotin, "UNIMOD:20", "PEO-Iodoacetyl-LC-Biotin", "Biotinyl-iodoacetamidyl-3,6-dioxaoctanediamine.", false}, {UNIMOD_Phospho, "UNIMOD:21", "Phospho", "Phosphorylation.", false}, {UNIMOD_Dehydrated, "UNIMOD:23", "Dehydrated", "Dehydration.", false}, {UNIMOD_Propionamide, "UNIMOD:24", "Propionamide", "Acrylamide adduct.", false}, {UNIMOD_Pyridylacetyl, "UNIMOD:25", "Pyridylacetyl", "Pyridylacetyl.", false}, {UNIMOD_Pyro_carbamidomethyl, "UNIMOD:26", "Pyro-carbamidomethyl", "S-carbamoylmethylcysteine cyclization (N-terminus).", false}, {UNIMOD_Glu__pyro_Glu, "UNIMOD:27", "Glu->pyro-Glu", "Pyro-glu from E.", false}, {UNIMOD_Gln__pyro_Glu, "UNIMOD:28", "Gln->pyro-Glu", "Pyro-glu from Q.", false}, {UNIMOD_SMA, "UNIMOD:29", "SMA", "N-Succinimidyl-2-morpholine acetate.", false}, {UNIMOD_Cation_Na, "UNIMOD:30", "Cation:Na", "Sodium adduct.", false}, {UNIMOD_Pyridylethyl, "UNIMOD:31", "Pyridylethyl", "S-pyridylethylation.", false}, {UNIMOD_Methyl, "UNIMOD:34", "Methyl", "Methylation.", false}, {UNIMOD_Oxidation, "UNIMOD:35", "Oxidation", "Oxidation or Hydroxylation.", false}, {UNIMOD_Dimethyl, "UNIMOD:36", "Dimethyl", "Di-Methylation.", false}, {UNIMOD_Trimethyl, "UNIMOD:37", "Trimethyl", "Tri-Methylation.", false}, {UNIMOD_Methylthio, "UNIMOD:39", "Methylthio", "Beta-methylthiolation.", false}, {UNIMOD_Sulfo, "UNIMOD:40", "Sulfo", "O-Sulfonation.", false}, {UNIMOD_Hex, "UNIMOD:41", "Hex", "Hexose.", false}, {UNIMOD_Lipoyl, "UNIMOD:42", "Lipoyl", "Lipoyl.", false}, {UNIMOD_HexNAc, "UNIMOD:43", "HexNAc", "N-Acetylhexosamine.", false}, {UNIMOD_Farnesyl, "UNIMOD:44", "Farnesyl", "Farnesylation.", false}, {UNIMOD_Myristoyl, "UNIMOD:45", "Myristoyl", "Myristoylation.", false}, {UNIMOD_PyridoxalPhosphate, "UNIMOD:46", "PyridoxalPhosphate", "Pyridoxal phosphate.", false}, {UNIMOD_Palmitoyl, "UNIMOD:47", "Palmitoyl", "Palmitoylation.", false}, {UNIMOD_GeranylGeranyl, "UNIMOD:48", "GeranylGeranyl", "Geranyl-geranyl.", false}, {UNIMOD_Phosphopantetheine, "UNIMOD:49", "Phosphopantetheine", "Phosphopantetheine.", false}, {UNIMOD_FAD, "UNIMOD:50", "FAD", "Flavin adenine dinucleotide.", false}, {UNIMOD_Tripalmitate, "UNIMOD:51", "Tripalmitate", "N-acyl diglyceride cysteine.", false}, {UNIMOD_Guanidinyl, "UNIMOD:52", "Guanidinyl", "Guanidination.", false}, {UNIMOD_HNE, "UNIMOD:53", "HNE", "4-hydroxynonenal (HNE).", false}, {UNIMOD_Glucuronyl, "UNIMOD:54", "Glucuronyl", "Hexuronic acid.", false}, {UNIMOD_Glutathione, "UNIMOD:55", "Glutathione", "Glutathione disulfide.", false}, {UNIMOD_Acetyl_2H_3_, "UNIMOD:56", "Acetyl:2H(3)", "Acetate labeling reagent (N-term & K) (heavy form, +3amu).", false}, {UNIMOD_Propionyl, "UNIMOD:58", "Propionyl", "Propionate labeling reagent light form (N-term & K).", false}, {UNIMOD_Propionyl_13C_3_, "UNIMOD:59", "Propionyl:13C(3)", "Propionate labeling reagent heavy form (+3amu), N-term & K.", false}, {UNIMOD_GIST_Quat, "UNIMOD:60", "GIST-Quat", "Quaternary amine labeling reagent light form (N-term & K).", false}, {UNIMOD_GIST_Quat_2H_3_, "UNIMOD:61", "GIST-Quat:2H(3)", "Quaternary amine labeling reagent heavy (+3amu) form, N-term & K.", false}, {UNIMOD_GIST_Quat_2H_6_, "UNIMOD:62", "GIST-Quat:2H(6)", "Quaternary amine labeling reagent heavy form (+6amu), N-term & K.", false}, {UNIMOD_GIST_Quat_2H_9_, "UNIMOD:63", "GIST-Quat:2H(9)", "Quaternary amine labeling reagent heavy form (+9amu), N-term & K.", false}, {UNIMOD_Succinyl, "UNIMOD:64", "Succinyl", "Succinic anhydride labeling reagent light form (N-term & K).", false}, {UNIMOD_Succinyl_2H_4_, "UNIMOD:65", "Succinyl:2H(4)", "Succinic anhydride labeling reagent, heavy form (+4amu, 4H2), N-term & K.", false}, {UNIMOD_Succinyl_13C_4_, "UNIMOD:66", "Succinyl:13C(4)", "Succinic anhydride labeling reagent, heavy form (+4amu, 4C13), N-term & K.", false}, {UNIMOD_Iminobiotin, "UNIMOD:89", "Iminobiotin", "Iminobiotinylation.", false}, {UNIMOD_ESP, "UNIMOD:90", "ESP", "ESP-Tag light d0.", false}, {UNIMOD_ESP_2H_10_, "UNIMOD:91", "ESP:2H(10)", "ESP-Tag heavy d10.", false}, {UNIMOD_NHS_LC_Biotin, "UNIMOD:92", "NHS-LC-Biotin", "NHS-LC-Biotin.", false}, {UNIMOD_EDT_maleimide_PEO_biotin, "UNIMOD:93", "EDT-maleimide-PEO-biotin", "EDT-maleimide-PEO-biotin.", false}, {UNIMOD_IMID, "UNIMOD:94", "IMID", "IMID d0.", false}, {UNIMOD_IMID_2H_4_, "UNIMOD:95", "IMID:2H(4)", "IMID d4.", false}, {UNIMOD_Propionamide_2H_3_, "UNIMOD:97", "Propionamide:2H(3)", "Acrylamide d3.", false}, {UNIMOD_ICAT_C, "UNIMOD:105", "ICAT-C", "Applied Biosystems cleavable ICAT(TM) light.", false}, {UNIMOD_ICAT_C_13C_9_, "UNIMOD:106", "ICAT-C:13C(9)", "Applied Biosystems cleavable ICAT(TM) heavy.", false}, {UNIMOD_FormylMet, "UNIMOD:107", "FormylMet", "Addition of N-formyl met.", false}, {UNIMOD_Nethylmaleimide, "UNIMOD:108", "Nethylmaleimide", "N-ethylmaleimide on cysteines.", false}, {UNIMOD_OxLysBiotinRed, "UNIMOD:112", "OxLysBiotinRed", "Oxidized lysine biotinylated with biotin-LC-hydrazide, reduced.", false}, {UNIMOD_OxLysBiotin, "UNIMOD:113", "OxLysBiotin", "Oxidized lysine biotinylated with biotin-LC-hydrazide.", false}, {UNIMOD_OxProBiotinRed, "UNIMOD:114", "OxProBiotinRed", "Oxidized proline biotinylated with biotin-LC-hydrazide, reduced.", false}, {UNIMOD_OxProBiotin, "UNIMOD:115", "OxProBiotin", "Oxidized Proline biotinylated with biotin-LC-hydrazide.", false}, {UNIMOD_OxArgBiotin, "UNIMOD:116", "OxArgBiotin", "Oxidized arginine biotinylated with biotin-LC-hydrazide.", false}, {UNIMOD_OxArgBiotinRed, "UNIMOD:117", "OxArgBiotinRed", "Oxidized arginine biotinylated with biotin-LC-hydrazide, reduced.", false}, {UNIMOD_EDT_iodoacetyl_PEO_biotin, "UNIMOD:118", "EDT-iodoacetyl-PEO-biotin", "EDT-iodo-PEO-biotin.", false}, {UNIMOD_IBTP, "UNIMOD:119", "IBTP", "Thio Ether Formation - BTP Adduct.", false}, {UNIMOD_GG, "UNIMOD:121", "GG", "Ubiquitinylation residue.", false}, {UNIMOD_Formyl, "UNIMOD:122", "Formyl", "Formylation.", false}, {UNIMOD_ICAT_H, "UNIMOD:123", "ICAT-H", "N-iodoacetyl, p-chlorobenzyl-12C6-glucamine.", false}, {UNIMOD_ICAT_H_13C_6_, "UNIMOD:124", "ICAT-H:13C(6)", "N-iodoacetyl, p-chlorobenzyl-13C6-glucamine.", false}, {UNIMOD_Thioacyl, "UNIMOD:126", "Thioacyl", "3-sulfanylpropanoyl.", false}, {UNIMOD_Fluoro, "UNIMOD:127", "Fluoro", "Fluorination.", false}, {UNIMOD_Fluorescein, "UNIMOD:128", "Fluorescein", "5-Iodoacetamidofluorescein (Molecular Probe, Eugene, OR).", false}, {UNIMOD_Iodo, "UNIMOD:129", "Iodo", "Iodination.", false}, {UNIMOD_Diiodo, "UNIMOD:130", "Diiodo", "Di-Iodination.", false}, {UNIMOD_Triiodo, "UNIMOD:131", "Triiodo", "Tri-Iodination.", false}, {UNIMOD_Myristoleyl, "UNIMOD:134", "Myristoleyl", "(cis-delta 5)-tetradecaenoyl.", false}, {UNIMOD_Myristoyl_Delta_H__4_, "UNIMOD:135", "Myristoyl+Delta:H(-4)", "(cis,cis-delta 5, delta 8)-tetradecadienoyl.", false}, {UNIMOD_Benzoyl, "UNIMOD:136", "Benzoyl", "Labeling reagent light form (N-term & K).", false}, {UNIMOD_Hex_5_HexNAc_2_, "UNIMOD:137", "Hex(5)HexNAc(2)", "N-linked glycan core.", false}, {UNIMOD_Dansyl, "UNIMOD:139", "Dansyl", "5-dimethylaminonaphthalene-1-sulfonyl.", false}, {UNIMOD_a_type_ion, "UNIMOD:140", "a-type-ion", "ISD a-series (C-Term).", false}, {UNIMOD_Amidine, "UNIMOD:141", "Amidine", "Amidination of lysines or N-terminal amines with methyl acetimidate.", false}, {UNIMOD_HexNAc_1_dHex_1_, "UNIMOD:142", "HexNAc(1)dHex(1)", "HexNAc1dHex1.", false}, {UNIMOD_HexNAc_2_, "UNIMOD:143", "HexNAc(2)", "HexNAc2.", false}, {UNIMOD_Hex_3_, "UNIMOD:144", "Hex(3)", "Hex3.", false}, {UNIMOD_HexNAc_1_dHex_2_, "UNIMOD:145", "HexNAc(1)dHex(2)", "HexNAc1dHex2.", false}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_, "UNIMOD:146", "Hex(1)HexNAc(1)dHex(1)", "Hex1HexNAc1dHex1.", false}, {UNIMOD_HexNAc_2_dHex_1_, "UNIMOD:147", "HexNAc(2)dHex(1)", "HexNAc2dHex1.", false}, {UNIMOD_Hex_1_HexNAc_2_, "UNIMOD:148", "Hex(1)HexNAc(2)", "Hex1HexNAc2.", false}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_, "UNIMOD:149", "Hex(1)HexNAc(1)NeuAc(1)", "Hex1HexNAc1NeuAc1.", false}, {UNIMOD_HexNAc_2_dHex_2_, "UNIMOD:150", "HexNAc(2)dHex(2)", "HexNAc2dHex2.", false}, {UNIMOD_Hex_1_HexNAc_2_Pent_1_, "UNIMOD:151", "Hex(1)HexNAc(2)Pent(1)", "Hex1HexNAc2Pent1.", false}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_, "UNIMOD:152", "Hex(1)HexNAc(2)dHex(1)", "Hex1HexNAc2dHex1.", false}, {UNIMOD_Hex_2_HexNAc_2_, "UNIMOD:153", "Hex(2)HexNAc(2)", "Hex2HexNAc2.", false}, {UNIMOD_Hex_3_HexNAc_1_Pent_1_, "UNIMOD:154", "Hex(3)HexNAc(1)Pent(1)", "Hex3HexNAc1Pent1.", false}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_Pent_1_, "UNIMOD:155", "Hex(1)HexNAc(2)dHex(1)Pent(1)", "Hex1HexNAc2dHex1Pent1.", false}, {UNIMOD_Hex_1_HexNAc_2_dHex_2_, "UNIMOD:156", "Hex(1)HexNAc(2)dHex(2)", "Hex1HexNAc2dHex2.", false}, {UNIMOD_Hex_2_HexNAc_2_Pent_1_, "UNIMOD:157", "Hex(2)HexNAc(2)Pent(1)", "Hex2HexNAc2Pent1.", false}, {UNIMOD_Hex_2_HexNAc_2_dHex_1_, "UNIMOD:158", "Hex(2)HexNAc(2)dHex(1)", "Hex2HexNAc2dHex1.", false}, {UNIMOD_Hex_3_HexNAc_2_, "UNIMOD:159", "Hex(3)HexNAc(2)", "Hex3HexNAc2.", false}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_, "UNIMOD:160", "Hex(1)HexNAc(1)NeuAc(2)", "Hex1HexNAc1NeuAc2.", false}, {UNIMOD_Hex_3_HexNAc_2_Phos_1_, "UNIMOD:161", "Hex(3)HexNAc(2)Phos(1)", "Hex(3) HexNAc(2) Phos.", false}, {UNIMOD_Delta_S__1_Se_1_, "UNIMOD:162", "Delta:S(-1)Se(1)", "Selenium replaces sulfur.", false}, {UNIMOD_Delta_H_1_N__1_18O_1_, "UNIMOD:170", "Delta:H(1)N(-1)18O(1)", "Glycosylated asparagine 18O labeling.", false}, {UNIMOD_NBS_13C_6_, "UNIMOD:171", "NBS:13C(6)", "Shimadzu NBS-13C.", false}, {UNIMOD_NBS, "UNIMOD:172", "NBS", "Shimadzu NBS-12C.", false}, {UNIMOD_BHT, "UNIMOD:176", "BHT", "Michael addition of BHT quinone methide to Cysteine and Lysine.", false}, {UNIMOD_DAET, "UNIMOD:178", "DAET", "Phosphorylation to amine thiol.", false}, {UNIMOD_Label_13C_9_, "UNIMOD:184", "Label:13C(9)", "13C(9) Silac label.", false}, {UNIMOD_Label_13C_9__Phospho, "UNIMOD:185", "Label:13C(9)+Phospho", "C13 label (Phosphotyrosine).", false}, {UNIMOD_HPG, "UNIMOD:186", "HPG", "Hydroxyphenylglyoxal arginine.", false}, {UNIMOD_2HPG, "UNIMOD:187", "2HPG", "Bis(hydroxphenylglyoxal) arginine.", false}, {UNIMOD_Label_13C_6_, "UNIMOD:188", "Label:13C(6)", "13C(6) Silac label.", false}, {UNIMOD_Label_18O_2_, "UNIMOD:193", "Label:18O(2)", "O18 label at both C-terminal oxygens.", false}, {UNIMOD_AccQTag, "UNIMOD:194", "AccQTag", "6-aminoquinolyl-N-hydroxysuccinimidyl carbamate.", false}, {UNIMOD_QAT, "UNIMOD:195", "QAT", "APTA-d0.", false}, {UNIMOD_QAT_2H_3_, "UNIMOD:196", "QAT:2H(3)", "APTA d3.", false}, {UNIMOD_EQAT, "UNIMOD:197", "EQAT", "EAPTA d0.", false}, {UNIMOD_EQAT_2H_5_, "UNIMOD:198", "EQAT:2H(5)", "EAPTA d5.", false}, {UNIMOD_Dimethyl_2H_4_, "UNIMOD:199", "Dimethyl:2H(4)", "DiMethyl-CHD2.", false}, {UNIMOD_Ethanedithiol, "UNIMOD:200", "Ethanedithiol", "EDT.", false}, {UNIMOD_Delta_H_6_C_6_O_1_, "UNIMOD:205", "Delta:H(6)C(6)O(1)", "Acrolein addition +94.", false}, {UNIMOD_Delta_H_4_C_3_O_1_, "UNIMOD:206", "Delta:H(4)C(3)O(1)", "Acrolein addition +56.", false}, {UNIMOD_Delta_H_2_C_3_, "UNIMOD:207", "Delta:H(2)C(3)", "Acrolein addition +38.", false}, {UNIMOD_Delta_H_4_C_6_, "UNIMOD:208", "Delta:H(4)C(6)", "Acrolein addition +76.", false}, {UNIMOD_Delta_H_8_C_6_O_2_, "UNIMOD:209", "Delta:H(8)C(6)O(2)", "Acrolein addition +112.", false}, {UNIMOD_NEIAA, "UNIMOD:211", "NEIAA", "N-ethyl iodoacetamide-d0.", false}, {UNIMOD_NEIAA_2H_5_, "UNIMOD:212", "NEIAA:2H(5)", "N-ethyl iodoacetamide-d5.", false}, {UNIMOD_ADP_Ribosyl, "UNIMOD:213", "ADP-Ribosyl", "ADP Ribose addition.", false}, {UNIMOD_iTRAQ4plex, "UNIMOD:214", "iTRAQ4plex", "Representative mass and accurate mass for 116 & 117.", false}, {UNIMOD_IGBP, "UNIMOD:243", "IGBP", "Light IDBEST tag for quantitation.", false}, {UNIMOD_Crotonaldehyde, "UNIMOD:253", "Crotonaldehyde", "Crotonaldehyde.", false}, {UNIMOD_Delta_H_2_C_2_, "UNIMOD:254", "Delta:H(2)C(2)", "Acetaldehyde +26.", false}, {UNIMOD_Delta_H_4_C_2_, "UNIMOD:255", "Delta:H(4)C(2)", "Acetaldehyde +28.", false}, {UNIMOD_Delta_H_4_C_3_, "UNIMOD:256", "Delta:H(4)C(3)", "Propionaldehyde +40.", false}, {UNIMOD_Label_18O_1_, "UNIMOD:258", "Label:18O(1)", "O18 Labeling.", false}, {UNIMOD_Label_13C_6_15N_2_, "UNIMOD:259", "Label:13C(6)15N(2)", "13C(6) 15N(2) Silac label.", false}, {UNIMOD_Thiophospho, "UNIMOD:260", "Thiophospho", "Thiophosphorylation.", false}, {UNIMOD_SPITC, "UNIMOD:261", "SPITC", "4-sulfophenyl isothiocyanate.", false}, {UNIMOD_Label_2H_3_, "UNIMOD:262", "Label:2H(3)", "Trideuteration.", false}, {UNIMOD_PET, "UNIMOD:264", "PET", "Phosphorylation to pyridyl thiol.", false}, {UNIMOD_Label_13C_6_15N_4_, "UNIMOD:267", "Label:13C(6)15N(4)", "13C(6) 15N(4) Silac label.", false}, {UNIMOD_Label_13C_5_15N_1_, "UNIMOD:268", "Label:13C(5)15N(1)", "13C(5) 15N(1) Silac label.", false}, {UNIMOD_Label_13C_9_15N_1_, "UNIMOD:269", "Label:13C(9)15N(1)", "13C(9) 15N(1) Silac label.", false}, {UNIMOD_Cytopiloyne, "UNIMOD:270", "Cytopiloyne", "Nucleophilic addtion to cytopiloyne.", false}, {UNIMOD_Cytopiloyne_water, "UNIMOD:271", "Cytopiloyne+water", "Nucleophilic addition to cytopiloyne+H2O.", false}, {UNIMOD_CAF, "UNIMOD:272", "CAF", "Sulfonation of N-terminus.", false}, {UNIMOD_Xlink_SSD, "UNIMOD:273", "Xlink:SSD", "Covalent modification of lysine by cross-linking reagent.", false}, {UNIMOD_Nitrosyl, "UNIMOD:275", "Nitrosyl", "S-nitrosylation.", false}, {UNIMOD_AEBS, "UNIMOD:276", "AEBS", "Aminoethylbenzenesulfonylation.", false}, {UNIMOD_Ethanolyl, "UNIMOD:278", "Ethanolyl", "Ethanolation.", false}, {UNIMOD_Ethyl, "UNIMOD:280", "Ethyl", "Ethylation.", false}, {UNIMOD_CoenzymeA, "UNIMOD:281", "CoenzymeA", "Cysteine modified Coenzyme A.", false}, {UNIMOD_Methyl_2H_2_, "UNIMOD:284", "Methyl:2H(2)", "Deuterium Methylation of Lysine.", false}, {UNIMOD_SulfanilicAcid, "UNIMOD:285", "SulfanilicAcid", "Light Sulfanilic Acid (SA) C12.", false}, {UNIMOD_SulfanilicAcid_13C_6_, "UNIMOD:286", "SulfanilicAcid:13C(6)", "Heavy Sulfanilic Acid (SA) C13.", false}, {UNIMOD_Trp__Oxolactone, "UNIMOD:288", "Trp->Oxolactone", "Tryptophan oxidation to oxolactone.", false}, {UNIMOD_Biotin_PEO_Amine, "UNIMOD:289", "Biotin-PEO-Amine", "Biotin polyethyleneoxide amine.", false}, {UNIMOD_Biotin_HPDP, "UNIMOD:290", "Biotin-HPDP", "Pierce EZ-Link Biotin-HPDP.", false}, {UNIMOD_Delta_Hg_1_, "UNIMOD:291", "Delta:Hg(1)", "Mercury Mercaptan.", false}, {UNIMOD_IodoU_AMP, "UNIMOD:292", "IodoU-AMP", "Cross-link of (Iodo)-uracil MP with W,F,Y.", false}, {UNIMOD_CAMthiopropanoyl, "UNIMOD:293", "CAMthiopropanoyl", "3-(carbamidomethylthio)propanoyl.", false}, {UNIMOD_IED_Biotin, "UNIMOD:294", "IED-Biotin", "Biotinoyl-iodoacetyl-ethylenediamine.", false}, {UNIMOD_dHex, "UNIMOD:295", "dHex", "Fucose.", false}, {UNIMOD_Methyl_2H_3_, "UNIMOD:298", "Methyl:2H(3)", "Deuterated methyl ester.", false}, {UNIMOD_Carboxy, "UNIMOD:299", "Carboxy", "Carboxylation.", false}, {UNIMOD_Bromobimane, "UNIMOD:301", "Bromobimane", "Monobromobimane derivative.", false}, {UNIMOD_Menadione, "UNIMOD:302", "Menadione", "Menadione quinone derivative.", false}, {UNIMOD_DeStreak, "UNIMOD:303", "DeStreak", "Cysteine mercaptoethanol.", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_, "UNIMOD:305", "dHex(1)Hex(3)HexNAc(4)", "Fucosylated biantennary (-2 galactose).", false}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_, "UNIMOD:307", "dHex(1)Hex(4)HexNAc(4)", "Fucosylated biantennary (-1 galactose).", false}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_, "UNIMOD:308", "dHex(1)Hex(5)HexNAc(4)", "Fucosylated biantennary.", false}, {UNIMOD_Hex_3_HexNAc_4_, "UNIMOD:309", "Hex(3)HexNAc(4)", "Biantennary (-2 galactose).", false}, {UNIMOD_Hex_4_HexNAc_4_, "UNIMOD:310", "Hex(4)HexNAc(4)", "Biantennary (-1 galactose).", false}, {UNIMOD_Hex_5_HexNAc_4_, "UNIMOD:311", "Hex(5)HexNAc(4)", "Biantennary.", false}, {UNIMOD_Cysteinyl, "UNIMOD:312", "Cysteinyl", "Cysteinylation.", false}, {UNIMOD_Lys_loss, "UNIMOD:313", "Lys-loss", "Loss of C-terminal K from Heavy Chain of MAb.", false}, {UNIMOD_Nmethylmaleimide, "UNIMOD:314", "Nmethylmaleimide", "Nmethylmaleimide.", false}, {UNIMOD_DimethylpyrroleAdduct, "UNIMOD:316", "DimethylpyrroleAdduct", "2,5-dimethypyrrole.", false}, {UNIMOD_Delta_H_2_C_5_, "UNIMOD:318", "Delta:H(2)C(5)", "MDA adduct +62.", false}, {UNIMOD_Delta_H_2_C_3_O_1_, "UNIMOD:319", "Delta:H(2)C(3)O(1)", "MDA adduct +54.", false}, {UNIMOD_Nethylmaleimide_water, "UNIMOD:320", "Nethylmaleimide+water", "Nethylmaleimidehydrolysis.", false}, {UNIMOD_Xlink_B10621, "UNIMOD:323", "Xlink:B10621", "Bis-N-I-sulfonerahodamine.", false}, {UNIMOD_DTBP, "UNIMOD:324", "DTBP", "Dimethyl 3,3\\'-dithiobispropionimidate.", false}, {UNIMOD_FP_Biotin, "UNIMOD:325", "FP-Biotin", "10-ethoxyphosphinyl-N-(biotinamidopentyl)decanamide.", false}, {UNIMOD_Delta_H_4_C_2_O__1_S_1_, "UNIMOD:327", "Delta:H(4)C(2)O(-1)S(1)", "S-Ethylcystine from Serine.", false}, {UNIMOD_Methyl_2H_3_13C_1_, "UNIMOD:329", "Methyl:2H(3)13C(1)", "Monomethylation.", false}, {UNIMOD_Dimethyl_2H_6_13C_2_, "UNIMOD:330", "Dimethyl:2H(6)13C(2)", "Dimethylation.", false}, {UNIMOD_Thiophos_S_S_biotin, "UNIMOD:332", "Thiophos-S-S-biotin", "Thiophosphate labeled with biotin-HPDP.", false}, {UNIMOD_Can_FP_biotin, "UNIMOD:333", "Can-FP-biotin", "6-N-biotinylaminohexyl isopropyl phosphate.", false}, {UNIMOD_HNE_Delta_H_2_, "UNIMOD:335", "HNE+Delta:H(2)", "Reduced 4-Hydroxynonenal.", false}, {UNIMOD_Methylamine, "UNIMOD:337", "Methylamine", "Michael addition with methylamine.", false}, {UNIMOD_Bromo, "UNIMOD:340", "Bromo", "Bromination.", false}, {UNIMOD_Amino, "UNIMOD:342", "Amino", "Tyrosine oxidation to 2-aminotyrosine.", false}, {UNIMOD_Argbiotinhydrazide, "UNIMOD:343", "Argbiotinhydrazide", "Oxidized Arginine biotinylated with biotin hydrazide.", false}, {UNIMOD_Arg__GluSA, "UNIMOD:344", "Arg->GluSA", "Arginine oxidation to glutamic semialdehyde.", false}, {UNIMOD_Trioxidation, "UNIMOD:345", "Trioxidation", "Cysteine oxidation to cysteic acid.", false}, {UNIMOD_His__Asn, "UNIMOD:348", "His->Asn", "His->Asn substitution.", false}, {UNIMOD_His__Asp, "UNIMOD:349", "His->Asp", "His->Asp substitution.", false}, {UNIMOD_Trp__Hydroxykynurenin, "UNIMOD:350", "Trp->Hydroxykynurenin", "Tryptophan oxidation to hydroxykynurenin.", false}, {UNIMOD_Trp__Kynurenin, "UNIMOD:351", "Trp->Kynurenin", "Tryptophan oxidation to kynurenin.", false}, {UNIMOD_Lys__Allysine, "UNIMOD:352", "Lys->Allysine", "Lysine oxidation to aminoadipic semialdehyde.", false}, {UNIMOD_Lysbiotinhydrazide, "UNIMOD:353", "Lysbiotinhydrazide", "Oxidized Lysine biotinylated with biotin hydrazide.", false}, {UNIMOD_Nitro, "UNIMOD:354", "Nitro", "Oxidation to nitro.", false}, {UNIMOD_probiotinhydrazide, "UNIMOD:357", "probiotinhydrazide", "Oxidized proline biotinylated with biotin hydrazide.", false}, {UNIMOD_Pro__pyro_Glu, "UNIMOD:359", "Pro->pyro-Glu", "Proline oxidation to pyroglutamic acid.", false}, {UNIMOD_Pro__Pyrrolidinone, "UNIMOD:360", "Pro->Pyrrolidinone", "Proline oxidation to pyrrolidinone.", false}, {UNIMOD_Thrbiotinhydrazide, "UNIMOD:361", "Thrbiotinhydrazide", "Oxidized Threonine biotinylated with biotin hydrazide.", false}, {UNIMOD_Diisopropylphosphate, "UNIMOD:362", "Diisopropylphosphate", "O-Diisopropylphosphorylation.", false}, {UNIMOD_Isopropylphospho, "UNIMOD:363", "Isopropylphospho", "O-Isopropylphosphorylation.", false}, {UNIMOD_ICPL_13C_6_, "UNIMOD:364", "ICPL:13C(6)", "Bruker Daltonics SERVA-ICPL(TM) quantification chemistry, heavy form.", false}, {UNIMOD_ICPL, "UNIMOD:365", "ICPL", "Bruker Daltonics SERVA-ICPL(TM) quantification chemistry, light form.", false}, {UNIMOD_Deamidated_18O_1_, "UNIMOD:366", "Deamidated:18O(1)", "Deamidation in presence of O18.", false}, {UNIMOD_Cys__Dha, "UNIMOD:368", "Cys->Dha", "Dehydroalanine (from Cysteine).", false}, {UNIMOD_Pro__Pyrrolidone, "UNIMOD:369", "Pro->Pyrrolidone", "Pyrrolidone from Proline.", false}, {UNIMOD_HMVK, "UNIMOD:371", "HMVK", "Michael addition of hydroxymethylvinyl ketone to cysteine.", false}, {UNIMOD_Arg__Orn, "UNIMOD:372", "Arg->Orn", "Ornithine from Arginine.", false}, {UNIMOD_Dehydro, "UNIMOD:374", "Dehydro", "Half of a disulfide bridge.", false}, {UNIMOD_Diphthamide, "UNIMOD:375", "Diphthamide", "Diphthamide.", false}, {UNIMOD_Hydroxyfarnesyl, "UNIMOD:376", "Hydroxyfarnesyl", "Hydroxyfarnesyl.", false}, {UNIMOD_Diacylglycerol, "UNIMOD:377", "Diacylglycerol", "Diacylglycerol.", false}, {UNIMOD_Carboxyethyl, "UNIMOD:378", "Carboxyethyl", "Carboxyethyl.", false}, {UNIMOD_Hypusine, "UNIMOD:379", "Hypusine", "Hypusine.", false}, {UNIMOD_Retinylidene, "UNIMOD:380", "Retinylidene", "Retinal.", false}, {UNIMOD_Lys__AminoadipicAcid, "UNIMOD:381", "Lys->AminoadipicAcid", "Alpha-amino adipic acid.", false}, {UNIMOD_Cys__PyruvicAcid, "UNIMOD:382", "Cys->PyruvicAcid", "Pyruvic acid from N-term cys.", false}, {UNIMOD_Ammonia_loss, "UNIMOD:385", "Ammonia-loss", "Loss of ammonia.", false}, {UNIMOD_Phycocyanobilin, "UNIMOD:387", "Phycocyanobilin", "Phycocyanobilin.", false}, {UNIMOD_Phycoerythrobilin, "UNIMOD:388", "Phycoerythrobilin", "Phycoerythrobilin.", false}, {UNIMOD_Phytochromobilin, "UNIMOD:389", "Phytochromobilin", "Phytochromobilin.", false}, {UNIMOD_Heme, "UNIMOD:390", "Heme", "Heme.", false}, {UNIMOD_Molybdopterin, "UNIMOD:391", "Molybdopterin", "Molybdopterin.", false}, {UNIMOD_Quinone, "UNIMOD:392", "Quinone", "Quinone.", false}, {UNIMOD_Glucosylgalactosyl, "UNIMOD:393", "Glucosylgalactosyl", "Glucosylgalactosyl hydroxylysine.", false}, {UNIMOD_GPIanchor, "UNIMOD:394", "GPIanchor", "Glycosylphosphatidylinositol.", false}, {UNIMOD_PhosphoribosyldephosphoCoA, "UNIMOD:395", "PhosphoribosyldephosphoCoA", "Phosphoribosyl dephospho-coenzyme A.", false}, {UNIMOD_GlycerylPE, "UNIMOD:396", "GlycerylPE", "Glycerylphosphorylethanolamine.", false}, {UNIMOD_Triiodothyronine, "UNIMOD:397", "Triiodothyronine", "Triiodo.", false}, {UNIMOD_Thyroxine, "UNIMOD:398", "Thyroxine", "Tetraiodo.", false}, {UNIMOD_Tyr__Dha, "UNIMOD:400", "Tyr->Dha", "Dehydroalanine (from Tyrosine).", false}, {UNIMOD_Didehydro, "UNIMOD:401", "Didehydro", "2-amino-3-oxo-butanoic_acid.", false}, {UNIMOD_Cys__Oxoalanine, "UNIMOD:402", "Cys->Oxoalanine", "Oxoalanine.", false}, {UNIMOD_Ser__LacticAcid, "UNIMOD:403", "Ser->LacticAcid", "Lactic acid from N-term Ser.", false}, {UNIMOD_Phosphoadenosine, "UNIMOD:405", "Phosphoadenosine", "AMP.", false}, {UNIMOD_Hydroxycinnamyl, "UNIMOD:407", "Hydroxycinnamyl", "Hydroxycinnamyl.", false}, {UNIMOD_Glycosyl, "UNIMOD:408", "Glycosyl", "Glycosyl-L-hydroxyproline.", false}, {UNIMOD_FMNH, "UNIMOD:409", "FMNH", "Flavin mononucleotide.", false}, {UNIMOD_Archaeol, "UNIMOD:410", "Archaeol", "S-diphytanylglycerol diether.", false}, {UNIMOD_Phenylisocyanate, "UNIMOD:411", "Phenylisocyanate", "Phenyl isocyanate.", false}, {UNIMOD_Phenylisocyanate_2H_5_, "UNIMOD:412", "Phenylisocyanate:2H(5)", "D5-phenyl isocyanate.", false}, {UNIMOD_Phosphoguanosine, "UNIMOD:413", "Phosphoguanosine", "Phospho-guanosine.", false}, {UNIMOD_Hydroxymethyl, "UNIMOD:414", "Hydroxymethyl", "Hydroxymethyl.", false}, {UNIMOD_MolybdopterinGD_Delta_S__1_Se_1_, "UNIMOD:415", "MolybdopterinGD+Delta:S(-1)Se(1)", "L-selenocysteinyl molybdenum bis(molybdopterin guanine dinucleotide).", false}, {UNIMOD_Dipyrrolylmethanemethyl, "UNIMOD:416", "Dipyrrolylmethanemethyl", "Dipyrrolylmethanemethyl.", false}, {UNIMOD_PhosphoUridine, "UNIMOD:417", "PhosphoUridine", "Uridine phosphodiester.", false}, {UNIMOD_Glycerophospho, "UNIMOD:419", "Glycerophospho", "Glycerophospho.", false}, {UNIMOD_Carboxy__Thiocarboxy, "UNIMOD:420", "Carboxy->Thiocarboxy", "Thiocarboxylic acid.", false}, {UNIMOD_Sulfide, "UNIMOD:421", "Sulfide", "Persulfide.", false}, {UNIMOD_PyruvicAcidIminyl, "UNIMOD:422", "PyruvicAcidIminyl", "N-pyruvic acid 2-iminyl.", false}, {UNIMOD_Delta_Se_1_, "UNIMOD:423", "Delta:Se(1)", "Selenyl.", false}, {UNIMOD_MolybdopterinGD, "UNIMOD:424", "MolybdopterinGD", "Molybdenum bis(molybdopterin guanine dinucleotide).", false}, {UNIMOD_Dioxidation, "UNIMOD:425", "Dioxidation", "Dihydroxy.", false}, {UNIMOD_Octanoyl, "UNIMOD:426", "Octanoyl", "Octanoyl.", false}, {UNIMOD_PhosphoHexNAc, "UNIMOD:428", "PhosphoHexNAc", "N-acetylglucosamine-1-phosphoryl.", false}, {UNIMOD_PhosphoHex, "UNIMOD:429", "PhosphoHex", "Phosphoglycosyl-D-mannose-1-phosphoryl.", false}, {UNIMOD_Palmitoleyl, "UNIMOD:431", "Palmitoleyl", "Palmitoleyl.", false}, {UNIMOD_Cholesterol, "UNIMOD:432", "Cholesterol", "Cholesterol ester.", false}, {UNIMOD_Didehydroretinylidene, "UNIMOD:433", "Didehydroretinylidene", "3,4-didehydroretinylidene.", false}, {UNIMOD_CHDH, "UNIMOD:434", "CHDH", "Cis-14-hydroxy-10,13-dioxo-7-heptadecenoic ester.", false}, {UNIMOD_Methylpyrroline, "UNIMOD:435", "Methylpyrroline", "4-methyl-delta-1-pyrroline-5-carboxyl.", false}, {UNIMOD_Hydroxyheme, "UNIMOD:436", "Hydroxyheme", "Hydroxyheme.", false}, {UNIMOD_MicrocinC7, "UNIMOD:437", "MicrocinC7", "(3-aminopropyl)(L-aspartyl-1-amino)phosphoryl-5-adenosine.", false}, {UNIMOD_Cyano, "UNIMOD:438", "Cyano", "Cyano.", false}, {UNIMOD_Diironsubcluster, "UNIMOD:439", "Diironsubcluster", "Hydrogenase diiron subcluster.", false}, {UNIMOD_Amidino, "UNIMOD:440", "Amidino", "Amidino.", false}, {UNIMOD_FMN, "UNIMOD:442", "FMN", "O3-(riboflavin phosphoryl).", false}, {UNIMOD_FMNC, "UNIMOD:443", "FMNC", "S-(4a-FMN).", false}, {UNIMOD_CuSMo, "UNIMOD:444", "CuSMo", "Copper sulfido molybdopterin cytosine dinuncleotide.", false}, {UNIMOD_Hydroxytrimethyl, "UNIMOD:445", "Hydroxytrimethyl", "5-hydroxy-N6,N6,N6-trimethyl.", false}, {UNIMOD_Deoxy, "UNIMOD:447", "Deoxy", "Reduction.", false}, {UNIMOD_Microcin, "UNIMOD:448", "Microcin", "Microcin E492 siderophore ester from serine.", false}, {UNIMOD_Decanoyl, "UNIMOD:449", "Decanoyl", "Lipid.", false}, {UNIMOD_Glu, "UNIMOD:450", "Glu", "Monoglutamyl.", false}, {UNIMOD_GluGlu, "UNIMOD:451", "GluGlu", "Diglutamyl.", false}, {UNIMOD_GluGluGlu, "UNIMOD:452", "GluGluGlu", "Triglutamyl.", false}, {UNIMOD_GluGluGluGlu, "UNIMOD:453", "GluGluGluGlu", "Tetraglutamyl.", false}, {UNIMOD_HexN, "UNIMOD:454", "HexN", "Hexosamine.", false}, {UNIMOD_Xlink_DMP_s, "UNIMOD:455", "Xlink:DMP-s", "One end of crosslink attached, one end free.", false}, {UNIMOD_Xlink_DMP, "UNIMOD:456", "Xlink:DMP", "Both ends of crosslink attached to same peptide.", false}, {UNIMOD_NDA, "UNIMOD:457", "NDA", "Naphthalene-2,3-dicarboxaldehyde.", false}, {UNIMOD_SPITC_13C_6_, "UNIMOD:464", "SPITC:13C(6)", "4-sulfophenyl isothiocyanate (Heavy C13).", false}, {UNIMOD_AEC_MAEC, "UNIMOD:472", "AEC-MAEC", "Aminoethylcysteine.", false}, {UNIMOD_TMAB, "UNIMOD:476", "TMAB", "4-trimethyllammoniumbutyryl-.", false}, {UNIMOD_TMAB_2H_9_, "UNIMOD:477", "TMAB:2H(9)", "D9-4-trimethyllammoniumbutyryl-.", false}, {UNIMOD_FTC, "UNIMOD:478", "FTC", "Fluorescein-5-thiosemicarbazide.", false}, {UNIMOD_Label_2H_4_, "UNIMOD:481", "Label:2H(4)", "4,4,5,5-D4 Lysine.", false}, {UNIMOD_DHP, "UNIMOD:488", "DHP", "Dehydropyrrolizidine alkaloid (dehydroretronecine) on cysteines.", false}, {UNIMOD_Hep, "UNIMOD:490", "Hep", "Heptose.", false}, {UNIMOD_BADGE, "UNIMOD:493", "BADGE", "Bisphenol A diglycidyl ether derivative.", false}, {UNIMOD_CyDye_Cy3, "UNIMOD:494", "CyDye-Cy3", "Cy3 CyDye DIGE Fluor saturation dye.", false}, {UNIMOD_CyDye_Cy5, "UNIMOD:495", "CyDye-Cy5", "Cy5 CyDye DIGE Fluor saturation dye.", false}, {UNIMOD_BHTOH, "UNIMOD:498", "BHTOH", "Michael addition of t-butyl hydroxylated BHT (BHTOH) to C, H or K.", false}, {UNIMOD_IGBP_13C_2_, "UNIMOD:499", "IGBP:13C(2)", "Heavy IDBEST tag for quantitation.", false}, {UNIMOD_Nmethylmaleimide_water, "UNIMOD:500", "Nmethylmaleimide+water", "Nmethylmaleimidehydrolysis.", false}, {UNIMOD_PyMIC, "UNIMOD:501", "PyMIC", "3-methyl-2-pyridyl isocyanate.", false}, {UNIMOD_LG_lactam_K, "UNIMOD:503", "LG-lactam-K", "Levuglandinyl - lysine lactam adduct.", false}, {UNIMOD_LG_Hlactam_K, "UNIMOD:504", "LG-Hlactam-K", "Levuglandinyl - lysine hydroxylactam adduct.", false}, {UNIMOD_LG_lactam_R, "UNIMOD:505", "LG-lactam-R", "Levuglandinyl - arginine lactam adduct.", false}, {UNIMOD_LG_Hlactam_R, "UNIMOD:506", "LG-Hlactam-R", "Levuglandinyl - arginine hydroxylactam adduct.", false}, {UNIMOD_Dimethyl_2H_4_13C_2_, "UNIMOD:510", "Dimethyl:2H(4)13C(2)", "DiMethyl-C13HD2.", false}, {UNIMOD_Hex_2_, "UNIMOD:512", "Hex(2)", "Lactosylation.", false}, {UNIMOD_C8_QAT, "UNIMOD:513", "C8-QAT", "[3-(2,5)-Dioxopyrrolidin-1-yloxycarbonyl)-propyl]dimethyloctylammonium.", false}, {UNIMOD_PropylNAGthiazoline, "UNIMOD:514", "PropylNAGthiazoline", "Propyl-1,2-dideoxy-2\\'-methyl-alpha-D-glucopyranoso-[2,1-d]-Delta2\\'-thiazoline.", false}, {UNIMOD_FNEM, "UNIMOD:515", "FNEM", "Fluorescein-5-maleimide.", false}, {UNIMOD_Diethyl, "UNIMOD:518", "Diethyl", "Diethylation, analogous to Dimethylation.", false}, {UNIMOD_BisANS, "UNIMOD:519", "BisANS", "4,4\\'-dianilino-1,1\\'-binaphthyl-5,5\\'-disulfonic acid.", false}, {UNIMOD_Piperidine, "UNIMOD:520", "Piperidine", "Piperidination.", false}, {UNIMOD_Maleimide_PEO2_Biotin, "UNIMOD:522", "Maleimide-PEO2-Biotin", "Maleimide-Biotin.", false}, {UNIMOD_Sulfo_NHS_LC_LC_Biotin, "UNIMOD:523", "Sulfo-NHS-LC-LC-Biotin", "Biot_LC_LC.", false}, {UNIMOD_CLIP_TRAQ_2, "UNIMOD:525", "CLIP_TRAQ_2", "CLIP_TRAQ_2.", false}, {UNIMOD_Dethiomethyl, "UNIMOD:526", "Dethiomethyl", "Prompt loss of side chain from oxidised Met.", false}, {UNIMOD_Methyl_Deamidated, "UNIMOD:528", "Methyl+Deamidated", "Deamidation followed by a methylation.", false}, {UNIMOD_Delta_H_5_C_2_, "UNIMOD:529", "Delta:H(5)C(2)", "Dimethylation of proline residue.", false}, {UNIMOD_Cation_K, "UNIMOD:530", "Cation:K", "Replacement of proton by potassium.", false}, {UNIMOD_Cation_Cu_I_, "UNIMOD:531", "Cation:Cu[I]", "Replacement of proton by copper.", false}, {UNIMOD_iTRAQ4plex114, "UNIMOD:532", "iTRAQ4plex114", "Accurate mass for 114.", false}, {UNIMOD_iTRAQ4plex115, "UNIMOD:533", "iTRAQ4plex115", "Accurate mass for 115.", false}, {UNIMOD_Dibromo, "UNIMOD:534", "Dibromo", "Dibromo.", false}, {UNIMOD_LRGG, "UNIMOD:535", "LRGG", "Ubiquitination.", false}, {UNIMOD_CLIP_TRAQ_3, "UNIMOD:536", "CLIP_TRAQ_3", "CLIP_TRAQ_3.", false}, {UNIMOD_CLIP_TRAQ_4, "UNIMOD:537", "CLIP_TRAQ_4", "CLIP_TRAQ_4.", false}, {UNIMOD_Biotin_Cayman_10141, "UNIMOD:538", "Biotin:Cayman-10141", "Was 15dB-biotin.", false}, {UNIMOD_Biotin_Cayman_10013, "UNIMOD:539", "Biotin:Cayman-10013", "Was PGA1-biotin.", false}, {UNIMOD_Ala__Ser, "UNIMOD:540", "Ala->Ser", "Ala->Ser substitution.", false}, {UNIMOD_Ala__Thr, "UNIMOD:541", "Ala->Thr", "Ala->Thr substitution.", false}, {UNIMOD_Ala__Asp, "UNIMOD:542", "Ala->Asp", "Ala->Asp substitution.", false}, {UNIMOD_Ala__Pro, "UNIMOD:543", "Ala->Pro", "Ala->Pro substitution.", false}, {UNIMOD_Ala__Gly, "UNIMOD:544", "Ala->Gly", "Ala->Gly substitution.", false}, {UNIMOD_Ala__Glu, "UNIMOD:545", "Ala->Glu", "Ala->Glu substitution.", false}, {UNIMOD_Ala__Val, "UNIMOD:546", "Ala->Val", "Ala->Val substitution.", false}, {UNIMOD_Cys__Phe, "UNIMOD:547", "Cys->Phe", "Cys->Phe substitution.", false}, {UNIMOD_Cys__Ser, "UNIMOD:548", "Cys->Ser", "Cys->Ser substitution.", false}, {UNIMOD_Cys__Trp, "UNIMOD:549", "Cys->Trp", "Cys->Trp substitution.", false}, {UNIMOD_Cys__Tyr, "UNIMOD:550", "Cys->Tyr", "Cys->Tyr substitution.", false}, {UNIMOD_Cys__Arg, "UNIMOD:551", "Cys->Arg", "Cys->Arg substitution.", false}, {UNIMOD_Cys__Gly, "UNIMOD:552", "Cys->Gly", "Cys->Gly substitution.", false}, {UNIMOD_Asp__Ala, "UNIMOD:553", "Asp->Ala", "Asp->Ala substitution.", false}, {UNIMOD_Asp__His, "UNIMOD:554", "Asp->His", "Asp->His substitution.", false}, {UNIMOD_Asp__Asn, "UNIMOD:555", "Asp->Asn", "Asp->Asn substitution.", false}, {UNIMOD_Asp__Gly, "UNIMOD:556", "Asp->Gly", "Asp->Gly substitution.", false}, {UNIMOD_Asp__Tyr, "UNIMOD:557", "Asp->Tyr", "Asp->Tyr substitution.", false}, {UNIMOD_Asp__Glu, "UNIMOD:558", "Asp->Glu", "Asp->Glu substitution.", false}, {UNIMOD_Asp__Val, "UNIMOD:559", "Asp->Val", "Asp->Val substitution.", false}, {UNIMOD_Glu__Ala, "UNIMOD:560", "Glu->Ala", "Glu->Ala substitution.", false}, {UNIMOD_Glu__Gln, "UNIMOD:561", "Glu->Gln", "Glu->Gln substitution.", false}, {UNIMOD_Glu__Asp, "UNIMOD:562", "Glu->Asp", "Glu->Asp substitution.", false}, {UNIMOD_Glu__Lys, "UNIMOD:563", "Glu->Lys", "Glu->Lys substitution.", false}, {UNIMOD_Glu__Gly, "UNIMOD:564", "Glu->Gly", "Glu->Gly substitution.", false}, {UNIMOD_Glu__Val, "UNIMOD:565", "Glu->Val", "Glu->Val substitution.", false}, {UNIMOD_Phe__Ser, "UNIMOD:566", "Phe->Ser", "Phe->Ser substitution.", false}, {UNIMOD_Phe__Cys, "UNIMOD:567", "Phe->Cys", "Phe->Cys substitution.", false}, {UNIMOD_Phe__Xle, "UNIMOD:568", "Phe->Xle", "Phe->Leu/Ile substitution.", false}, {UNIMOD_Phe__Tyr, "UNIMOD:569", "Phe->Tyr", "Phe->Tyr substitution.", false}, {UNIMOD_Phe__Val, "UNIMOD:570", "Phe->Val", "Phe->Val substitution.", false}, {UNIMOD_Gly__Ala, "UNIMOD:571", "Gly->Ala", "Gly->Ala substitution.", false}, {UNIMOD_Gly__Ser, "UNIMOD:572", "Gly->Ser", "Gly->Ser substitution.", false}, {UNIMOD_Gly__Trp, "UNIMOD:573", "Gly->Trp", "Gly->Trp substitution.", false}, {UNIMOD_Gly__Glu, "UNIMOD:574", "Gly->Glu", "Gly->Glu substitution.", false}, {UNIMOD_Gly__Val, "UNIMOD:575", "Gly->Val", "Gly->Val substitution.", false}, {UNIMOD_Gly__Asp, "UNIMOD:576", "Gly->Asp", "Gly->Asp substitution.", false}, {UNIMOD_Gly__Cys, "UNIMOD:577", "Gly->Cys", "Gly->Cys substitution.", false}, {UNIMOD_Gly__Arg, "UNIMOD:578", "Gly->Arg", "Gly->Arg substitution.", false}, {UNIMOD_His__Pro, "UNIMOD:580", "His->Pro", "His->Pro substitution.", false}, {UNIMOD_His__Tyr, "UNIMOD:581", "His->Tyr", "His->Tyr substitution.", false}, {UNIMOD_His__Gln, "UNIMOD:582", "His->Gln", "His->Gln substitution.", false}, {UNIMOD_His__Arg, "UNIMOD:584", "His->Arg", "His->Arg substitution.", false}, {UNIMOD_His__Xle, "UNIMOD:585", "His->Xle", "His->Leu/Ile substitution.", false}, {UNIMOD_Xle__Thr, "UNIMOD:588", "Xle->Thr", "Leu/Ile->Thr substitution.", false}, {UNIMOD_Xle__Asn, "UNIMOD:589", "Xle->Asn", "Leu/Ile->Asn substitution.", false}, {UNIMOD_Xle__Lys, "UNIMOD:590", "Xle->Lys", "Leu/Ile->Lys substitution.", false}, {UNIMOD_Lys__Thr, "UNIMOD:594", "Lys->Thr", "Lys->Thr substitution.", false}, {UNIMOD_Lys__Asn, "UNIMOD:595", "Lys->Asn", "Lys->Asn substitution.", false}, {UNIMOD_Lys__Glu, "UNIMOD:596", "Lys->Glu", "Lys->Glu substitution.", false}, {UNIMOD_Lys__Gln, "UNIMOD:597", "Lys->Gln", "Lys->Gln substitution.", false}, {UNIMOD_Lys__Met, "UNIMOD:598", "Lys->Met", "Lys->Met substitution.", false}, {UNIMOD_Lys__Arg, "UNIMOD:599", "Lys->Arg", "Lys->Arg substitution.", false}, {UNIMOD_Lys__Xle, "UNIMOD:600", "Lys->Xle", "Lys->Leu/Ile substitution.", false}, {UNIMOD_Xle__Ser, "UNIMOD:601", "Xle->Ser", "Leu/Ile->Ser substitution.", false}, {UNIMOD_Xle__Phe, "UNIMOD:602", "Xle->Phe", "Leu/Ile->Phe substitution.", false}, {UNIMOD_Xle__Trp, "UNIMOD:603", "Xle->Trp", "Leu/Ile->Trp substitution.", false}, {UNIMOD_Xle__Pro, "UNIMOD:604", "Xle->Pro", "Leu/Ile->Pro substitution.", false}, {UNIMOD_Xle__Val, "UNIMOD:605", "Xle->Val", "Leu/Ile->Val substitution.", false}, {UNIMOD_Xle__His, "UNIMOD:606", "Xle->His", "Leu/Ile->His substitution.", false}, {UNIMOD_Xle__Gln, "UNIMOD:607", "Xle->Gln", "Leu/Ile->Gln substitution.", false}, {UNIMOD_Xle__Met, "UNIMOD:608", "Xle->Met", "Leu/Ile->Met substitution.", false}, {UNIMOD_Xle__Arg, "UNIMOD:609", "Xle->Arg", "Leu/Ile->Arg substitution.", false}, {UNIMOD_Met__Thr, "UNIMOD:610", "Met->Thr", "Met->Thr substitution.", false}, {UNIMOD_Met__Arg, "UNIMOD:611", "Met->Arg", "Met->Arg substitution.", false}, {UNIMOD_Met__Lys, "UNIMOD:613", "Met->Lys", "Met->Lys substitution.", false}, {UNIMOD_Met__Xle, "UNIMOD:614", "Met->Xle", "Met->Leu/Ile substitution.", false}, {UNIMOD_Met__Val, "UNIMOD:615", "Met->Val", "Met->Val substitution.", false}, {UNIMOD_Asn__Ser, "UNIMOD:616", "Asn->Ser", "Asn->Ser substitution.", false}, {UNIMOD_Asn__Thr, "UNIMOD:617", "Asn->Thr", "Asn->Thr substitution.", false}, {UNIMOD_Asn__Lys, "UNIMOD:618", "Asn->Lys", "Asn->Lys substitution.", false}, {UNIMOD_Asn__Tyr, "UNIMOD:619", "Asn->Tyr", "Asn->Tyr substitution.", false}, {UNIMOD_Asn__His, "UNIMOD:620", "Asn->His", "Asn->His substitution.", false}, {UNIMOD_Asn__Asp, "UNIMOD:621", "Asn->Asp", "Asn->Asp substitution.", false}, {UNIMOD_Asn__Xle, "UNIMOD:622", "Asn->Xle", "Asn->Leu/Ile substitution.", false}, {UNIMOD_Pro__Ser, "UNIMOD:623", "Pro->Ser", "Pro->Ser substitution.", false}, {UNIMOD_Pro__Ala, "UNIMOD:624", "Pro->Ala", "Pro->Ala substitution.", false}, {UNIMOD_Pro__His, "UNIMOD:625", "Pro->His", "Pro->His substitution.", false}, {UNIMOD_Pro__Gln, "UNIMOD:626", "Pro->Gln", "Pro->Gln substitution.", false}, {UNIMOD_Pro__Thr, "UNIMOD:627", "Pro->Thr", "Pro->Thr substitution.", false}, {UNIMOD_Pro__Arg, "UNIMOD:628", "Pro->Arg", "Pro->Arg substitution.", false}, {UNIMOD_Pro__Xle, "UNIMOD:629", "Pro->Xle", "Pro->Leu/Ile substitution.", false}, {UNIMOD_Gln__Pro, "UNIMOD:630", "Gln->Pro", "Gln->Pro substitution.", false}, {UNIMOD_Gln__Lys, "UNIMOD:631", "Gln->Lys", "Gln->Lys substitution.", false}, {UNIMOD_Gln__Glu, "UNIMOD:632", "Gln->Glu", "Gln->Glu substitution.", false}, {UNIMOD_Gln__His, "UNIMOD:633", "Gln->His", "Gln->His substitution.", false}, {UNIMOD_Gln__Arg, "UNIMOD:634", "Gln->Arg", "Gln->Arg substitution.", false}, {UNIMOD_Gln__Xle, "UNIMOD:635", "Gln->Xle", "Gln->Leu/Ile substitution.", false}, {UNIMOD_Arg__Ser, "UNIMOD:636", "Arg->Ser", "Arg->Ser substitution.", false}, {UNIMOD_Arg__Trp, "UNIMOD:637", "Arg->Trp", "Arg->Trp substitution.", false}, {UNIMOD_Arg__Thr, "UNIMOD:638", "Arg->Thr", "Arg->Thr substitution.", false}, {UNIMOD_Arg__Pro, "UNIMOD:639", "Arg->Pro", "Arg->Pro substitution.", false}, {UNIMOD_Arg__Lys, "UNIMOD:640", "Arg->Lys", "Arg->Lys substitution.", false}, {UNIMOD_Arg__His, "UNIMOD:641", "Arg->His", "Arg->His substitution.", false}, {UNIMOD_Arg__Gln, "UNIMOD:642", "Arg->Gln", "Arg->Gln substitution.", false}, {UNIMOD_Arg__Met, "UNIMOD:643", "Arg->Met", "Arg->Met substitution.", false}, {UNIMOD_Arg__Cys, "UNIMOD:644", "Arg->Cys", "Arg->Cys substitution.", false}, {UNIMOD_Arg__Xle, "UNIMOD:645", "Arg->Xle", "Arg->Leu/Ile substitution.", false}, {UNIMOD_Arg__Gly, "UNIMOD:646", "Arg->Gly", "Arg->Gly substitution.", false}, {UNIMOD_Ser__Phe, "UNIMOD:647", "Ser->Phe", "Ser->Phe substitution.", false}, {UNIMOD_Ser__Ala, "UNIMOD:648", "Ser->Ala", "Ser->Ala substitution.", false}, {UNIMOD_Ser__Trp, "UNIMOD:649", "Ser->Trp", "Ser->Trp substitution.", false}, {UNIMOD_Ser__Thr, "UNIMOD:650", "Ser->Thr", "Ser->Thr substitution.", false}, {UNIMOD_Ser__Asn, "UNIMOD:651", "Ser->Asn", "Ser->Asn substitution.", false}, {UNIMOD_Ser__Pro, "UNIMOD:652", "Ser->Pro", "Ser->Pro substitution.", false}, {UNIMOD_Ser__Tyr, "UNIMOD:653", "Ser->Tyr", "Ser->Tyr substitution.", false}, {UNIMOD_Ser__Cys, "UNIMOD:654", "Ser->Cys", "Ser->Cys substitution.", false}, {UNIMOD_Ser__Arg, "UNIMOD:655", "Ser->Arg", "Ser->Arg substitution.", false}, {UNIMOD_Ser__Xle, "UNIMOD:656", "Ser->Xle", "Ser->Leu/Ile substitution.", false}, {UNIMOD_Ser__Gly, "UNIMOD:657", "Ser->Gly", "Ser->Gly substitution.", false}, {UNIMOD_Thr__Ser, "UNIMOD:658", "Thr->Ser", "Thr->Ser substitution.", false}, {UNIMOD_Thr__Ala, "UNIMOD:659", "Thr->Ala", "Thr->Ala substitution.", false}, {UNIMOD_Thr__Asn, "UNIMOD:660", "Thr->Asn", "Thr->Asn substitution.", false}, {UNIMOD_Thr__Lys, "UNIMOD:661", "Thr->Lys", "Thr->Lys substitution.", false}, {UNIMOD_Thr__Pro, "UNIMOD:662", "Thr->Pro", "Thr->Pro substitution.", false}, {UNIMOD_Thr__Met, "UNIMOD:663", "Thr->Met", "Thr->Met substitution.", false}, {UNIMOD_Thr__Xle, "UNIMOD:664", "Thr->Xle", "Thr->Leu/Ile substitution.", false}, {UNIMOD_Thr__Arg, "UNIMOD:665", "Thr->Arg", "Thr->Arg substitution.", false}, {UNIMOD_Val__Phe, "UNIMOD:666", "Val->Phe", "Val->Phe substitution.", false}, {UNIMOD_Val__Ala, "UNIMOD:667", "Val->Ala", "Val->Ala substitution.", false}, {UNIMOD_Val__Glu, "UNIMOD:668", "Val->Glu", "Val->Glu substitution.", false}, {UNIMOD_Val__Met, "UNIMOD:669", "Val->Met", "Val->Met substitution.", false}, {UNIMOD_Val__Asp, "UNIMOD:670", "Val->Asp", "Val->Asp substitution.", false}, {UNIMOD_Val__Xle, "UNIMOD:671", "Val->Xle", "Val->Leu/Ile substitution.", false}, {UNIMOD_Val__Gly, "UNIMOD:672", "Val->Gly", "Val->Gly substitution.", false}, {UNIMOD_Trp__Ser, "UNIMOD:673", "Trp->Ser", "Trp->Ser substitution.", false}, {UNIMOD_Trp__Cys, "UNIMOD:674", "Trp->Cys", "Trp->Cys substitution.", false}, {UNIMOD_Trp__Arg, "UNIMOD:675", "Trp->Arg", "Trp->Arg substitution.", false}, {UNIMOD_Trp__Gly, "UNIMOD:676", "Trp->Gly", "Trp->Gly substitution.", false}, {UNIMOD_Trp__Xle, "UNIMOD:677", "Trp->Xle", "Trp->Leu/Ile substitution.", false}, {UNIMOD_Tyr__Phe, "UNIMOD:678", "Tyr->Phe", "Tyr->Phe substitution.", false}, {UNIMOD_Tyr__Ser, "UNIMOD:679", "Tyr->Ser", "Tyr->Ser substitution.", false}, {UNIMOD_Tyr__Asn, "UNIMOD:680", "Tyr->Asn", "Tyr->Asn substitution.", false}, {UNIMOD_Tyr__His, "UNIMOD:681", "Tyr->His", "Tyr->His substitution.", false}, {UNIMOD_Tyr__Asp, "UNIMOD:682", "Tyr->Asp", "Tyr->Asp substitution.", false}, {UNIMOD_Tyr__Cys, "UNIMOD:683", "Tyr->Cys", "Tyr->Cys substitution.", false}, {UNIMOD_BDMAPP, "UNIMOD:684", "BDMAPP", "Mass Defect Tag on lysine e-amino.", false}, {UNIMOD_NA_LNO2, "UNIMOD:685", "NA-LNO2", "Nitroalkylation by Nitro Linoleic Acid.", false}, {UNIMOD_NA_OA_NO2, "UNIMOD:686", "NA-OA-NO2", "Nitroalkylation by Nitro Oleic Acid.", false}, {UNIMOD_ICPL_2H_4_, "UNIMOD:687", "ICPL:2H(4)", "Bruker Daltonics SERVA-ICPL(TM) quantification chemistry, medium form.", false}, {UNIMOD_Label_13C_6_15N_1_, "UNIMOD:695", "Label:13C(6)15N(1)", "13C(6) 15N(1) Silac label.", false}, {UNIMOD_Label_2H_9_13C_6_15N_2_, "UNIMOD:696", "Label:2H(9)13C(6)15N(2)", "13C(6) 15N(2) (D)9 SILAC label.", false}, {UNIMOD_NIC, "UNIMOD:697", "NIC", "Nicotinic Acid.", false}, {UNIMOD_dNIC, "UNIMOD:698", "dNIC", "Deuterated Nicotinic Acid.", false}, {UNIMOD_HNE_Delta_H_2_O, "UNIMOD:720", "HNE-Delta:H(2)O", "Dehydrated 4-hydroxynonenal.", false}, {UNIMOD_4_ONE, "UNIMOD:721", "4-ONE", "4-Oxononenal (ONE).", false}, {UNIMOD_O_Dimethylphosphate, "UNIMOD:723", "O-Dimethylphosphate", "O-Dimethylphosphorylation.", false}, {UNIMOD_O_Methylphosphate, "UNIMOD:724", "O-Methylphosphate", "O-Methylphosphorylation.", false}, {UNIMOD_Diethylphosphate, "UNIMOD:725", "Diethylphosphate", "O-Diethylphosphorylation.", false}, {UNIMOD_Ethylphosphate, "UNIMOD:726", "Ethylphosphate", "O-Ethylphosphorylation.", false}, {UNIMOD_O_pinacolylmethylphosphonate, "UNIMOD:727", "O-pinacolylmethylphosphonate", "O-pinacolylmethylphosphonylation.", false}, {UNIMOD_Methylphosphonate, "UNIMOD:728", "Methylphosphonate", "Methylphosphonylation.", false}, {UNIMOD_O_Isopropylmethylphosphonate, "UNIMOD:729", "O-Isopropylmethylphosphonate", "O-Isopropylmethylphosphonylation.", false}, {UNIMOD_iTRAQ8plex, "UNIMOD:730", "iTRAQ8plex", "Representative mass and accurate mass for 113, 114, 116 & 117.", false}, {UNIMOD_iTRAQ8plex_13C_6_15N_2_, "UNIMOD:731", "iTRAQ8plex:13C(6)15N(2)", "Accurate mass for 115, 118, 119 & 121.", false}, {UNIMOD_Ethanolamine, "UNIMOD:734", "Ethanolamine", "Carboxyl modification with ethanolamine.", false}, {UNIMOD_DTT_ST, "UNIMOD:735", "DTT_ST", "Dithiothreitol (DTT).", false}, {UNIMOD_DTT_C, "UNIMOD:736", "DTT_C", "Dithiothreitol (DTT) on Cys.", false}, {UNIMOD_TMT6plex, "UNIMOD:737", "TMT6plex", "Sixplex Tandem Mass Tag®.", false}, {UNIMOD_TMT2plex, "UNIMOD:738", "TMT2plex", "Duplex Tandem Mass Tag®.", false}, {UNIMOD_TMT, "UNIMOD:739", "TMT", "Native Tandem Mass Tag®.", false}, {UNIMOD_ExacTagThiol, "UNIMOD:740", "ExacTagThiol", "ExacTag Thiol label mass for 2-4-7-10 plex.", false}, {UNIMOD_ExacTagAmine, "UNIMOD:741", "ExacTagAmine", "ExacTag Amine label mass for 2-4-7-10 plex.", false}, {UNIMOD_4_ONE_Delta_H__2_O__1_, "UNIMOD:743", "4-ONE+Delta:H(-2)O(-1)", "Dehydrated 4-Oxononenal Michael adduct.", false}, {UNIMOD_NO_SMX_SEMD, "UNIMOD:744", "NO_SMX_SEMD", "Nitroso Sulfamethoxazole Sulphenamide thiol adduct.", false}, {UNIMOD_NO_SMX_SMCT, "UNIMOD:745", "NO_SMX_SMCT", "Nitroso Sulfamethoxazole semimercaptal thiol adduct.", false}, {UNIMOD_NO_SMX_SIMD, "UNIMOD:746", "NO_SMX_SIMD", "Nitroso Sulfamethoxazole Sulfinamide thiol adduct.", false}, {UNIMOD_Malonyl, "UNIMOD:747", "Malonyl", "Malonylation of C and S residues.", false}, {UNIMOD_3sulfo, "UNIMOD:748", "3sulfo", "Derivatization by N-term modification using 3-Sulfobenzoic succinimidyl ester.", false}, {UNIMOD_trifluoro, "UNIMOD:750", "trifluoro", "Trifluoroleucine replacement of leucine.", false}, {UNIMOD_TNBS, "UNIMOD:751", "TNBS", "Tri nitro benzene.", false}, {UNIMOD_IDEnT, "UNIMOD:762", "IDEnT", "Isotope Distribution Encoded Tag.", false}, {UNIMOD_DTT_ST_2H_6_, "UNIMOD:763", "DTT_ST:2H(6)", "Isotopically labeled Dithiothreitol (DTT) modification of serines or threonines.", false}, {UNIMOD_DTT_C_2H_6_, "UNIMOD:764", "DTT_C:2H(6)", "Isotopically labeled Dithiothreitol (DTT) modification of cysteines.", false}, {UNIMOD_Met_loss, "UNIMOD:765", "Met-loss", "Removal of initiator methionine from protein N-terminus.", false}, {UNIMOD_Met_loss_Acetyl, "UNIMOD:766", "Met-loss+Acetyl", "Removal of initiator methionine from protein N-terminus, then acetylation of the new N-terminus.", false}, {UNIMOD_Menadione_HQ, "UNIMOD:767", "Menadione-HQ", "Menadione hydroquinone derivative.", false}, {UNIMOD_Methyl_Acetyl_2H_3_, "UNIMOD:768", "Methyl+Acetyl:2H(3)", "Mono-methylated lysine labelled with Acetyl_heavy.", false}, {UNIMOD_lapachenole, "UNIMOD:771", "lapachenole", "Lapachenole photochemically added to cysteine.", false}, {UNIMOD_Label_13C_5_, "UNIMOD:772", "Label:13C(5)", "13C(5) Silac label.", false}, {UNIMOD_maleimide, "UNIMOD:773", "maleimide", "Maleimide.", false}, {UNIMOD_Biotin_phenacyl, "UNIMOD:774", "Biotin-phenacyl", "Alkylation by biotinylated form of phenacyl bromide.", false}, {UNIMOD_Carboxymethyl_13C_2_, "UNIMOD:775", "Carboxymethyl:13C(2)", "Iodoacetic acid derivative w/ 13C label.", false}, {UNIMOD_NEM_2H_5_, "UNIMOD:776", "NEM:2H(5)", "D5 N-ethylmaleimide on cysteines.", false}, {UNIMOD_AEC_MAEC_2H_4_, "UNIMOD:792", "AEC-MAEC:2H(4)", "Deuterium cysteamine modification to S or T.", false}, {UNIMOD_Hex_1_HexNAc_1_, "UNIMOD:793", "Hex(1)HexNAc(1)", "Hex1HexNAc1.", false}, {UNIMOD_Label_13C_6__GG, "UNIMOD:799", "Label:13C(6)+GG", "13C6 labeled ubiquitinylation residue.", false}, {UNIMOD_Biotin_Thermo_21345, "UNIMOD:800", "Biotin:Thermo-21345", "Was PentylamineBiotin.", false}, {UNIMOD_Pentylamine, "UNIMOD:801", "Pentylamine", "Labeling transglutaminase substrate on glutamine side chain.", false}, {UNIMOD_Biotin_Thermo_21360, "UNIMOD:811", "Biotin:Thermo-21360", "Was Biotin-PEO4-hydrazide.", false}, {UNIMOD_Cy3b_maleimide, "UNIMOD:821", "Cy3b-maleimide", "Fluorescent dye that labels cysteines.", false}, {UNIMOD_Gly_loss_Amide, "UNIMOD:822", "Gly-loss+Amide", "Enzymatic glycine removal leaving an amidated C-terminus.", false}, {UNIMOD_BMOE, "UNIMOD:824", "BMOE", "Addition of BMOE crosslinker.", false}, {UNIMOD_DFDNB, "UNIMOD:825", "DFDNB", "Addition of DFDNB crosslinker.", false}, {UNIMOD_TMPP_Ac, "UNIMOD:827", "TMPP-Ac", "Tris(2,4,6-trimethoxyphenyl)phosphonium acetic acid N-hydroxysuccinimide ester derivative.", false}, {UNIMOD_Dihydroxyimidazolidine, "UNIMOD:830", "Dihydroxyimidazolidine", "Dihydroxy methylglyoxal adduct.", false}, {UNIMOD_Label_2H_4__Acetyl, "UNIMOD:834", "Label:2H(4)+Acetyl", "Acetyl 4,4,5,5-D4 Lysine.", false}, {UNIMOD_Label_13C_6__Acetyl, "UNIMOD:835", "Label:13C(6)+Acetyl", "Acetyl 13C(6) Silac label.", false}, {UNIMOD_Label_13C_6_15N_2__Acetyl, "UNIMOD:836", "Label:13C(6)15N(2)+Acetyl", "Acetyl_13C(6) 15N(2) Silac label.", false}, {UNIMOD_Arg__Npo, "UNIMOD:837", "Arg->Npo", "Arginine replacement by Nitropyrimidyl ornithine.", false}, {UNIMOD_EQIGG, "UNIMOD:846", "EQIGG", "Sumo mutant Smt3-WT tail following trypsin digestion.", false}, {UNIMOD_Arg2PG, "UNIMOD:848", "Arg2PG", "Adduct of phenylglyoxal with Arg.", false}, {UNIMOD_cGMP, "UNIMOD:849", "cGMP", "S-guanylation.", false}, {UNIMOD_cGMP_RMP_loss, "UNIMOD:851", "cGMP+RMP-loss", "S-guanylation-2.", false}, {UNIMOD_Label_2H_4__GG, "UNIMOD:853", "Label:2H(4)+GG", "Ubiquitination 2H4 lysine.", false}, {UNIMOD_MG_H1, "UNIMOD:859", "MG-H1", "Methylglyoxal-derived hydroimidazolone.", false}, {UNIMOD_G_H1, "UNIMOD:860", "G-H1", "Glyoxal-derived hydroimiadazolone.", false}, {UNIMOD_ZGB, "UNIMOD:861", "ZGB", "NHS ester linked Green Fluorescent Bodipy Dye.", false}, {UNIMOD_Label_13C_1_2H_3_, "UNIMOD:862", "Label:13C(1)2H(3)", "SILAC.", false}, {UNIMOD_Label_13C_6_15N_2__GG, "UNIMOD:864", "Label:13C(6)15N(2)+GG", "13C(6) 15N(2) Lysine glygly.", false}, {UNIMOD_ICPL_13C_6_2H_4_, "UNIMOD:866", "ICPL:13C(6)2H(4)", "Bruker Daltonics SERVA-ICPL(TM) quantification chemistry, +10 Da form.", false}, {UNIMOD_QEQTGG, "UNIMOD:876", "QEQTGG", "SUMOylation by SUMO-1.", false}, {UNIMOD_QQQTGG, "UNIMOD:877", "QQQTGG", "SUMOylation by SUMO-2/3.", false}, {UNIMOD_Bodipy, "UNIMOD:878", "Bodipy", "Bodipy modifications onto cysteine.", false}, {UNIMOD_Biotin_Thermo_21325, "UNIMOD:884", "Biotin:Thermo-21325", "Was ChromoBiotin.", false}, {UNIMOD_Label_13C_1_2H_3__Oxidation, "UNIMOD:885", "Label:13C(1)2H(3)+Oxidation", "Oxidised methionine 13C(1)2H(3) SILAC label.", false}, {UNIMOD_HydroxymethylOP, "UNIMOD:886", "HydroxymethylOP", "2-ammonio-6-[4-(hydroxymethyl)-3-oxidopyridinium-1-yl]- hexanoate.", false}, {UNIMOD_MDCC, "UNIMOD:887", "MDCC", "Covalent linkage of maleimidyl coumarin probe (Molecular Probes D-10253).", false}, {UNIMOD_mTRAQ, "UNIMOD:888", "mTRAQ", "MTRAQ light.", false}, {UNIMOD_mTRAQ_13C_3_15N_1_, "UNIMOD:889", "mTRAQ:13C(3)15N(1)", "MTRAQ medium.", false}, {UNIMOD_DyLight_maleimide, "UNIMOD:890", "DyLight-maleimide", "Thiol-reactive dye for fluorescence labelling of proteins.", false}, {UNIMOD_Methyl_PEO12_Maleimide, "UNIMOD:891", "Methyl-PEO12-Maleimide", "Methyl-PEO12-Maleimide.", false}, {UNIMOD_CarbamidomethylDTT, "UNIMOD:893", "CarbamidomethylDTT", "Carbamidomethylated DTT modification of cysteine.", false}, {UNIMOD_CarboxymethylDTT, "UNIMOD:894", "CarboxymethylDTT", "Carboxymethylated DTT modification of cysteine.", false}, {UNIMOD_Biotin_PEG_PRA, "UNIMOD:895", "Biotin-PEG-PRA", "Biotin polyethyleneoxide (n=3) alkyne.", false}, {UNIMOD_Met__Aha, "UNIMOD:896", "Met->Aha", "Methionine replacement by azido homoalanine.", false}, {UNIMOD_Label_15N_4_, "UNIMOD:897", "Label:15N(4)", "SILAC 15N(4).", false}, {UNIMOD_pyrophospho, "UNIMOD:898", "pyrophospho", "Pyrophosphorylation of Ser/Thr.", false}, {UNIMOD_Met__Hpg, "UNIMOD:899", "Met->Hpg", "Methionine replacement by homopropargylglycine.", false}, {UNIMOD_4AcAllylGal, "UNIMOD:901", "4AcAllylGal", "2,3,4,6-tetra-O-Acetyl-1-allyl-alpha-D-galactopyranoside modification of cysteine.", false}, {UNIMOD_DimethylArsino, "UNIMOD:902", "DimethylArsino", "Reaction with dimethylarsinous (AsIII) acid.", false}, {UNIMOD_Lys__CamCys, "UNIMOD:903", "Lys->CamCys", "Lys->Cys substitution and carbamidomethylation.", false}, {UNIMOD_Phe__CamCys, "UNIMOD:904", "Phe->CamCys", "Phe->Cys substitution and carbamidomethylation.", false}, {UNIMOD_Leu__MetOx, "UNIMOD:905", "Leu->MetOx", "Leu->Met substitution and sulfoxidation.", false}, {UNIMOD_Lys__MetOx, "UNIMOD:906", "Lys->MetOx", "Lys->Met substitution and sulfoxidation.", false}, {UNIMOD_Galactosyl, "UNIMOD:907", "Galactosyl", "Galactosyl hydroxylysine.", false}, {UNIMOD_SMCC_maleimide, "UNIMOD:908", "SMCC-maleimide", "Modified SMCC maleimide with 3-(dimethylamino)-1-propylamine.", false}, {UNIMOD_Bacillosamine, "UNIMOD:910", "Bacillosamine", "2,4-diacetamido-2,4,6-trideoxyglucopyranose.", false}, {UNIMOD_MTSL, "UNIMOD:911", "MTSL", "Cys modification by (1-oxyl-2,2,5,5-tetramethyl-3-pyrroline-3-methyl)methanesulfonate (MTSL).", false}, {UNIMOD_HNE_BAHAH, "UNIMOD:912", "HNE-BAHAH", "4-hydroxy-2-nonenal and biotinamidohexanoic acid hydrazide, reduced.", false}, {UNIMOD_Methylmalonylation, "UNIMOD:914", "Methylmalonylation", "Methylmalonylation on Serine.", false}, {UNIMOD_Ethoxyformyl, "UNIMOD:915", "Ethoxyformyl", "Ethoxyformylation.", false}, {UNIMOD_Label_13C_4_15N_2__GG, "UNIMOD:923", "Label:13C(4)15N(2)+GG", "13C(4) 15N(2) Lysine glygly.", false}, {UNIMOD_ethylamino, "UNIMOD:926", "ethylamino", "Ethyl amino.", false}, {UNIMOD_MercaptoEthanol, "UNIMOD:928", "MercaptoEthanol", "2-OH-ethyl thio-Ser.", false}, {UNIMOD_Ethyl_Deamidated, "UNIMOD:931", "Ethyl+Deamidated", "Deamidation followed by esterification with ethanol.", false}, {UNIMOD_VFQQQTGG, "UNIMOD:932", "VFQQQTGG", "SUMOylation by SUMO-2/3 (formic acid cleavage).", false}, {UNIMOD_VIEVYQEQTGG, "UNIMOD:933", "VIEVYQEQTGG", "SUMOylation by SUMO-1 (formic acid cleavage).", false}, {UNIMOD_AMTzHexNAc2, "UNIMOD:934", "AMTzHexNAc2", "Photocleavable Biotin + GalNAz on O-GlcNAc.", false}, {UNIMOD_Atto495Maleimide, "UNIMOD:935", "Atto495Maleimide", "High molecular absorption maleimide label for proteins.", false}, {UNIMOD_Chlorination, "UNIMOD:936", "Chlorination", "Chlorination of tyrosine residues.", false}, {UNIMOD_dichlorination, "UNIMOD:937", "dichlorination", "Dichlorination.", false}, {UNIMOD_AROD, "UNIMOD:938", "AROD", "Cysteine modifier.", false}, {UNIMOD_Cys__methylaminoAla, "UNIMOD:939", "Cys->methylaminoAla", "Carbamidomethylated Cys that undergoes beta-elimination and Michael addition of methylamine.", false}, {UNIMOD_Cys__ethylaminoAla, "UNIMOD:940", "Cys->ethylaminoAla", "Carbamidomethylated Cys that undergoes beta-elimination and Michael addition of ethylamine.", false}, {UNIMOD_DNPS, "UNIMOD:941", "DNPS", "2,4-Dinitrobenzenesulfenyl.", false}, {UNIMOD_SulfoGMBS, "UNIMOD:942", "SulfoGMBS", "High molecular absorption label for proteins.", false}, {UNIMOD_DimethylamineGMBS, "UNIMOD:943", "DimethylamineGMBS", "Modified GMBS X linker for proteins.", false}, {UNIMOD_Label_15N_2_2H_9_, "UNIMOD:944", "Label:15N(2)2H(9)", "SILAC label.", false}, {UNIMOD_LG_anhydrolactam, "UNIMOD:946", "LG-anhydrolactam", "Levuglandinyl-lysine anhydrolactam adduct.", false}, {UNIMOD_LG_pyrrole, "UNIMOD:947", "LG-pyrrole", "Levuglandinyl-lysine pyrrole adduct.", false}, {UNIMOD_LG_anhyropyrrole, "UNIMOD:948", "LG-anhyropyrrole", "Levuglandinyl-lysine anhyropyrrole adduct.", false}, {UNIMOD_3_deoxyglucosone, "UNIMOD:949", "3-deoxyglucosone", "Condensation product of 3-deoxyglucosone.", false}, {UNIMOD_Cation_Li, "UNIMOD:950", "Cation:Li", "Replacement of proton by lithium.", false}, {UNIMOD_Cation_Ca_II_, "UNIMOD:951", "Cation:Ca[II]", "Replacement of 2 protons by calcium.", false}, {UNIMOD_Cation_Fe_II_, "UNIMOD:952", "Cation:Fe[II]", "Replacement of 2 protons by iron.", false}, {UNIMOD_Cation_Ni_II_, "UNIMOD:953", "Cation:Ni[II]", "Replacement of 2 protons by nickel.", false}, {UNIMOD_Cation_Zn_II_, "UNIMOD:954", "Cation:Zn[II]", "Replacement of 2 protons by zinc.", false}, {UNIMOD_Cation_Ag, "UNIMOD:955", "Cation:Ag", "Replacement of proton by silver.", false}, {UNIMOD_Cation_Mg_II_, "UNIMOD:956", "Cation:Mg[II]", "Replacement of 2 protons by magnesium.", false}, {UNIMOD_2_succinyl, "UNIMOD:957", "2-succinyl", "S-(2-succinyl) cysteine.", false}, {UNIMOD_Propargylamine, "UNIMOD:958", "Propargylamine", "Propargylamine.", false}, {UNIMOD_Phosphopropargyl, "UNIMOD:959", "Phosphopropargyl", "Phospho-propargylamine.", false}, {UNIMOD_SUMO2135, "UNIMOD:960", "SUMO2135", "SUMOylation by SUMO-1 after tryptic cleavage.", false}, {UNIMOD_SUMO3549, "UNIMOD:961", "SUMO3549", "SUMOylation by SUMO-2/3 after tryptic cleavage.", false}, {UNIMOD_thioacylPA, "UNIMOD:967", "thioacylPA", "Membrane protein extraction.", false}, {UNIMOD_maleimide3, "UNIMOD:971", "maleimide3", "Maleimide-3-saccharide.", false}, {UNIMOD_maleimide5, "UNIMOD:972", "maleimide5", "Maleimide-5-saccharide.", false}, {UNIMOD_Puromycin, "UNIMOD:973", "Puromycin", "Puromycin.", false}, {UNIMOD_Chlorpyrifos, "UNIMOD:975", "Chlorpyrifos", "O,O-diethyl o-3,5,6-trichloro-2-pyridyl phosphorothioate.", false}, {UNIMOD_Carbofuran, "UNIMOD:977", "Carbofuran", "2,3-dihydro-2,2-dimethyl-7-benzofuranol N-methyl carbamate.", false}, {UNIMOD_BITC, "UNIMOD:978", "BITC", "Benzyl isothiocyanate.", false}, {UNIMOD_PEITC, "UNIMOD:979", "PEITC", "Phenethyl isothiocyanate.", false}, {UNIMOD_glucosone, "UNIMOD:981", "glucosone", "Condensation product of glucosone.", false}, {UNIMOD_cysTMT, "UNIMOD:984", "cysTMT", "Native cysteine-reactive Tandem Mass Tag®.", false}, {UNIMOD_cysTMT6plex, "UNIMOD:985", "cysTMT6plex", "Cysteine-reactive Sixplex Tandem Mass Tag®.", false}, {UNIMOD_Label_13C_6__Dimethyl, "UNIMOD:986", "Label:13C(6)+Dimethyl", "Dimethyl 13C(6) Silac label.", false}, {UNIMOD_Label_13C_6_15N_2__Dimethyl, "UNIMOD:987", "Label:13C(6)15N(2)+Dimethyl", "Dimethyl 13C(6)15N(2) Silac label.", false}, {UNIMOD_Ammonium, "UNIMOD:989", "Ammonium", "Replacement of proton with ammonium ion.", false}, {UNIMOD_ISD_z_2_ion, "UNIMOD:991", "ISD_z+2_ion", "ISD (z+2)-series.", false}, {UNIMOD_Biotin_Sigma_B1267, "UNIMOD:993", "Biotin:Sigma-B1267", "Was Biotin-maleimide.", false}, {UNIMOD_Label_15N_1_, "UNIMOD:994", "Label:15N(1)", "15N(1).", false}, {UNIMOD_Label_15N_2_, "UNIMOD:995", "Label:15N(2)", "15N(2).", false}, {UNIMOD_Label_15N_3_, "UNIMOD:996", "Label:15N(3)", "15N(3).", false}, {UNIMOD_sulfo_amino, "UNIMOD:997", "sulfo+amino", "Aminotyrosine with sulfation.", false}, {UNIMOD_BHAc, "UNIMOD:998", "BHAc", "N-biotinyl-6-aminohexanoyl.", false}, {UNIMOD_AHA_Alkyne, "UNIMOD:1000", "AHA-Alkyne", "Azidohomoalanine (AHA) bound to propargylglycine-NH2 (alkyne).", false}, {UNIMOD_AHA_Alkyne_KDDDD, "UNIMOD:1001", "AHA-Alkyne-KDDDD", "Azidohomoalanine (AHA) bound to DDDDK-propargylglycine-NH2 (alkyne).", false}, {UNIMOD_EGCG1, "UNIMOD:1002", "EGCG1", "(-)-epigallocatechin-3-gallate.", false}, {UNIMOD_EGCG2, "UNIMOD:1003", "EGCG2", "(-)-dehydroepigallocatechin.", false}, {UNIMOD_Label_13C_6_15N_4__Methyl, "UNIMOD:1004", "Label:13C(6)15N(4)+Methyl", "Monomethylated Arg13C(6) 15N(4).", false}, {UNIMOD_Label_13C_6_15N_4__Dimethyl, "UNIMOD:1005", "Label:13C(6)15N(4)+Dimethyl", "Dimethylated Arg13C(6) 15N(4).", false}, {UNIMOD_Label_13C_6_15N_4__Methyl_2H_3_13C_1_, "UNIMOD:1006", "Label:13C(6)15N(4)+Methyl:2H(3)13C(1)", "2H(3) 13C(1) monomethylated Arg13C(6) 15N(4).", false}, {UNIMOD_Label_13C_6_15N_4__Dimethyl_2H_6_13C_2_, "UNIMOD:1007", "Label:13C(6)15N(4)+Dimethyl:2H(6)13C(2)", "2H(6) 13C(2) Dimethylated Arg13C(6) 15N(4).", false}, {UNIMOD_SecCarbamidomethyl, "UNIMOD:1008", "SecCarbamidomethyl", "Sec Iodoacetamide derivative.", false}, {UNIMOD_Thiazolidine, "UNIMOD:1009", "Thiazolidine", "Addition of Carbon to cysteine.", false}, {UNIMOD_DEDGFLYMVYASQETFG, "UNIMOD:1010", "DEDGFLYMVYASQETFG", "Addition of DEDGFLYMVYASQETFG.", false}, {UNIMOD_Biotin_Invitrogen_M1602, "UNIMOD:1012", "Biotin:Invitrogen-M1602", "Nalpha-(3-maleimidylpropionyl)biocytin.", false}, {UNIMOD_glycidamide, "UNIMOD:1014", "glycidamide", "Glycidamide adduct.", false}, {UNIMOD_Ahx2_Hsl, "UNIMOD:1015", "Ahx2+Hsl", "C-terminal homoserine lactone and two aminohexanoic acids.", false}, {UNIMOD_DMPO, "UNIMOD:1017", "DMPO", "DMPO spin-trap nitrone adduct.", false}, {UNIMOD_ICDID, "UNIMOD:1018", "ICDID", "Isotope-Coded Dimedone light form.", false}, {UNIMOD_ICDID_2H_6_, "UNIMOD:1019", "ICDID:2H(6)", "Isotope-Coded Dimedone heavy form.", false}, {UNIMOD_Xlink_DSS, "UNIMOD:1020", "Xlink:DSS", "Monolink of DSS/BS3 crosslinker to Lys or N-terminus.", false}, {UNIMOD_Xlink_EGS, "UNIMOD:1021", "Xlink:EGS", "Monolink of EGS crosslinker to Lys or N-terminus.", false}, {UNIMOD_Xlink_DST, "UNIMOD:1022", "Xlink:DST", "Monolink of DST crosslinker to Lys or N-terminus.", false}, {UNIMOD_Xlink_DTSSP, "UNIMOD:1023", "Xlink:DTSSP", "Monolink of DSP/DTSSP crosslinker to Lys or N-terminus.", false}, {UNIMOD_Xlink_SMCC, "UNIMOD:1024", "Xlink:SMCC", "Monolink of sulfoSMCC/SMCC crosslinker to Cys.", false}, {UNIMOD_Xlink_DMP_de, "UNIMOD:1027", "Xlink:DMP-de", "Monolink of DMP crosslinker to Lys or N-terminus.", false}, {UNIMOD_Xlink_EGScleaved, "UNIMOD:1028", "Xlink:EGScleaved", "EGS crosslinker to Lys or N-terminus following hydroxylamine cleavage.", false}, {UNIMOD_Biotin_Thermo_88310, "UNIMOD:1031", "Biotin:Thermo-88310", "Desthiobiotin modification of lysine.", false}, {UNIMOD_2_nitrobenzyl, "UNIMOD:1032", "2-nitrobenzyl", "Tyrosine caged with 2-nitrobenzyl (ONB).", false}, {UNIMOD_SecNEM, "UNIMOD:1033", "SecNEM", "N-ethylmaleimide on selenocysteines.", false}, {UNIMOD_SecNEM_2H_5_, "UNIMOD:1034", "SecNEM:2H(5)", "D5 N-ethylmaleimide on selenocysteines.", false}, {UNIMOD_Thiadiazole, "UNIMOD:1035", "Thiadiazole", "Thiadiazolydation of Cys.", false}, {UNIMOD_Withaferin, "UNIMOD:1036", "Withaferin", "Modification of cystein by withaferin.", false}, {UNIMOD_Biotin_Thermo_88317, "UNIMOD:1037", "Biotin:Thermo-88317", "Desthiobiotin fluorophosphonate.", false}, {UNIMOD_TAMRA_FP, "UNIMOD:1038", "TAMRA-FP", "TAMRA fluorophosphonate modification of serine.", false}, {UNIMOD_Biotin_Thermo_21901_H2O, "UNIMOD:1039", "Biotin:Thermo-21901+H2O", "Maleimide-Biotin + Water.", false}, {UNIMOD_Deoxyhypusine, "UNIMOD:1041", "Deoxyhypusine", "Deoxyhypusine.", false}, {UNIMOD_Acetyldeoxyhypusine, "UNIMOD:1042", "Acetyldeoxyhypusine", "Acetyldeoxyhypusine.", false}, {UNIMOD_Acetylhypusine, "UNIMOD:1043", "Acetylhypusine", "Acetylhypusine.", false}, {UNIMOD_Ala__Cys, "UNIMOD:1044", "Ala->Cys", "Ala->Cys substitution.", false}, {UNIMOD_Ala__Phe, "UNIMOD:1045", "Ala->Phe", "Ala->Phe substitution.", false}, {UNIMOD_Ala__His, "UNIMOD:1046", "Ala->His", "Ala->His substitution.", false}, {UNIMOD_Ala__Xle, "UNIMOD:1047", "Ala->Xle", "Ala->Leu/Ile substitution.", false}, {UNIMOD_Ala__Lys, "UNIMOD:1048", "Ala->Lys", "Ala->Lys substitution.", false}, {UNIMOD_Ala__Met, "UNIMOD:1049", "Ala->Met", "Ala->Met substitution.", false}, {UNIMOD_Ala__Asn, "UNIMOD:1050", "Ala->Asn", "Ala->Asn substitution.", false}, {UNIMOD_Ala__Gln, "UNIMOD:1051", "Ala->Gln", "Ala->Gln substitution.", false}, {UNIMOD_Ala__Arg, "UNIMOD:1052", "Ala->Arg", "Ala->Arg substitution.", false}, {UNIMOD_Ala__Trp, "UNIMOD:1053", "Ala->Trp", "Ala->Trp substitution.", false}, {UNIMOD_Ala__Tyr, "UNIMOD:1054", "Ala->Tyr", "Ala->Tyr substitution.", false}, {UNIMOD_Cys__Ala, "UNIMOD:1055", "Cys->Ala", "Cys->Ala substitution.", false}, {UNIMOD_Cys__Asp, "UNIMOD:1056", "Cys->Asp", "Cys->Asp substitution.", false}, {UNIMOD_Cys__Glu, "UNIMOD:1057", "Cys->Glu", "Cys->Glu substitution.", false}, {UNIMOD_Cys__His, "UNIMOD:1058", "Cys->His", "Cys->His substitution.", false}, {UNIMOD_Cys__Xle, "UNIMOD:1059", "Cys->Xle", "Cys->Leu/Ile substitution.", false}, {UNIMOD_Cys__Lys, "UNIMOD:1060", "Cys->Lys", "Cys->Lys substitution.", false}, {UNIMOD_Cys__Met, "UNIMOD:1061", "Cys->Met", "Cys->Met substitution.", false}, {UNIMOD_Cys__Asn, "UNIMOD:1062", "Cys->Asn", "Cys->Asn substitution.", false}, {UNIMOD_Cys__Pro, "UNIMOD:1063", "Cys->Pro", "Cys->Pro substitution.", false}, {UNIMOD_Cys__Gln, "UNIMOD:1064", "Cys->Gln", "Cys->Gln substitution.", false}, {UNIMOD_Cys__Thr, "UNIMOD:1065", "Cys->Thr", "Cys->Thr substitution.", false}, {UNIMOD_Cys__Val, "UNIMOD:1066", "Cys->Val", "Cys->Val substitution.", false}, {UNIMOD_Asp__Cys, "UNIMOD:1067", "Asp->Cys", "Asp->Cys substitution.", false}, {UNIMOD_Asp__Phe, "UNIMOD:1068", "Asp->Phe", "Asp->Phe substitution.", false}, {UNIMOD_Asp__Xle, "UNIMOD:1069", "Asp->Xle", "Asp->Leu/Ile substitution.", false}, {UNIMOD_Asp__Lys, "UNIMOD:1070", "Asp->Lys", "Asp->Lys substitution.", false}, {UNIMOD_Asp__Met, "UNIMOD:1071", "Asp->Met", "Asp->Met substitution.", false}, {UNIMOD_Asp__Pro, "UNIMOD:1072", "Asp->Pro", "Asp->Pro substitution.", false}, {UNIMOD_Asp__Gln, "UNIMOD:1073", "Asp->Gln", "Asp->Gln substitution.", false}, {UNIMOD_Asp__Arg, "UNIMOD:1074", "Asp->Arg", "Asp->Arg substitution.", false}, {UNIMOD_Asp__Ser, "UNIMOD:1075", "Asp->Ser", "Asp->Ser substitution.", false}, {UNIMOD_Asp__Thr, "UNIMOD:1076", "Asp->Thr", "Asp->Thr substitution.", false}, {UNIMOD_Asp__Trp, "UNIMOD:1077", "Asp->Trp", "Asp->Trp substitution.", false}, {UNIMOD_Glu__Cys, "UNIMOD:1078", "Glu->Cys", "Glu->Cys substitution.", false}, {UNIMOD_Glu__Phe, "UNIMOD:1079", "Glu->Phe", "Glu->Phe substitution.", false}, {UNIMOD_Glu__His, "UNIMOD:1080", "Glu->His", "Glu->His substitution.", false}, {UNIMOD_Glu__Xle, "UNIMOD:1081", "Glu->Xle", "Glu->Leu/Ile substitution.", false}, {UNIMOD_Glu__Met, "UNIMOD:1082", "Glu->Met", "Glu->Met substitution.", false}, {UNIMOD_Glu__Asn, "UNIMOD:1083", "Glu->Asn", "Glu->Asn substitution.", false}, {UNIMOD_Glu__Pro, "UNIMOD:1084", "Glu->Pro", "Glu->Pro substitution.", false}, {UNIMOD_Glu__Arg, "UNIMOD:1085", "Glu->Arg", "Glu->Arg substitution.", false}, {UNIMOD_Glu__Ser, "UNIMOD:1086", "Glu->Ser", "Glu->Ser substitution.", false}, {UNIMOD_Glu__Thr, "UNIMOD:1087", "Glu->Thr", "Glu->Thr substitution.", false}, {UNIMOD_Glu__Trp, "UNIMOD:1088", "Glu->Trp", "Glu->Trp substitution.", false}, {UNIMOD_Glu__Tyr, "UNIMOD:1089", "Glu->Tyr", "Glu->Tyr substitution.", false}, {UNIMOD_Phe__Ala, "UNIMOD:1090", "Phe->Ala", "Phe->Ala substitution.", false}, {UNIMOD_Phe__Asp, "UNIMOD:1091", "Phe->Asp", "Phe->Asp substitution.", false}, {UNIMOD_Phe__Glu, "UNIMOD:1092", "Phe->Glu", "Phe->Glu substitution.", false}, {UNIMOD_Phe__Gly, "UNIMOD:1093", "Phe->Gly", "Phe->Gly substitution.", false}, {UNIMOD_Phe__His, "UNIMOD:1094", "Phe->His", "Phe->His substitution.", false}, {UNIMOD_Phe__Lys, "UNIMOD:1095", "Phe->Lys", "Phe->Lys substitution.", false}, {UNIMOD_Phe__Met, "UNIMOD:1096", "Phe->Met", "Phe->Met substitution.", false}, {UNIMOD_Phe__Asn, "UNIMOD:1097", "Phe->Asn", "Phe->Asn substitution.", false}, {UNIMOD_Phe__Pro, "UNIMOD:1098", "Phe->Pro", "Phe->Pro substitution.", false}, {UNIMOD_Phe__Gln, "UNIMOD:1099", "Phe->Gln", "Phe->Gln substitution.", false}, {UNIMOD_Phe__Arg, "UNIMOD:1100", "Phe->Arg", "Phe->Arg substitution.", false}, {UNIMOD_Phe__Thr, "UNIMOD:1101", "Phe->Thr", "Phe->Thr substitution.", false}, {UNIMOD_Phe__Trp, "UNIMOD:1102", "Phe->Trp", "Phe->Trp substitution.", false}, {UNIMOD_Gly__Phe, "UNIMOD:1103", "Gly->Phe", "Gly->Phe substitution.", false}, {UNIMOD_Gly__His, "UNIMOD:1104", "Gly->His", "Gly->His substitution.", false}, {UNIMOD_Gly__Xle, "UNIMOD:1105", "Gly->Xle", "Gly->Leu/Ile substitution.", false}, {UNIMOD_Gly__Lys, "UNIMOD:1106", "Gly->Lys", "Gly->Lys substitution.", false}, {UNIMOD_Gly__Met, "UNIMOD:1107", "Gly->Met", "Gly->Met substitution.", false}, {UNIMOD_Gly__Asn, "UNIMOD:1108", "Gly->Asn", "Gly->Asn substitution.", false}, {UNIMOD_Gly__Pro, "UNIMOD:1109", "Gly->Pro", "Gly->Pro substitution.", false}, {UNIMOD_Gly__Gln, "UNIMOD:1110", "Gly->Gln", "Gly->Gln substitution.", false}, {UNIMOD_Gly__Thr, "UNIMOD:1111", "Gly->Thr", "Gly->Thr substitution.", false}, {UNIMOD_Gly__Tyr, "UNIMOD:1112", "Gly->Tyr", "Gly->Tyr substitution.", false}, {UNIMOD_His__Ala, "UNIMOD:1113", "His->Ala", "His->Ala substitution.", false}, {UNIMOD_His__Cys, "UNIMOD:1114", "His->Cys", "His->Cys substitution.", false}, {UNIMOD_His__Glu, "UNIMOD:1115", "His->Glu", "His->Glu substitution.", false}, {UNIMOD_His__Phe, "UNIMOD:1116", "His->Phe", "His->Phe substitution.", false}, {UNIMOD_His__Gly, "UNIMOD:1117", "His->Gly", "His->Gly substitution.", false}, {UNIMOD_His__Lys, "UNIMOD:1119", "His->Lys", "His->Lys substitution.", false}, {UNIMOD_His__Met, "UNIMOD:1120", "His->Met", "His->Met substitution.", false}, {UNIMOD_His__Ser, "UNIMOD:1121", "His->Ser", "His->Ser substitution.", false}, {UNIMOD_His__Thr, "UNIMOD:1122", "His->Thr", "His->Thr substitution.", false}, {UNIMOD_His__Val, "UNIMOD:1123", "His->Val", "His->Val substitution.", false}, {UNIMOD_His__Trp, "UNIMOD:1124", "His->Trp", "His->Trp substitution.", false}, {UNIMOD_Xle__Ala, "UNIMOD:1125", "Xle->Ala", "Leu/Ile->Ala substitution.", false}, {UNIMOD_Xle__Cys, "UNIMOD:1126", "Xle->Cys", "Leu/Ile->Cys substitution.", false}, {UNIMOD_Xle__Asp, "UNIMOD:1127", "Xle->Asp", "Leu/Ile->Asp substitution.", false}, {UNIMOD_Xle__Glu, "UNIMOD:1128", "Xle->Glu", "Leu/Ile->Glu substitution.", false}, {UNIMOD_Xle__Gly, "UNIMOD:1129", "Xle->Gly", "Leu/Ile->Gly substitution.", false}, {UNIMOD_Xle__Tyr, "UNIMOD:1130", "Xle->Tyr", "Leu/Ile->Tyr substitution.", false}, {UNIMOD_Lys__Ala, "UNIMOD:1131", "Lys->Ala", "Lys->Ala substitution.", false}, {UNIMOD_Lys__Cys, "UNIMOD:1132", "Lys->Cys", "Lys->Cys substitution.", false}, {UNIMOD_Lys__Asp, "UNIMOD:1133", "Lys->Asp", "Lys->Asp substitution.", false}, {UNIMOD_Lys__Phe, "UNIMOD:1134", "Lys->Phe", "Lys->Phe substitution.", false}, {UNIMOD_Lys__Gly, "UNIMOD:1135", "Lys->Gly", "Lys->Gly substitution.", false}, {UNIMOD_Lys__His, "UNIMOD:1136", "Lys->His", "Lys->His substitution.", false}, {UNIMOD_Lys__Pro, "UNIMOD:1137", "Lys->Pro", "Lys->Pro substitution.", false}, {UNIMOD_Lys__Ser, "UNIMOD:1138", "Lys->Ser", "Lys->Ser substitution.", false}, {UNIMOD_Lys__Val, "UNIMOD:1139", "Lys->Val", "Lys->Val substitution.", false}, {UNIMOD_Lys__Trp, "UNIMOD:1140", "Lys->Trp", "Lys->Trp substitution.", false}, {UNIMOD_Lys__Tyr, "UNIMOD:1141", "Lys->Tyr", "Lys->Tyr substitution.", false}, {UNIMOD_Met__Ala, "UNIMOD:1142", "Met->Ala", "Met->Ala substitution.", false}, {UNIMOD_Met__Cys, "UNIMOD:1143", "Met->Cys", "Met->Cys substitution.", false}, {UNIMOD_Met__Asp, "UNIMOD:1144", "Met->Asp", "Met->Asp substitution.", false}, {UNIMOD_Met__Glu, "UNIMOD:1145", "Met->Glu", "Met->Glu substitution.", false}, {UNIMOD_Met__Phe, "UNIMOD:1146", "Met->Phe", "Met->Phe substitution.", false}, {UNIMOD_Met__Gly, "UNIMOD:1147", "Met->Gly", "Met->Gly substitution.", false}, {UNIMOD_Met__His, "UNIMOD:1148", "Met->His", "Met->His substitution.", false}, {UNIMOD_Met__Asn, "UNIMOD:1149", "Met->Asn", "Met->Asn substitution.", false}, {UNIMOD_Met__Pro, "UNIMOD:1150", "Met->Pro", "Met->Pro substitution.", false}, {UNIMOD_Met__Gln, "UNIMOD:1151", "Met->Gln", "Met->Gln substitution.", false}, {UNIMOD_Met__Ser, "UNIMOD:1152", "Met->Ser", "Met->Ser substitution.", false}, {UNIMOD_Met__Trp, "UNIMOD:1153", "Met->Trp", "Met->Trp substitution.", false}, {UNIMOD_Met__Tyr, "UNIMOD:1154", "Met->Tyr", "Met->Tyr substitution.", false}, {UNIMOD_Asn__Ala, "UNIMOD:1155", "Asn->Ala", "Asn->Ala substitution.", false}, {UNIMOD_Asn__Cys, "UNIMOD:1156", "Asn->Cys", "Asn->Cys substitution.", false}, {UNIMOD_Asn__Glu, "UNIMOD:1157", "Asn->Glu", "Asn->Glu substitution.", false}, {UNIMOD_Asn__Phe, "UNIMOD:1158", "Asn->Phe", "Asn->Phe substitution.", false}, {UNIMOD_Asn__Gly, "UNIMOD:1159", "Asn->Gly", "Asn->Gly substitution.", false}, {UNIMOD_Asn__Met, "UNIMOD:1160", "Asn->Met", "Asn->Met substitution.", false}, {UNIMOD_Asn__Pro, "UNIMOD:1161", "Asn->Pro", "Asn->Pro substitution.", false}, {UNIMOD_Asn__Gln, "UNIMOD:1162", "Asn->Gln", "Asn->Gln substitution.", false}, {UNIMOD_Asn__Arg, "UNIMOD:1163", "Asn->Arg", "Asn->Arg substitution.", false}, {UNIMOD_Asn__Val, "UNIMOD:1164", "Asn->Val", "Asn->Val substitution.", false}, {UNIMOD_Asn__Trp, "UNIMOD:1165", "Asn->Trp", "Asn->Trp substitution.", false}, {UNIMOD_Pro__Cys, "UNIMOD:1166", "Pro->Cys", "Pro->Cys substitution.", false}, {UNIMOD_Pro__Asp, "UNIMOD:1167", "Pro->Asp", "Pro->Asp substitution.", false}, {UNIMOD_Pro__Glu, "UNIMOD:1168", "Pro->Glu", "Pro->Glu substitution.", false}, {UNIMOD_Pro__Phe, "UNIMOD:1169", "Pro->Phe", "Pro->Phe substitution.", false}, {UNIMOD_Pro__Gly, "UNIMOD:1170", "Pro->Gly", "Pro->Gly substitution.", false}, {UNIMOD_Pro__Lys, "UNIMOD:1171", "Pro->Lys", "Pro->Lys substitution.", false}, {UNIMOD_Pro__Met, "UNIMOD:1172", "Pro->Met", "Pro->Met substitution.", false}, {UNIMOD_Pro__Asn, "UNIMOD:1173", "Pro->Asn", "Pro->Asn substitution.", false}, {UNIMOD_Pro__Val, "UNIMOD:1174", "Pro->Val", "Pro->Val substitution.", false}, {UNIMOD_Pro__Trp, "UNIMOD:1175", "Pro->Trp", "Pro->Trp substitution.", false}, {UNIMOD_Pro__Tyr, "UNIMOD:1176", "Pro->Tyr", "Pro->Tyr substitution.", false}, {UNIMOD_Gln__Ala, "UNIMOD:1177", "Gln->Ala", "Gln->Ala substitution.", false}, {UNIMOD_Gln__Cys, "UNIMOD:1178", "Gln->Cys", "Gln->Cys substitution.", false}, {UNIMOD_Gln__Asp, "UNIMOD:1179", "Gln->Asp", "Gln->Asp substitution.", false}, {UNIMOD_Gln__Phe, "UNIMOD:1180", "Gln->Phe", "Gln->Phe substitution.", false}, {UNIMOD_Gln__Gly, "UNIMOD:1181", "Gln->Gly", "Gln->Gly substitution.", false}, {UNIMOD_Gln__Met, "UNIMOD:1182", "Gln->Met", "Gln->Met substitution.", false}, {UNIMOD_Gln__Asn, "UNIMOD:1183", "Gln->Asn", "Gln->Asn substitution.", false}, {UNIMOD_Gln__Ser, "UNIMOD:1184", "Gln->Ser", "Gln->Ser substitution.", false}, {UNIMOD_Gln__Thr, "UNIMOD:1185", "Gln->Thr", "Gln->Thr substitution.", false}, {UNIMOD_Gln__Val, "UNIMOD:1186", "Gln->Val", "Gln->Val substitution.", false}, {UNIMOD_Gln__Trp, "UNIMOD:1187", "Gln->Trp", "Gln->Trp substitution.", false}, {UNIMOD_Gln__Tyr, "UNIMOD:1188", "Gln->Tyr", "Gln->Tyr substitution.", false}, {UNIMOD_Arg__Ala, "UNIMOD:1189", "Arg->Ala", "Arg->Ala substitution.", false}, {UNIMOD_Arg__Asp, "UNIMOD:1190", "Arg->Asp", "Arg->Asp substitution.", false}, {UNIMOD_Arg__Glu, "UNIMOD:1191", "Arg->Glu", "Arg->Glu substitution.", false}, {UNIMOD_Arg__Asn, "UNIMOD:1192", "Arg->Asn", "Arg->Asn substitution.", false}, {UNIMOD_Arg__Val, "UNIMOD:1193", "Arg->Val", "Arg->Val substitution.", false}, {UNIMOD_Arg__Tyr, "UNIMOD:1194", "Arg->Tyr", "Arg->Tyr substitution.", false}, {UNIMOD_Arg__Phe, "UNIMOD:1195", "Arg->Phe", "Arg->Phe substitution.", false}, {UNIMOD_Ser__Asp, "UNIMOD:1196", "Ser->Asp", "Ser->Asp substitution.", false}, {UNIMOD_Ser__Glu, "UNIMOD:1197", "Ser->Glu", "Ser->Glu substitution.", false}, {UNIMOD_Ser__His, "UNIMOD:1198", "Ser->His", "Ser->His substitution.", false}, {UNIMOD_Ser__Lys, "UNIMOD:1199", "Ser->Lys", "Ser->Lys substitution.", false}, {UNIMOD_Ser__Met, "UNIMOD:1200", "Ser->Met", "Ser->Met substitution.", false}, {UNIMOD_Ser__Gln, "UNIMOD:1201", "Ser->Gln", "Ser->Gln substitution.", false}, {UNIMOD_Ser__Val, "UNIMOD:1202", "Ser->Val", "Ser->Val substitution.", false}, {UNIMOD_Thr__Cys, "UNIMOD:1203", "Thr->Cys", "Thr->Cys substitution.", false}, {UNIMOD_Thr__Asp, "UNIMOD:1204", "Thr->Asp", "Thr->Asp substitution.", false}, {UNIMOD_Thr__Glu, "UNIMOD:1205", "Thr->Glu", "Thr->Glu substitution.", false}, {UNIMOD_Thr__Phe, "UNIMOD:1206", "Thr->Phe", "Thr->Phe substitution.", false}, {UNIMOD_Thr__Gly, "UNIMOD:1207", "Thr->Gly", "Thr->Gly substitution.", false}, {UNIMOD_Thr__His, "UNIMOD:1208", "Thr->His", "Thr->His substitution.", false}, {UNIMOD_Thr__Gln, "UNIMOD:1209", "Thr->Gln", "Thr->Gln substitution.", false}, {UNIMOD_Thr__Val, "UNIMOD:1210", "Thr->Val", "Thr->Val substitution.", false}, {UNIMOD_Thr__Trp, "UNIMOD:1211", "Thr->Trp", "Thr->Trp substitution.", false}, {UNIMOD_Thr__Tyr, "UNIMOD:1212", "Thr->Tyr", "Thr->Tyr substitution.", false}, {UNIMOD_Val__Cys, "UNIMOD:1213", "Val->Cys", "Val->Cys substitution.", false}, {UNIMOD_Val__His, "UNIMOD:1214", "Val->His", "Val->His substitution.", false}, {UNIMOD_Val__Lys, "UNIMOD:1215", "Val->Lys", "Val->Lys substitution.", false}, {UNIMOD_Val__Asn, "UNIMOD:1216", "Val->Asn", "Val->Asn substitution.", false}, {UNIMOD_Val__Pro, "UNIMOD:1217", "Val->Pro", "Val->Pro substitution.", false}, {UNIMOD_Val__Gln, "UNIMOD:1218", "Val->Gln", "Val->Gln substitution.", false}, {UNIMOD_Val__Arg, "UNIMOD:1219", "Val->Arg", "Val->Arg substitution.", false}, {UNIMOD_Val__Ser, "UNIMOD:1220", "Val->Ser", "Val->Ser substitution.", false}, {UNIMOD_Val__Thr, "UNIMOD:1221", "Val->Thr", "Val->Thr substitution.", false}, {UNIMOD_Val__Trp, "UNIMOD:1222", "Val->Trp", "Val->Trp substitution.", false}, {UNIMOD_Val__Tyr, "UNIMOD:1223", "Val->Tyr", "Val->Tyr substitution.", false}, {UNIMOD_Trp__Ala, "UNIMOD:1224", "Trp->Ala", "Trp->Ala substitution.", false}, {UNIMOD_Trp__Asp, "UNIMOD:1225", "Trp->Asp", "Trp->Asp substitution.", false}, {UNIMOD_Trp__Glu, "UNIMOD:1226", "Trp->Glu", "Trp->Glu substitution.", false}, {UNIMOD_Trp__Phe, "UNIMOD:1227", "Trp->Phe", "Trp->Phe substitution.", false}, {UNIMOD_Trp__His, "UNIMOD:1228", "Trp->His", "Trp->His substitution.", false}, {UNIMOD_Trp__Lys, "UNIMOD:1229", "Trp->Lys", "Trp->Lys substitution.", false}, {UNIMOD_Trp__Met, "UNIMOD:1230", "Trp->Met", "Trp->Met substitution.", false}, {UNIMOD_Trp__Asn, "UNIMOD:1231", "Trp->Asn", "Trp->Asn substitution.", false}, {UNIMOD_Trp__Pro, "UNIMOD:1232", "Trp->Pro", "Trp->Pro substitution.", false}, {UNIMOD_Trp__Gln, "UNIMOD:1233", "Trp->Gln", "Trp->Gln substitution.", false}, {UNIMOD_Trp__Thr, "UNIMOD:1234", "Trp->Thr", "Trp->Thr substitution.", false}, {UNIMOD_Trp__Val, "UNIMOD:1235", "Trp->Val", "Trp->Val substitution.", false}, {UNIMOD_Trp__Tyr, "UNIMOD:1236", "Trp->Tyr", "Trp->Tyr substitution.", false}, {UNIMOD_Tyr__Ala, "UNIMOD:1237", "Tyr->Ala", "Tyr->Ala substitution.", false}, {UNIMOD_Tyr__Glu, "UNIMOD:1238", "Tyr->Glu", "Tyr->Glu substitution.", false}, {UNIMOD_Tyr__Gly, "UNIMOD:1239", "Tyr->Gly", "Tyr->Gly substitution.", false}, {UNIMOD_Tyr__Lys, "UNIMOD:1240", "Tyr->Lys", "Tyr->Lys substitution.", false}, {UNIMOD_Tyr__Met, "UNIMOD:1241", "Tyr->Met", "Tyr->Met substitution.", false}, {UNIMOD_Tyr__Pro, "UNIMOD:1242", "Tyr->Pro", "Tyr->Pro substitution.", false}, {UNIMOD_Tyr__Gln, "UNIMOD:1243", "Tyr->Gln", "Tyr->Gln substitution.", false}, {UNIMOD_Tyr__Arg, "UNIMOD:1244", "Tyr->Arg", "Tyr->Arg substitution.", false}, {UNIMOD_Tyr__Thr, "UNIMOD:1245", "Tyr->Thr", "Tyr->Thr substitution.", false}, {UNIMOD_Tyr__Val, "UNIMOD:1246", "Tyr->Val", "Tyr->Val substitution.", false}, {UNIMOD_Tyr__Trp, "UNIMOD:1247", "Tyr->Trp", "Tyr->Trp substitution.", false}, {UNIMOD_Tyr__Xle, "UNIMOD:1248", "Tyr->Xle", "Tyr->Leu/Ile substitution.", false}, {UNIMOD_AHA_SS, "UNIMOD:1249", "AHA-SS", "Azidohomoalanine coupled to reductively cleaved tag.", false}, {UNIMOD_AHA_SS_CAM, "UNIMOD:1250", "AHA-SS_CAM", "Carbamidomethylated form of reductively cleaved tag coupled to azidohomoalanine.", false}, {UNIMOD_Biotin_Thermo_33033, "UNIMOD:1251", "Biotin:Thermo-33033", "Sulfo-SBED Label Photoreactive Biotin Crosslinker.", false}, {UNIMOD_Biotin_Thermo_33033_H, "UNIMOD:1252", "Biotin:Thermo-33033-H", "Sulfo-SBED Label Photoreactive Biotin Crosslinker minus Hydrogen.", false}, {UNIMOD_2_monomethylsuccinyl, "UNIMOD:1253", "2-monomethylsuccinyl", "S-(2-monomethylsuccinyl) cysteine.", false}, {UNIMOD_Saligenin, "UNIMOD:1254", "Saligenin", "O-toluene.", false}, {UNIMOD_Cresylphosphate, "UNIMOD:1255", "Cresylphosphate", "O-toluyl-phosphorylation.", false}, {UNIMOD_CresylSaligeninPhosphate, "UNIMOD:1256", "CresylSaligeninPhosphate", "Cresyl-Saligenin-phosphorylation.", false}, {UNIMOD_Ub_Br2, "UNIMOD:1257", "Ub-Br2", "Ub Bromide probe addition.", false}, {UNIMOD_Ub_VME, "UNIMOD:1258", "Ub-VME", "Ubiquitin vinylmethylester.", false}, {UNIMOD_Ub_amide, "UNIMOD:1260", "Ub-amide", "Ub amide probe addition.", false}, {UNIMOD_Ub_fluorescein, "UNIMOD:1261", "Ub-fluorescein", "Ub Fluorescein probe addition.", false}, {UNIMOD_2_dimethylsuccinyl, "UNIMOD:1262", "2-dimethylsuccinyl", "S-(2-dimethylsuccinyl) cysteine.", false}, {UNIMOD_Gly, "UNIMOD:1263", "Gly", "Addition of Glycine.", false}, {UNIMOD_pupylation, "UNIMOD:1264", "pupylation", "Addition of GGE.", false}, {UNIMOD_Label_13C_4_, "UNIMOD:1266", "Label:13C(4)", "13C4 Methionine label.", false}, {UNIMOD_Label_13C_4__Oxidation, "UNIMOD:1267", "Label:13C(4)+Oxidation", "Oxidised 13C4 labelled Methionine.", false}, {UNIMOD_HCysThiolactone, "UNIMOD:1270", "HCysThiolactone", "N-Homocysteine thiolactone.", false}, {UNIMOD_HCysteinyl, "UNIMOD:1271", "HCysteinyl", "S-homocysteinylation.", false}, {UNIMOD_UgiJoullie, "UNIMOD:1276", "UgiJoullie", "Side reaction of HisTag.", false}, {UNIMOD_Dipyridyl, "UNIMOD:1277", "Dipyridyl", "Cys modified with dipy ligand.", false}, {UNIMOD_Furan, "UNIMOD:1278", "Furan", "Chemical modification of the iodinated sites of thyroglobulin by Suzuki reaction.", false}, {UNIMOD_Difuran, "UNIMOD:1279", "Difuran", "Chemical modification of the diiodinated sites of thyroglobulin by Suzuki reaction.", false}, {UNIMOD_BMP_piperidinol, "UNIMOD:1281", "BMP-piperidinol", "1-methyl-3-benzoyl-4-hydroxy-4-phenylpiperidine.", false}, {UNIMOD_UgiJoullieProGly, "UNIMOD:1282", "UgiJoullieProGly", "Side reaction of PG with Side chain of aspartic or glutamic acid.", false}, {UNIMOD_UgiJoullieProGlyProGly, "UNIMOD:1283", "UgiJoullieProGlyProGly", "Side reaction of PGPG with Side chain of aspartic or glutamic acid.", false}, {UNIMOD_IMEHex_2_NeuAc_1_, "UNIMOD:1286", "IMEHex(2)NeuAc(1)", "Glycosylation with IME linked Hex(2) NeuAc.", false}, {UNIMOD_Arg_loss, "UNIMOD:1287", "Arg-loss", "Loss of arginine due to transpeptidation.", false}, {UNIMOD_Arg, "UNIMOD:1288", "Arg", "Addition of arginine due to transpeptidation.", false}, {UNIMOD_Butyryl, "UNIMOD:1289", "Butyryl", "Butyryl.", false}, {UNIMOD_Dicarbamidomethyl, "UNIMOD:1290", "Dicarbamidomethyl", "Double Carbamidomethylation.", false}, {UNIMOD_Dimethyl_2H_6_, "UNIMOD:1291", "Dimethyl:2H(6)", "Dimethyl-Medium.", false}, {UNIMOD_GGQ, "UNIMOD:1292", "GGQ", "SUMOylation leaving GlyGlyGln.", false}, {UNIMOD_QTGG, "UNIMOD:1293", "QTGG", "SUMOylation leaving GlnThrGlyGly.", false}, {UNIMOD_Label_13C_3_, "UNIMOD:1296", "Label:13C(3)", "13C3 label for SILAC.", false}, {UNIMOD_Label_13C_3_15N_1_, "UNIMOD:1297", "Label:13C(3)15N(1)", "13C3 15N1 label for SILAC.", false}, {UNIMOD_Label_13C_4_15N_1_, "UNIMOD:1298", "Label:13C(4)15N(1)", "13C4 15N1 label for SILAC.", false}, {UNIMOD_Label_2H_10_, "UNIMOD:1299", "Label:2H(10)", "2H(10) label.", false}, {UNIMOD_Label_2H_4_13C_1_, "UNIMOD:1300", "Label:2H(4)13C(1)", "Label:2H(4)13C(1).", false}, {UNIMOD_Lys, "UNIMOD:1301", "Lys", "Addition of lysine due to transpeptidation.", false}, {UNIMOD_mTRAQ_13C_6_15N_2_, "UNIMOD:1302", "mTRAQ:13C(6)15N(2)", "MTRAQ heavy.", false}, {UNIMOD_NeuAc, "UNIMOD:1303", "NeuAc", "N-acetyl neuraminic acid.", false}, {UNIMOD_NeuGc, "UNIMOD:1304", "NeuGc", "N-glycoyl neuraminic acid.", false}, {UNIMOD_Propyl, "UNIMOD:1305", "Propyl", "Propyl.", false}, {UNIMOD_Propyl_2H_6_, "UNIMOD:1306", "Propyl:2H(6)", "Propyl:2H(6).", false}, {UNIMOD_Propiophenone, "UNIMOD:1310", "Propiophenone", "Propiophenone.", false}, {UNIMOD_Delta_H_6_C_3_O_1_, "UNIMOD:1312", "Delta:H(6)C(3)O(1)", "Reduced acrolein addition +58.", false}, {UNIMOD_Delta_H_8_C_6_O_1_, "UNIMOD:1313", "Delta:H(8)C(6)O(1)", "Reduced acrolein addition +96.", false}, {UNIMOD_biotinAcrolein298, "UNIMOD:1314", "biotinAcrolein298", "Biotin hydrazide labeled acrolein addition +298.", false}, {UNIMOD_MM_diphenylpentanone, "UNIMOD:1315", "MM-diphenylpentanone", "3-methyl-5-(methylamino)-1,3-diphenylpentan-1-one.", false}, {UNIMOD_EHD_diphenylpentanone, "UNIMOD:1317", "EHD-diphenylpentanone", "2-ethyl-3-hydroxy-1,3-diphenylpentan-1-one.", false}, {UNIMOD_Biotin_Thermo_21901_2H2O, "UNIMOD:1320", "Biotin:Thermo-21901+2H2O", "Maleimide-Biotin + 2Water.", false}, {UNIMOD_DiLeu4plex115, "UNIMOD:1321", "DiLeu4plex115", "Accurate mass for DiLeu 115 isobaric tag.", false}, {UNIMOD_DiLeu4plex, "UNIMOD:1322", "DiLeu4plex", "Accurate mass for DiLeu 116 isobaric tag.", false}, {UNIMOD_DiLeu4plex117, "UNIMOD:1323", "DiLeu4plex117", "Accurate mass for DiLeu 117 isobaric tag.", false}, {UNIMOD_DiLeu4plex118, "UNIMOD:1324", "DiLeu4plex118", "Accurate mass for DiLeu 118 isobaric tag.", false}, {UNIMOD_NEMsulfur, "UNIMOD:1326", "NEMsulfur", "N-ethylmaleimideSulfur.", false}, {UNIMOD_SulfurDioxide, "UNIMOD:1327", "SulfurDioxide", "SulfurDioxide.", false}, {UNIMOD_NEMsulfurWater, "UNIMOD:1328", "NEMsulfurWater", "N-ethylmaleimideSulfurWater.", false}, {UNIMOD_bisANS_sulfonates, "UNIMOD:1330", "bisANS-sulfonates", "BisANS with loss of both sulfonates.", false}, {UNIMOD_DNCB_hapten, "UNIMOD:1331", "DNCB_hapten", "Chemical reaction with 2,4-dinitro-1-chloro benzene (DNCB).", false}, {UNIMOD_Biotin_Thermo_21911, "UNIMOD:1340", "Biotin:Thermo-21911", "Biotin-PEG11-maleimide.", false}, {UNIMOD_iodoTMT, "UNIMOD:1341", "iodoTMT", "Native iodoacetyl Tandem Mass Tag®.", false}, {UNIMOD_iodoTMT6plex, "UNIMOD:1342", "iodoTMT6plex", "Sixplex iodoacetyl Tandem Mass Tag®.", false}, {UNIMOD_Gluconoylation, "UNIMOD:1343", "Gluconoylation", "Gluconoylation.", false}, {UNIMOD_Phosphogluconoylation, "UNIMOD:1344", "Phosphogluconoylation", "Phosphogluconoylation.", false}, {UNIMOD_PS_Hapten, "UNIMOD:1345", "PS_Hapten", "Reaction with phenyl salicylate (PS).", false}, {UNIMOD_Cy3_maleimide, "UNIMOD:1348", "Cy3-maleimide", "Cy3 Maleimide mono-Reactive dye.", false}, {UNIMOD_benzylguanidine, "UNIMOD:1349", "benzylguanidine", "Modification of the lysine side chain from NH2 to guanidine with a H removed in favor of a benzyl group.", false}, {UNIMOD_CarboxymethylDMAP, "UNIMOD:1350", "CarboxymethylDMAP", "A fixed +1 charge tag attached to the N-terminus of peptides.", false}, {UNIMOD_azole, "UNIMOD:1355", "azole", "Formation of five membered aromatic heterocycle.", false}, {UNIMOD_phosphoRibosyl, "UNIMOD:1356", "phosphoRibosyl", "Phosphate-ribosylation.", false}, {UNIMOD_NEM_2H_5__H2O, "UNIMOD:1358", "NEM:2H(5)+H2O", "D5 N-ethylmaleimide+water on cysteines.", false}, {UNIMOD_Crotonyl, "UNIMOD:1363", "Crotonyl", "Crotonylation.", false}, {UNIMOD_O_Et_N_diMePhospho, "UNIMOD:1364", "O-Et-N-diMePhospho", "O-ethyl, N-dimethyl phosphate.", false}, {UNIMOD_N_dimethylphosphate, "UNIMOD:1365", "N-dimethylphosphate", "N-dimethylphosphate.", false}, {UNIMOD_dHex_1_Hex_1_, "UNIMOD:1367", "dHex(1)Hex(1)", "Hex1dHex1.", false}, {UNIMOD_Methyl_2H_3__Acetyl_2H_3_, "UNIMOD:1368", "Methyl:2H(3)+Acetyl:2H(3)", "3-fold methylated lysine labelled with Acetyl_heavy.", false}, {UNIMOD_Label_2H_3__Oxidation, "UNIMOD:1370", "Label:2H(3)+Oxidation", "Oxidised 2H(3) labelled Methionine.", false}, {UNIMOD_Trimethyl_2H_9_, "UNIMOD:1371", "Trimethyl:2H(9)", "3-fold methylation with deuterated methyl groups.", false}, {UNIMOD_Acetyl_13C_2_, "UNIMOD:1372", "Acetyl:13C(2)", "Heavy acetylation.", false}, {UNIMOD_dHex_1_Hex_2_, "UNIMOD:1375", "dHex(1)Hex(2)", "Hex2dHex1.", false}, {UNIMOD_dHex_1_Hex_3_, "UNIMOD:1376", "dHex(1)Hex(3)", "Hex3dHex1.", false}, {UNIMOD_dHex_1_Hex_4_, "UNIMOD:1377", "dHex(1)Hex(4)", "Hex4dHex1.", false}, {UNIMOD_dHex_1_Hex_5_, "UNIMOD:1378", "dHex(1)Hex(5)", "Hex5dHex1.", false}, {UNIMOD_dHex_1_Hex_6_, "UNIMOD:1379", "dHex(1)Hex(6)", "Hex6dHex1.", false}, {UNIMOD_methylsulfonylethyl, "UNIMOD:1380", "methylsulfonylethyl", "Reaction with methyl vinyl sulfone.", false}, {UNIMOD_ethylsulfonylethyl, "UNIMOD:1381", "ethylsulfonylethyl", "Reaction with ethyl vinyl sulfone.", false}, {UNIMOD_phenylsulfonylethyl, "UNIMOD:1382", "phenylsulfonylethyl", "Reaction with phenyl vinyl sulfone.", false}, {UNIMOD_PyridoxalPhosphateH2, "UNIMOD:1383", "PyridoxalPhosphateH2", "PLP bound to lysine reduced by sodium borohydride (NaBH4) to create amine linkage.", false}, {UNIMOD_Homocysteic_acid, "UNIMOD:1384", "Homocysteic_acid", "Methionine oxidation to homocysteic acid.", false}, {UNIMOD_Hydroxamic_acid, "UNIMOD:1385", "Hydroxamic_acid", "Conversion of carboxylic acid to hydroxamic acid.", false}, {UNIMOD_3_phosphoglyceryl, "UNIMOD:1387", "3-phosphoglyceryl", "3-phosphoglyceryl.", false}, {UNIMOD_HN2_mustard, "UNIMOD:1388", "HN2_mustard", "Modification by hydroxylated mechloroethamine (HN-2).", false}, {UNIMOD_HN3_mustard, "UNIMOD:1389", "HN3_mustard", "Modification by hydroxylated tris-(2-chloroethyl)amine (HN-3).", false}, {UNIMOD_Oxidation_NEM, "UNIMOD:1390", "Oxidation+NEM", "N-ethylmaleimide on cysteine sulfenic acid.", false}, {UNIMOD_NHS_fluorescein, "UNIMOD:1391", "NHS-fluorescein", "Fluorescein-hexanoate-NHS hydrolysis.", false}, {UNIMOD_DiART6plex, "UNIMOD:1392", "DiART6plex", "Representative mass and accurate mass for 114.", false}, {UNIMOD_DiART6plex115, "UNIMOD:1393", "DiART6plex115", "Accurate mass for DiART6plex 115.", false}, {UNIMOD_DiART6plex116_119, "UNIMOD:1394", "DiART6plex116/119", "Accurate mass for DiART6plex 116 and 119.", false}, {UNIMOD_DiART6plex117, "UNIMOD:1395", "DiART6plex117", "Accurate mass for DiART6plex 117.", false}, {UNIMOD_DiART6plex118, "UNIMOD:1396", "DiART6plex118", "Accurate mass for DiART6plex 118.", false}, {UNIMOD_Iodoacetanilide, "UNIMOD:1397", "Iodoacetanilide", "Iodoacetanilide derivative.", false}, {UNIMOD_Iodoacetanilide_13C_6_, "UNIMOD:1398", "Iodoacetanilide:13C(6)", "13C labelled iodoacetanilide derivative.", false}, {UNIMOD_Dap_DSP, "UNIMOD:1399", "Dap-DSP", "Diaminopimelic acid-DSP monolinked.", false}, {UNIMOD_MurNAc, "UNIMOD:1400", "MurNAc", "N-Acetylmuramic acid.", false}, {UNIMOD_Label_2H_7_15N_4_, "UNIMOD:1402", "Label:2H(7)15N(4)", "Label:2H(7)15N(4).", false}, {UNIMOD_Label_2H_6_15N_1_, "UNIMOD:1403", "Label:2H(6)15N(1)", "Label:2H(6)15N(1).", false}, {UNIMOD_EEEDVIEVYQEQTGG, "UNIMOD:1405", "EEEDVIEVYQEQTGG", "Sumoylation by SUMO-1 after Cyanogen bromide (CNBr) cleavage.", false}, {UNIMOD_EDEDTIDVFQQQTGG, "UNIMOD:1406", "EDEDTIDVFQQQTGG", "Sumoylation by SUMO-2/3 after Cyanogen bromide (CNBr) cleavage.", false}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_2_, "UNIMOD:1408", "Hex(5)HexNAc(4)NeuAc(2)", "Hex(5) HexNAc(4) NeuAc(2).", false}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_1_, "UNIMOD:1409", "Hex(5)HexNAc(4)NeuAc(1)", "Hex(5) HexNAc(4) NeuAc.", false}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_NeuAc_1_, "UNIMOD:1410", "dHex(1)Hex(5)HexNAc(4)NeuAc(1)", "DHex Hex(5) HexNAc(4) NeuAc.", false}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_NeuAc_2_, "UNIMOD:1411", "dHex(1)Hex(5)HexNAc(4)NeuAc(2)", "DHex Hex(5) HexNAc(4) NeuAc(2).", false}, {UNIMOD_s_GlcNAc, "UNIMOD:1412", "s-GlcNAc", "O3S1HexNAc1.", false}, {UNIMOD_PhosphoHex_2_, "UNIMOD:1413", "PhosphoHex(2)", "H1O3P1Hex2.", false}, {UNIMOD_Trimethyl_13C_3_2H_9_, "UNIMOD:1414", "Trimethyl:13C(3)2H(9)", "3-fold methylation with fully labelled methyl groups.", false}, {UNIMOD_15N_oxobutanoic, "UNIMOD:1419", "15N-oxobutanoic", "Loss of ammonia (15N).", false}, {UNIMOD_spermine, "UNIMOD:1420", "spermine", "Spermine adduct.", false}, {UNIMOD_spermidine, "UNIMOD:1421", "spermidine", "Spermidine adduct.", false}, {UNIMOD_Biotin_Thermo_21330, "UNIMOD:1423", "Biotin:Thermo-21330", "Biotin_PEG4.", false}, {UNIMOD_Pentose, "UNIMOD:1425", "Pentose", "Pentose.", false}, {UNIMOD_Hex_1_Pent_1_, "UNIMOD:1426", "Hex(1)Pent(1)", "Hex Pent.", false}, {UNIMOD_Hex_1_HexA_1_, "UNIMOD:1427", "Hex(1)HexA(1)", "Hex HexA.", false}, {UNIMOD_Hex_1_Pent_2_, "UNIMOD:1428", "Hex(1)Pent(2)", "Hex Pent(2).", false}, {UNIMOD_Hex_1_HexNAc_1_Phos_1_, "UNIMOD:1429", "Hex(1)HexNAc(1)Phos(1)", "Hex HexNAc Phos.", false}, {UNIMOD_Hex_1_HexNAc_1_Sulf_1_, "UNIMOD:1430", "Hex(1)HexNAc(1)Sulf(1)", "Hex HexNAc Sulf.", false}, {UNIMOD_Hex_1_NeuAc_1_, "UNIMOD:1431", "Hex(1)NeuAc(1)", "Hex NeuAc.", false}, {UNIMOD_Hex_1_NeuGc_1_, "UNIMOD:1432", "Hex(1)NeuGc(1)", "Hex NeuGc.", false}, {UNIMOD_HexNAc_3_, "UNIMOD:1433", "HexNAc(3)", "HexNAc(3).", false}, {UNIMOD_HexNAc_1_NeuAc_1_, "UNIMOD:1434", "HexNAc(1)NeuAc(1)", "HexNAc NeuAc.", false}, {UNIMOD_HexNAc_1_NeuGc_1_, "UNIMOD:1435", "HexNAc(1)NeuGc(1)", "HexNAc NeuGc.", false}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_1_, "UNIMOD:1436", "Hex(1)HexNAc(1)dHex(1)Me(1)", "Hex HexNAc dHex Me.", false}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_2_, "UNIMOD:1437", "Hex(1)HexNAc(1)dHex(1)Me(2)", "Hex HexNAc dHex Me(2).", false}, {UNIMOD_Hex_2_HexNAc_1_, "UNIMOD:1438", "Hex(2)HexNAc(1)", "Hex(2) HexNAc.", false}, {UNIMOD_Hex_1_HexA_1_HexNAc_1_, "UNIMOD:1439", "Hex(1)HexA(1)HexNAc(1)", "Hex HexA HexNAc.", false}, {UNIMOD_Hex_2_HexNAc_1_Me_1_, "UNIMOD:1440", "Hex(2)HexNAc(1)Me(1)", "Hex(2) HexNAc Me.", false}, {UNIMOD_Hex_3_Phos_1_, "UNIMOD:1441", "Hex(3)Phos(1)", "Hex(3) Phos.", false}, {UNIMOD_Hex_1_NeuAc_1_Pent_1_, "UNIMOD:1442", "Hex(1)NeuAc(1)Pent(1)", "Hex NeuAc Pent.", false}, {UNIMOD_Hex_2_HexNAc_1_Sulf_1_, "UNIMOD:1443", "Hex(2)HexNAc(1)Sulf(1)", "Hex(2) HexNAc Sulf.", false}, {UNIMOD_Hex_2_NeuAc_1_, "UNIMOD:1444", "Hex(2)NeuAc(1)", "Hex(2) NeuAc.", false}, {UNIMOD_dHex_2_Hex_2_, "UNIMOD:1445", "dHex(2)Hex(2)", "Hex2 dHex2.", false}, {UNIMOD_dHex_1_Hex_2_HexA_1_, "UNIMOD:1446", "dHex(1)Hex(2)HexA(1)", "DHex Hex(2) HexA.", false}, {UNIMOD_Hex_1_HexNAc_2_Sulf_1_, "UNIMOD:1447", "Hex(1)HexNAc(2)Sulf(1)", "Hex HexNAc(2) Sulf.", false}, {UNIMOD_Hex_4_, "UNIMOD:1448", "Hex(4)", "Hex(4).", false}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_Pent_1_, "UNIMOD:1449", "dHex(1)Hex(2)HexNAc(2)Pent(1)", "DHex Hex(2) HexNAc(2) Pent.", false}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_1_, "UNIMOD:1450", "Hex(2)HexNAc(2)NeuAc(1)", "Hex(2) HexNAc(2) NeuAc.", false}, {UNIMOD_Hex_3_HexNAc_2_Pent_1_, "UNIMOD:1451", "Hex(3)HexNAc(2)Pent(1)", "Hex(3) HexNAc(2) Pent.", false}, {UNIMOD_Hex_4_HexNAc_2_, "UNIMOD:1452", "Hex(4)HexNAc(2)", "Hex(4) HexNAc(2).", false}, {UNIMOD_dHex_1_Hex_4_HexNAc_1_Pent_1_, "UNIMOD:1453", "dHex(1)Hex(4)HexNAc(1)Pent(1)", "DHex Hex(4) HexNAc Pent.", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Pent_1_, "UNIMOD:1454", "dHex(1)Hex(3)HexNAc(2)Pent(1)", "DHex Hex(3) HexNAc(2) Pent.", false}, {UNIMOD_Hex_3_HexNAc_2_NeuAc_1_, "UNIMOD:1455", "Hex(3)HexNAc(2)NeuAc(1)", "Hex(3) HexNAc(2) NeuAc.", false}, {UNIMOD_Hex_4_HexNAc_2_Pent_1_, "UNIMOD:1456", "Hex(4)HexNAc(2)Pent(1)", "Hex(4) HexNAc(2) Pent.", false}, {UNIMOD_Hex_3_HexNAc_3_Pent_1_, "UNIMOD:1457", "Hex(3)HexNAc(3)Pent(1)", "Hex(3) HexNAc(3) Pent.", false}, {UNIMOD_Hex_5_HexNAc_2_Phos_1_, "UNIMOD:1458", "Hex(5)HexNAc(2)Phos(1)", "Hex(5) HexNAc(2) Phos.", false}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_Pent_1_, "UNIMOD:1459", "dHex(1)Hex(4)HexNAc(2)Pent(1)", "DHex Hex(4) HexNAc(2) Pent.", false}, {UNIMOD_Hex_7_HexNAc_1_, "UNIMOD:1460", "Hex(7)HexNAc(1)", "Hex(7) HexNAc.", false}, {UNIMOD_Hex_4_HexNAc_2_NeuAc_1_, "UNIMOD:1461", "Hex(4)HexNAc(2)NeuAc(1)", "Hex(4) HexNAc(2) NeuAc.", false}, {UNIMOD_dHex_1_Hex_5_HexNAc_2_, "UNIMOD:1462", "dHex(1)Hex(5)HexNAc(2)", "DHex Hex(5) HexNAc(2).", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_1_, "UNIMOD:1463", "dHex(1)Hex(3)HexNAc(3)Pent(1)", "DHex Hex(3) HexNAc(3) Pent.", false}, {UNIMOD_Hex_3_HexNAc_4_Sulf_1_, "UNIMOD:1464", "Hex(3)HexNAc(4)Sulf(1)", "Hex(3) HexNAc(4) Sulf.", false}, {UNIMOD_Hex_6_HexNAc_2_, "UNIMOD:1465", "Hex(6)HexNAc(2)", "Hex(6) HexNAc(2).", false}, {UNIMOD_Hex_4_HexNAc_3_Pent_1_, "UNIMOD:1466", "Hex(4)HexNAc(3)Pent(1)", "Hex(4) HexNAc(3) Pent.", false}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_, "UNIMOD:1467", "dHex(1)Hex(4)HexNAc(3)", "DHex Hex(4) HexNAc(3).", false}, {UNIMOD_Hex_5_HexNAc_3_, "UNIMOD:1468", "Hex(5)HexNAc(3)", "Hex(5) HexNAc(3).", false}, {UNIMOD_Hex_3_HexNAc_4_Pent_1_, "UNIMOD:1469", "Hex(3)HexNAc(4)Pent(1)", "Hex(3) HexNAc(4) Pent.", false}, {UNIMOD_Hex_6_HexNAc_2_Phos_1_, "UNIMOD:1470", "Hex(6)HexNAc(2)Phos(1)", "Hex(6) HexNAc(2) Phos.", false}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_Sulf_1_, "UNIMOD:1471", "dHex(1)Hex(4)HexNAc(3)Sulf(1)", "DHex Hex(4) HexNAc(3) Sulf.", false}, {UNIMOD_dHex_1_Hex_5_HexNAc_2_Pent_1_, "UNIMOD:1472", "dHex(1)Hex(5)HexNAc(2)Pent(1)", "DHex Hex(5) HexNAc(2) Pent.", false}, {UNIMOD_Hex_8_HexNAc_1_, "UNIMOD:1473", "Hex(8)HexNAc(1)", "Hex(8) HexNAc.", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_2_, "UNIMOD:1474", "dHex(1)Hex(3)HexNAc(3)Pent(2)", "DHex Hex(3) HexNAc(3) Pent(2).", false}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_Pent_1_, "UNIMOD:1475", "dHex(2)Hex(3)HexNAc(3)Pent(1)", "DHex(2) Hex(3) HexNAc(3) Pent.", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Sulf_1_, "UNIMOD:1476", "dHex(1)Hex(3)HexNAc(4)Sulf(1)", "DHex Hex(3) HexNAc(4) Sulf.", false}, {UNIMOD_dHex_1_Hex_6_HexNAc_2_, "UNIMOD:1477", "dHex(1)Hex(6)HexNAc(2)", "DHex Hex(6) HexNAc(2).", false}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_Pent_1_, "UNIMOD:1478", "dHex(1)Hex(4)HexNAc(3)Pent(1)", "DHex Hex(4) HexNAc(3) Pent.", false}, {UNIMOD_Hex_4_HexNAc_4_Sulf_1_, "UNIMOD:1479", "Hex(4)HexNAc(4)Sulf(1)", "Hex(4) HexNAc(4) Sulf.", false}, {UNIMOD_Hex_7_HexNAc_2_, "UNIMOD:1480", "Hex(7)HexNAc(2)", "Hex(7) HexNAc(2).", false}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_, "UNIMOD:1481", "dHex(2)Hex(4)HexNAc(3)", "DHex(2) Hex(4) HexNAc(3).", false}, {UNIMOD_Hex_5_HexNAc_3_Pent_1_, "UNIMOD:1482", "Hex(5)HexNAc(3)Pent(1)", "Hex(5) HexNAc(3) Pent.", false}, {UNIMOD_Hex_4_HexNAc_3_NeuGc_1_, "UNIMOD:1483", "Hex(4)HexNAc(3)NeuGc(1)", "Hex(4) HexNAc(3) NeuGc.", false}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_, "UNIMOD:1484", "dHex(1)Hex(5)HexNAc(3)", "DHex Hex(5) HexNAc(3).", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_1_, "UNIMOD:1485", "dHex(1)Hex(3)HexNAc(4)Pent(1)", "DHex Hex(3) HexNAc(4) Pent.", false}, {UNIMOD_Hex_3_HexNAc_5_Sulf_1_, "UNIMOD:1486", "Hex(3)HexNAc(5)Sulf(1)", "Hex(3) HexNAc(5) Sulf.", false}, {UNIMOD_Hex_6_HexNAc_3_, "UNIMOD:1487", "Hex(6)HexNAc(3)", "Hex(6) HexNAc(3).", false}, {UNIMOD_Hex_3_HexNAc_4_NeuAc_1_, "UNIMOD:1488", "Hex(3)HexNAc(4)NeuAc(1)", "Hex(3) HexNAc(4) NeuAc.", false}, {UNIMOD_Hex_4_HexNAc_4_Pent_1_, "UNIMOD:1489", "Hex(4)HexNAc(4)Pent(1)", "Hex(4) HexNAc(4) Pent.", false}, {UNIMOD_Hex_7_HexNAc_2_Phos_1_, "UNIMOD:1490", "Hex(7)HexNAc(2)Phos(1)", "Hex(7) HexNAc(2) Phos.", false}, {UNIMOD_Hex_4_HexNAc_4_Me_2_Pent_1_, "UNIMOD:1491", "Hex(4)HexNAc(4)Me(2)Pent(1)", "Hex(4) HexNAc(4) Me(2) Pent.", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_3_, "UNIMOD:1492", "dHex(1)Hex(3)HexNAc(3)Pent(3)", "DHex Hex(3) HexNAc(3) Pent(3).", false}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_Sulf_1_, "UNIMOD:1493", "dHex(1)Hex(5)HexNAc(3)Sulf(1)", "DHex Hex(5) HexNAc(3) Sulf.", false}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_Pent_2_, "UNIMOD:1494", "dHex(2)Hex(3)HexNAc(3)Pent(2)", "DHex(2) Hex(3) HexNAc(3) Pent(2).", false}, {UNIMOD_Hex_6_HexNAc_3_Phos_1_, "UNIMOD:1495", "Hex(6)HexNAc(3)Phos(1)", "Hex(6) HexNAc(3) Phos.", false}, {UNIMOD_Hex_4_HexNAc_5_, "UNIMOD:1496", "Hex(4)HexNAc(5)", "Hex(4) HexNAc(5).", false}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_Pent_1_, "UNIMOD:1497", "dHex(3)Hex(3)HexNAc(3)Pent(1)", "DHex(3) Hex(3) HexNAc(3) Pent.", false}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_Pent_1_, "UNIMOD:1498", "dHex(2)Hex(4)HexNAc(3)Pent(1)", "DHex(2) Hex(4) HexNAc(3) Pent.", false}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_Sulf_1_, "UNIMOD:1499", "dHex(1)Hex(4)HexNAc(4)Sulf(1)", "DHex Hex(4) HexNAc(4) Sulf.", false}, {UNIMOD_dHex_1_Hex_7_HexNAc_2_, "UNIMOD:1500", "dHex(1)Hex(7)HexNAc(2)", "DHex Hex(7) HexNAc(2).", false}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuAc_1_, "UNIMOD:1501", "dHex(1)Hex(4)HexNAc(3)NeuAc(1)", "DHex Hex(4) HexNAc(3) NeuAc.", false}, {UNIMOD_Hex_7_HexNAc_2_Phos_2_, "UNIMOD:1502", "Hex(7)HexNAc(2)Phos(2)", "Hex(7) HexNAc(2) Phos(2).", false}, {UNIMOD_Hex_5_HexNAc_4_Sulf_1_, "UNIMOD:1503", "Hex(5)HexNAc(4)Sulf(1)", "Hex(5) HexNAc(4) Sulf.", false}, {UNIMOD_Hex_8_HexNAc_2_, "UNIMOD:1504", "Hex(8)HexNAc(2)", "Hex(8) HexNAc(2).", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_2_, "UNIMOD:1505", "dHex(1)Hex(3)HexNAc(4)Pent(2)", "DHex Hex(3) HexNAc(4) Pent(2).", false}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuGc_1_, "UNIMOD:1506", "dHex(1)Hex(4)HexNAc(3)NeuGc(1)", "DHex Hex(4) HexNAc(3) NeuGc.", false}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_Pent_1_, "UNIMOD:1507", "dHex(2)Hex(3)HexNAc(4)Pent(1)", "DHex(2) Hex(3) HexNAc(4) Pent.", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_Sulf_1_, "UNIMOD:1508", "dHex(1)Hex(3)HexNAc(5)Sulf(1)", "DHex Hex(3) HexNAc(5) Sulf.", false}, {UNIMOD_dHex_1_Hex_6_HexNAc_3_, "UNIMOD:1509", "dHex(1)Hex(6)HexNAc(3)", "DHex Hex(6) HexNAc(3).", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_NeuAc_1_, "UNIMOD:1510", "dHex(1)Hex(3)HexNAc(4)NeuAc(1)", "DHex Hex(3) HexNAc(4) NeuAc.", false}, {UNIMOD_dHex_3_Hex_3_HexNAc_4_, "UNIMOD:1511", "dHex(3)Hex(3)HexNAc(4)", "DHex(3) Hex(3) HexNAc(4).", false}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_Pent_1_, "UNIMOD:1512", "dHex(1)Hex(4)HexNAc(4)Pent(1)", "DHex Hex(4) HexNAc(4) Pent.", false}, {UNIMOD_Hex_4_HexNAc_5_Sulf_1_, "UNIMOD:1513", "Hex(4)HexNAc(5)Sulf(1)", "Hex(4) HexNAc(5) Sulf.", false}, {UNIMOD_Hex_7_HexNAc_3_, "UNIMOD:1514", "Hex(7)HexNAc(3)", "Hex(7) HexNAc(3).", false}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuAc_1_Sulf_1_, "UNIMOD:1515", "dHex(1)Hex(4)HexNAc(3)NeuAc(1)Sulf(1)", "DHex Hex(4) HexNAc(3) NeuAc Sulf.", false}, {UNIMOD_Hex_5_HexNAc_4_Me_2_Pent_1_, "UNIMOD:1516", "Hex(5)HexNAc(4)Me(2)Pent(1)", "Hex(5) HexNAc(4) Me(2) Pent.", false}, {UNIMOD_Hex_3_HexNAc_6_Sulf_1_, "UNIMOD:1517", "Hex(3)HexNAc(6)Sulf(1)", "Hex(3) HexNAc(6) Sulf.", false}, {UNIMOD_dHex_1_Hex_6_HexNAc_3_Sulf_1_, "UNIMOD:1518", "dHex(1)Hex(6)HexNAc(3)Sulf(1)", "DHex Hex(6) HexNAc(3) Sulf.", false}, {UNIMOD_dHex_1_Hex_4_HexNAc_5_, "UNIMOD:1519", "dHex(1)Hex(4)HexNAc(5)", "DHex Hex(4) HexNAc(5).", false}, {UNIMOD_dHex_1_Hex_5_HexA_1_HexNAc_3_Sulf_1_, "UNIMOD:1520", "dHex(1)Hex(5)HexA(1)HexNAc(3)Sulf(1)", "DHex Hex(5) HexA HexNAc(3) Sulf.", false}, {UNIMOD_Hex_7_HexNAc_3_Phos_1_, "UNIMOD:1521", "Hex(7)HexNAc(3)Phos(1)", "Hex(7) HexNAc(3) Phos.", false}, {UNIMOD_Hex_6_HexNAc_4_Me_3_, "UNIMOD:1522", "Hex(6)HexNAc(4)Me(3)", "Hex(6) HexNAc(4) Me(3).", false}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_Sulf_1_, "UNIMOD:1523", "dHex(2)Hex(4)HexNAc(4)Sulf(1)", "DHex(2) Hex(4) HexNAc(4) Sulf.", false}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_2_, "UNIMOD:1524", "Hex(4)HexNAc(3)NeuAc(2)", "Hex(4) HexNAc(3) NeuAc(2).", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_3_, "UNIMOD:1525", "dHex(1)Hex(3)HexNAc(4)Pent(3)", "DHex Hex(3) HexNAc(4) Pent(3).", false}, {UNIMOD_dHex_2_Hex_5_HexNAc_3_Pent_1_, "UNIMOD:1526", "dHex(2)Hex(5)HexNAc(3)Pent(1)", "DHex(2) Hex(5) HexNAc(3) Pent.", false}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Sulf_1_, "UNIMOD:1527", "dHex(1)Hex(5)HexNAc(4)Sulf(1)", "DHex Hex(5) HexNAc(4) Sulf.", false}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_Pent_2_, "UNIMOD:1528", "dHex(2)Hex(3)HexNAc(4)Pent(2)", "DHex(2) Hex(3) HexNAc(4) Pent(2).", false}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuAc_1_, "UNIMOD:1529", "dHex(1)Hex(5)HexNAc(3)NeuAc(1)", "DHex Hex(5) HexNAc(3) NeuAc.", false}, {UNIMOD_Hex_3_HexNAc_6_Sulf_2_, "UNIMOD:1530", "Hex(3)HexNAc(6)Sulf(2)", "Hex(3) HexNAc(6) Sulf(2).", false}, {UNIMOD_Hex_9_HexNAc_2_, "UNIMOD:1531", "Hex(9)HexNAc(2)", "Hex(9) HexNAc(2).", false}, {UNIMOD_Hex_4_HexNAc_6_, "UNIMOD:1532", "Hex(4)HexNAc(6)", "Hex(4) HexNAc(6).", false}, {UNIMOD_dHex_3_Hex_3_HexNAc_4_Pent_1_, "UNIMOD:1533", "dHex(3)Hex(3)HexNAc(4)Pent(1)", "DHex(3) Hex(3) HexNAc(4) Pent.", false}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuGc_1_, "UNIMOD:1534", "dHex(1)Hex(5)HexNAc(3)NeuGc(1)", "DHex Hex(5) HexNAc(3) NeuGc.", false}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_Pent_1_, "UNIMOD:1535", "dHex(2)Hex(4)HexNAc(4)Pent(1)", "DHex(2) Hex(4) HexNAc(4) Pent.", false}, {UNIMOD_dHex_1_Hex_4_HexNAc_5_Sulf_1_, "UNIMOD:1536", "dHex(1)Hex(4)HexNAc(5)Sulf(1)", "DHex Hex(4) HexNAc(5) Sulf.", false}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_, "UNIMOD:1537", "dHex(1)Hex(7)HexNAc(3)", "DHex Hex(7) HexNAc(3).", false}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Pent_1_, "UNIMOD:1538", "dHex(1)Hex(5)HexNAc(4)Pent(1)", "DHex Hex(5) HexNAc(4) Pent.", false}, {UNIMOD_dHex_1_Hex_5_HexA_1_HexNAc_3_Sulf_2_, "UNIMOD:1539", "dHex(1)Hex(5)HexA(1)HexNAc(3)Sulf(2)", "DHex Hex(5) HexA HexNAc(3) Sulf(2).", false}, {UNIMOD_Hex_3_HexNAc_7_, "UNIMOD:1540", "Hex(3)HexNAc(7)", "Hex(3) HexNAc(7).", false}, {UNIMOD_dHex_2_Hex_5_HexNAc_4_, "UNIMOD:1541", "dHex(2)Hex(5)HexNAc(4)", "DHex(2) Hex(5) HexNAc(4).", false}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_NeuAc_1_Sulf_1_, "UNIMOD:1542", "dHex(2)Hex(4)HexNAc(3)NeuAc(1)Sulf(1)", "DHex(2) Hex(4) HexNAc(3) NeuAc Sulf.", false}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Sulf_2_, "UNIMOD:1543", "dHex(1)Hex(5)HexNAc(4)Sulf(2)", "DHex Hex(5) HexNAc(4) Sulf(2).", false}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Me_2_Pent_1_, "UNIMOD:1544", "dHex(1)Hex(5)HexNAc(4)Me(2)Pent(1)", "DHex Hex(5) HexNAc(4) Me(2) Pent.", false}, {UNIMOD_Hex_5_HexNAc_4_NeuGc_1_, "UNIMOD:1545", "Hex(5)HexNAc(4)NeuGc(1)", "Hex(5) HexNAc(4) NeuGc.", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_Sulf_1_, "UNIMOD:1546", "dHex(1)Hex(3)HexNAc(6)Sulf(1)", "DHex Hex(3) HexNAc(6) Sulf.", false}, {UNIMOD_dHex_1_Hex_6_HexNAc_4_, "UNIMOD:1547", "dHex(1)Hex(6)HexNAc(4)", "DHex Hex(6) HexNAc(4).", false}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuAc_1_Sulf_1_, "UNIMOD:1548", "dHex(1)Hex(5)HexNAc(3)NeuAc(1)Sulf(1)", "DHex Hex(5) HexNAc(3) NeuAc Sulf.", false}, {UNIMOD_Hex_7_HexNAc_4_, "UNIMOD:1549", "Hex(7)HexNAc(4)", "Hex(7) HexNAc(4).", false}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuGc_1_Sulf_1_, "UNIMOD:1550", "dHex(1)Hex(5)HexNAc(3)NeuGc(1)Sulf(1)", "DHex Hex(5) HexNAc(3) NeuGc Sulf.", false}, {UNIMOD_Hex_4_HexNAc_5_NeuAc_1_, "UNIMOD:1551", "Hex(4)HexNAc(5)NeuAc(1)", "Hex(4) HexNAc(5) NeuAc.", false}, {UNIMOD_Hex_6_HexNAc_4_Me_3_Pent_1_, "UNIMOD:1552", "Hex(6)HexNAc(4)Me(3)Pent(1)", "Hex(6) HexNAc(4) Me(3) Pent.", false}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_Sulf_1_, "UNIMOD:1553", "dHex(1)Hex(7)HexNAc(3)Sulf(1)", "DHex Hex(7) HexNAc(3) Sulf.", false}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_Phos_1_, "UNIMOD:1554", "dHex(1)Hex(7)HexNAc(3)Phos(1)", "DHex Hex(7) HexNAc(3) Phos.", false}, {UNIMOD_dHex_1_Hex_5_HexNAc_5_, "UNIMOD:1555", "dHex(1)Hex(5)HexNAc(5)", "DHex Hex(5) HexNAc(5).", false}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_Sulf_1_, "UNIMOD:1556", "dHex(1)Hex(4)HexNAc(4)NeuAc(1)Sulf(1)", "DHex Hex(4) HexNAc(4) NeuAc Sulf.", false}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_Sulf_1_, "UNIMOD:1557", "dHex(3)Hex(4)HexNAc(4)Sulf(1)", "DHex(3) Hex(4) HexNAc(4) Sulf.", false}, {UNIMOD_Hex_3_HexNAc_7_Sulf_1_, "UNIMOD:1558", "Hex(3)HexNAc(7)Sulf(1)", "Hex(3) HexNAc(7) Sulf.", false}, {UNIMOD_Hex_6_HexNAc_5_, "UNIMOD:1559", "Hex(6)HexNAc(5)", "Hex(6) HexNAc(5).", false}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_1_Sulf_1_, "UNIMOD:1560", "Hex(5)HexNAc(4)NeuAc(1)Sulf(1)", "Hex(5) HexNAc(4) NeuAc Sulf.", false}, {UNIMOD_Hex_3_HexNAc_6_NeuAc_1_, "UNIMOD:1561", "Hex(3)HexNAc(6)NeuAc(1)", "Hex(3) HexNAc(6) NeuAc.", false}, {UNIMOD_dHex_2_Hex_3_HexNAc_6_, "UNIMOD:1562", "dHex(2)Hex(3)HexNAc(6)", "DHex(2) Hex(3) HexNAc(6).", false}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_1_, "UNIMOD:1563", "Hex(1)HexNAc(1)NeuGc(1)", "Hex HexNAc NeuGc.", false}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_, "UNIMOD:1564", "dHex(1)Hex(2)HexNAc(1)", "DHex Hex(2) HexNAc.", false}, {UNIMOD_HexNAc_3_Sulf_1_, "UNIMOD:1565", "HexNAc(3)Sulf(1)", "HexNAc(3) Sulf.", false}, {UNIMOD_Hex_3_HexNAc_1_, "UNIMOD:1566", "Hex(3)HexNAc(1)", "Hex(3) HexNAc.", false}, {UNIMOD_Hex_1_HexNAc_1_Kdn_1_Sulf_1_, "UNIMOD:1567", "Hex(1)HexNAc(1)Kdn(1)Sulf(1)", "Hex HexNAc Kdn Sulf.", false}, {UNIMOD_HexNAc_2_NeuAc_1_, "UNIMOD:1568", "HexNAc(2)NeuAc(1)", "HexNAc(2) NeuAc.", false}, {UNIMOD_HexNAc_1_Kdn_2_, "UNIMOD:1570", "HexNAc(1)Kdn(2)", "HexNAc Kdn(2).", false}, {UNIMOD_Hex_3_HexNAc_1_Me_1_, "UNIMOD:1571", "Hex(3)HexNAc(1)Me(1)", "Hex(3) HexNAc Me.", false}, {UNIMOD_Hex_2_HexA_1_Pent_1_Sulf_1_, "UNIMOD:1572", "Hex(2)HexA(1)Pent(1)Sulf(1)", "Hex(2) HexA Pent Sulf.", false}, {UNIMOD_HexNAc_2_NeuGc_1_, "UNIMOD:1573", "HexNAc(2)NeuGc(1)", "HexNAc(2) NeuGc.", false}, {UNIMOD_Hex_4_Phos_1_, "UNIMOD:1575", "Hex(4)Phos(1)", "Hex(4) Phos.", false}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Sulf_1_, "UNIMOD:1577", "Hex(1)HexNAc(1)NeuAc(1)Sulf(1)", "Hex HexNAc NeuAc Sulf.", false}, {UNIMOD_Hex_1_HexA_1_HexNAc_2_, "UNIMOD:1578", "Hex(1)HexA(1)HexNAc(2)", "Hex HexA HexNAc(2).", false}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_Sulf_1_, "UNIMOD:1579", "dHex(1)Hex(2)HexNAc(1)Sulf(1)", "DHex Hex(2) HexNAc Sulf.", false}, {UNIMOD_dHex_1_HexNAc_3_, "UNIMOD:1580", "dHex(1)HexNAc(3)", "DHex HexNAc(3).", false}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_Kdn_1_, "UNIMOD:1581", "dHex(1)Hex(1)HexNAc(1)Kdn(1)", "DHex Hex HexNAc Kdn.", false}, {UNIMOD_Hex_1_HexNAc_3_, "UNIMOD:1582", "Hex(1)HexNAc(3)", "Hex HexNAc(3).", false}, {UNIMOD_HexNAc_2_NeuAc_1_Sulf_1_, "UNIMOD:1583", "HexNAc(2)NeuAc(1)Sulf(1)", "HexNAc(2) NeuAc Sulf.", false}, {UNIMOD_dHex_2_Hex_3_, "UNIMOD:1584", "dHex(2)Hex(3)", "DHex(2) Hex(3).", false}, {UNIMOD_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "UNIMOD:1585", "Hex(2)HexA(1)HexNAc(1)Sulf(1)", "Hex(2) HexA HexNAc Sulf.", false}, {UNIMOD_dHex_2_Hex_2_HexA_1_, "UNIMOD:1586", "dHex(2)Hex(2)HexA(1)", "DHex(2) Hex(2) HexA.", false}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Sulf_1_, "UNIMOD:1587", "dHex(1)Hex(1)HexNAc(2)Sulf(1)", "DHex Hex HexNAc(2) Sulf.", false}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuAc_1_, "UNIMOD:1588", "dHex(1)Hex(1)HexNAc(1)NeuAc(1)", "DHex Hex HexNAc NeuAc.", false}, {UNIMOD_Hex_2_HexNAc_2_Sulf_1_, "UNIMOD:1589", "Hex(2)HexNAc(2)Sulf(1)", "Hex(2) HexNAc(2) Sulf.", false}, {UNIMOD_Hex_5_, "UNIMOD:1590", "Hex(5)", "Hex(5).", false}, {UNIMOD_HexNAc_4_, "UNIMOD:1591", "HexNAc(4)", "HexNAc(4).", false}, {UNIMOD_HexNAc_1_NeuGc_2_, "UNIMOD:1592", "HexNAc(1)NeuGc(2)", "HexNAc NeuGc(2).", false}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuGc_1_, "UNIMOD:1593", "dHex(1)Hex(1)HexNAc(1)NeuGc(1)", "DHex Hex HexNAc NeuGc.", false}, {UNIMOD_dHex_2_Hex_2_HexNAc_1_, "UNIMOD:1594", "dHex(2)Hex(2)HexNAc(1)", "DHex(2) Hex(2) HexNAc.", false}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_1_, "UNIMOD:1595", "Hex(2)HexNAc(1)NeuGc(1)", "Hex(2) HexNAc NeuGc.", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_, "UNIMOD:1596", "dHex(1)Hex(3)HexNAc(1)", "DHex Hex(3) HexNAc.", false}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_, "UNIMOD:1597", "dHex(1)Hex(2)HexA(1)HexNAc(1)", "DHex Hex(2) HexA HexNAc.", false}, {UNIMOD_Hex_1_HexNAc_3_Sulf_1_, "UNIMOD:1598", "Hex(1)HexNAc(3)Sulf(1)", "Hex HexNAc(3) Sulf.", false}, {UNIMOD_Hex_4_HexNAc_1_, "UNIMOD:1599", "Hex(4)HexNAc(1)", "Hex(4) HexNAc.", false}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_, "UNIMOD:1600", "Hex(1)HexNAc(2)NeuAc(1)", "Hex HexNAc(2) NeuAc.", false}, {UNIMOD_Hex_1_HexNAc_2_NeuGc_1_, "UNIMOD:1602", "Hex(1)HexNAc(2)NeuGc(1)", "Hex HexNAc(2) NeuGc.", false}, {UNIMOD_Hex_5_Phos_1_, "UNIMOD:1604", "Hex(5)Phos(1)", "Hex(5) Phos.", false}, {UNIMOD_dHex_2_Hex_1_HexNAc_1_Kdn_1_, "UNIMOD:1606", "dHex(2)Hex(1)HexNAc(1)Kdn(1)", "DHex(2) Hex HexNAc Kdn.", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_Sulf_1_, "UNIMOD:1607", "dHex(1)Hex(3)HexNAc(1)Sulf(1)", "DHex Hex(3) HexNAc Sulf.", false}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_, "UNIMOD:1608", "dHex(1)Hex(1)HexNAc(3)", "DHex Hex HexNAc(3).", false}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "UNIMOD:1609", "dHex(1)Hex(2)HexA(1)HexNAc(1)Sulf(1)", "DHex Hex(2) HexA HexNAc Sulf.", false}, {UNIMOD_Hex_2_HexNAc_3_, "UNIMOD:1610", "Hex(2)HexNAc(3)", "Hex(2) HexNAc(3).", false}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "UNIMOD:1611", "Hex(1)HexNAc(2)NeuAc(1)Sulf(1)", "Hex HexNAc(2) NeuAc Sulf.", false}, {UNIMOD_dHex_2_Hex_4_, "UNIMOD:1612", "dHex(2)Hex(4)", "DHex(2) Hex(4).", false}, {UNIMOD_dHex_2_HexNAc_2_Kdn_1_, "UNIMOD:1614", "dHex(2)HexNAc(2)Kdn(1)", "DHex(2) HexNAc(2) Kdn.", false}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_Sulf_1_, "UNIMOD:1615", "dHex(1)Hex(2)HexNAc(2)Sulf(1)", "DHex Hex(2) HexNAc(2) Sulf.", false}, {UNIMOD_dHex_1_HexNAc_4_, "UNIMOD:1616", "dHex(1)HexNAc(4)", "DHex HexNAc(4).", false}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_NeuGc_1_, "UNIMOD:1617", "Hex(1)HexNAc(1)NeuAc(1)NeuGc(1)", "Hex HexNAc NeuAc NeuGc.", false}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Kdn_1_, "UNIMOD:1618", "dHex(1)Hex(1)HexNAc(2)Kdn(1)", "DHex Hex HexNAc(2) Kdn.", false}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_2_, "UNIMOD:1619", "Hex(1)HexNAc(1)NeuGc(2)", "Hex HexNAc NeuGc(2).", false}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_1_, "UNIMOD:1620", "Hex(1)HexNAc(1)NeuAc(2)Ac(1)", "Ac Hex HexNAc NeuAc(2).", false}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_1_, "UNIMOD:1621", "dHex(2)Hex(2)HexA(1)HexNAc(1)", "DHex(2) Hex(2) HexA HexNAc.", false}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_Sulf_1_, "UNIMOD:1622", "dHex(1)Hex(1)HexNAc(3)Sulf(1)", "DHex Hex HexNAc(3) Sulf.", false}, {UNIMOD_Hex_2_HexA_1_NeuAc_1_Pent_1_Sulf_1_, "UNIMOD:1623", "Hex(2)HexA(1)NeuAc(1)Pent(1)Sulf(1)", "Hex(2) HexA NeuAc Pent Sulf.", false}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_, "UNIMOD:1624", "dHex(1)Hex(1)HexNAc(2)NeuAc(1)", "DHex Hex HexNAc(2) NeuAc.", false}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_, "UNIMOD:1625", "dHex(1)Hex(3)HexA(1)HexNAc(1)", "DHex Hex(3) HexA HexNAc.", false}, {UNIMOD_Hex_2_HexNAc_3_Sulf_1_, "UNIMOD:1626", "Hex(2)HexNAc(3)Sulf(1)", "Hex(2) HexNAc(3) Sulf.", false}, {UNIMOD_Hex_5_HexNAc_1_, "UNIMOD:1627", "Hex(5)HexNAc(1)", "Hex(5) HexNAc.", false}, {UNIMOD_HexNAc_5_, "UNIMOD:1628", "HexNAc(5)", "HexNAc(5).", false}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuGc_1_, "UNIMOD:1629", "dHex(1)Hex(1)HexNAc(2)NeuGc(1)", "DHex Hex HexNAc(2) NeuGc.", false}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_2_, "UNIMOD:1630", "Hex(1)HexNAc(1)NeuAc(2)Ac(2)", "Ac(2) Hex HexNAc NeuAc(2).", false}, {UNIMOD_Hex_2_HexNAc_2_NeuGc_1_, "UNIMOD:1631", "Hex(2)HexNAc(2)NeuGc(1)", "Hex(2) HexNAc(2) NeuGc.", false}, {UNIMOD_Hex_5_Phos_3_, "UNIMOD:1632", "Hex(5)Phos(3)", "Hex(5) Phos(3).", false}, {UNIMOD_Hex_6_Phos_1_, "UNIMOD:1633", "Hex(6)Phos(1)", "Hex(6) Phos.", false}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_2_, "UNIMOD:1634", "dHex(1)Hex(2)HexA(1)HexNAc(2)", "DHex Hex(2) HexA HexNAc(2).", false}, {UNIMOD_dHex_2_Hex_3_HexNAc_1_Sulf_1_, "UNIMOD:1635", "dHex(2)Hex(3)HexNAc(1)Sulf(1)", "DHex(2) Hex(3) HexNAc Sulf.", false}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_1_, "UNIMOD:1636", "Hex(1)HexNAc(3)NeuAc(1)", "Hex HexNAc(3) NeuAc.", false}, {UNIMOD_dHex_2_Hex_1_HexNAc_3_, "UNIMOD:1637", "dHex(2)Hex(1)HexNAc(3)", "DHex(2) Hex HexNAc(3).", false}, {UNIMOD_Hex_1_HexNAc_3_NeuGc_1_, "UNIMOD:1638", "Hex(1)HexNAc(3)NeuGc(1)", "Hex HexNAc(3) NeuGc.", false}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "UNIMOD:1639", "dHex(1)Hex(1)HexNAc(2)NeuAc(1)Sulf(1)", "DHex Hex HexNAc(2) NeuAc Sulf.", false}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "UNIMOD:1640", "dHex(1)Hex(3)HexA(1)HexNAc(1)Sulf(1)", "DHex Hex(3) HexA HexNAc Sulf.", false}, {UNIMOD_dHex_1_Hex_1_HexA_1_HexNAc_3_, "UNIMOD:1641", "dHex(1)Hex(1)HexA(1)HexNAc(3)", "DHex Hex HexA HexNAc(3).", false}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "UNIMOD:1642", "Hex(2)HexNAc(2)NeuAc(1)Sulf(1)", "Hex(2) HexNAc(2) NeuAc Sulf.", false}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_1_, "UNIMOD:1643", "dHex(2)Hex(2)HexNAc(2)Sulf(1)", "DHex(2) Hex(2) HexNAc(2) Sulf.", false}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_Kdn_1_, "UNIMOD:1644", "dHex(2)Hex(1)HexNAc(2)Kdn(1)", "DHex(2) Hex HexNAc(2) Kdn.", false}, {UNIMOD_dHex_1_Hex_1_HexNAc_4_, "UNIMOD:1645", "dHex(1)Hex(1)HexNAc(4)", "DHex Hex HexNAc(4).", false}, {UNIMOD_Hex_2_HexNAc_4_, "UNIMOD:1646", "Hex(2)HexNAc(4)", "Hex(2) HexNAc(4).", false}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_2_, "UNIMOD:1647", "Hex(2)HexNAc(1)NeuGc(2)", "Hex(2) HexNAc NeuGc(2).", false}, {UNIMOD_dHex_2_Hex_4_HexNAc_1_, "UNIMOD:1648", "dHex(2)Hex(4)HexNAc(1)", "DHex(2) Hex(4) HexNAc.", false}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_, "UNIMOD:1649", "Hex(1)HexNAc(2)NeuAc(2)", "Hex HexNAc(2) NeuAc(2).", false}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuAc_1_, "UNIMOD:1650", "dHex(2)Hex(1)HexNAc(2)NeuAc(1)", "DHex(2) Hex HexNAc(2) NeuAc.", false}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_Sulf_1_, "UNIMOD:1651", "dHex(1)Hex(2)HexNAc(3)Sulf(1)", "DHex Hex(2) HexNAc(3) Sulf.", false}, {UNIMOD_dHex_1_HexNAc_5_, "UNIMOD:1652", "dHex(1)HexNAc(5)", "DHex HexNAc(5).", false}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuGc_1_, "UNIMOD:1653", "dHex(2)Hex(1)HexNAc(2)NeuGc(1)", "DHex(2) Hex HexNAc(2) NeuGc.", false}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_, "UNIMOD:1654", "dHex(3)Hex(2)HexNAc(2)", "DHex(3) Hex(2) HexNAc(2).", false}, {UNIMOD_Hex_3_HexNAc_3_Sulf_1_, "UNIMOD:1655", "Hex(3)HexNAc(3)Sulf(1)", "Hex(3) HexNAc(3) Sulf.", false}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_2_, "UNIMOD:1656", "dHex(2)Hex(2)HexNAc(2)Sulf(2)", "DHex(2) Hex(2) HexNAc(2) Sulf(2).", false}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_1_, "UNIMOD:1657", "dHex(1)Hex(2)HexNAc(2)NeuGc(1)", "DHex Hex(2) HexNAc(2) NeuGc.", false}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_, "UNIMOD:1658", "dHex(1)Hex(1)HexNAc(3)NeuAc(1)", "DHex Hex HexNAc(3) NeuAc.", false}, {UNIMOD_Hex_6_Phos_3_, "UNIMOD:1659", "Hex(6)Phos(3)", "Hex(6) Phos(3).", false}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_, "UNIMOD:1660", "dHex(1)Hex(3)HexA(1)HexNAc(2)", "DHex Hex(3) HexA HexNAc(2).", false}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuGc_1_, "UNIMOD:1661", "dHex(1)Hex(1)HexNAc(3)NeuGc(1)", "DHex Hex HexNAc(3) NeuGc.", false}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_Sulf_1_, "UNIMOD:1662", "Hex(1)HexNAc(2)NeuAc(2)Sulf(1)", "Hex HexNAc(2) NeuAc(2) Sulf.", false}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "UNIMOD:1663", "dHex(2)Hex(3)HexA(1)HexNAc(1)Sulf(1)", "DHex(2) Hex(3) HexA HexNAc Sulf.", false}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_3_, "UNIMOD:1664", "Hex(1)HexNAc(1)NeuAc(3)", "Hex HexNAc NeuAc(3).", false}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_1_, "UNIMOD:1665", "Hex(2)HexNAc(3)NeuGc(1)", "Hex(2) HexNAc(3) NeuGc.", false}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "UNIMOD:1666", "dHex(1)Hex(2)HexNAc(2)NeuAc(1)Sulf(1)", "DHex Hex(2) HexNAc(2) NeuAc Sulf.", false}, {UNIMOD_dHex_3_Hex_1_HexNAc_2_Kdn_1_, "UNIMOD:1667", "dHex(3)Hex(1)HexNAc(2)Kdn(1)", "DHex(3) Hex HexNAc(2) Kdn.", false}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_Sulf_1_, "UNIMOD:1668", "dHex(2)Hex(3)HexNAc(2)Sulf(1)", "DHex(2) Hex(3) HexNAc(2) Sulf.", false}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Kdn_1_, "UNIMOD:1669", "dHex(2)Hex(2)HexNAc(2)Kdn(1)", "DHex(2) Hex(2) HexNAc(2) Kdn.", false}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "UNIMOD:1670", "dHex(2)Hex(2)HexA(1)HexNAc(2)Sulf(1)", "DHex(2) Hex(2) HexA HexNAc(2) Sulf.", false}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_, "UNIMOD:1671", "dHex(1)Hex(2)HexNAc(4)", "DHex Hex(2) HexNAc(4).", false}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_3_, "UNIMOD:1672", "Hex(1)HexNAc(1)NeuGc(3)", "Hex HexNAc NeuGc(3).", false}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_Sulf_1_, "UNIMOD:1673", "dHex(1)Hex(1)HexNAc(3)NeuAc(1)Sulf(1)", "DHex Hex HexNAc(3) NeuAc Sulf.", false}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "UNIMOD:1674", "dHex(1)Hex(3)HexA(1)HexNAc(2)Sulf(1)", "DHex Hex(3) HexA HexNAc(2) Sulf.", false}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_2_, "UNIMOD:1675", "dHex(1)Hex(1)HexNAc(2)NeuAc(2)", "DHex Hex HexNAc(2) NeuAc(2).", false}, {UNIMOD_dHex_3_HexNAc_3_Kdn_1_, "UNIMOD:1676", "dHex(3)HexNAc(3)Kdn(1)", "DHex(3) HexNAc(3) Kdn.", false}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "UNIMOD:1678", "Hex(2)HexNAc(3)NeuAc(1)Sulf(1)", "Hex(2) HexNAc(3) NeuAc Sulf.", false}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_Sulf_1_, "UNIMOD:1679", "dHex(2)Hex(2)HexNAc(3)Sulf(1)", "DHex(2) Hex(2) HexNAc(3) Sulf.", false}, {UNIMOD_dHex_2_HexNAc_5_, "UNIMOD:1680", "dHex(2)HexNAc(5)", "DHex(2) HexNAc(5).", false}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_, "UNIMOD:1681", "Hex(2)HexNAc(2)NeuAc(2)", "Hex(2) HexNAc(2) NeuAc(2).", false}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_, "UNIMOD:1682", "dHex(2)Hex(2)HexNAc(2)NeuAc(1)", "DHex(2) Hex(2) HexNAc(2) NeuAc.", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Sulf_1_, "UNIMOD:1683", "dHex(1)Hex(3)HexNAc(3)Sulf(1)", "DHex Hex(3) HexNAc(3) Sulf.", false}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuGc_1_, "UNIMOD:1684", "dHex(2)Hex(2)HexNAc(2)NeuGc(1)", "DHex(2) Hex(2) HexNAc(2) NeuGc.", false}, {UNIMOD_Hex_2_HexNAc_5_, "UNIMOD:1685", "Hex(2)HexNAc(5)", "Hex(2) HexNAc(5).", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_NeuGc_1_, "UNIMOD:1686", "dHex(1)Hex(3)HexNAc(2)NeuGc(1)", "DHex Hex(3) HexNAc(2) NeuGc.", false}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_2_, "UNIMOD:1687", "Hex(1)HexNAc(3)NeuAc(2)", "Hex HexNAc(3) NeuAc(2).", false}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_, "UNIMOD:1688", "dHex(1)Hex(2)HexNAc(3)NeuAc(1)", "DHex Hex(2) HexNAc(3) NeuAc.", false}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_, "UNIMOD:1689", "dHex(3)Hex(2)HexNAc(3)", "DHex(3) Hex(2) HexNAc(3).", false}, {UNIMOD_Hex_7_Phos_3_, "UNIMOD:1690", "Hex(7)Phos(3)", "Hex(7) Phos(3).", false}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_2_, "UNIMOD:1691", "dHex(1)Hex(4)HexA(1)HexNAc(2)", "DHex Hex(4) HexA HexNAc(2).", false}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_, "UNIMOD:1692", "Hex(3)HexNAc(3)NeuAc(1)", "Hex(3) HexNAc(3) NeuAc.", false}, {UNIMOD_dHex_1_Hex_3_HexA_2_HexNAc_2_, "UNIMOD:1693", "dHex(1)Hex(3)HexA(2)HexNAc(2)", "DHex Hex(3) HexA(2) HexNAc(2).", false}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "UNIMOD:1694", "Hex(2)HexNAc(2)NeuAc(2)Sulf(1)", "Hex(2) HexNAc(2) NeuAc(2) Sulf.", false}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "UNIMOD:1695", "dHex(2)Hex(2)HexNAc(2)NeuAc(1)Sulf(1)", "DHex(2) Hex(2) HexNAc(2) NeuAc Sulf.", false}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_, "UNIMOD:1696", "Hex(3)HexNAc(3)NeuGc(1)", "Hex(3) HexNAc(3) NeuGc.", false}, {UNIMOD_dHex_4_Hex_1_HexNAc_2_Kdn_1_, "UNIMOD:1697", "dHex(4)Hex(1)HexNAc(2)Kdn(1)", "DHex(4) Hex HexNAc(2) Kdn.", false}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_Kdn_1_, "UNIMOD:1698", "dHex(3)Hex(2)HexNAc(2)Kdn(1)", "DHex(3) Hex(2) HexNAc(2) Kdn.", false}, {UNIMOD_dHex_3_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "UNIMOD:1699", "dHex(3)Hex(2)HexA(1)HexNAc(2)Sulf(1)", "DHex(3) Hex(2) HexA HexNAc(2) Sulf.", false}, {UNIMOD_Hex_2_HexNAc_4_NeuAc_1_, "UNIMOD:1700", "Hex(2)HexNAc(4)NeuAc(1)", "Hex(2) HexNAc(4) NeuAc.", false}, {UNIMOD_dHex_2_Hex_2_HexNAc_4_, "UNIMOD:1701", "dHex(2)Hex(2)HexNAc(4)", "DHex(2) Hex(2) HexNAc(4).", false}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "UNIMOD:1702", "dHex(2)Hex(3)HexA(1)HexNAc(2)Sulf(1)", "DHex(2) Hex(3) HexA HexNAc(2) Sulf.", false}, {UNIMOD_dHex_4_HexNAc_3_Kdn_1_, "UNIMOD:1703", "dHex(4)HexNAc(3)Kdn(1)", "DHex(4) HexNAc(3) Kdn.", false}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_3_, "UNIMOD:1705", "Hex(2)HexNAc(1)NeuGc(3)", "Hex(2) HexNAc NeuGc(3).", false}, {UNIMOD_dHex_4_Hex_1_HexNAc_1_Kdn_2_, "UNIMOD:1706", "dHex(4)Hex(1)HexNAc(1)Kdn(2)", "DHex(4) Hex HexNAc Kdn(2).", false}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "UNIMOD:1707", "dHex(1)Hex(2)HexNAc(3)NeuAc(1)Sulf(1)", "DHex Hex(2) HexNAc(3) NeuAc Sulf.", false}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_, "UNIMOD:1708", "dHex(1)Hex(2)HexNAc(2)NeuAc(2)", "DHex Hex(2) HexNAc(2) NeuAc(2).", false}, {UNIMOD_dHex_3_Hex_1_HexNAc_3_Kdn_1_, "UNIMOD:1709", "dHex(3)Hex(1)HexNAc(3)Kdn(1)", "DHex(3) Hex HexNAc(3) Kdn.", false}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_Sulf_1_, "UNIMOD:1711", "Hex(3)HexNAc(3)NeuAc(1)Sulf(1)", "Hex(3) HexNAc(3) NeuAc Sulf.", false}, {UNIMOD_Hex_3_HexNAc_2_NeuAc_2_, "UNIMOD:1712", "Hex(3)HexNAc(2)NeuAc(2)", "Hex(3) HexNAc(2) NeuAc(2).", false}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_Sulf_1_, "UNIMOD:1713", "Hex(3)HexNAc(3)NeuGc(1)Sulf(1)", "Hex(3) HexNAc(3) NeuGc Sulf.", false}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_2_, "UNIMOD:1714", "dHex(1)Hex(2)HexNAc(2)NeuGc(2)", "DHex Hex(2) HexNAc(2) NeuGc(2).", false}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_NeuGc_1_, "UNIMOD:1715", "dHex(2)Hex(3)HexNAc(2)NeuGc(1)", "DHex(2) Hex(3) HexNAc(2) NeuGc.", false}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "UNIMOD:1716", "dHex(1)Hex(3)HexA(1)HexNAc(3)Sulf(1)", "DHex Hex(3) HexA HexNAc(3) Sulf.", false}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_2_, "UNIMOD:1717", "Hex(2)HexNAc(3)NeuAc(2)", "Hex(2) HexNAc(3) NeuAc(2).", false}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuAc_1_, "UNIMOD:1718", "dHex(2)Hex(2)HexNAc(3)NeuAc(1)", "DHex(2) Hex(2) HexNAc(3) NeuAc.", false}, {UNIMOD_dHex_4_Hex_2_HexNAc_3_, "UNIMOD:1719", "dHex(4)Hex(2)HexNAc(3)", "DHex(4) Hex(2) HexNAc(3).", false}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_NeuGc_1_, "UNIMOD:1720", "Hex(2)HexNAc(3)NeuAc(1)NeuGc(1)", "Hex(2) HexNAc(3) NeuAc NeuGc.", false}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuGc_1_, "UNIMOD:1721", "dHex(2)Hex(2)HexNAc(3)NeuGc(1)", "DHex(2) Hex(2) HexNAc(3) NeuGc.", false}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_, "UNIMOD:1722", "dHex(3)Hex(3)HexNAc(3)", "DHex(3) Hex(3) HexNAc(3).", false}, {UNIMOD_Hex_8_Phos_3_, "UNIMOD:1723", "Hex(8)Phos(3)", "Hex(8) Phos(3).", false}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "UNIMOD:1724", "dHex(1)Hex(2)HexNAc(2)NeuAc(2)Sulf(1)", "DHex Hex(2) HexNAc(2) NeuAc(2) Sulf.", false}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_2_, "UNIMOD:1725", "Hex(2)HexNAc(3)NeuGc(2)", "Hex(2) HexNAc(3) NeuGc(2).", false}, {UNIMOD_dHex_4_Hex_2_HexNAc_2_Kdn_1_, "UNIMOD:1726", "dHex(4)Hex(2)HexNAc(2)Kdn(1)", "DHex(4) Hex(2) HexNAc(2) Kdn.", false}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_1_, "UNIMOD:1727", "dHex(1)Hex(2)HexNAc(4)NeuAc(1)", "DHex Hex(2) HexNAc(4) NeuAc.", false}, {UNIMOD_dHex_3_Hex_2_HexNAc_4_, "UNIMOD:1728", "dHex(3)Hex(2)HexNAc(4)", "DHex(3) Hex(2) HexNAc(4).", false}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_4_, "UNIMOD:1729", "Hex(1)HexNAc(1)NeuGc(4)", "Hex HexNAc NeuGc(4).", false}, {UNIMOD_dHex_4_Hex_1_HexNAc_3_Kdn_1_, "UNIMOD:1730", "dHex(4)Hex(1)HexNAc(3)Kdn(1)", "DHex(4) Hex HexNAc(3) Kdn.", false}, {UNIMOD_Hex_4_HexNAc_4_Sulf_2_, "UNIMOD:1732", "Hex(4)HexNAc(4)Sulf(2)", "Hex(4) HexNAc(4) Sulf(2).", false}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_Kdn_1_, "UNIMOD:1733", "dHex(3)Hex(2)HexNAc(3)Kdn(1)", "DHex(3) Hex(2) HexNAc(3) Kdn.", false}, {UNIMOD_dHex_2_Hex_2_HexNAc_5_, "UNIMOD:1735", "dHex(2)Hex(2)HexNAc(5)", "DHex(2) Hex(2) HexNAc(5).", false}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "UNIMOD:1736", "dHex(2)Hex(3)HexA(1)HexNAc(3)Sulf(1)", "DHex(2) Hex(3) HexA HexNAc(3) Sulf.", false}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "UNIMOD:1737", "dHex(1)Hex(4)HexA(1)HexNAc(3)Sulf(1)", "DHex Hex(4) HexA HexNAc(3) Sulf.", false}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_, "UNIMOD:1738", "Hex(3)HexNAc(3)NeuAc(2)", "Hex(3) HexNAc(3) NeuAc(2).", false}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_1_, "UNIMOD:1739", "dHex(2)Hex(3)HexNAc(3)NeuAc(1)", "DHex(2) Hex(3) HexNAc(3) NeuAc.", false}, {UNIMOD_dHex_4_Hex_3_HexNAc_3_, "UNIMOD:1740", "dHex(4)Hex(3)HexNAc(3)", "DHex(4) Hex(3) HexNAc(3).", false}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuGc_1_, "UNIMOD:1741", "dHex(2)Hex(3)HexNAc(3)NeuGc(1)", "DHex(2) Hex(3) HexNAc(3) NeuGc.", false}, {UNIMOD_Hex_9_Phos_3_, "UNIMOD:1742", "Hex(9)Phos(3)", "Hex(9) Phos(3).", false}, {UNIMOD_dHex_2_HexNAc_7_, "UNIMOD:1743", "dHex(2)HexNAc(7)", "DHex(2) HexNAc(7).", false}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_4_, "UNIMOD:1744", "Hex(2)HexNAc(1)NeuGc(4)", "Hex(2) HexNAc NeuGc(4).", false}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_Sulf_1_, "UNIMOD:1745", "Hex(3)HexNAc(3)NeuAc(2)Sulf(1)", "Hex(3) HexNAc(3) NeuAc(2) Sulf.", false}, {UNIMOD_dHex_2_Hex_3_HexNAc_5_, "UNIMOD:1746", "dHex(2)Hex(3)HexNAc(5)", "DHex(2) Hex(3) HexNAc(5).", false}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_3_, "UNIMOD:1747", "dHex(1)Hex(2)HexNAc(2)NeuGc(3)", "DHex Hex(2) HexNAc(2) NeuGc(3).", false}, {UNIMOD_dHex_2_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "UNIMOD:1748", "dHex(2)Hex(4)HexA(1)HexNAc(3)Sulf(1)", "DHex(2) Hex(4) HexA HexNAc(3) Sulf.", false}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_3_, "UNIMOD:1749", "Hex(2)HexNAc(3)NeuAc(3)", "Hex(2) HexNAc(3) NeuAc(3).", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_NeuAc_2_, "UNIMOD:1750", "dHex(1)Hex(3)HexNAc(3)NeuAc(2)", "DHex Hex(3) HexNAc(3) NeuAc(2).", false}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_NeuAc_1_, "UNIMOD:1751", "dHex(3)Hex(3)HexNAc(3)NeuAc(1)", "DHex(3) Hex(3) HexNAc(3) NeuAc.", false}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_3_, "UNIMOD:1752", "Hex(2)HexNAc(3)NeuGc(3)", "Hex(2) HexNAc(3) NeuGc(3).", false}, {UNIMOD_Hex_10_Phos_3_, "UNIMOD:1753", "Hex(10)Phos(3)", "Hex(10) Phos(3).", false}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_2_, "UNIMOD:1754", "dHex(1)Hex(2)HexNAc(4)NeuAc(2)", "DHex Hex(2) HexNAc(4) NeuAc(2).", false}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_5_, "UNIMOD:1755", "Hex(1)HexNAc(1)NeuGc(5)", "Hex HexNAc NeuGc(5).", false}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_2_, "UNIMOD:1756", "Hex(4)HexNAc(4)NeuAc(1)Sulf(2)", "Hex(4) HexNAc(4) NeuAc Sulf(2).", false}, {UNIMOD_Hex_4_HexNAc_4_NeuGc_1_Sulf_2_, "UNIMOD:1757", "Hex(4)HexNAc(4)NeuGc(1)Sulf(2)", "Hex(4) HexNAc(4) NeuGc Sulf(2).", false}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_2_, "UNIMOD:1758", "dHex(2)Hex(3)HexNAc(3)NeuAc(2)", "DHex(2) Hex(3) HexNAc(3) NeuAc(2).", false}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_3_, "UNIMOD:1759", "Hex(4)HexNAc(4)NeuAc(1)Sulf(3)", "Hex(4) HexNAc(4) NeuAc Sulf(3).", false}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_, "UNIMOD:1760", "dHex(2)Hex(2)HexNAc(2)", "DHex(2) Hex(2) HexNAc(2).", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_, "UNIMOD:1761", "dHex(1)Hex(3)HexNAc(2)", "DHex Hex(3) HexNAc(2).", false}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_, "UNIMOD:1762", "dHex(1)Hex(2)HexNAc(3)", "DHex Hex(2) HexNAc(3).", false}, {UNIMOD_Hex_3_HexNAc_3_, "UNIMOD:1763", "Hex(3)HexNAc(3)", "Hex(3) HexNAc(3).", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Sulf_1_, "UNIMOD:1764", "dHex(1)Hex(3)HexNAc(2)Sulf(1)", "DHex Hex(3) HexNAc(2) Sulf.", false}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_, "UNIMOD:1765", "dHex(2)Hex(3)HexNAc(2)", "DHex(2) Hex(3) HexNAc(2).", false}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_, "UNIMOD:1766", "dHex(1)Hex(4)HexNAc(2)", "DHex Hex(4) HexNAc(2).", false}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_, "UNIMOD:1767", "dHex(2)Hex(2)HexNAc(3)", "DHex(2) Hex(2) HexNAc(3).", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_, "UNIMOD:1768", "dHex(1)Hex(3)HexNAc(3)", "DHex Hex(3) HexNAc(3).", false}, {UNIMOD_Hex_4_HexNAc_3_, "UNIMOD:1769", "Hex(4)HexNAc(3)", "Hex(4) HexNAc(3).", false}, {UNIMOD_dHex_2_Hex_4_HexNAc_2_, "UNIMOD:1770", "dHex(2)Hex(4)HexNAc(2)", "DHex(2) Hex(4) HexNAc(2).", false}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_, "UNIMOD:1771", "dHex(2)Hex(3)HexNAc(3)", "DHex(2) Hex(3) HexNAc(3).", false}, {UNIMOD_Hex_3_HexNAc_5_, "UNIMOD:1772", "Hex(3)HexNAc(5)", "Hex(3) HexNAc(5).", false}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_1_, "UNIMOD:1773", "Hex(4)HexNAc(3)NeuAc(1)", "Hex(4) HexNAc(3) NeuAc.", false}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_, "UNIMOD:1774", "dHex(2)Hex(3)HexNAc(4)", "DHex(2) Hex(3) HexNAc(4).", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_, "UNIMOD:1775", "dHex(1)Hex(3)HexNAc(5)", "DHex Hex(3) HexNAc(5).", false}, {UNIMOD_Hex_3_HexNAc_6_, "UNIMOD:1776", "Hex(3)HexNAc(6)", "Hex(3) HexNAc(6).", false}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_, "UNIMOD:1777", "Hex(4)HexNAc(4)NeuAc(1)", "Hex(4) HexNAc(4) NeuAc.", false}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_, "UNIMOD:1778", "dHex(2)Hex(4)HexNAc(4)", "DHex(2) Hex(4) HexNAc(4).", false}, {UNIMOD_Hex_6_HexNAc_4_, "UNIMOD:1779", "Hex(6)HexNAc(4)", "Hex(6) HexNAc(4).", false}, {UNIMOD_Hex_5_HexNAc_5_, "UNIMOD:1780", "Hex(5)HexNAc(5)", "Hex(5) HexNAc(5).", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_, "UNIMOD:1781", "dHex(1)Hex(3)HexNAc(6)", "DHex Hex(3) HexNAc(6).", false}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_, "UNIMOD:1782", "dHex(1)Hex(4)HexNAc(4)NeuAc(1)", "DHex Hex(4) HexNAc(4) NeuAc.", false}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_, "UNIMOD:1783", "dHex(3)Hex(4)HexNAc(4)", "DHex(3) Hex(4) HexNAc(4).", false}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_NeuAc_1_, "UNIMOD:1784", "dHex(1)Hex(3)HexNAc(5)NeuAc(1)", "DHex Hex(3) HexNAc(5) NeuAc.", false}, {UNIMOD_dHex_2_Hex_4_HexNAc_5_, "UNIMOD:1785", "dHex(2)Hex(4)HexNAc(5)", "DHex(2) Hex(4) HexNAc(5).", false}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Ac_1_, "UNIMOD:1786", "Hex(1)HexNAc(1)NeuAc(1)Ac(1)", "Ac Hex HexNAc NeuAc.", false}, {UO_unit, "UO:0000000", "unit", "A unit of measurement is a standardized quantity of a physical quality.", false}, {UO_length_unit, "UO:0000001", "length unit", "A unit which is a standard measure of the distance between two points.", false}, {UO_mass_unit, "UO:0000002", "mass unit", "A unit which is a standard measure of the amount of matter/energy of a physical object.", false}, {UO_time_unit, "UO:0000003", "time unit", "A unit which is a standard measure of the dimension in which events occur in sequence.", false}, {UO_electric_current_unit, "UO:0000004", "electric current unit", "A unit which is a standard measure of the flow of electric charge.", false}, {UO_temperature_unit, "UO:0000005", "temperature unit", "A unit which is a standard measure of the average kinetic energy of the particles in a sample of matter.", false}, {UO_substance_unit, "UO:0000006", "substance unit", "A unit which is a standardised quantity of an element or compound with uniform composition.", false}, {UO_luminous_intensity_unit, "UO:0000007", "luminous intensity unit", "A unit which is a standard measure of the wavelength-weighted power emitted by a light source in a particular direction.", false}, {UO_meter, "UO:0000008", "meter", "A length unit which is equal to the length of the path traveled by light in vacuum during a time interval of 1/299 792 458 of a second.", false}, {UO_kilogram, "UO:0000009", "kilogram", "A mass unit which is equal to the mass of the International Prototype Kilogram kept by the BIPM at Svres, France.", false}, {UO_second, "UO:0000010", "second", "A time unit which is equal to the duration of 9 192 631 770 periods of the radiation corresponding to the transition between the two hyperfine levels of the ground state of the caesium 133 atom.", false}, {UO_ampere, "UO:0000011", "ampere", "An electric current unit which is equal to the constant current which, if maintained in two straight parallel conductors of infinite length, of negligible circular cross-section, and placed 1 m apart in vacuum, would produce between these conductors a force equal to 2 x 10^[-7] newton per meter of length.", false}, {UO_kelvin, "UO:0000012", "kelvin", "A thermodynamic temperature unit which is equal to the fraction 1/273.16 of the thermodynamic temperature of the triple point of water.", false}, {UO_mole, "UO:0000013", "mole", "A substance unit which is equal to the amount of substance of a molecular system which contains as many elementary entities as there are atoms in 0.012 kilogram of carbon 12.", false}, {UO_candela, "UO:0000014", "candela", "A luminous intensity unit which equal to the luminous intensity, in a given direction, of a source that emits monochromatic radiation of frequency 540 x 1012 hertz and that has a radiant intensity in that direction of 1/683 watt per steradian.", false}, {UO_centimeter, "UO:0000015", "centimeter", "A length unit which is equal to one hundredth of a meter or 10^[-2] m.", false}, {UO_millimeter, "UO:0000016", "millimeter", "A length unit which is equal to one thousandth of a meter or 10^[-3] m.", false}, {UO_micrometer, "UO:0000017", "micrometer", "A length unit which is equal to one millionth of a meter or 10^[-6] m.", false}, {UO_nanometer, "UO:0000018", "nanometer", "A length unit which is equal to one thousandth of one millionth of a meter or 10^[-9] m.", false}, {UO_angstrom, "UO:0000019", "angstrom", "A length unit which is equal to 10 [-10] m.", false}, {UO_picometer, "UO:0000020", "picometer", "A length unit which is equal to 10^[-12] m.", false}, {UO_gram, "UO:0000021", "gram", "A mass unit which is equal to one thousandth of a kilogram or 10^[-3] kg.", false}, {UO_milligram, "UO:0000022", "milligram", "A mass unit which is equal to one thousandth of a gram or 10^[-3] g.", false}, {UO_microgram, "UO:0000023", "microgram", "A mass unit which is equal to one millionth of a gram or 10^[-6] g.", false}, {UO_nanogram, "UO:0000024", "nanogram", "A mass unit which is equal to one thousandth of one millionth of a gram or 10^[-9] g.", false}, {UO_picogram, "UO:0000025", "picogram", "A mass unit which is equal to 10^[-12] g.", false}, {UO_femtogram, "UO:0000026", "femtogram", "A mass unit which is equal to 10^[-15] g.", false}, {UO_degree_celsius, "UO:0000027", "degree celsius", "A temperature unit which is equal to one Kelvin degree. However, they have their zeros at different points. The Centigrade scale has its zero at 273.15 K.", false}, {UO_millisecond, "UO:0000028", "millisecond", "A time unit which is equal to one thousandth of a second or 10^[-3] s.", false}, {UO_microsecond, "UO:0000029", "microsecond", "A time unit which is equal to one millionth of a second or 10^[-6] s.", false}, {UO_picosecond, "UO:0000030", "picosecond", "A time unit which is equal to 10^[-12] s.", false}, {UO_minute, "UO:0000031", "minute", "A time unit which is equal to 60 seconds.", false}, {UO_hour, "UO:0000032", "hour", "A time unit which is equal to 3600 seconds or 60 minutes.", false}, {UO_day, "UO:0000033", "day", "A time unit which is equal to 24 hours.", false}, {UO_week, "UO:0000034", "week", "A time unit which is equal to 7 days.", false}, {UO_month, "UO:0000035", "month", "A time unit which is approximately equal to the length of time of one of cycle of the moon's phases which in science is taken to be equal to 30 days.", false}, {UO_year, "UO:0000036", "year", "A time unit which is equal to 12 months which is science is taken to be equal to 365.25 days.", false}, {UO_milliampere, "UO:0000037", "milliampere", "An electric current unit current which is equal to one thousandth of an ampere or 10^[-3] A.", false}, {UO_microampere, "UO:0000038", "microampere", "An electric current unit current which is equal to one millionth of an ampere or 10^[-6] A.", false}, {UO_micromole, "UO:0000039", "micromole", "A substance unit equal to a millionth of a mol or 10^[-6] mol.", false}, {UO_millimole, "UO:0000040", "millimole", "A substance unit equal to a thousandth of a mol or 10^[-3] mol.", false}, {UO_nanomole, "UO:0000041", "nanomole", "A substance unit equal to one thousandth of one millionth of a mole or 10^[-9] mol.", false}, {UO_picomole, "UO:0000042", "picomole", "A substance unit equal to 10^[-12] mol.", false}, {UO_femtomole, "UO:0000043", "femtomole", "A substance unit equal to 10^[-15] mol.", false}, {UO_attomole, "UO:0000044", "attomole", "A substance unit equal to 10^[-18] mol.", false}, {UO_base_unit, "UO:0000045", "base unit", "A unit which is one of a particular measure to which all measures of that type can be related.", false}, {UO_derived_unit_OBSOLETE, "UO:0000046", "derived unit", "A unit which is derived from base units.", true}, {UO_area_unit, "UO:0000047", "area unit", "A unit which is a standard measure of the amount of a 2-dimensional flat surface.", false}, {UO_acceleration_unit, "UO:0000048", "acceleration unit", "A unit which is a standard measure of the rate of change of velocity in either speed or direction.", false}, {UO_angular_velocity_unit, "UO:0000049", "angular velocity unit", "A unit which is a standard measure of the rate of angular movement about an axis; the angle rotated in a given time.", false}, {UO_angular_acceleration_unit, "UO:0000050", "angular acceleration unit", "A unit which is a standard measure of the rate of change of angular velocity.", false}, {UO_concentration_unit, "UO:0000051", "concentration unit", "A unit which represents a standard measurement of how much of a given substance there is mixed with another substance.", false}, {UO_mass_density_unit, "UO:0000052", "mass density unit", "A density unit which is a standard measure of the mass of a substance in a given volume.", false}, {UO_luminance_unit, "UO:0000053", "luminance unit", "A unit which is a standard measure of the luminous intensity impinging on a given area.", false}, {UO_area_density_unit, "UO:0000054", "area density unit", "A density unit which is a standard measure of the mass exerting an influence on a given area.", false}, {UO_molar_mass_unit, "UO:0000055", "molar mass unit", "A unit which is a standard measure of the mass of a homogeneous substance containing 6.02 x 1023 atoms or molecules.", false}, {UO_molar_volume_unit, "UO:0000056", "molar volume unit", "A unit which is a standard measure of the volume of a homogeneous substance containing 6.02 x 1023 atoms or molecules.", false}, {UO_momentum_unit, "UO:0000057", "momentum unit", "A unit which is a standard measure of the quantity of motion measured by the product of mass and velocity.", false}, {UO_rotational_frequency_unit, "UO:0000058", "rotational frequency unit", "A unit which is a standard measure of the number of rotations in a given time.", false}, {UO_specific_volume_unit, "UO:0000059", "specific volume unit", "A unit which is a standard measure of the volume of a given mass of substance (the reciprocal of density).", false}, {UO_speed_velocity_unit, "UO:0000060", "speed/velocity unit", "A unit which is a standard measure of the rate of movement. Speed is measured in the same physical units of measurement as velocity, but does not contain the element of direction that velocity has. Speed is thus the magnitude component of velocity.", false}, {UO_unit_of_molarity, "UO:0000061", "unit of molarity", "A concentration unit which is a standard measure of the number of moles of a given substance per liter of solution.", false}, {UO_molar, "UO:0000062", "molar", "A unit of concentration which expresses a concentration of 1 mole of solute per liter of solution (mol/L).", false}, {UO_millimolar, "UO:0000063", "millimolar", "A unit of molarity which is equal to one thousandth of a molar or 10^[-3] M.", false}, {UO_micromolar, "UO:0000064", "micromolar", "A unit of molarity which is equal to one millionth of a molar or 10^[-6] M.", false}, {UO_nanomolar, "UO:0000065", "nanomolar", "A unit of molarity which is equal to one thousandth of one millionth of a molar or 10^[-9] M.", false}, {UO_picomolar, "UO:0000066", "picomolar", "A unit of molarity which is equal to 10^[-12] M.", false}, {UO_unit_of_molality, "UO:0000067", "unit of molality", "A concentration unit which is a standard measure of the number of moles of a given substance per kilogram of solvent.", false}, {UO_molal, "UO:0000068", "molal", "A unit of concentration which expresses a concentration of a solution of 1 mole per kilogram of solvent (mol/kg).", false}, {UO_millimolal, "UO:0000069", "millimolal", "A molality unit which is equal to one thousandth of a molal or 10^[-3] m.", false}, {UO_micromolal, "UO:0000070", "micromolal", "A molality unit which is equal to one millionth of a molal or 10^[-6] m.", false}, {UO_nanomolal, "UO:0000071", "nanomolal", "A molality unit which is equal to one thousandth of one millionth of a molal or 10^[-9] m.", false}, {UO_picomolal, "UO:0000072", "picomolal", "A molality unit which is equal to 10^[-12] m.", false}, {UO_femtomolar, "UO:0000073", "femtomolar", "A unit of molarity which is equal to 10^[-15] M.", false}, {UO_unit_of_normality, "UO:0000074", "unit of normality", "A unit of concentration which highlights the chemical nature of salts.", false}, {UO_normal, "UO:0000075", "normal", "A unit of concentration which is one gram equivalent of a solute per liter of solution. A gram equivalent weight or equivalent is a measure of the reactive capacity of a given molecule.", false}, {UO_mole_fraction, "UO:0000076", "mole fraction", "A concentration unit which denotes the number of moles of solute as a proportion of the total number of moles in a solution.", false}, {UO_meter_per_second_per_second, "UO:0000077", "meter per second per second", "An acceleration unit which is equal to the acceleration an object changing its velocity by 1meter/s over a time period that equals one second.", false}, {UO_radian_per_second_per_second, "UO:0000078", "radian per second per second", "An angular unit acceleration which is equal to the angular acceleration of an object changing its angular velocity by 1rad/s over a time period that equals one second.", false}, {UO_radian_per_second, "UO:0000079", "radian per second", "An angular unit velocity which is equal to about 9.54930 rpm (revolutions per minute).", false}, {UO_square_meter, "UO:0000080", "square meter", "An area unit which is equal to an area enclosed by a square with sides each 1 meter long.", false}, {UO_square_centimeter, "UO:0000081", "square centimeter", "An area unit which is equal to one thousand of square meter or 10^[-3] m^[2].", false}, {UO_square_millimeter, "UO:0000082", "square millimeter", "An area unit which is equal to one millionth of a square meter or 10^[-6] m^[2].", false}, {UO_kilogram_per_cubic_meter, "UO:0000083", "kilogram per cubic meter", "A mass unit density which is equal to mass of an object in kilograms divided by the volume in cubic meters.", false}, {UO_gram_per_cubic_centimeter, "UO:0000084", "gram per cubic centimeter", "A mass unit density which is equal to mass of an object in grams divided by the volume in cubic centimeters.", false}, {UO_candela_per_square_meter, "UO:0000085", "candela per square meter", "A luminance unit which is equal to a luminous intensity of one candela radiating from a surface whose area is one square meter.", false}, {UO_kilogram_per_square_meter, "UO:0000086", "kilogram per square meter", "An area density unit which is equal to the mass of an object in kilograms divided by the surface area in meters squared.", false}, {UO_kilogram_per_mole, "UO:0000087", "kilogram per mole", "A molar mass unit which is equal to one kilogram of mass of one mole of chemical element or chemical compound.", false}, {UO_gram_per_mole, "UO:0000088", "gram per mole", "A molar mass unit which is equal to one gram of mass of one mole of chemical element or chemical compound.", false}, {UO_cubic_meter_per_mole, "UO:0000089", "cubic meter per mole", "A molar volume unit which is equal to 1 cubic meter occupied by one mole of a substance in the form of a solid, liquid, or gas.", false}, {UO_cubic_centimeter_per_mole, "UO:0000090", "cubic centimeter per mole", "A molar volume unit which is equal to 1 cubic centimeter occupied by one mole of a substance in the form of a solid, liquid, or gas.", false}, {UO_kilogram_meter_per_second, "UO:0000091", "kilogram meter per second", "A momentum unit which is equal to the momentum of a one kilogram mass object with a speed of one meter per second.", false}, {UO_turns_per_second, "UO:0000092", "turns per second", "A rotational frequency unit which is equal to the number complete turn in a period of time that equals to 1 second.", false}, {UO_cubic_meter_per_kilogram, "UO:0000093", "cubic meter per kilogram", "A specific volume unit which is equal to one cubic meter volume occupied by one kilogram of a particular substance.", false}, {UO_meter_per_second, "UO:0000094", "meter per second", "A speed/velocity unit which is equal to the speed of an object traveling 1 meter distance in one second.", false}, {UO_volume_unit, "UO:0000095", "volume unit", "A unit which is a standard measure of the amount of space occupied by any substance, whether solid, liquid, or gas.", false}, {UO_cubic_meter, "UO:0000096", "cubic meter", "A volume unit which is equal to the volume of a cube with edges one meter in length. One cubic meter equals to 1000 liters.", false}, {UO_cubic_centimeter, "UO:0000097", "cubic centimeter", "A volume unit which is equal to one millionth of a cubic meter or 10^[-9] m^[3], or to 1 ml.", false}, {UO_milliliter, "UO:0000098", "milliliter", "A volume unit which is equal to one thousandth of a liter or 10^[-3] L, or to 1 cubic centimeter.", false}, {UO_liter, "UO:0000099", "liter", "A volume unit which is equal to one thousandth of a cubic meter or 10^[-3] m^[3], or to 1 decimeter.", false}, {UO_cubic_decimeter, "UO:0000100", "cubic decimeter", "A volume unit which is equal to one thousand of a cubic meter or 10^[-3] m^[3], or to 1 L.", false}, {UO_microliter, "UO:0000101", "microliter", "A volume unit which is equal to one millionth of a liter or 10^[-6] L.", false}, {UO_nanoliter, "UO:0000102", "nanoliter", "A volume unit which is equal to one thousandth of one millionth of a liter or 10^[-9] L.", false}, {UO_picoliter, "UO:0000103", "picoliter", "A volume unit which is equal to 10^[-12] L.", false}, {UO_femtoliter, "UO:0000104", "femtoliter", "A volume unit which is equal to 10^[-15] L.", false}, {UO_frequency_unit, "UO:0000105", "frequency unit", "A unit which is a standard measure of the number of repetitive actions in a particular time.", false}, {UO_hertz, "UO:0000106", "hertz", "A frequency unit which is equal to 1 complete cycle of a recurring phenomenon in 1 second.", false}, {UO_force_unit, "UO:0000107", "force unit", "A unit which is a standard measure of the force is applied when a mass is accelerated.", false}, {UO_newton, "UO:0000108", "newton", "A force unit which is equal to the force required to cause an acceleration of 1m/s2 of a mass of 1 Kg in the direction of the force.", false}, {UO_pressure_unit, "UO:0000109", "pressure unit", "A unit which is a standard measure of the force applied to a given area.", false}, {UO_pascal, "UO:0000110", "pascal", "A pressure unit which is equal to the pressure or stress on a surface caused by a force of 1 newton spread over a surface of 1 m^[2].", false}, {UO_energy_unit, "UO:0000111", "energy unit", "A unit which is a standard measure of the work done by a certain force (gravitational, electric, magnetic, force of inertia, etc).", false}, {UO_joule, "UO:0000112", "joule", "An energy unit which is equal to the energy required when a force of 1 newton moves an object 1 meter in the direction of the force.", false}, {UO_power_unit, "UO:0000113", "power unit", "A unit which is a standard measure power or the rate of doing work.", false}, {UO_watt, "UO:0000114", "watt", "A power unit which is equal to the power used when work is done at the rate of 1 joule per second.", false}, {UO_illuminance_unit, "UO:0000115", "illuminance unit", "A unit which is a standard measure of the luminous flux incident on a unit area.", false}, {UO_lux, "UO:0000116", "lux", "An illuminance unit which is equal to the illuminance produced by 1 lumen evenly spread over an area 1 m^[2].", false}, {UO_luminous_flux_unit, "UO:0000117", "luminous flux unit", "A unit which is a standard measure of the flow of radiant energy.", false}, {UO_lumen, "UO:0000118", "lumen", "A luminous flux unit which is equal to the luminous flux emitted into 1 steradian by a point source of 1 candela.", false}, {UO_catalytic_activity_unit, "UO:0000119", "catalytic activity unit", "A unit which is a standard measure of the amount of the action of a catalyst.", false}, {UO_katal, "UO:0000120", "katal", "A catalytic unit activity which is equal to the activity of a catalyst in moles per second, such as the amount of an enzyme needed to transform one mole of substrate per second.", false}, {UO_angle_unit, "UO:0000121", "angle unit", "A unit which is a standard measure of the figure or space formed by the junction of two lines or planes.", false}, {UO_plane_angle_unit, "UO:0000122", "plane angle unit", "A unit which is a standard measure of the angle formed by two straight lines in the same plane.", false}, {UO_radian, "UO:0000123", "radian", "A plane angle unit which is equal to the angle subtended at the center of a circle by an arc equal in length to the radius of the circle, approximately 57 degrees 17 minutes and 44.6 seconds.", false}, {UO_solid_angle_unit, "UO:0000124", "solid angle unit", "A unit which is a standard measure of the angle formed by three or more planes intersecting at a common point.", false}, {UO_steradian, "UO:0000125", "steradian", "A solid angle unit which is equal to the solid angle subtended at the center of a sphere by an area on the surface of the sphere that is equal to the radius squared.", false}, {UO_radiation_unit, "UO:0000127", "radiation unit", "A unit which is a standard measure of the amount of radiation emitted by a given radiation source as well as the amount of radiation absorbed or deposited in a specific material by a radiation source.", false}, {UO_activity__of_a_radionuclide__unit, "UO:0000128", "activity (of a radionuclide) unit", "A unit which is a standard measure of the transformation (disintegration) rate of a radioactive substance.", false}, {UO_absorbed_dose_unit, "UO:0000129", "absorbed dose unit", "A unit which is a standard measure of the energy imparted by ionizing radiation to unit mass of matter such as tissue.", false}, {UO_dose_equivalent_unit, "UO:0000130", "dose equivalent unit", "A unit which is a standard measure of the expression of dose in terms of its biological effect.", false}, {UO_exposure_unit, "UO:0000131", "exposure unit", "A unit which is a standard measure of the quantity that expresses the ability of radiation to ionize air and thereby create electric charges which can be collected and measured.", false}, {UO_becquerel, "UO:0000132", "becquerel", "An activity (of a radionuclide) unit which is equal to the activity of a quantity of radioactive material in which one nucleus decays per second or there is one atom disintegration per second (dps).", false}, {UO_curie, "UO:0000133", "curie", "An activity (of a radionuclide) unit which is equal to the activity of a quantity of radioactive material in which there are 3.7 x 10^[10] atom disintegration per second (dps).", false}, {UO_gray, "UO:0000134", "gray", "An absorbed dose unit which is equal to the absorption of one joule of radiation energy by one kilogram of matter.", false}, {UO_rad, "UO:0000135", "rad", "An absorbed dose unit which is equal to 0.01 gray (Gy).", false}, {UO_roentgen, "UO:0000136", "roentgen", "An exposure unit which is equal to the amount of radiation required to liberate positive and negative charges of one electrostatic unit of charge in 1 cm^[3] of air at standard temperature and pressure (STP). This corresponds to the generation of approximately 2.0810^[9] ion pairs.", false}, {UO_sievert, "UO:0000137", "sievert", "A dose equivalent unit which is equal to the absorption of one joule of radiation energy by one kilogram of matter.", false}, {UO_millisievert, "UO:0000138", "millisievert", "A dose equivalent unit which is equal to one thousandth of a sievert or 10^[-3] Sv.", false}, {UO_microsievert, "UO:0000139", "microsievert", "A dose equivalent unit which is equal to one millionth of a sievert or 10^[-6] Sv.", false}, {UO_Roentgen_equivalent_man, "UO:0000140", "Roentgen equivalent man", "A dose equivalent unit which when multiplied by hundred is equal to one sievert or 1 Sv. 1 Sv is equal to 100 rem.", false}, {UO_microgray, "UO:0000141", "microgray", "An absorbed dose unit which is equal to one millionth of a gray or 10^[-6] Gy.", false}, {UO_milligray, "UO:0000142", "milligray", "An absorbed dose unit which is equal to one thousandth of a gray or 10^[-3] Gy.", false}, {UO_nanogray, "UO:0000143", "nanogray", "An absorbed dose unit which is equal to one thousandth of a millionth of a gray or 10^[-9] Gy.", false}, {UO_nanosievert, "UO:0000144", "nanosievert", "A dose equivalent unit which is equal to one thousandth of a millionth of a sievert or 10^[-9] Sv.", false}, {UO_millicurie, "UO:0000145", "millicurie", "An activity (of a radionuclide) unit which is equal to one thousandth of a curie or 10^[-3] Ci.", false}, {UO_microcurie, "UO:0000146", "microcurie", "An activity (of a radionuclide) unit which is equal to one millionth of a curie or 10^[-6] Ci.", false}, {UO_disintegrations_per_minute, "UO:0000147", "disintegrations per minute", "An activity (of a radionuclide) unit which is equal to the activity of a quantity of radioactive material in which one nucleus decays per minute or there is one atom disintegration per minute.", false}, {UO_counts_per_minute, "UO:0000148", "counts per minute", "An activity (of a radionuclide) unit which is equal to the number of light emissions produced by ionizing radiation in one minute.", false}, {UO_nanosecond, "UO:0000150", "nanosecond", "A time unit which is equal to one thousandth of one millionth of a second or 10^[-9] s.", false}, {UO_century, "UO:0000151", "century", "A time unit which is equal to 100 years.", false}, {UO_half_life, "UO:0000152", "half life", "A time unit which represents the period over which the activity or concentration of a specified chemical or element falls to half its original activity or concentration.", false}, {UO_foot_candle, "UO:0000153", "foot candle", "An illuminance unit which is equal to the illuminance produced by 1 lumen evenly spread over an area 1 foot^[2]. One footcandle is equal to 10.76 lux.", false}, {UO_irradiance_unit, "UO:0000154", "irradiance unit", "A unit which is a standard measure of the power of electromagnetic radiation at a surface, per unit area.", false}, {UO_watt_per_square_meter, "UO:0000155", "watt per square meter", "An irradiance unit which is equal to 1 watt of radiant power incident per one square meter surface area.", false}, {UO_einstein_per_square_meter_per_second, "UO:0000156", "einstein per square meter per second", "An irradiance unit which is equal to one einstein per square meter per second. One einstein is one mole of photons, regardless of their frequency. Therefore, the number of photons in an einstein is Avogadro's number.", false}, {UO_light_unit, "UO:0000157", "light unit", "A unit which is a standard measure of the intensity of light.", false}, {UO_watt_per_steradian_per_square_meter, "UO:0000158", "watt per steradian per square meter", "A radiance unit which is equal to one watt of radiant power incident per steradian solid angle per one square meter projected area of the source, as viewed from the given direction.", false}, {UO_radiant_intensity_unit, "UO:0000159", "radiant intensity unit", "A unit which is a standard measure of the intensity of electromagnetic radiation.", false}, {UO_microeinstein_per_square_meter_per_second, "UO:0000160", "microeinstein per square meter per second", "An irradiance unit which is equal to one microeinstein per square meter per second or 10^[-6] microeinstein/sm^[2].", false}, {UO_radiance_unit, "UO:0000161", "radiance unit", "A unit which is a standard measure of the power of electromagnetic radiation through space or through a material medium in the form of electromagnetic waves.", false}, {UO_watt_per_steradian, "UO:0000162", "watt per steradian", "A radiant intensity unit which is equal to one kilogram meter squared per second cubed per steradian.", false}, {UO_mass_percentage, "UO:0000163", "mass percentage", "A dimensionless concentration unit which denotes the mass of a substance in a mixture as a percentage of the mass of the entire mixture.", false}, {UO_mass_volume_percentage, "UO:0000164", "mass volume percentage", "A dimensionless concentration unit which denotes the mass of the substance in a mixture as a percentage of the volume of the entire mixture.", false}, {UO_volume_percentage, "UO:0000165", "volume percentage", "A dimensionless concentration unit which denotes the volume of the solute in mL per 100 mL of the resulting solution.", false}, {UO_parts_per_notation_unit, "UO:0000166", "parts per notation unit", "A dimensionless concentration notation which describes the amount of one substance in another. It is the ratio of the amount of the substance of interest to the amount of that substance plus the amount of the substance.", false}, {UO_parts_per_hundred, "UO:0000167", "parts per hundred", "A dimensionless concentration notation which denotes the amount of a given substance in a total amount of 100 regardless of the units of measure as long as they are the same.", false}, {UO_parts_per_thousand, "UO:0000168", "parts per thousand", "A dimensionless concentration notation which denotes the amount of a given substance in a total amount of 1000 regardless of the units of measure as long as they are the same.", false}, {UO_parts_per_million, "UO:0000169", "parts per million", "A dimensionless concentration notation which denotes the amount of a given substance in a total amount of 1,000,000 regardless of the units of measure used as long as they are the same or 1 part in 10^[6].", false}, {UO_parts_per_billion, "UO:0000170", "parts per billion", "A dimensionless concentration notation which denotes the amount of a given substance in a total amount of 1,000,000,000 regardless of the units of measure as long as they are the same or 1 part in 10^[9].", false}, {UO_parts_per_trillion, "UO:0000171", "parts per trillion", "A dimensionless concentration notation which denotes the amount of a given substance in a total amount of 1,000,000,000 regardless of the units of measure used as long as they are the same or 1 part in 10^[12].", false}, {UO_parts_per_quadrillion, "UO:0000172", "parts per quadrillion", "A dimensionless concentration notation which denotes the amount of a given substance in a total amount of 1,000,000,000,000 regardless of the units of measure used as long as they are the same or 1 part in 10^[15].", false}, {UO_gram_per_milliliter, "UO:0000173", "gram per milliliter", "A mass unit density which is equal to mass of an object in grams divided by the volume in milliliter.", false}, {UO_kilogram_per_liter, "UO:0000174", "kilogram per liter", "A mass unit density which is equal to mass of an object in kilograms divided by the volume in liters.", false}, {UO_gram_per_liter, "UO:0000175", "gram per liter", "A mass unit density which is equal to mass of an object in grams divided by the volume in liters.", false}, {UO_milligram_per_milliliter, "UO:0000176", "milligram per milliliter", "A mass unit density which is equal to mass of an object in milligrams divided by the volume in milliliters.", false}, {UO_unit_per_volume_unit, "UO:0000177", "unit per volume unit", "A concentration unit which is a standard measure of the number of units, as an agreed arbitrary amount, of a given substance per a specific volume of solution.", false}, {UO_unit_per_milliliter, "UO:0000178", "unit per milliliter", "A unit per milliliter unit which is equal to one unit of an agreed arbitrary amount per one milliliter.", false}, {UO_unit_per_liter, "UO:0000179", "unit per liter", "A unit per milliliter unit which is equal to one unit of an agreed arbitrary amount per one liter.", false}, {UO_mass_per_unit_volume, "UO:0000180", "mass per unit volume", "A concentration unit which is a standard measure of the mass of a substance in a given volume (density).", false}, {UO_enzyme_unit, "UO:0000181", "enzyme unit", "A catalytic unit activity which is equal to the amount of the enzyme that catalyzes the conversion of 1 micro mole of substrate per minute.", false}, {UO_density_unit, "UO:0000182", "density unit", "A unit which is a standard measure of the influence exerted by some mass.", false}, {UO_linear_density_unit, "UO:0000183", "linear density unit", "A density unit which is a standard measure of the mass exerting an influence on a one-dimensional object.", false}, {UO_kilogram_per_meter, "UO:0000184", "kilogram per meter", "An area density unit which is equal to the mass of an object in kilograms divided by one meter.", false}, {UO_degree, "UO:0000185", "degree", "A plane angle unit which is equal to 1/360 of a full rotation or 1.7453310^[-2] rad.", false}, {UO_dimensionless_unit, "UO:0000186", "dimensionless unit", "A unit which is a standard measure of physical quantity consisting of only a numerical number without any units.", false}, {UO_percent, "UO:0000187", "percent", "A dimensionless ratio unit which denotes numbers as fractions of 100.", false}, {UO_pi, "UO:0000188", "pi", "A dimensionless unit which denoted an irrational real number, approximately equal to 3.14159 which is the ratio of a circle's circumference to its diameter in Euclidean geometry.", false}, {UO_count_unit, "UO:0000189", "count unit", "A dimensionless unit which denotes a simple count of things.", false}, {UO_ratio, "UO:0000190", "ratio", "A dimensionless unit which denotes an amount or magnitude of one quantity relative to another.", false}, {UO_fraction, "UO:0000191", "fraction", "A dimensionless ratio unit which relates the part (the numerator) to the whole (the denominator).", false}, {UO_molecule_count, "UO:0000192", "molecule count", "A dimensionless count unit which denotes the number of molecules.", false}, {UO_purity_percentage, "UO:0000193", "purity percentage", "A dimensionless percent unit which denotes the homogeneity of a biomaterial.", false}, {UO_confluence_percentage, "UO:0000194", "confluence percentage", "A dimensionless percent unit which denotes the density of an attached or monolayer culture (e.g., cell culture).", false}, {UO_degree_fahrenheit, "UO:0000195", "degree fahrenheit", "A temperature unit which is equal to 5/9ths of a kelvin. Negative 40 degrees Fahrenheit is equal to negative 40 degrees Celsius.", false}, {UO_pH, "UO:0000196", "pH", "A dimensionless concentration notation which denotes the acidity of a solution in terms of activity of hydrogen ions (H+).", false}, {UO_liter_per_kilogram, "UO:0000197", "liter per kilogram", "A specific volume unit which is equal to one liter volume occupied by one kilogram of a particular substance.", false}, {UO_milliliter_per_kilogram, "UO:0000198", "milliliter per kilogram", "A specific volume unit which is equal to a thousandth of a liter per kilogram or 10^[-3] l/kg.", false}, {UO_microliter_per_kilogram, "UO:0000199", "microliter per kilogram", "A specific volume unit which is equal to one millionth of a liter per kilogram or 10^[-6] l/kg.", false}, {UO_cell_concentration_unit, "UO:0000200", "cell concentration unit", "A concentration unit which denotes the average cell number in a given volume.", false}, {UO_cells_per_milliliter, "UO:0000201", "cells per milliliter", "A unit of cell concentration which is equal to one cell in a volume of 1 milliliter.", false}, {UO_catalytic__activity__concentration_unit, "UO:0000202", "catalytic (activity) concentration unit", "A concentration unit which is a standard measure of the amount of the action of a catalyst in a given volume.", false}, {UO_katal_per_cubic_meter, "UO:0000203", "katal per cubic meter", "A catalytic (activity) concentration unit which is equal to 1 katal activity of a catalyst in a given volume of one cubic meter.", false}, {UO_katal_per_liter, "UO:0000204", "katal per liter", "A catalytic (activity) concentration unit which is equal to 1 katal activity of a catalyst in a given volume of one thousandth of a cubic meter.", false}, {UO_volume_per_unit_volume, "UO:0000205", "volume per unit volume", "A dimensionless concentration unit which denotes the given volume of the solute in the total volume of the resulting solution.", false}, {UO_milliliter_per_cubic_meter, "UO:0000206", "milliliter per cubic meter", "A volume per unit volume unit which is equal to one millionth of a liter of solute in one cubic meter of solution.", false}, {UO_milliliter_per_liter, "UO:0000207", "milliliter per liter", "A volume per unit volume unit which is equal to one millionth of a liter of solute in one liter of solution.", false}, {UO_gram_per_deciliter, "UO:0000208", "gram per deciliter", "A mass density unit which is equal to mass of an object in grams divided by the volume in deciliters.", false}, {UO_deciliter, "UO:0000209", "deciliter", "A volume unit which is equal to one tenth of a liter or 10^[-1] L.", false}, {UO_colony_forming_unit, "UO:0000210", "colony forming unit", "A dimensionless count unit which a measure of viable bacterial numbers.", false}, {UO_plaque_forming_unit, "UO:0000211", "plaque forming unit", "A dimensionless count unit which a measure of plague forming units in a given volume.", false}, {UO_colony_forming_unit_per_volume, "UO:0000212", "colony forming unit per volume", "A concentration unit which a measure of viable bacterial numbers in a given volume.", false}, {UO_colony_forming_unit_per_milliliter, "UO:0000213", "colony forming unit per milliliter", "A colony forming unit which a measure of viable bacterial numbers in one milliliter.", false}, {UO_plaque_forming_unit_per_volume, "UO:0000214", "plaque forming unit per volume", "A concentration unit which a measure of plague forming units in a given volume.", false}, {UO_plaque_forming_unit_per_milliliter, "UO:0000215", "plaque forming unit per milliliter", "A concentration unit which a measure of plague forming units in one milliliter.", false}, {UO_disintegrations_per_second, "UO:0000216", "disintegrations per second", "An activity (of a radionuclide) unit which is equal to the activity of a quantity of radioactive material in which one nucleus decays per second or there is one atom disintegration per second.", false}, {UO_electric_potential_difference_unit, "UO:0000217", "electric potential difference unit", "A unit which is a standard measure of the work done per unit charge as a charge is moved between two points in an electric field.", false}, {UO_volt, "UO:0000218", "volt", "An electric potential difference unit which is equal to the work per unit charge. One volt is the potential difference required to move one coulomb of charge between two points in a circuit while using one joule of energy.", false}, {UO_electric_charge, "UO:0000219", "electric charge", "A unit which is a standard measure of the quantity of unbalanced electricity in a body (either positive or negative) and construed as an excess or deficiency of electrons.", false}, {UO_coulomb, "UO:0000220", "coulomb", "An electrical charge unit which is equal to the amount of charge transferred by a current of 1 ampere in 1 second.", false}, {UO_dalton, "UO:0000221", "dalton", "An independently to the base SI units defined mass unit which is equal to one twelfth of the mass of an unbound atom of the carbon-12 nuclide, at rest and in its ground state.", false}, {UO_kilodalton, "UO:0000222", "kilodalton", "A mass unit which is equal to one thousand daltons.", false}, {UO_watt_hour, "UO:0000223", "watt-hour", "An energy unit which is equal to the amount of electrical energy equivalent to a one-watt load drawing power for one hour.", false}, {UO_kilowatt_hour, "UO:0000224", "kilowatt-hour", "An energy unit which is equal to 1,000 watt-hours.", false}, {UO_magnetic_flux_unit, "UO:0000225", "magnetic flux unit", "A unit which is a standard measure of quantity of magnetism, taking account of the strength and the extent of a magnetic field.", false}, {UO_weber, "UO:0000226", "weber", "A magnetic flux unit which is equal to the amount of flux that when linked with a single turn of wire for an interval of one second will induce an electromotive force of one volt.", false}, {UO_magnetic_flux_density_unit, "UO:0000227", "magnetic flux density unit", "A unit which is a standard measure of the strength of a magnetic field.", false}, {UO_tesla, "UO:0000228", "tesla", "A magnetic flux density unit which is equal to one weber per square meter.", false}, {UO_volt_hour, "UO:0000229", "volt-hour", "A magnetic flux unit which is equal to 3600 Wb.", false}, {UO_kilovolt_hour, "UO:0000230", "kilovolt-hour", "A magnetic flux unit which is equal to one thousand volt-hours.", false}, {UO_information_unit, "UO:0000231", "information unit", "A unit which is a standard measure of the amount of information.", false}, {UO_bit, "UO:0000232", "bit", "An information unit which refers to a digit in the binary numeral system, which consists of base 2 digits (ie there are only 2 possible values: 0 or 1).", false}, {UO_byte, "UO:0000233", "byte", "An information unit which is equal to 8 bits.", false}, {UO_kilobyte, "UO:0000234", "kilobyte", "An information unit which is equal to 1000 bytes.", false}, {UO_megabyte, "UO:0000235", "megabyte", "An information unit which is equal to 1000 kB.", false}, {UO_image_resolution_unit, "UO:0000236", "image resolution unit", "An information unit which is a standard measure of the detail an image holds.", false}, {UO_chroma_sampling_unit, "UO:0000237", "chroma sampling unit", "An image resolution unit which is a standard measure of the amount of spatial detail in an image.", false}, {UO_dynamic_range_unit, "UO:0000238", "dynamic range unit", "An image resolution unit which is a standard measure of the amount of contrast available in a pixel.", false}, {UO_spatial_resolution_unit, "UO:0000239", "spatial resolution unit", "An image resolution unit which is a standard measure of the way luminance and chrominance may be sampled at different levels.", false}, {UO_dots_per_inch, "UO:0000240", "dots per inch", "A spatial resolution unit which is a standard measure of the printing resolution, in particular the number of individual dots of ink a printer or toner can produce within a linear one-inch space.", false}, {UO_micron_pixel, "UO:0000241", "micron pixel", "A spatial resolution unit which is equal to a pixel size of one micrometer.", false}, {UO_pixels_per_inch, "UO:0000242", "pixels per inch", "A spatial resolution unit which is a standard measure of the resolution of a computer display, related to the size of the display in inches and the total number of pixels in the horizontal and vertical directions.", false}, {UO_pixels_per_millimeter, "UO:0000243", "pixels per millimeter", "A spatial resolution unit which is a standard measure of the number of pixels in one millimeter length or width of a digital image divided by the physical length or width of a printed image.", false}, {UO_base_pair, "UO:0000244", "base pair", "A count unit which contains one nucleotide.", false}, {UO_kibibyte, "UO:0000245", "kibibyte", "An information unit which is equal to 1024 B.", false}, {UO_mebibyte, "UO:0000246", "mebibyte", "An information unit which is equal to 1024 KiB.", false}, {UO_millivolt, "UO:0000247", "millivolt", "An electric potential difference unit which is equal to one thousandth of a volt or 10^[-3] V.", false}, {UO_kilovolt, "UO:0000248", "kilovolt", "An electric potential difference unit which is equal to one thousand volts or 10^[3] V.", false}, {UO_microvolt, "UO:0000249", "microvolt", "An electric potential difference unit which is equal to one millionth of a volt or 10^[-6] V.", false}, {UO_nanovolt, "UO:0000250", "nanovolt", "An electric potential difference unit which is equal to one billionth of a volt or 10^[-12] V.", false}, {UO_picovolt, "UO:0000251", "picovolt", "An electric potential difference unit which is equal to one trillionth of a volt or 10^[-12] V.", false}, {UO_megavolt, "UO:0000252", "megavolt", "An electric potential difference unit which is equal to one million volts or 10^[6] V.", false}, {UO_surface_tension_unit, "UO:0000253", "surface tension unit", "A unit which is a standard measure of the ability of a liguid to attraction of molecules at its surface as a result of unbalanced molecular cohesive forces.", false}, {UO_newton_per_meter, "UO:0000254", "newton per meter", "A surface tension unit which is equal to one newton per meter.", false}, {UO_dyne_per_cm, "UO:0000255", "dyne per cm", "A surface tension unit which is equal to one dyne per centimeter.", false}, {UO_viscosity_unit, "UO:0000256", "viscosity unit", "A unit which is a standard measure of the internal resistance of fluids to flow.", false}, {UO_pascal_second, "UO:0000257", "pascal second", "A viscosity unit which is equal to one pascale per second.", false}, {UO_poise, "UO:0000258", "poise", "A viscosity unit which is equal to one dyne second per square centimeter.", false}, {UO_decibel, "UO:0000259", "decibel", "An ratio unit which is an indicator of sound power per unit area.", false}, {UO_effective_dose_unit, "UO:0000260", "effective dose unit", "A unit which is a standard measure of the estimate of the stochastic effect that a non-uniform radiation dose has on a human.", false}, {UO_conduction_unit, "UO:0000261", "conduction unit", "A unit which represents a standard measurement of the transmission of an entity through a medium.", false}, {UO_electrical_conduction_unit, "UO:0000262", "electrical conduction unit", "A unit which represents a standard measurement of the movement of electrically charged particles through a transmission medium (electrical conductor).", false}, {UO_heat_conduction_unit, "UO:0000263", "heat conduction unit", "A unit which represents a standard measurement of the spontaneous transfer of thermal energy through matter, from a region of higher temperature to a region of lower temperature.", false}, {UO_siemens, "UO:0000264", "siemens", "An electrical conduction unit which is equal to A/V.", false}, {UO_watt_per_meter_kelvin, "UO:0000265", "watt per meter kelvin", "An heat conduction unit which is equal to one watt divided by meter kelvin.", false}, {UO_electronvolt, "UO:0000266", "electronvolt", "A non-SI unit of energy (eV) defined as the energy acquired by a single unbound electron when it passes through an electrostatic potential difference of one volt. An electronvolt is equal to 1.602 176 53(14) x 10^-19 J.", false}, {UO_electric_field_strength_unit, "UO:0000267", "electric field strength unit", "The electric field strength is a unit which is a measure of the potential difference between two points some distance apart.", false}, {UO_volt_per_meter, "UO:0000268", "volt per meter", "The volt per meter is a unit of electric field strength equal to the a potential difference of 1 volt existing between two points that are 1 meter apart.", false}, {UO_absorbance_unit, "UO:0000269", "absorbance unit", "A dimensionless logarithmic unit assigned to a measure of absorbance of light through a partially absorbing substance, defined as -log10(I/I_0) where I = transmitted light and I_0 = incident light.", false}, {UO_volumetric_flow_rate_unit, "UO:0000270", "volumetric flow rate unit", "A unit which is a standard measure of the volume of fluid which passes through a given surface per unit time .", false}, {UO_microliters_per_minute, "UO:0000271", "microliters per minute", "A volumetric flow rate unit which is equal to one microliter volume through a given surface in one minute.", false}, {UO_millimetres_of_mercury, "UO:0000272", "millimetres of mercury", "A unit of pressure equal to the amount of fluid pressure one millimeter deep in mercury at zero degrees centigrade on Earth.", false}, {UO_milligram_per_liter, "UO:0000273", "milligram per liter", "A mass unit density which is equal to mass of an object in milligrams divided by the volume in liters.", false}, {UO_microgram_per_milliliter, "UO:0000274", "microgram per milliliter", "A mass unit density which is equal to mass of an object in micrograms divided by the volume in millliters.", false}, {UO_nanogram_per_milliliter, "UO:0000275", "nanogram per milliliter", "A mass unit density which is equal to mass of an object in nanograms divided by the volume in milliliters.", false}, {UO_amount_per_container, "UO:0000276", "amount per container", "A concentration unit which is a standard measure of the amount of a substance in a given container.", false}, {UO_ug_disk, "UO:0000277", "ug/disk", "A unit which is equal to one microgram per disk, where a disk is some physical surface/container upon which the substance is deposited.", false}, {UO_nmole_disk, "UO:0000278", "nmole/disk", "A unit which is equal to one nanomole per disk, where a disk is some physical surface/container upon which the substance is deposited.", false}, {UO_milliunits_per_milliliter, "UO:0000279", "milliunits per milliliter", "A unit per milliliter unit which is equal to one thousandth of a unit of an agreed arbitrary amount per one milliliter.", false}, {UO_rate_unit, "UO:0000280", "rate unit", "A unit which represents a standard measurement occurrence of a process per unit time.", false}, {UO_count_per_nanomolar_second, "UO:0000281", "count per nanomolar second", "A rate unit which is equal to one over one nanomolar second.", false}, {UO_count_per_molar_second, "UO:0000282", "count per molar second", "A rate unit which is equal to one over one molar second.", false}, {UO_kilogram_per_hectare, "UO:0000283", "kilogram per hectare", "An area density unit which is equal to the mass of an object in kilograms divided by the surface area in hectares..", false}, {UO_count_per_nanomolar, "UO:0000284", "count per nanomolar", "A rate unit which is equal to one over one nanomolar.", false}, {UO_count_per_molar, "UO:0000285", "count per molar", "A rate unit which is equal to one over one molar.", false}, {UO_microgram_per_liter, "UO:0000301", "microgram per liter", "A mass unit density which is equal to mass of an object in micrograms divided by the volume in liters.", false}, }; // termInfos_ const size_t termInfosSize_ = sizeof(termInfos_)/sizeof(TermInfo); struct CVIDPair { CVID first; CVID second; }; CVIDPair relationsIsA_[] = { {MS_sample_number, MS_sample_attribute}, {MS_sample_name, MS_sample_attribute}, {MS_sample_state, MS_sample_attribute}, {MS_sample_mass, MS_sample_attribute}, {MS_sample_volume, MS_sample_attribute}, {MS_sample_concentration, MS_sample_attribute}, {MS_mass_resolution, MS_scan_attribute}, {MS_resolution_measurement_method, MS_measurement_method}, {MS_accuracy, MS_mass_analyzer_attribute}, {MS_scan_rate, MS_scan_attribute}, {MS_scan_start_time, MS_scan_attribute}, {MS_scan_start_time, MS_peptide_result_details}, {MS_scan_start_time, MS_spectrum_identification_result_details}, {MS_reflectron_state, MS_mass_analyzer_attribute}, {MS_TOF_Total_Path_Length, MS_mass_analyzer_attribute}, {MS_final_MS_exponent, MS_mass_analyzer_attribute}, {MS_magnetic_field_strength, MS_mass_analyzer_attribute}, {MS_detector_resolution, MS_detector_attribute}, {MS_sampling_frequency, MS_detector_attribute}, {MS_customization, MS_instrument_attribute}, {MS_deisotoping, MS_data_processing_action}, {MS_charge_deconvolution, MS_data_processing_action}, {MS_peak_picking, MS_data_processing_action}, {MS_charge_state, MS_ion_selection_attribute}, {MS_peak_intensity, MS_ion_selection_attribute}, {MS_collision_energy, MS_precursor_activation_attribute}, {MS_emulsion, MS_sample_state}, {MS_gaseous_sample_state, MS_sample_state}, {MS_liquid_sample_state, MS_sample_state}, {MS_solid_sample_state, MS_sample_state}, {MS_solution, MS_sample_state}, {MS_suspension, MS_sample_state}, {MS_sample_batch, MS_sample_attribute}, {MS_continuous_flow_fast_atom_bombardment, MS_inlet_type}, {MS_direct_inlet, MS_inlet_type}, {MS_electrospray_inlet, MS_inlet_type}, {MS_flow_injection_analysis, MS_inlet_type}, {MS_inductively_coupled_plasma, MS_inlet_type}, {MS_infusion, MS_inlet_type}, {MS_jet_separator, MS_inlet_type}, {MS_membrane_separator, MS_inlet_type}, {MS_moving_belt, MS_inlet_type}, {MS_moving_wire, MS_inlet_type}, {MS_open_split, MS_inlet_type}, {MS_particle_beam, MS_inlet_type}, {MS_reservoir, MS_inlet_type}, {MS_septum, MS_inlet_type}, {MS_thermospray_inlet, MS_inlet_type}, {MS_atmospheric_pressure_chemical_ionization, MS_atmospheric_pressure_ionization}, {MS_chemical_ionization, MS_ionization_type}, {MS_electrospray_ionization, MS_ionization_type}, {MS_fast_atom_bombardment_ionization, MS_ionization_type}, {MS_matrix_assisted_laser_desorption_ionization, MS_desorption_ionization}, {MS_axial_ejection_linear_ion_trap, MS_linear_ion_trap}, {MS_fourier_transform_ion_cyclotron_resonance_mass_spectrometer, MS_mass_analyzer_type}, {MS_magnetic_sector, MS_mass_analyzer_type}, {MS_quadrupole, MS_mass_analyzer_type}, {MS_quadrupole_ion_trap, MS_ion_trap}, {MS_radial_ejection_linear_ion_trap, MS_linear_ion_trap}, {MS_time_of_flight, MS_mass_analyzer_type}, {MS_baseline, MS_resolution_measurement_method}, {MS_full_width_at_half_maximum, MS_resolution_measurement_method}, {MS_ten_percent_valley, MS_resolution_measurement_method}, {MS_decreasing_m_z_scan, MS_scan_direction}, {MS_increasing_m_z_scan, MS_scan_direction}, {MS_exponential, MS_scan_law}, {MS_linear_OBSOLETE, MS_scan_law}, {MS_quadratic, MS_scan_law}, {MS_reflectron_off, MS_reflectron_state}, {MS_reflectron_on, MS_reflectron_state}, {MS_channeltron, MS_detector_type}, {MS_conversion_dynode_electron_multiplier, MS_conversion_dynode}, {MS_conversion_dynode_photomultiplier, MS_conversion_dynode}, {MS_daly_detector, MS_detector_type}, {MS_electron_multiplier_tube, MS_electron_multiplier}, {MS_faraday_cup, MS_detector_type}, {MS_focal_plane_array, MS_focal_plane_collector}, {MS_microchannel_plate_detector, MS_array_detector}, {MS_multi_collector, MS_detector_type}, {MS_photomultiplier, MS_detector_type}, {MS_analog_digital_converter, MS_detector_acquisition_mode}, {MS_pulse_counting, MS_detector_acquisition_mode}, {MS_time_digital_converter, MS_detector_acquisition_mode}, {MS_transient_recorder, MS_detector_acquisition_mode}, {MS_SCIEX_instrument_model, MS_instrument_model}, {MS_Bruker_Daltonics_instrument_model, MS_instrument_model}, {MS_IonSpec_instrument_model, MS_Varian_instrument_model}, {MS_Shimadzu_instrument_model, MS_instrument_model}, {MS_Thermo_Finnigan_instrument_model, MS_Thermo_Fisher_Scientific_instrument_model}, {MS_Waters_instrument_model, MS_instrument_model}, {MS_centroid_spectrum, MS_spectrum_representation}, {MS_profile_spectrum, MS_spectrum_representation}, {MS_negative_scan, MS_scan_polarity}, {MS_negative_scan, MS_chromatogram_attribute}, {MS_positive_scan, MS_scan_polarity}, {MS_positive_scan, MS_chromatogram_attribute}, {MS_number_of_detector_counts, MS_intensity_unit}, {MS_percent_of_base_peak, MS_intensity_unit}, {MS_collision_induced_dissociation, MS_dissociation_method}, {MS_plasma_desorption, MS_dissociation_method}, {MS_post_source_decay, MS_dissociation_method}, {MS_surface_induced_dissociation, MS_dissociation_method}, {MS_normalized_collision_energy, MS_precursor_activation_attribute}, {MS_4000_QTRAP, MS_SCIEX_instrument_model}, {MS_4700_Proteomics_Analyzer, MS_Applied_Biosystems_instrument_model}, {MS_apex_IV, MS_Bruker_Daltonics_apex_series}, {MS_apex_Q, MS_Bruker_Daltonics_apex_series}, {MS_API_150EX, MS_SCIEX_instrument_model}, {MS_API_150EX_Prep, MS_SCIEX_instrument_model}, {MS_API_2000, MS_SCIEX_instrument_model}, {MS_API_3000, MS_SCIEX_instrument_model}, {MS_API_4000, MS_SCIEX_instrument_model}, {MS_autoflex_II, MS_Bruker_Daltonics_flex_series}, {MS_autoflex_TOF_TOF, MS_Bruker_Daltonics_flex_series}, {MS_Auto_Spec_Ultima_NT, MS_Waters_instrument_model}, {MS_BioTOF_II, MS_Bruker_Daltonics_BioTOF_series}, {MS_BioTOF_Q, MS_Bruker_Daltonics_BioTOF_series}, {MS_DELTA_plusAdvantage, MS_Thermo_Finnigan_instrument_model}, {MS_DELTAplusXP, MS_Thermo_Finnigan_instrument_model}, {MS_esquire_4000, MS_Bruker_Daltonics_esquire_series}, {MS_esquire_6000, MS_Bruker_Daltonics_esquire_series}, {MS_explorer, MS_IonSpec_instrument_model}, {MS_GCT, MS_Waters_instrument_model}, {MS_HCT, MS_Bruker_Daltonics_HCT_Series}, {MS_HCTplus, MS_Bruker_Daltonics_HCT_Series}, {MS_HiRes_ESI, MS_IonSpec_instrument_model}, {MS_HiRes_MALDI, MS_IonSpec_instrument_model}, {MS_IsoPrime, MS_Waters_instrument_model}, {MS_IsoProbe, MS_Waters_instrument_model}, {MS_IsoProbe_T, MS_Waters_instrument_model}, {MS_LCQ_Advantage, MS_Thermo_Finnigan_instrument_model}, {MS_LCQ_Classic, MS_Thermo_Finnigan_instrument_model}, {MS_LCQ_Deca_XP_Plus, MS_Thermo_Finnigan_instrument_model}, {MS_M_LDI_L, MS_Waters_instrument_model}, {MS_M_LDI_LR, MS_Waters_instrument_model}, {MS_MAT253, MS_Finnigan_MAT_instrument_model}, {MS_MAT900XP, MS_Finnigan_MAT_instrument_model}, {MS_MAT900XP_Trap, MS_Finnigan_MAT_instrument_model}, {MS_MAT95XP, MS_Finnigan_MAT_instrument_model}, {MS_MAT95XP_Trap, MS_Finnigan_MAT_instrument_model}, {MS_microflex, MS_Bruker_Daltonics_flex_series}, {MS_microTOF_LC, MS_Bruker_Daltonics_micrOTOF_series}, {MS_neptune, MS_Thermo_Finnigan_instrument_model}, {MS_NG_5400, MS_Waters_instrument_model}, {MS_OMEGA, MS_IonSpec_instrument_model}, {MS_OMEGA_2001, MS_IonSpec_instrument_model}, {MS_OmniFlex, MS_Bruker_Daltonics_flex_series}, {MS_Platform_ICP, MS_Waters_instrument_model}, {MS_PolarisQ, MS_Thermo_Finnigan_instrument_model}, {MS_proteomics_solution_1, MS_SCIEX_instrument_model}, {MS_Q_TRAP, MS_SCIEX_instrument_model}, {MS_Q_Tof_micro, MS_Waters_instrument_model}, {MS_Q_Tof_ultima, MS_Waters_instrument_model}, {MS_QSTAR, MS_SCIEX_instrument_model}, {MS_quattro_micro, MS_Waters_instrument_model}, {MS_Quattro_UItima, MS_Waters_instrument_model}, {MS_Surveyor_MSQ, MS_Thermo_Finnigan_instrument_model}, {MS_SymBiot_I, MS_SCIEX_instrument_model}, {MS_SymBiot_XVI, MS_SCIEX_instrument_model}, {MS_TEMPUS_TOF, MS_Thermo_Finnigan_instrument_model}, {MS_TRACE_DSQ, MS_Thermo_Finnigan_instrument_model}, {MS_TRITON, MS_Thermo_Finnigan_instrument_model}, {MS_TSQ_Quantum, MS_Thermo_Finnigan_instrument_model}, {MS_ultima, MS_IonSpec_instrument_model}, {MS_ultraflex, MS_Bruker_Daltonics_flex_series}, {MS_ultraflex_TOF_TOF, MS_Bruker_Daltonics_flex_series}, {MS_Voyager_DE_PRO, MS_Applied_Biosystems_instrument_model}, {MS_Voyager_DE_STR, MS_Applied_Biosystems_instrument_model}, {MS_selected_ion_monitoring, MS_measurement_method}, {MS_selected_reaction_monitoring, MS_measurement_method}, {MS_base_peak, MS_peak}, {MS_field_free_region, MS_ion_optics_attribute}, {MS_magnetic_deflection, MS_ion_optics_type}, {MS_multiphoton_ionization, MS_ionization_type}, {MS_total_ion_current_chromatogram, MS_data_file_content}, {MS_total_ion_current_chromatogram, MS_mass_chromatogram}, {MS_transmission, MS_instrument_attribute}, {MS_atmospheric_pressure_matrix_assisted_laser_desorption_ionization, MS_atmospheric_pressure_ionization}, {MS_atmospheric_pressure_ionization, MS_ionization_type}, {MS_blackbody_infrared_radiative_dissociation, MS_dissociation_method}, {MS_charge_stripping, MS_precursor_activation_attribute}, {MS_delayed_extraction, MS_ion_optics_type}, {MS_desorption_ionization, MS_ionization_type}, {MS_direct_insertion_probe, MS_inlet_type}, {MS_direct_liquid_introduction, MS_inlet_type}, {MS_electron_capture_dissociation, MS_dissociation_method}, {MS_electron_multiplier, MS_detector_type}, {MS_electrostatic_energy_analyzer, MS_mass_analyzer_type}, {MS_flowing_afterglow, MS_ionization_type}, {MS_field_desorption, MS_desorption_ionization}, {MS_field_ionization, MS_ionization_type}, {MS_glow_discharge_ionization, MS_ionization_type}, {MS_infrared_multiphoton_dissociation, MS_dissociation_method}, {MS_ion_trap, MS_mass_analyzer_type}, {MS_Negative_Ion_chemical_ionization, MS_ionization_type}, {MS_neutralization_reionization_mass_spectrometry, MS_ionization_type}, {MS_photoionization, MS_ionization_type}, {MS_pyrolysis_mass_spectrometry, MS_ionization_type}, {MS_collision_quadrupole, MS_ion_optics_type}, {MS_resonance_enhanced_multiphoton_ionization, MS_ionization_type}, {MS_surface_enhanced_laser_desorption_ionization, MS_surface_ionization}, {MS_surface_enhanced_neat_desorption, MS_surface_ionization}, {MS_selected_ion_flow_tube, MS_ion_optics_type}, {MS_sustained_off_resonance_irradiation, MS_dissociation_method}, {MS_stored_waveform_inverse_fourier_transform, MS_mass_analyzer_type}, {MS_total_ion_current, MS_spectrum_attribute}, {MS_time_lag_focusing, MS_ion_optics_type}, {MS_cyclotron, MS_mass_analyzer_type}, {MS_linear_ion_trap, MS_ion_trap}, {MS_mass_spectrum, MS_data_file_content}, {MS_mass_spectrum, MS_spectrum_type}, {MS_reflectron, MS_ion_optics_type}, {MS_accelerating_voltage, MS_ion_optics_attribute}, {MS_einzel_lens, MS_ion_optics_type}, {MS_electric_field_strength, MS_ion_optics_attribute}, {MS_first_stability_region, MS_ion_optics_type}, {MS_fringing_field, MS_ion_optics_type}, {MS_kinetic_energy_analyzer, MS_ion_optics_type}, {MS_space_charge_effect, MS_ion_optics_attribute}, {MS_static_field, MS_ion_optics_type}, {MS_charge_inversion_mass_spectrum, MS_mass_spectrum}, {MS_charge_inversion_mass_spectrum, MS_data_file_content}, {MS_constant_neutral_gain_spectrum, MS_mass_spectrum}, {MS_constant_neutral_gain_spectrum, MS_data_file_content}, {MS_constant_neutral_loss_spectrum, MS_mass_spectrum}, {MS_constant_neutral_loss_spectrum, MS_data_file_content}, {MS_e_2_mass_spectrum, MS_mass_spectrum}, {MS_neutral_loss, MS_modification_parameters}, {MS_precursor_ion_spectrum, MS_mass_spectrum}, {MS_precursor_ion_spectrum, MS_data_file_content}, {MS_product_ion_spectrum_OBSOLETE, MS_mass_spectrum}, {MS_product_ion_spectrum_OBSOLETE, MS_data_file_content}, {MS_array_detector, MS_detector_type}, {MS_conversion_dynode, MS_detector_type}, {MS_dynode, MS_detector_type}, {MS_focal_plane_collector, MS_detector_type}, {MS_ion_to_photon_detector, MS_detector_type}, {MS_point_collector, MS_detector_type}, {MS_postacceleration_detector, MS_detector_type}, {MS_adiabatic_ionization, MS_ionization_type}, {MS_associative_ionization, MS_ionization_type}, {MS_atmospheric_pressure_photoionization, MS_atmospheric_pressure_ionization}, {MS_autodetachment, MS_ionization_type}, {MS_autoionization, MS_ionization_type}, {MS_charge_exchange_ionization, MS_ionization_type}, {MS_chemi_ionization, MS_ionization_type}, {MS_desorption_ionization_on_silicon, MS_desorption_ionization}, {MS_dissociative_ionization, MS_ionization_type}, {MS_electron_ionization, MS_ionization_type}, {MS_ionization_efficiency, MS_source_attribute}, {MS_laser_desorption_ionization, MS_desorption_ionization}, {MS_liquid_secondary_ionization, MS_ionization_type}, {MS_membrane_inlet, MS_inlet_type}, {MS_microelectrospray, MS_electrospray_ionization}, {MS_nanoelectrospray, MS_electrospray_ionization}, {MS_penning_ionization, MS_ionization_type}, {MS_plasma_desorption_ionization, MS_ionization_type}, {MS_secondary_ionization, MS_ionization_type}, {MS_soft_ionization, MS_ionization_type}, {MS_spark_ionization, MS_ionization_type}, {MS_surface_assisted_laser_desorption_ionization, MS_desorption_ionization}, {MS_surface_ionization, MS_ionization_type}, {MS_thermal_ionization, MS_ionization_type}, {MS_vertical_ionization, MS_ionization_type}, {MS_buffer_gas, MS_precursor_activation_attribute}, {MS_collision_gas, MS_precursor_activation_attribute}, {MS_beam_type_collision_induced_dissociation, MS_collision_induced_dissociation}, {MS_low_energy_collision_induced_dissociation, MS_dissociation_method}, {MS_photodissociation, MS_dissociation_method}, {MS_fast_ion_bombardment, MS_ionization_type}, {MS_LTQ, MS_Thermo_Scientific_instrument_model}, {MS_LTQ_FT, MS_Thermo_Scientific_instrument_model}, {MS_LTQ_Orbitrap, MS_Thermo_Scientific_instrument_model}, {MS_LXQ, MS_Thermo_Scientific_instrument_model}, {MS_ion_selection_attribute, MS_object_attribute}, {MS_1200_series_LC_MSD_SL, MS_Agilent_instrument_model}, {MS_6110_Quadrupole_LC_MS, MS_Agilent_instrument_model}, {MS_6120_Quadrupole_LC_MS, MS_Agilent_instrument_model}, {MS_6130_Quadrupole_LC_MS, MS_Agilent_instrument_model}, {MS_6140_Quadrupole_LC_MS, MS_Agilent_instrument_model}, {MS_6210_Time_of_Flight_LC_MS, MS_Agilent_instrument_model}, {MS_6310_Ion_Trap_LC_MS, MS_Agilent_instrument_model}, {MS_6320_Ion_Trap_LC_MS, MS_Agilent_instrument_model}, {MS_6330_Ion_Trap_LC_MS, MS_Agilent_instrument_model}, {MS_6340_Ion_Trap_LC_MS, MS_Agilent_instrument_model}, {MS_6410_Triple_Quadrupole_LC_MS, MS_Agilent_instrument_model}, {MS_1200_series_LC_MSD_VL, MS_Agilent_instrument_model}, {MS_Thermo_Fisher_Scientific_instrument_model, MS_instrument_model}, {MS_orbitrap, MS_mass_analyzer_type}, {MS_nanospray_inlet, MS_electrospray_inlet}, {MS_source_potential, MS_source_attribute}, {MS_ion_optics_attribute, MS_ion_optics}, {MS_Hitachi_instrument_model, MS_instrument_model}, {MS_Varian_instrument_model, MS_instrument_model}, {MS_Agilent_instrument_model, MS_instrument_model}, {MS_Dionex_instrument_model, MS_instrument_model}, {MS_Thermo_Electron_instrument_model, MS_Thermo_Fisher_Scientific_instrument_model}, {MS_Finnigan_MAT_instrument_model, MS_Thermo_Fisher_Scientific_instrument_model}, {MS_Thermo_Scientific_instrument_model, MS_Thermo_Fisher_Scientific_instrument_model}, {MS_Applied_Biosystems_instrument_model, MS_instrument_model}, {MS_instrument_attribute, MS_object_attribute}, {MS_zoom_scan, MS_spectrum_attribute}, {MS_spectrum_attribute, MS_object_attribute}, {MS_scan_window_upper_limit, MS_selection_window_attribute}, {MS_scan_window_lower_limit, MS_selection_window_attribute}, {MS_dwell_time, MS_scan_attribute}, {MS_scan_attribute, MS_object_attribute}, {MS_base_peak_m_z, MS_spectrum_attribute}, {MS_base_peak_intensity, MS_spectrum_attribute}, {MS_activation_energy, MS_precursor_activation_attribute}, {MS_ms_level, MS_spectrum_attribute}, {MS_filter_string, MS_scan_attribute}, {MS_m_z_array, MS_binary_data_array}, {MS_intensity_array, MS_binary_data_array}, {MS_charge_array, MS_binary_data_array}, {MS_signal_to_noise_array, MS_binary_data_array}, {MS_32_bit_integer, MS_binary_data_type}, {MS_16_bit_float_OBSOLETE, MS_binary_data_type}, {MS_32_bit_float, MS_binary_data_type}, {MS_64_bit_integer, MS_binary_data_type}, {MS_64_bit_float, MS_binary_data_type}, {MS_Waters_raw_format, MS_mass_spectrometer_file_format}, {MS_highest_observed_m_z, MS_spectrum_attribute}, {MS_highest_observed_m_z, MS_chromatogram_attribute}, {MS_lowest_observed_m_z, MS_spectrum_attribute}, {MS_lowest_observed_m_z, MS_chromatogram_attribute}, {MS_instrument_serial_number, MS_instrument_attribute}, {MS_file_format_conversion, MS_data_transformation}, {MS_Xcalibur, MS_Thermo_Finnigan_software}, {MS_Xcalibur, MS_acquisition_software}, {MS_Xcalibur, MS_analysis_software}, {MS_Xcalibur, MS_data_processing_software}, {MS_Bioworks, MS_Thermo_Finnigan_software}, {MS_Bioworks, MS_analysis_software}, {MS_Bioworks, MS_data_processing_software}, {MS_MassLynx, MS_Waters_software}, {MS_MassLynx, MS_acquisition_software}, {MS_MassLynx, MS_analysis_software}, {MS_MassLynx, MS_data_processing_software}, {MS_FlexAnalysis, MS_Bruker_software}, {MS_FlexAnalysis, MS_analysis_software}, {MS_FlexAnalysis, MS_data_processing_software}, {MS_Data_Explorer, MS_Applied_Biosystems_software}, {MS_Data_Explorer, MS_acquisition_software}, {MS_Data_Explorer, MS_analysis_software}, {MS_Data_Explorer, MS_data_processing_software}, {MS_4700_Explorer, MS_Applied_Biosystems_software}, {MS_4700_Explorer, MS_acquisition_software}, {MS_4700_Explorer, MS_analysis_software}, {MS_4700_Explorer, MS_data_processing_software}, {MS_massWolf, MS_data_processing_software}, {MS_Voyager_Biospectrometry_Workstation_System, MS_Applied_Biosystems_software}, {MS_Voyager_Biospectrometry_Workstation_System, MS_acquisition_software}, {MS_Voyager_Biospectrometry_Workstation_System, MS_analysis_software}, {MS_Voyager_Biospectrometry_Workstation_System, MS_data_processing_software}, {MS_FlexControl, MS_Bruker_software}, {MS_FlexControl, MS_acquisition_software}, {MS_ReAdW, MS_data_processing_software}, {MS_MzStar, MS_data_processing_software}, {MS_data_processing_action, MS_data_transformation}, {MS_Conversion_to_mzML, MS_file_format_conversion}, {MS_Conversion_to_mzXML, MS_file_format_conversion}, {MS_Conversion_to_mzData, MS_file_format_conversion}, {MS_sample_attribute, MS_object_attribute}, {MS_selection_window_attribute, MS_object_attribute}, {MS_Analyst, MS_SCIEX_software}, {MS_Analyst, MS_acquisition_software}, {MS_Analyst, MS_analysis_software}, {MS_Analyst, MS_data_processing_software}, {MS_Trapper, MS_data_processing_software}, {MS_LCQ_Deca, MS_Thermo_Finnigan_instrument_model}, {MS_LTQ_Orbitrap_Discovery, MS_Thermo_Scientific_instrument_model}, {MS_LTQ_Orbitrap_XL, MS_Thermo_Scientific_instrument_model}, {MS_LTQ_FT_Ultra, MS_Thermo_Scientific_instrument_model}, {MS_GC_Quantum, MS_Thermo_Finnigan_instrument_model}, {MS_mass_spectrometer_file_format, MS_file_format}, {MS_ABI_WIFF_format, MS_mass_spectrometer_file_format}, {MS_Thermo_RAW_format, MS_mass_spectrometer_file_format}, {MS_PSI_mzData_format, MS_mass_spectrometer_file_format}, {MS_Micromass_PKL_format, MS_mass_spectrometer_file_format}, {MS_ISB_mzXML_format, MS_mass_spectrometer_file_format}, {MS_Bruker_Agilent_YEP_format, MS_mass_spectrometer_file_format}, {MS_MD5, MS_data_file_checksum_type}, {MS_SHA_1, MS_data_file_checksum_type}, {MS_sum_of_spectra, MS_spectra_combination}, {MS_median_of_spectra, MS_spectra_combination}, {MS_zlib_compression, MS_binary_data_compression_type}, {MS_mean_of_spectra, MS_spectra_combination}, {MS_no_compression, MS_binary_data_compression_type}, {MS_LCQ_Fleet, MS_Thermo_Finnigan_instrument_model}, {MS_MS1_spectrum, MS_mass_spectrum}, {MS_MS1_spectrum, MS_data_file_content}, {MS_MSn_spectrum, MS_mass_spectrum}, {MS_MSn_spectrum, MS_data_file_content}, {MS_CRM_spectrum, MS_mass_spectrum}, {MS_CRM_spectrum, MS_data_file_content}, {MS_SIM_spectrum, MS_mass_spectrum}, {MS_SIM_spectrum, MS_data_file_content}, {MS_SRM_spectrum, MS_mass_spectrum}, {MS_SRM_spectrum, MS_data_file_content}, {MS_mzML_format, MS_mass_spectrometer_file_format}, {MS_contact_attribute, MS_object_attribute}, {MS_contact_name, MS_contact_attribute}, {MS_contact_address, MS_contact_attribute}, {MS_contact_URL, MS_contact_attribute}, {MS_contact_email, MS_contact_attribute}, {MS_contact_affiliation, MS_contact_attribute}, {MS_MzWiff, MS_data_processing_software}, {MS_smoothing, MS_data_processing_action}, {MS_baseline_reduction, MS_data_processing_action}, {MS_low_intensity_data_point_removal, MS_data_filtering}, {MS_time_array, MS_binary_data_array}, {MS_ion_optics_type, MS_ion_optics}, {MS_electron_transfer_dissociation, MS_dissociation_method}, {MS_pulsed_q_dissociation, MS_dissociation_method}, {MS_Proteios, MS_analysis_software}, {MS_Proteios, MS_data_processing_software}, {MS_ProteinLynx_Global_Server, MS_Waters_software}, {MS_ProteinLynx_Global_Server, MS_analysis_software}, {MS_ProteinLynx_Global_Server, MS_data_processing_software}, {MS_Shimadzu_MALDI_TOF_instrument_model, MS_Shimadzu_instrument_model}, {MS_Shimadzu_Scientific_Instruments_instrument_model, MS_Shimadzu_instrument_model}, {MS_LCMS_IT_TOF, MS_Shimadzu_Scientific_Instruments_instrument_model}, {MS_LCMS_2010EV, MS_Shimadzu_Scientific_Instruments_instrument_model}, {MS_LCMS_2010A, MS_Shimadzu_Scientific_Instruments_instrument_model}, {MS_AXIMA_CFR_MALDI_TOF, MS_Shimadzu_MALDI_TOF_instrument_model}, {MS_AXIMA_QIT, MS_Shimadzu_MALDI_TOF_instrument_model}, {MS_AXIMA_CFR_plus, MS_Shimadzu_MALDI_TOF_instrument_model}, {MS_AXIMA_Performance_MALDI_TOF_TOF, MS_Shimadzu_MALDI_TOF_instrument_model}, {MS_AXIMA_Confidence_MALDI_TOF, MS_Shimadzu_MALDI_TOF_instrument_model}, {MS_AXIMA_Assurance_Linear_MALDI_TOF, MS_Shimadzu_MALDI_TOF_instrument_model}, {MS_DTA_format, MS_mass_spectrometer_file_format}, {MS_ProteinLynx_Global_Server_mass_spectrum_XML_format, MS_mass_spectrometer_file_format}, {MS_ProteoWizard_software, MS_analysis_software}, {MS_ProteoWizard_software, MS_data_processing_software}, {MS_preset_scan_configuration, MS_scan_attribute}, {MS_wavelength_array, MS_binary_data_array}, {MS_highest_observed_wavelength, MS_spectrum_attribute}, {MS_highest_observed_wavelength, MS_chromatogram_attribute}, {MS_lowest_observed_wavelength, MS_spectrum_attribute}, {MS_lowest_observed_wavelength, MS_chromatogram_attribute}, {MS_PDA_spectrum_OBSOLETE, MS_data_file_content}, {MS_PDA_spectrum_OBSOLETE, MS_spectrum_type}, {MS_photodiode_array_detector, MS_array_detector}, {MS_Surveyor_PDA, MS_Thermo_Scientific_instrument_model}, {MS_Accela_PDA, MS_Thermo_Scientific_instrument_model}, {MS_inductive_detector, MS_detector_type}, {MS_selected_ion_current_chromatogram, MS_data_file_content}, {MS_selected_ion_current_chromatogram, MS_mass_chromatogram}, {MS_basepeak_chromatogram, MS_data_file_content}, {MS_basepeak_chromatogram, MS_mass_chromatogram}, {MS_low_intensity_threshold, MS_data_processing_parameter}, {MS_high_intensity_threshold, MS_data_processing_parameter}, {MS_Q_Tof_Premier, MS_Waters_instrument_model}, {MS_possible_charge_state, MS_ion_selection_attribute}, {MS_DSQ, MS_Thermo_Finnigan_instrument_model}, {MS_ITQ_700, MS_Thermo_Scientific_instrument_model}, {MS_ITQ_900, MS_Thermo_Scientific_instrument_model}, {MS_ITQ_1100, MS_Thermo_Scientific_instrument_model}, {MS_LTQ_XL_ETD, MS_Thermo_Scientific_instrument_model}, {MS_LTQ_Orbitrap_XL_ETD, MS_Thermo_Scientific_instrument_model}, {MS_DFS, MS_Thermo_Scientific_instrument_model}, {MS_DSQ_II, MS_Thermo_Scientific_instrument_model}, {MS_MALDI_LTQ_XL, MS_Thermo_Scientific_instrument_model}, {MS_MALDI_LTQ_Orbitrap, MS_Thermo_Scientific_instrument_model}, {MS_TSQ_Quantum_Access, MS_Thermo_Scientific_instrument_model}, {MS_Element_XR, MS_Thermo_Scientific_instrument_model}, {MS_Element_2, MS_Thermo_Scientific_instrument_model}, {MS_Element_GD, MS_Thermo_Scientific_instrument_model}, {MS_GC_IsoLink, MS_Thermo_Scientific_instrument_model}, {MS_Exactive, MS_Thermo_Scientific_instrument_model}, {MS_Proteome_Discoverer, MS_Thermo_Finnigan_software}, {MS_Proteome_Discoverer, MS_analysis_software}, {MS_Proteome_Discoverer, MS_data_processing_software}, {MS_3200_QTRAP, MS_SCIEX_instrument_model}, {MS_4800_Plus_MALDI_TOF_TOF, MS_SCIEX_instrument_model}, {MS_API_3200, MS_SCIEX_instrument_model}, {MS_API_5000, MS_SCIEX_instrument_model}, {MS_QSTAR_Elite, MS_SCIEX_instrument_model}, {MS_QSTAR_Pulsar, MS_SCIEX_instrument_model}, {MS_QSTAR_XL, MS_SCIEX_instrument_model}, {MS_4800_Proteomics_Analyzer, MS_Applied_Biosystems_instrument_model}, {MS_4000_Series_Explorer_Software, MS_SCIEX_software}, {MS_4000_Series_Explorer_Software, MS_acquisition_software}, {MS_4000_Series_Explorer_Software, MS_analysis_software}, {MS_4000_Series_Explorer_Software, MS_data_processing_software}, {MS_GPS_Explorer, MS_SCIEX_software}, {MS_GPS_Explorer, MS_acquisition_software}, {MS_GPS_Explorer, MS_analysis_software}, {MS_GPS_Explorer, MS_data_processing_software}, {MS_LightSight_Software, MS_SCIEX_software}, {MS_LightSight_Software, MS_analysis_software}, {MS_LightSight_Software, MS_data_processing_software}, {MS_ProteinPilot_Software, MS_SCIEX_software}, {MS_ProteinPilot_Software, MS_analysis_software}, {MS_ProteinPilot_Software, MS_data_processing_software}, {MS_TissueView_Software, MS_SCIEX_software}, {MS_TissueView_Software, MS_analysis_software}, {MS_TissueView_Software, MS_data_processing_software}, {MS_MarkerView_Software, MS_SCIEX_software}, {MS_MarkerView_Software, MS_analysis_software}, {MS_MarkerView_Software, MS_data_processing_software}, {MS_MRMPilot_Software, MS_SCIEX_software}, {MS_MRMPilot_Software, MS_analysis_software}, {MS_MRMPilot_Software, MS_data_processing_software}, {MS_BioAnalyst, MS_SCIEX_software}, {MS_BioAnalyst, MS_analysis_software}, {MS_BioAnalyst, MS_data_processing_software}, {MS_Pro_ID, MS_SCIEX_software}, {MS_Pro_ID, MS_analysis_software}, {MS_Pro_ID, MS_data_processing_software}, {MS_Pro_ICAT, MS_SCIEX_software}, {MS_Pro_ICAT, MS_analysis_software}, {MS_Pro_ICAT, MS_data_processing_software}, {MS_Pro_Quant, MS_SCIEX_software}, {MS_Pro_Quant, MS_analysis_software}, {MS_Pro_Quant, MS_data_processing_software}, {MS_Pro_BLAST, MS_SCIEX_software}, {MS_Pro_BLAST, MS_analysis_software}, {MS_Pro_BLAST, MS_data_processing_software}, {MS_Cliquid, MS_SCIEX_software}, {MS_MIDAS_Workflow_Designer, MS_SCIEX_software}, {MS_MultiQuant, MS_SCIEX_software}, {MS_MultiQuant, MS_analysis_software}, {MS_MultiQuant, MS_data_processing_software}, {MS_6220_Time_of_Flight_LC_MS, MS_Agilent_instrument_model}, {MS_6510_Quadrupole_Time_of_Flight_LC_MS, MS_Agilent_instrument_model}, {MS_6520_Quadrupole_Time_of_Flight_LC_MS, MS_Agilent_instrument_model}, {MS_MassHunter_Data_Acquisition, MS_Agilent_software}, {MS_MassHunter_Data_Acquisition, MS_acquisition_software}, {MS_MassHunter_Easy_Access, MS_Agilent_software}, {MS_MassHunter_Easy_Access, MS_acquisition_software}, {MS_MassHunter_Qualitative_Analysis, MS_Agilent_software}, {MS_MassHunter_Qualitative_Analysis, MS_analysis_software}, {MS_MassHunter_Qualitative_Analysis, MS_data_processing_software}, {MS_MassHunter_Quantitative_Analysis, MS_Agilent_software}, {MS_MassHunter_Quantitative_Analysis, MS_analysis_software}, {MS_MassHunter_Quantitative_Analysis, MS_data_processing_software}, {MS_MassHunter_Metabolite_ID, MS_Agilent_software}, {MS_MassHunter_Metabolite_ID, MS_analysis_software}, {MS_MassHunter_Metabolite_ID, MS_data_processing_software}, {MS_MassHunter_BioConfirm, MS_Agilent_software}, {MS_MassHunter_BioConfirm, MS_analysis_software}, {MS_MassHunter_BioConfirm, MS_data_processing_software}, {MS_Genespring_MS, MS_Agilent_software}, {MS_Genespring_MS, MS_analysis_software}, {MS_Genespring_MS, MS_data_processing_software}, {MS_MassHunter_Mass_Profiler, MS_Agilent_software}, {MS_MassHunter_Mass_Profiler, MS_analysis_software}, {MS_MassHunter_Mass_Profiler, MS_data_processing_software}, {MS_METLIN, MS_Agilent_software}, {MS_METLIN, MS_analysis_software}, {MS_METLIN, MS_data_processing_software}, {MS_Spectrum_Mill_for_MassHunter_Workstation, MS_Agilent_software}, {MS_Spectrum_Mill_for_MassHunter_Workstation, MS_analysis_software}, {MS_Spectrum_Mill_for_MassHunter_Workstation, MS_data_processing_software}, {MS_6300_Series_Ion_Trap_Data_Analysis_Software, MS_Agilent_software}, {MS_6300_Series_Ion_Trap_Data_Analysis_Software, MS_acquisition_software}, {MS_6300_Series_Ion_Trap_Data_Analysis_Software, MS_analysis_software}, {MS_6300_Series_Ion_Trap_Data_Analysis_Software, MS_data_processing_software}, {MS_Agilent_software, MS_software}, {MS_SCIEX_software, MS_software}, {MS_Applied_Biosystems_software, MS_software}, {MS_Bruker_software, MS_software}, {MS_Thermo_Finnigan_software, MS_software}, {MS_Waters_software, MS_software}, {MS_apex_ultra, MS_Bruker_Daltonics_apex_series}, {MS_autoflex_III_smartbeam, MS_Bruker_Daltonics_flex_series}, {MS_Bruker_Daltonics_HCT_Series, MS_Bruker_Daltonics_instrument_model}, {MS_HCTultra, MS_Bruker_Daltonics_HCT_Series}, {MS_HCTultra_PTM, MS_Bruker_Daltonics_HCT_Series}, {MS_HCTultra_ETD_II, MS_Bruker_Daltonics_HCT_Series}, {MS_microflex_LT, MS_Bruker_Daltonics_flex_series}, {MS_micrOTOF, MS_Bruker_Daltonics_micrOTOF_series}, {MS_micrOTOF_Q, MS_Bruker_Daltonics_micrOTOF_series}, {MS_micrOTOF_Q_II, MS_Bruker_Daltonics_micrOTOF_series}, {MS_ultraflex_III_TOF_TOF, MS_Bruker_Daltonics_flex_series}, {MS_apexControl, MS_Bruker_software}, {MS_apexControl, MS_acquisition_software}, {MS_BioTools, MS_Bruker_software}, {MS_BioTools, MS_analysis_software}, {MS_BioTools, MS_data_processing_software}, {MS_CLINPROT, MS_Bruker_software}, {MS_CLINPROT, MS_analysis_software}, {MS_CLINPROT, MS_data_processing_software}, {MS_CLINPROT_micro, MS_Bruker_software}, {MS_CLINPROT_micro, MS_analysis_software}, {MS_CLINPROT_micro, MS_data_processing_software}, {MS_CLINPROT_robot, MS_Bruker_software}, {MS_ClinProTools, MS_Bruker_software}, {MS_Compass, MS_Bruker_software}, {MS_Compass, MS_analysis_software}, {MS_Compass, MS_data_processing_software}, {MS_Compass_for_HCT_esquire, MS_Bruker_software}, {MS_Compass_for_HCT_esquire, MS_analysis_software}, {MS_Compass_for_HCT_esquire, MS_data_processing_software}, {MS_Compass_for_micrOTOF, MS_Bruker_software}, {MS_Compass_for_micrOTOF, MS_analysis_software}, {MS_Compass_for_micrOTOF, MS_data_processing_software}, {MS_Compass_OpenAccess, MS_Bruker_software}, {MS_Compass_OpenAccess, MS_analysis_software}, {MS_Compass_OpenAccess, MS_data_processing_software}, {MS_Compass_Security_Pack, MS_Bruker_software}, {MS_CompassXport, MS_Bruker_software}, {MS_CompassXport, MS_data_processing_software}, {MS_CompassXtract, MS_Bruker_software}, {MS_CompassXtract, MS_data_processing_software}, {MS_DataAnalysis, MS_Bruker_software}, {MS_DataAnalysis, MS_analysis_software}, {MS_DataAnalysis, MS_data_processing_software}, {MS_dpControl, MS_Bruker_software}, {MS_dpControl, MS_acquisition_software}, {MS_esquireControl, MS_Bruker_software}, {MS_esquireControl, MS_acquisition_software}, {MS_flexImaging, MS_Bruker_software}, {MS_flexImaging, MS_analysis_software}, {MS_flexImaging, MS_data_processing_software}, {MS_GENOLINK, MS_Bruker_software}, {MS_GenoTools, MS_Bruker_software}, {MS_HCTcontrol, MS_Bruker_software}, {MS_HCTcontrol, MS_acquisition_software}, {MS_micrOTOFcontrol, MS_Bruker_software}, {MS_micrOTOFcontrol, MS_acquisition_software}, {MS_PolyTools, MS_Bruker_software}, {MS_ProfileAnalysis, MS_Bruker_software}, {MS_ProfileAnalysis, MS_analysis_software}, {MS_ProfileAnalysis, MS_data_processing_software}, {MS_PROTEINEER, MS_Bruker_software}, {MS_PROTEINEER_dp, MS_Bruker_software}, {MS_PROTEINEER_fc, MS_Bruker_software}, {MS_PROTEINEER_spII, MS_Bruker_software}, {MS_PROTEINEER_LC, MS_Bruker_software}, {MS_ProteinScape, MS_Bruker_software}, {MS_ProteinScape, MS_analysis_software}, {MS_PureDisk, MS_Bruker_software}, {MS_QuantAnalysis, MS_Bruker_software}, {MS_QuantAnalysis, MS_analysis_software}, {MS_QuantAnalysis, MS_data_processing_software}, {MS_spControl, MS_Bruker_software}, {MS_spControl, MS_acquisition_software}, {MS_TargetAnalysis, MS_Bruker_software}, {MS_WARP_LC, MS_Bruker_software}, {MS_WARP_LC, MS_quantitation_software_name}, {MS_parameter_file, MS_mass_spectrometer_file_format}, {MS_Conversion_to_dta, MS_file_format_conversion}, {MS_Bioworks_SRF_format, MS_mass_spectrometer_file_format}, {MS_Bioworks_SRF_format, MS_intermediate_analysis_format}, {MS_TSQ_Quantum_Ultra_AM, MS_Thermo_Scientific_instrument_model}, {MS_selected_ion_m_z, MS_ion_selection_attribute}, {MS_retention_time_alignment, MS_data_processing_action}, {MS_high_intensity_data_point_removal, MS_data_filtering}, {MS_completion_time, MS_data_processing_parameter}, {MS_SSQ_7000, MS_Finnigan_MAT_instrument_model}, {MS_TSQ_7000, MS_Finnigan_MAT_instrument_model}, {MS_TSQ, MS_Finnigan_MAT_instrument_model}, {MS_TSQ_Quantum_Ultra, MS_Thermo_Scientific_instrument_model}, {MS_TOPP_software, MS_analysis_software}, {MS_TOPP_software, MS_data_processing_software}, {MS_BaselineFilter, MS_TOPP_software}, {MS_DBExporter, MS_TOPP_software}, {MS_DBImporter, MS_TOPP_software}, {MS_FileConverter, MS_TOPP_software}, {MS_FileFilter, MS_TOPP_software}, {MS_FileMerger, MS_TOPP_software}, {MS_InternalCalibration, MS_TOPP_software}, {MS_MapAligner_OBSOLETE, MS_TOPP_software}, {MS_MapNormalizer, MS_TOPP_software}, {MS_NoiseFilter_OBSOLETE, MS_TOPP_software}, {MS_PeakPicker_OBSOLETE, MS_TOPP_software}, {MS_Resampler, MS_TOPP_software}, {MS_SpectraFilter_OBSOLETE, MS_TOPP_software}, {MS_TOFCalibration, MS_TOPP_software}, {MS_Thermo_nativeID_format, MS_native_spectrum_identifier_format}, {MS_Waters_nativeID_format, MS_native_spectrum_identifier_format}, {MS_WIFF_nativeID_format, MS_native_spectrum_identifier_format}, {MS_Bruker_Agilent_YEP_nativeID_format, MS_native_spectrum_identifier_format}, {MS_Bruker_BAF_nativeID_format, MS_native_spectrum_identifier_format}, {MS_Bruker_FID_nativeID_format, MS_native_spectrum_identifier_format}, {MS_multiple_peak_list_nativeID_format, MS_native_spectrum_identifier_format}, {MS_single_peak_list_nativeID_format, MS_native_spectrum_identifier_format}, {MS_scan_number_only_nativeID_format, MS_native_spectrum_identifier_format}, {MS_spectrum_identifier_nativeID_format, MS_native_spectrum_identifier_format}, {MS_charge_state_calculation, MS_data_processing_action}, {MS_below_precursor_intensity_dominance_charge_state_calculation, MS_charge_state_calculation}, {MS_precursor_recalculation, MS_data_processing_action}, {MS_msPrefix_precursor_recalculation, MS_precursor_recalculation}, {MS_Savitzky_Golay_smoothing, MS_smoothing}, {MS_LOWESS_smoothing, MS_smoothing}, {MS_Gaussian_smoothing, MS_smoothing}, {MS_moving_average_smoothing, MS_smoothing}, {MS_non_standard_data_array, MS_binary_data_array}, {MS_inclusive_low_intensity_threshold, MS_data_processing_parameter}, {MS_inclusive_high_intensity_threshold, MS_data_processing_parameter}, {MS_enhanced_multiply_charged_spectrum, MS_data_file_content}, {MS_enhanced_multiply_charged_spectrum, MS_MS1_spectrum}, {MS_time_delayed_fragmentation_spectrum, MS_data_file_content}, {MS_time_delayed_fragmentation_spectrum, MS_MSn_spectrum}, {MS_isolation_window_attribute, MS_object_attribute}, {MS_isolation_window_upper_limit_OBSOLETE, MS_isolation_window_attribute}, {MS_isolation_window_lower_limit_OBSOLETE, MS_isolation_window_attribute}, {MS_no_combination, MS_spectra_combination}, {MS_spectrum_title, MS_spectrum_attribute}, {MS_spectrum_title, MS_spectrum_identification_result_details}, {MS_peak_list_scans, MS_spectrum_attribute}, {MS_peak_list_scans, MS_spectrum_identification_result_details}, {MS_peak_list_raw_scans, MS_spectrum_attribute}, {MS_peak_list_raw_scans, MS_spectrum_identification_result_details}, {MS_custom_unreleased_software_tool, MS_software}, {MS_mass_resolving_power, MS_scan_attribute}, {MS_area_peak_picking, MS_peak_picking}, {MS_height_peak_picking, MS_peak_picking}, {MS_analyzer_scan_offset, MS_scan_attribute}, {MS_electromagnetic_radiation_spectrum, MS_data_file_content}, {MS_electromagnetic_radiation_spectrum, MS_spectrum_type}, {MS_emission_spectrum, MS_data_file_content}, {MS_emission_spectrum, MS_spectrum_type}, {MS_absorption_spectrum, MS_data_file_content}, {MS_absorption_spectrum, MS_spectrum_type}, {MS_chromatogram_attribute, MS_object_attribute}, {MS_chromatogram_title, MS_chromatogram_attribute}, {MS_mass_chromatogram, MS_data_file_content}, {MS_mass_chromatogram, MS_chromatogram_type}, {MS_electromagnetic_radiation_chromatogram, MS_data_file_content}, {MS_electromagnetic_radiation_chromatogram, MS_chromatogram_type}, {MS_absorption_chromatogram, MS_data_file_content}, {MS_absorption_chromatogram, MS_electromagnetic_radiation_chromatogram}, {MS_emission_chromatogram, MS_data_file_content}, {MS_emission_chromatogram, MS_electromagnetic_radiation_chromatogram}, {MS_counts_per_second, MS_intensity_unit}, {MS_Bruker_BAF_format, MS_mass_spectrometer_file_format}, {MS_Bruker_U2_format, MS_mass_spectrometer_file_format}, {MS_HyStar, MS_Bruker_software}, {MS_Acquity_UPLC_PDA, MS_Waters_instrument_model}, {MS_Acquity_UPLC_PDA, MS_photodiode_array_detector}, {MS_Acquity_UPLC_FLR, MS_Waters_instrument_model}, {MS_Acquity_UPLC_FLR, MS_fluorescence_detector}, {MS_flow_rate_array, MS_binary_data_array}, {MS_pressure_array, MS_binary_data_array}, {MS_temperature_array, MS_binary_data_array}, {MS_Bruker_U2_nativeID_format, MS_native_spectrum_identifier_format}, {MS_no_nativeID_format, MS_native_spectrum_identifier_format}, {MS_Bruker_FID_format, MS_mass_spectrometer_file_format}, {MS_elution_time, MS_scan_attribute}, {MS_isolation_window_target_m_z, MS_isolation_window_attribute}, {MS_isolation_window_lower_offset, MS_isolation_window_attribute}, {MS_isolation_window_upper_offset, MS_isolation_window_attribute}, {MS_sample_preparation, MS_object_attribute}, {MS_matrix_solution, MS_MALDI_matrix_application}, {MS_matrix_solution_concentration, MS_MALDI_matrix_application}, {MS_dried_droplet_MALDI_matrix_preparation, MS_matrix_application_type}, {MS_printed_MALDI_matrix_preparation, MS_matrix_application_type}, {MS_sprayed_MALDI_matrix_preparation, MS_matrix_application_type}, {MS_precoated_MALDI_sample_plate, MS_matrix_application_type}, {MS_precoated_MALDI_sample_plate, MS_sample_plate_type}, {MS_wavelength_OBSOLETE, MS_laser_attribute}, {MS_focus_diameter_x, MS_laser_attribute}, {MS_focus_diameter_y, MS_laser_attribute}, {MS_pulse_energy, MS_laser_attribute}, {MS_pulse_duration, MS_laser_attribute}, {MS_attenuation, MS_laser_attribute}, {MS_impact_angle, MS_laser_attribute}, {MS_gas_laser, MS_laser_type}, {MS_solid_state_laser, MS_laser_type}, {MS_dye_laser, MS_laser_type}, {MS_free_electron_laser, MS_laser_type}, {MS_LTQ_XL, MS_Thermo_Scientific_instrument_model}, {MS_LTQ_Velos, MS_Thermo_Scientific_instrument_model}, {MS_LTQ_Velos_ETD, MS_Thermo_Scientific_instrument_model}, {MS_run_attribute, MS_object_attribute}, {MS_fraction_identifier, MS_run_attribute}, {MS_peptide, MS_chemical_compound}, {MS_isoelectric_point, MS_chemical_compound_attribute}, {MS_predicted_isoelectric_point, MS_isoelectric_point}, {MS_empirical_formula, MS_chemical_compound_formula}, {MS_molecular_formula, MS_chemical_compound_formula}, {MS_structural_formula, MS_chemical_compound_formula}, {MS_SMILES_string, MS_chemical_compound_formula}, {MS_collision_gas_pressure, MS_precursor_activation_attribute}, {MS_4000_QTRAP_OBSOLETE, MS_SCIEX_instrument_model}, {MS_SRM_software, MS_software}, {MS_MaRiMba, MS_SRM_software}, {MS_peptide_attribute_calculation_software, MS_software}, {MS_SSRCalc, MS_peptide_attribute_calculation_software}, {MS_declustering_potential, MS_source_attribute}, {MS_cone_voltage, MS_source_attribute}, {MS_tube_lens_voltage, MS_source_attribute}, {MS_PubMed_identifier, MS_external_reference_identifier}, {MS_interchannel_delay, MS_scan_attribute}, {MS_protein, MS_chemical_compound}, {MS_protein_short_name, MS_protein_attribute}, {MS_protein_attribute, MS_quantification_object_attribute}, {MS_protein_accession, MS_protein_attribute}, {MS_protein_name, MS_protein_attribute}, {MS_unmodified_peptide_sequence, MS_peptide_attribute}, {MS_modified_peptide_sequence, MS_peptide_attribute}, {MS_peptide_labeling_state, MS_peptide_attribute}, {MS_heavy_labeled_peptide, MS_peptide_labeling_state}, {MS_unlabeled_peptide, MS_peptide_labeling_state}, {MS_peptide_group_label, MS_peptide_attribute}, {MS_retention_time, MS_peptide_attribute}, {MS_local_retention_time, MS_retention_time}, {MS_normalized_retention_time, MS_retention_time}, {MS_predicted_retention_time, MS_retention_time}, {MS_de_facto_standard, MS_standard}, {MS_minimum_information_standard, MS_standard}, {MS_retention_time_normalization_standard, MS_standard}, {MS_H_PINS_retention_time_normalization_standard, MS_retention_time_normalization_standard}, {MS_product_ion_series_ordinal, MS_fragmentation_information}, {MS_product_ion_m_z_delta, MS_fragmentation_information}, {MS_percent_of_base_peak_times_100, MS_intensity_unit}, {MS_peak_intensity_rank, MS_ion_selection_attribute}, {MS_peak_targeting_suitability_rank, MS_ion_selection_attribute}, {MS_transition_optimized_on_specified_instrument, MS_transition_validation_method}, {MS_transition_validated_with_an_MS_MS_spectrum_on_specified_instrument, MS_transition_validation_method}, {MS_transition_purported_from_an_MS_MS_spectrum_on_a_different__specified_instrument, MS_transition_validation_method}, {MS_transition_predicted_by_informatic_analysis, MS_transition_validation_method}, {MS_tab_delimited_text_format, MS_file_format}, {MS_tab_delimited_text_format, MS_intermediate_analysis_format}, {MS_retention_time_window_lower_offset, MS_retention_time_window_attribute}, {MS_retention_time_window_upper_offset, MS_retention_time_window_attribute}, {MS_includes_supersede_excludes, MS_target_inclusion_exclusion_priority}, {MS_excludes_supersede_includes, MS_target_inclusion_exclusion_priority}, {MS_Skyline, MS_SRM_software}, {MS_Skyline, MS_quantitation_software_name}, {MS_TIQAM, MS_SRM_software}, {MS_ATAQS, MS_SRM_software}, {MS_product_interpretation_rank, MS_fragmentation_information}, {MS_ion_injection_time, MS_scan_attribute}, {MS_calibration_spectrum, MS_spectrum_type}, {MS_Shimadzu_Biotech_nativeID_format, MS_native_spectrum_identifier_format}, {MS_Shimadzu_Biotech_database_entity, MS_mass_spectrometer_file_format}, {MS_QTRAP_5500, MS_SCIEX_instrument_model}, {MS_TripleTOF_5600, MS_SCIEX_instrument_model}, {MS_protein_modifications, MS_protein_attribute}, {MS_gene_name, MS_protein_attribute}, {MS_SEQUEST_CleavesAt, MS_SEQUEST_input_parameter}, {MS_SEQUEST_ViewCV, MS_SEQUEST_input_parameter}, {MS_SEQUEST_OutputLines, MS_SEQUEST_input_parameter}, {MS_SEQUEST_DescriptionLines, MS_SEQUEST_input_parameter}, {MS_de_novo_search, MS_search_type}, {MS_search_database_details, MS_search_input_details}, {MS_database_source, MS_search_database_details}, {MS_database_name, MS_search_database_details}, {MS_database_local_file_path_OBSOLETE, MS_search_database_details}, {MS_database_original_uri, MS_search_database_details}, {MS_database_version_OBSOLETE, MS_search_database_details}, {MS_database_release_date_OBSOLETE, MS_search_database_details}, {MS_database_type, MS_search_database_details}, {MS_database_filtering, MS_search_database_details}, {MS_DB_filter_taxonomy, MS_Sequence_database_filter_types}, {MS_DB_filter_on_accession_numbers, MS_Sequence_database_filter_types}, {MS_DB_MW_filter, MS_Sequence_database_filter_types}, {MS_DB_PI_filter, MS_Sequence_database_filter_types}, {MS_translation_frame, MS_search_database_details}, {MS_translation_table, MS_search_database_details}, {MS_SEQUEST_NormalizeXCorrValues, MS_SEQUEST_input_parameter}, {MS_DB_filter_on_sequence_pattern, MS_Sequence_database_filter_types}, {MS_SEQUEST_SequenceHeaderFilter, MS_SEQUEST_input_parameter}, {MS_number_of_sequences_searched, MS_search_database_details}, {MS_number_of_peptide_seqs_compared_to_each_spectrum, MS_search_database_details}, {MS_number_of_peptide_seqs_compared_to_each_spectrum, MS_spectrum_identification_result_details}, {MS_spectral_library_search, MS_search_type}, {MS_SEQUEST_SequencePartialFilter, MS_SEQUEST_input_parameter}, {MS_date___time_search_performed_OBSOLETE, MS_search_statistics}, {MS_search_time_taken, MS_search_statistics}, {MS_SEQUEST_ShowFragmentIons, MS_SEQUEST_input_parameter}, {MS_SEQUEST_Consensus, MS_SEQUEST_ViewCV}, {MS_intermediate_analysis_format, MS_file_format}, {MS_SEQUEST_sortCV, MS_SEQUEST_ViewCV}, {MS_SEQUEST_LimitTo, MS_SEQUEST_input_parameter}, {MS_cleavage_agent_details, MS_search_input_details}, {MS_cleavage_agent_name, MS_cleavage_agent_details}, {MS_SEQUEST_sort_by_dCn, MS_SEQUEST_sortCV}, {MS_SEQUEST_sort_by_dM, MS_SEQUEST_sortCV}, {MS_SEQUEST_sort_by_Ions, MS_SEQUEST_sortCV}, {MS_SEQUEST_sort_by_MH_, MS_SEQUEST_sortCV}, {MS_SEQUEST_sort_by_P, MS_SEQUEST_sortCV}, {MS_SEQUEST_sort_by_PreviousAminoAcid, MS_SEQUEST_sortCV}, {MS_SEQUEST_sort_by_Ref, MS_SEQUEST_sortCV}, {MS_modification_specificity_rule, MS_modification_parameters}, {MS_tolerance_on_types_OBSOLETE, MS_modification_parameters}, {MS_quality_estimation_by_manual_validation, MS_quality_estimation_method_details}, {MS_SEQUEST_sort_by_RSp, MS_SEQUEST_sortCV}, {MS_quality_estimation_method_details, MS_search_input_details}, {MS_neutral_loss_OBSOLETE, MS_modification_parameters}, {MS_Mascot_MGF_format, MS_mass_spectrometer_file_format}, {MS_TODOscoring_model_OBSOLETE, MS_search_input_details}, {MS_ions_series_considered_in_search, MS_search_input_details}, {MS_SEQUEST_sort_by_Sp, MS_SEQUEST_sortCV}, {MS_SEQUEST_sort_by_TIC, MS_SEQUEST_sortCV}, {MS_SEQUEST_sort_by_Scan, MS_SEQUEST_sortCV}, {MS_SEQUEST_sort_by_Sequence, MS_SEQUEST_sortCV}, {MS_SEQUEST_sort_by_Sf, MS_SEQUEST_sortCV}, {MS_database_type_amino_acid, MS_database_type}, {MS_database_type_nucleotide, MS_database_type}, {MS_search_type, MS_search_input_details}, {MS_pmf_search, MS_search_type}, {MS_tag_search, MS_search_type}, {MS_ms_ms_search, MS_search_type}, {MS_database_nr, MS_database_name}, {MS_protein_result_details, MS_spectrum_identification_result_details}, {MS_SEQUEST_sort_by_XCorr, MS_SEQUEST_sortCV}, {MS_SEQUEST_ProcessCV, MS_SEQUEST_input_parameter}, {MS_protein_description, MS_single_protein_result_details}, {MS_protein_description, MS_database_sequence_details}, {MS_molecule_taxonomy, MS_protein_result_details}, {MS_molecule_taxonomy, MS_database_sequence_details}, {MS_molecule_taxonomy, MS_Sequence_database_filters}, {MS_taxonomy_nomenclature_OBSOLETE, MS_molecule_taxonomy}, {MS_NoEnzyme_OBSOLETE, MS_cleavage_agent_name}, {MS_peptide_identification_confidence_metric, MS_peptide_result_details}, {MS_sequence_coverage, MS_single_protein_result_details}, {MS_SEQUEST_sort_by_z, MS_SEQUEST_sortCV}, {MS_SEQUEST_ProcessAll, MS_SEQUEST_ProcessCV}, {MS_SEQUEST_TopPercentMostIntense, MS_SEQUEST_ProcessCV}, {MS_distinct_peptide_sequences, MS_single_protein_result_details}, {MS_confident_distinct_peptide_sequences, MS_single_protein_result_details}, {MS_confident_peptide_qualification, MS_single_protein_result_details}, {MS_confident_peptide_sequence_number, MS_single_protein_result_details}, {MS_protein_group_or_subset_relationship, MS_protein_result_details}, {MS_SEQUEST_Chromatogram, MS_SEQUEST_ViewCV}, {MS_SEQUEST_InfoAndLog, MS_SEQUEST_ViewCV}, {MS_database_UniProtKB_Swiss_Prot, MS_database_UniProtKB}, {MS_peptide_result_details, MS_spectrum_identification_result_details}, {MS_SEQUEST_TopNumber, MS_SEQUEST_ProcessCV}, {MS_data_stored_in_database, MS_intermediate_analysis_format}, {MS_param__a_ion, MS_ion_series_considered_in_search}, {MS_SEQUEST_CullTo, MS_SEQUEST_ProcessCV}, {MS_SEQUEST_modeCV, MS_SEQUEST_input_parameter}, {MS_SEQUEST_Full, MS_SEQUEST_modeCV}, {MS_n_terminal_flanking_residue, MS_peptide_result_details}, {MS_c_terminal_flanking_residue, MS_peptide_result_details}, {MS_retention_time_s__OBSOLETE, MS_peptide_result_details}, {MS_retention_time_s__OBSOLETE, MS_spectrum_identification_result_details}, {MS_single_protein_result_details, MS_protein_result_details}, {MS_theoretical_mass, MS_peptide_result_details}, {MS_param__b_ion, MS_ion_series_considered_in_search}, {MS_param__c_ion, MS_ion_series_considered_in_search}, {MS_SEQUEST_FormatAndLinks, MS_SEQUEST_modeCV}, {MS_number_of_matched_peaks, MS_peptide_result_details}, {MS_ions_series_considered, MS_peptide_result_details}, {MS_number_of_peaks_used, MS_peptide_result_details}, {MS_number_of_peaks_submitted, MS_peptide_result_details}, {MS_manual_validation, MS_peptide_identification_confidence_metric}, {MS_manual_validation, MS_protein_identification_confidence_metric}, {MS_SEQUEST_Fast, MS_SEQUEST_modeCV}, {MS_peptide_sharing_details, MS_peptide_result_details}, {MS_SEQUEST_selectCV, MS_SEQUEST_input_parameter}, {MS_peptide_raw_area_OBSOLETE, MS_quantification_datatype}, {MS_error_on_peptide_area, MS_quantification_datatype}, {MS_peptide_ratio, MS_quantification_datatype}, {MS_error_on_peptide_ratio, MS_quantification_datatype}, {MS_protein_ratio, MS_quantification_datatype}, {MS_error_on_protein_ratio, MS_quantification_datatype}, {MS_p_value__protein_diff_from_1_randomly__OBSOLETE, MS_quantification_datatype}, {MS_absolute_quantity, MS_quantification_datatype}, {MS_error_on_absolute_quantity, MS_quantification_datatype}, {MS_quantitation_software_name, MS_software}, {MS_quantitation_software_name, MS_quantification_information}, {MS_quantitation_software_version_OBSOLETE, MS_quantification_information}, {MS_intensity_of_precursor_ion, MS_quantification_datatype}, {MS_database_IPI_human, MS_database_name}, {MS_search_engine_specific_score_for_PSMs, MS_peptide_result_details}, {MS_SEQUEST_SelectDefault, MS_SEQUEST_selectCV}, {MS_SEQUEST_SelectAdvancedCV, MS_SEQUEST_selectCV}, {MS_param__a_ion_NH3_DEPRECATED, MS_ions_series_considered_in_search}, {MS_protein_ambiguity_group_result_details, MS_protein_result_details}, {MS_protein_ambiguity_group_result_details, MS_search_engine_specific_score}, {MS_param__a_ion_H2O_DEPRECATED, MS_ions_series_considered_in_search}, {MS_param__b_ion_NH3_DEPRECATED, MS_ions_series_considered_in_search}, {MS_param__b_ion_H2O_DEPRECATED, MS_ions_series_considered_in_search}, {MS_param__y_ion_NH3_DEPRECATED, MS_ions_series_considered_in_search}, {MS_param__y_ion_H2O_DEPRECATED, MS_ions_series_considered_in_search}, {MS_search_engine_specific_score, MS_spectrum_identification_result_details}, {MS_SEQUEST_probability, MS_search_engine_specific_score_for_PSMs}, {MS_SEQUEST_probability, MS_search_engine_specific_score}, {MS_SEQUEST_xcorr, MS_search_engine_specific_score_for_PSMs}, {MS_SEQUEST_xcorr, MS_search_engine_specific_score}, {MS_SEQUEST_deltacn, MS_search_engine_specific_score_for_PSMs}, {MS_SEQUEST_deltacn, MS_search_engine_specific_score}, {MS_SEQUEST_sp, MS_single_protein_result_details}, {MS_SEQUEST_sp, MS_search_engine_specific_score}, {MS_SEQUEST_Uniq, MS_single_protein_result_details}, {MS_SEQUEST_Uniq, MS_search_engine_specific_score}, {MS_SEQUEST_expectation_value, MS_search_engine_specific_score}, {MS_SEQUEST_sf, MS_search_engine_specific_score_for_PSMs}, {MS_SEQUEST_sf, MS_search_engine_specific_score}, {MS_SEQUEST_matched_ions, MS_search_engine_specific_score_for_PSMs}, {MS_SEQUEST_matched_ions, MS_search_engine_specific_score}, {MS_SEQUEST_total_ions, MS_search_engine_specific_score_for_PSMs}, {MS_SEQUEST_total_ions, MS_search_engine_specific_score}, {MS_SEQUEST_consensus_score, MS_search_engine_specific_score}, {MS_Paragon_unused_protscore, MS_protein_ambiguity_group_result_details}, {MS_Paragon_unused_protscore, MS_search_engine_specific_score}, {MS_Paragon_total_protscore, MS_protein_ambiguity_group_result_details}, {MS_Paragon_total_protscore, MS_search_engine_specific_score}, {MS_Paragon_score, MS_search_engine_specific_score}, {MS_Paragon_confidence, MS_search_engine_specific_score}, {MS_Paragon_expression_error_factor, MS_search_engine_specific_score}, {MS_Paragon_expression_change_p_value, MS_search_engine_specific_score}, {MS_Paragon_expression_change_p_value, MS_protein_level_p_value}, {MS_Paragon_contrib, MS_search_engine_specific_score}, {MS_Mascot_score, MS_single_protein_result_details}, {MS_Mascot_score, MS_search_engine_specific_score_for_PSMs}, {MS_Mascot_score, MS_search_engine_specific_score}, {MS_Mascot_expectation_value, MS_single_protein_result_details}, {MS_Mascot_expectation_value, MS_search_engine_specific_score_for_PSMs}, {MS_Mascot_expectation_value, MS_search_engine_specific_score}, {MS_Mascot_matched_ions, MS_search_engine_specific_score_for_PSMs}, {MS_Mascot_matched_ions, MS_search_engine_specific_score}, {MS_Mascot_total_ions, MS_search_engine_specific_score_for_PSMs}, {MS_Mascot_total_ions, MS_search_engine_specific_score}, {MS_peptide_shared_in_multiple_proteins, MS_peptide_sharing_details}, {MS______KR_____P_, MS_Cleavage_agent_regular_expression}, {MS_number_of_molecular_hypothesis_considered, MS_search_statistics}, {MS_database_EST, MS_database_type_nucleotide}, {MS_Cleavage_agent_regular_expression, MS_regular_expression}, {MS_search_statistics, MS_spectrum_identification_result_details}, {MS_modification_specificity_peptide_N_term, MS_modification_specificity_rule}, {MS_modification_specificity_peptide_C_term, MS_modification_specificity_rule}, {MS_p_value_OBSOLETE, MS_peptide_identification_confidence_metric}, {MS_p_value_OBSOLETE, MS_protein_identification_confidence_metric}, {MS_Expect_value, MS_peptide_identification_confidence_metric}, {MS_Expect_value, MS_protein_identification_confidence_metric}, {MS_confidence_score, MS_peptide_identification_confidence_metric}, {MS_confidence_score, MS_protein_identification_confidence_metric}, {MS_quality_estimation_with_decoy_database, MS_quality_estimation_method_details}, {MS_decoy_DB_type_reverse, MS_decoy_DB_details}, {MS_decoy_DB_type_randomized, MS_decoy_DB_details}, {MS_DB_composition_target_decoy, MS_decoy_DB_details}, {MS_protein_identification_confidence_metric, MS_single_protein_result_details}, {MS_Mascot_DAT_format, MS_intermediate_analysis_format}, {MS_SEQUEST_out_file_format, MS_intermediate_analysis_format}, {MS_DB_MW_filter_maximum, MS_Sequence_database_filters}, {MS_DB_MW_filter_minimum, MS_Sequence_database_filters}, {MS_DB_PI_filter_maximum, MS_Sequence_database_filters}, {MS_DB_PI_filter_minimum, MS_Sequence_database_filters}, {MS_Mascot, MS_analysis_software}, {MS_SEQUEST, MS_analysis_software}, {MS_Phenyx, MS_analysis_software}, {MS_mass_type_settings, MS_search_input_details}, {MS_parent_mass_type_mono, MS_mass_type_settings}, {MS_parent_mass_type_average, MS_mass_type_settings}, {MS_protein_level_global_FDR, MS_single_protein_result_details}, {MS_SEQUEST_PeptideSp, MS_search_engine_specific_score_for_PSMs}, {MS_SEQUEST_PeptideSp, MS_search_engine_specific_score}, {MS_SEQUEST_PeptideRankSp, MS_search_engine_specific_score_for_PSMs}, {MS_SEQUEST_PeptideRankSp, MS_search_engine_specific_score}, {MS_SEQUEST_PeptideNumber, MS_search_engine_specific_score_for_PSMs}, {MS_SEQUEST_PeptideNumber, MS_search_engine_specific_score}, {MS_SEQUEST_PeptideIdnumber, MS_search_engine_specific_score_for_PSMs}, {MS_SEQUEST_PeptideIdnumber, MS_search_engine_specific_score}, {MS_frag__y_ion, MS_fragmentation_ion_type}, {MS_fragmentation_information, MS_peptide_result_details}, {MS_frag__b_ion___H2O, MS_fragmentation_ion_type}, {MS_frag__y_ion___H2O, MS_fragmentation_ion_type}, {MS_frag__b_ion, MS_fragmentation_ion_type}, {MS_product_ion_m_z, MS_fragmentation_information}, {MS_product_ion_intensity, MS_fragmentation_information}, {MS_product_ion_m_z_error, MS_fragmentation_information}, {MS_frag__x_ion, MS_fragmentation_ion_type}, {MS_frag__a_ion, MS_fragmentation_ion_type}, {MS_frag__z_ion, MS_fragmentation_ion_type}, {MS_frag__c_ion, MS_fragmentation_ion_type}, {MS_frag__b_ion___NH3, MS_fragmentation_ion_type}, {MS_frag__y_ion___NH3, MS_fragmentation_ion_type}, {MS_frag__a_ion___H2O, MS_fragmentation_ion_type}, {MS_frag__a_ion___NH3, MS_fragmentation_ion_type}, {MS_frag__d_ion, MS_fragmentation_ion_type}, {MS_frag__v_ion, MS_fragmentation_ion_type}, {MS_frag__w_ion, MS_fragmentation_ion_type}, {MS_frag__immonium_ion, MS_fragmentation_ion_type}, {MS_non_identified_ion, MS_fragmentation_information}, {MS_co_eluting_ion, MS_fragmentation_information}, {MS_SEQUEST_out_folder, MS_intermediate_analysis_format}, {MS_SEQUEST_summary, MS_intermediate_analysis_format}, {MS_PerSeptive_PKS_format, MS_mass_spectrometer_file_format}, {MS_SCIEX_API_III_format, MS_mass_spectrometer_file_format}, {MS_Bruker_XML_format, MS_mass_spectrometer_file_format}, {MS_local_FDR, MS_peptide_identification_confidence_metric}, {MS_local_FDR, MS_protein_identification_confidence_metric}, {MS_Trypsin, MS_cleavage_agent_name}, {MS_DB_source_EBI, MS_database_source}, {MS_DB_source_NCBI, MS_database_source}, {MS_DB_source_UniProt, MS_database_source}, {MS_fragment_mass_type_average, MS_mass_type_settings}, {MS_fragment_mass_type_mono, MS_mass_type_settings}, {MS_param__v_ion, MS_ion_series_considered_in_search}, {MS_param__d_ion, MS_ion_series_considered_in_search}, {MS_param__immonium_ion, MS_ion_series_considered_in_search}, {MS_param__w_ion, MS_ion_series_considered_in_search}, {MS_param__x_ion, MS_ion_series_considered_in_search}, {MS_param__y_ion, MS_ion_series_considered_in_search}, {MS_param__z_ion, MS_ion_series_considered_in_search}, {MS_role_type, MS_contact_attribute}, {MS_software_vendor, MS_role_type}, {MS_programmer, MS_role_type}, {MS_instrument_vendor, MS_role_type}, {MS_lab_personnel, MS_role_type}, {MS_researcher, MS_role_type}, {MS_____R____P_, MS_Cleavage_agent_regular_expression}, {MS_____BD__, MS_Cleavage_agent_regular_expression}, {MS_____DE__, MS_Cleavage_agent_regular_expression}, {MS_ProteinScape_SearchEvent, MS_intermediate_analysis_format}, {MS_ProteinScape_Gel, MS_intermediate_analysis_format}, {MS_decoy_DB_accession_regexp, MS_decoy_DB_details}, {MS_decoy_DB_derived_from_OBSOLETE, MS_decoy_DB_details}, {MS_database_IPI_mouse, MS_database_name}, {MS_database_IPI_rat, MS_database_name}, {MS_database_IPI_zebrafish, MS_database_name}, {MS_database_IPI_chicken, MS_database_name}, {MS_database_IPI_cow, MS_database_name}, {MS_database_IPI_arabidopsis, MS_database_name}, {MS_protein_rank, MS_protein_ambiguity_group_result_details}, {MS_search_engine_specific_input_parameter, MS_search_engine_input_parameter}, {MS_Arg_C, MS_cleavage_agent_name}, {MS_Asp_N, MS_cleavage_agent_name}, {MS_Asp_N_ambic, MS_cleavage_agent_name}, {MS_Chymotrypsin, MS_cleavage_agent_name}, {MS_CNBr, MS_cleavage_agent_name}, {MS_Formic_acid, MS_cleavage_agent_name}, {MS_Lys_C, MS_cleavage_agent_name}, {MS_Lys_C_P, MS_cleavage_agent_name}, {MS_PepsinA, MS_cleavage_agent_name}, {MS_TrypChymo, MS_cleavage_agent_name}, {MS_Trypsin_P, MS_cleavage_agent_name}, {MS_V8_DE, MS_cleavage_agent_name}, {MS_V8_E, MS_cleavage_agent_name}, {MS_Mascot_SigThreshold, MS_Mascot_input_parameter}, {MS_Mascot_MaxProteinHits, MS_Mascot_input_parameter}, {MS_Mascot_ProteinScoringMethod, MS_Mascot_input_parameter}, {MS_Mascot_MinMSMSThreshold, MS_Mascot_input_parameter}, {MS_Mascot_ShowHomologousProteinsWithSamePeptides, MS_Mascot_input_parameter}, {MS_Mascot_ShowHomologousProteinsWithSubsetOfPeptides, MS_Mascot_input_parameter}, {MS_Mascot_RequireBoldRed, MS_Mascot_input_parameter}, {MS_Mascot_UseUnigeneClustering, MS_Mascot_input_parameter}, {MS_Mascot_IncludeErrorTolerantMatches, MS_Mascot_input_parameter}, {MS_Mascot_ShowDecoyMatches, MS_Mascot_input_parameter}, {MS_OMSSA_evalue, MS_search_engine_specific_score_for_PSMs}, {MS_OMSSA_evalue, MS_search_engine_specific_score}, {MS_OMSSA_evalue, MS_distinct_peptide_level_e_value}, {MS_OMSSA_pvalue, MS_search_engine_specific_score_for_PSMs}, {MS_OMSSA_pvalue, MS_search_engine_specific_score}, {MS_OMSSA_pvalue, MS_distinct_peptide_level_p_value}, {MS_X_Tandem_expect, MS_search_engine_specific_score_for_PSMs}, {MS_X_Tandem_expect, MS_search_engine_specific_score}, {MS_X_Tandem_expect, MS_distinct_peptide_level_e_value}, {MS_X_Tandem_hyperscore, MS_search_engine_specific_score_for_PSMs}, {MS_X_Tandem_hyperscore, MS_search_engine_specific_score}, {MS______FYWL_____P_, MS_Cleavage_agent_regular_expression}, {MS_____M_, MS_Cleavage_agent_regular_expression}, {MS______D_______D__, MS_Cleavage_agent_regular_expression}, {MS_____K____P_, MS_Cleavage_agent_regular_expression}, {MS_____K_, MS_Cleavage_agent_regular_expression}, {MS______FL__, MS_Cleavage_agent_regular_expression}, {MS______FYWLKR_____P_, MS_Cleavage_agent_regular_expression}, {MS______KR__, MS_Cleavage_agent_regular_expression}, {MS______BDEZ_____P_, MS_Cleavage_agent_regular_expression}, {MS______EZ_____P_, MS_Cleavage_agent_regular_expression}, {MS_database_sequence_details, MS_search_database_details}, {MS_NA_sequence, MS_database_sequence_details}, {MS_AA_sequence, MS_database_sequence_details}, {MS_mass_table_source, MS_mass_table_options}, {MS_AAIndex_mass_table, MS_mass_table_source}, {MS_database_file_formats, MS_search_database_details}, {MS_FASTA_format, MS_database_file_formats}, {MS_ASN_1, MS_database_file_formats}, {MS_NCBI___p_, MS_database_file_formats}, {MS_clustal_aln, MS_database_file_formats}, {MS_embl_em, MS_database_file_formats}, {MS_NBRF_PIR, MS_database_file_formats}, {MS_peptide_descriptions, MS_peptide_result_details}, {MS_spectrum_descriptions, MS_search_input_details}, {MS_spectrum_quality_descriptions, MS_spectrum_descriptions}, {MS_msmsEval_quality, MS_spectrum_quality_descriptions}, {MS_alternate_single_letter_codes, MS_ambiguous_residues}, {MS_alternate_mass, MS_ambiguous_residues}, {MS_number_of_unmatched_peaks, MS_single_protein_result_details}, {MS_number_of_unmatched_peaks, MS_spectrum_identification_result_details}, {MS_peptide_unique_to_one_protein, MS_peptide_sharing_details}, {MS_distinct_peptide_level_global_FDR, MS_peptide_result_details}, {MS_distinct_peptide_level_global_FDR, MS_peptide_level_statistical_threshold}, {MS_frag__internal_yb_ion, MS_fragmentation_ion_type}, {MS_frag__internal_ya_ion, MS_fragmentation_ion_type}, {MS_frag__z_1_ion, MS_fragmentation_ion_type}, {MS_frag__z_2_ion, MS_fragmentation_ion_type}, {MS_text_format, MS_mass_spectrometer_file_format}, {MS_Mascot_homology_threshold, MS_search_engine_specific_score_for_PSMs}, {MS_Mascot_homology_threshold, MS_search_engine_specific_score}, {MS_Mascot_homology_threshold, MS_spectrum_identification_result_details}, {MS_Mascot_identity_threshold, MS_single_protein_result_details}, {MS_Mascot_identity_threshold, MS_search_engine_specific_score_for_PSMs}, {MS_Mascot_identity_threshold, MS_search_engine_specific_score}, {MS_Mascot_identity_threshold, MS_spectrum_identification_result_details}, {MS_SEQUEST_Sequences, MS_single_protein_result_details}, {MS_SEQUEST_Sequences, MS_search_engine_specific_score}, {MS_SEQUEST_TIC, MS_single_protein_result_details}, {MS_SEQUEST_TIC, MS_search_engine_specific_score}, {MS_SEQUEST_Sum, MS_single_protein_result_details}, {MS_SEQUEST_Sum, MS_search_engine_specific_score}, {MS_Phenyx_Instrument_Type, MS_Phenyx_input_parameter}, {MS_Phenyx_Scoring_Model, MS_Phenyx_input_parameter}, {MS_Phenyx_Default_Parent_Charge, MS_Phenyx_input_parameter}, {MS_Phenyx_Trust_Parent_Charge, MS_Phenyx_input_parameter}, {MS_Phenyx_Turbo, MS_Phenyx_input_parameter}, {MS_Phenyx_Turbo_ErrorTol, MS_Phenyx_input_parameter}, {MS_Phenyx_Turbo_Coverage, MS_Phenyx_input_parameter}, {MS_Phenyx_Turbo_Series, MS_Phenyx_input_parameter}, {MS_Phenyx_MinPepLength, MS_Phenyx_input_parameter}, {MS_Phenyx_MinPepzscore, MS_Phenyx_input_parameter}, {MS_Phenyx_MaxPepPvalue, MS_Phenyx_input_parameter}, {MS_Phenyx_AC_Score, MS_Phenyx_input_parameter}, {MS_Phenyx_Conflict_Resolution, MS_Phenyx_input_parameter}, {MS_Phenyx_AC, MS_single_protein_result_details}, {MS_Phenyx_AC, MS_search_engine_specific_score}, {MS_Phenyx_ID, MS_single_protein_result_details}, {MS_Phenyx_ID, MS_search_engine_specific_score}, {MS_Phenyx_Score, MS_single_protein_result_details}, {MS_Phenyx_Score, MS_search_engine_specific_score}, {MS_Phenyx_Peptides1, MS_single_protein_result_details}, {MS_Phenyx_Peptides1, MS_search_engine_specific_score}, {MS_Phenyx_Peptides2, MS_single_protein_result_details}, {MS_Phenyx_Peptides2, MS_search_engine_specific_score}, {MS_Phenyx_Auto, MS_search_engine_specific_score_for_PSMs}, {MS_Phenyx_Auto, MS_search_engine_specific_score}, {MS_Phenyx_User, MS_search_engine_specific_score_for_PSMs}, {MS_Phenyx_User, MS_search_engine_specific_score}, {MS_Phenyx_Pepzscore, MS_search_engine_specific_score_for_PSMs}, {MS_Phenyx_Pepzscore, MS_search_engine_specific_score}, {MS_Phenyx_PepPvalue, MS_search_engine_specific_score_for_PSMs}, {MS_Phenyx_PepPvalue, MS_search_engine_specific_score}, {MS_Phenyx_PepPvalue, MS_distinct_peptide_level_p_value}, {MS_Phenyx_NumberOfMC, MS_search_engine_specific_score_for_PSMs}, {MS_Phenyx_NumberOfMC, MS_search_engine_specific_score}, {MS_Phenyx_Modif, MS_search_engine_specific_score_for_PSMs}, {MS_Phenyx_Modif, MS_search_engine_specific_score}, {MS_OMSSA_csv_format, MS_intermediate_analysis_format}, {MS_OMSSA_xml_format, MS_intermediate_analysis_format}, {MS_X_Tandem_xml_format, MS_intermediate_analysis_format}, {MS_param__internal_yb_ion, MS_ion_series_considered_in_search}, {MS_param__internal_ya_ion, MS_ion_series_considered_in_search}, {MS_param__z_1_ion, MS_ion_series_considered_in_search}, {MS_param__z_2_ion, MS_ion_series_considered_in_search}, {MS_translation_start_codons, MS_search_database_details}, {MS_search_tolerance_specification, MS_search_input_details}, {MS_search_tolerance_plus_value, MS_search_tolerance_specification}, {MS_search_tolerance_minus_value, MS_search_tolerance_specification}, {MS_MGF_scans_OBSOLETE, MS_spectrum_identification_result_details}, {MS_MGF_raw_scans_OBSOLETE, MS_spectrum_identification_result_details}, {MS_spectrum_title_OBSOLETE, MS_spectrum_identification_result_details}, {MS_SpectraST_dot, MS_search_engine_specific_score_for_PSMs}, {MS_SpectraST_dot, MS_search_engine_specific_score}, {MS_SpectraST_dot_bias, MS_search_engine_specific_score_for_PSMs}, {MS_SpectraST_dot_bias, MS_search_engine_specific_score}, {MS_SpectraST_discriminant_score_F, MS_search_engine_specific_score_for_PSMs}, {MS_SpectraST_discriminant_score_F, MS_search_engine_specific_score}, {MS_SpectraST_delta, MS_search_engine_specific_score_for_PSMs}, {MS_SpectraST_delta, MS_search_engine_specific_score}, {MS_pepXML_format, MS_intermediate_analysis_format}, {MS_protXML_format, MS_intermediate_analysis_format}, {MS_translation_table_description, MS_search_database_details}, {MS_ProteinExtractor_Methodname, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_GenerateNonRedundant, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_IncludeIdentified, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_MaxNumberOfProteins, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_MaxProteinMass, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_MinNumberOfPeptides, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_UseMascot, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_MascotPeptideScoreThreshold, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_MascotUniqueScore, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_MascotUseIdentityScore, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_MascotWeighting, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_UseSequest, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_SequestPeptideScoreThreshold, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_SequestUniqueScore, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_SequestWeighting, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_UseProteinSolver, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_ProteinSolverPeptideScoreThreshold, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_ProteinSolverUniqueScore, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_ProteinSolverWeighting, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_UsePhenyx, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_PhenyxPeptideScoreThreshold, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_PhenyxUniqueScore, MS_ProteinExtractor_input_parameter}, {MS_ProteinExtractor_PhenyxWeighting, MS_ProteinExtractor_input_parameter}, {MS_prot_FDR_threshold, MS_protein_level_statistical_threshold}, {MS_pep_FDR_threshold, MS_peptide_level_statistical_threshold}, {MS_OMSSA_e_value_threshold, MS_OMSSA_input_parameter}, {MS_decoy_DB_details, MS_search_database_details}, {MS_decoy_DB_generation_algorithm, MS_decoy_DB_details}, {MS_decoy_DB_type_shuffle, MS_decoy_DB_details}, {MS_DB_composition_only_decoy, MS_decoy_DB_details}, {MS_quality_estimation_with_implicite_decoy_sequences, MS_quality_estimation_method_details}, {MS_acquisition_software, MS_software}, {MS_analysis_software, MS_software}, {MS_data_processing_software, MS_software}, {MS_unknown_modification, MS_peptide_modification_details}, {MS_greylag, MS_analysis_software}, {MS_PEFF_format, MS_database_file_formats}, {MS_Phenyx_XML_format, MS_mass_spectrometer_file_format}, {MS_Phenyx_XML_format, MS_intermediate_analysis_format}, {MS_DTASelect_format, MS_intermediate_analysis_format}, {MS_MS2_format, MS_intermediate_analysis_format}, {MS_taxonomy__NCBI_TaxID, MS_molecule_taxonomy}, {MS_taxonomy__common_name, MS_molecule_taxonomy}, {MS_taxonomy__scientific_name, MS_molecule_taxonomy}, {MS_taxonomy__Swiss_Prot_ID, MS_molecule_taxonomy}, {MS_selected_ion_monitoring_chromatogram, MS_data_file_content}, {MS_selected_ion_monitoring_chromatogram, MS_mass_chromatogram}, {MS_selected_reaction_monitoring_chromatogram, MS_data_file_content}, {MS_selected_reaction_monitoring_chromatogram, MS_mass_chromatogram}, {MS_consecutive_reaction_monitoring_chromatogram_OBSOLETE, MS_data_file_content}, {MS_consecutive_reaction_monitoring_chromatogram_OBSOLETE, MS_mass_chromatogram}, {MS_OMSSA, MS_analysis_software}, {MS_X_Tandem, MS_analysis_software}, {MS_SpectraST, MS_analysis_software}, {MS_Mascot_Parser, MS_analysis_software}, {MS_null_terminated_ASCII_string, MS_binary_data_type}, {MS_SCIEX_TOF_TOF_nativeID_format, MS_native_spectrum_identifier_format}, {MS_SCIEX_TOF_TOF_database, MS_mass_spectrometer_file_format}, {MS_5800_TOF_TOF, MS_SCIEX_instrument_model}, {MS_SCIEX_TOF_TOF_Series_Explorer_Software, MS_SCIEX_software}, {MS_SCIEX_TOF_TOF_Series_Explorer_Software, MS_acquisition_software}, {MS_SCIEX_TOF_TOF_Series_Explorer_Software, MS_analysis_software}, {MS_SCIEX_TOF_TOF_Series_Explorer_Software, MS_data_processing_software}, {MS_intensity_normalization, MS_data_processing_action}, {MS_m_z_calibration, MS_data_processing_action}, {MS_data_filtering, MS_data_processing_action}, {MS_ProteinExtractor, MS_Bruker_software}, {MS_ProteinExtractor, MS_analysis_software}, {MS_Mascot_Distiller, MS_quantitation_software_name}, {MS_Mascot_Distiller, MS_analysis_software}, {MS_Mascot_Integra, MS_analysis_software}, {MS_Percolator, MS_analysis_software}, {MS_percolator_Q_value, MS_search_engine_specific_score_for_PSMs}, {MS_percolator_Q_value, MS_search_engine_specific_score}, {MS_percolator_Q_value, MS_distinct_peptide_level_q_value}, {MS_percolator_score, MS_search_engine_specific_score_for_PSMs}, {MS_percolator_score, MS_search_engine_specific_score}, {MS_percolator_PEP, MS_search_engine_specific_score_for_PSMs}, {MS_percolator_PEP, MS_search_engine_specific_score}, {MS_no_threshold, MS_statistical_threshold}, {MS_ProteinScape_SearchResultId, MS_search_engine_specific_score_for_PSMs}, {MS_ProteinScape_SearchResultId, MS_search_engine_specific_score}, {MS_ProteinScape_SearchEventId, MS_search_engine_specific_score_for_PSMs}, {MS_ProteinScape_SearchEventId, MS_search_engine_specific_score}, {MS_ProteinScape_ProfoundProbability, MS_search_engine_specific_score_for_PSMs}, {MS_ProteinScape_ProfoundProbability, MS_search_engine_specific_score}, {MS_Profound_z_value, MS_search_engine_specific_score_for_PSMs}, {MS_Profound_z_value, MS_search_engine_specific_score}, {MS_Profound_Cluster, MS_search_engine_specific_score_for_PSMs}, {MS_Profound_Cluster, MS_search_engine_specific_score}, {MS_Profound_ClusterRank, MS_search_engine_specific_score_for_PSMs}, {MS_Profound_ClusterRank, MS_search_engine_specific_score}, {MS_MSFit_Mowse_score, MS_search_engine_specific_score_for_PSMs}, {MS_MSFit_Mowse_score, MS_search_engine_specific_score}, {MS_Sonar_Score, MS_search_engine_specific_score_for_PSMs}, {MS_Sonar_Score, MS_search_engine_specific_score}, {MS_ProteinScape_PFFSolverExp, MS_search_engine_specific_score_for_PSMs}, {MS_ProteinScape_PFFSolverExp, MS_search_engine_specific_score}, {MS_ProteinScape_PFFSolverScore, MS_search_engine_specific_score_for_PSMs}, {MS_ProteinScape_PFFSolverScore, MS_search_engine_specific_score}, {MS_ProteinScape_IntensityCoverage, MS_search_engine_specific_score_for_PSMs}, {MS_ProteinScape_IntensityCoverage, MS_search_engine_specific_score}, {MS_ProteinScape_SequestMetaScore, MS_search_engine_specific_score_for_PSMs}, {MS_ProteinScape_SequestMetaScore, MS_search_engine_specific_score}, {MS_ProteinExtractor_Score, MS_single_protein_result_details}, {MS_ProteinExtractor_Score, MS_search_engine_specific_score}, {MS_Agilent_MassHunter_nativeID_format, MS_native_spectrum_identifier_format}, {MS_Agilent_MassHunter_format, MS_mass_spectrometer_file_format}, {MS_TSQ_Vantage, MS_Thermo_Scientific_instrument_model}, {MS_Sequence_database_filter_types, MS_database_filtering}, {MS_Sequence_database_filters, MS_database_filtering}, {MS_DB_sequence_filter_pattern, MS_Sequence_database_filters}, {MS_DB_accession_filter_string, MS_Sequence_database_filters}, {MS_frag__c_ion___H2O, MS_fragmentation_ion_type}, {MS_frag__c_ion___NH3, MS_fragmentation_ion_type}, {MS_frag__z_ion___H2O, MS_fragmentation_ion_type}, {MS_frag__z_ion___NH3, MS_fragmentation_ion_type}, {MS_frag__x_ion___H2O, MS_fragmentation_ion_type}, {MS_frag__x_ion___NH3, MS_fragmentation_ion_type}, {MS_frag__precursor_ion___H2O, MS_fragmentation_ion_type}, {MS_frag__precursor_ion___NH3, MS_fragmentation_ion_type}, {MS_frag__precursor_ion, MS_fragmentation_ion_type}, {MS_fragment_neutral_loss, MS_peptide_modification_details}, {MS_precursor_neutral_loss, MS_peptide_modification_details}, {MS_spectrum_from_database_integer_nativeID_format, MS_native_spectrum_identifier_format}, {MS_Proteinscape_spectra, MS_mass_spectrometer_file_format}, {MS_Mascot_query_number, MS_native_spectrum_identifier_format}, {MS_Mascot_query_number, MS_spectrum_identification_result_details}, {MS_spectra_data_details, MS_search_input_details}, {MS_mzML_unique_identifier, MS_spectra_data_details}, {MS_spectrum_from_ProteinScape_database_nativeID_format, MS_native_spectrum_identifier_format}, {MS_spectrum_from_ProteinScape_database_nativeID_format, MS_spectra_data_details}, {MS_spectrum_from_database_string_nativeID_format, MS_native_spectrum_identifier_format}, {MS_spectrum_from_database_string_nativeID_format, MS_spectra_data_details}, {MS_Bruker_Daltonics_esquire_series, MS_Bruker_Daltonics_instrument_model}, {MS_Bruker_Daltonics_flex_series, MS_Bruker_Daltonics_instrument_model}, {MS_Bruker_Daltonics_BioTOF_series, MS_Bruker_Daltonics_instrument_model}, {MS_Bruker_Daltonics_micrOTOF_series, MS_Bruker_Daltonics_instrument_model}, {MS_BioTOF, MS_Bruker_Daltonics_BioTOF_series}, {MS_BioTOF_III, MS_Bruker_Daltonics_BioTOF_series}, {MS_UltroTOF_Q, MS_Bruker_Daltonics_BioTOF_series}, {MS_micrOTOF_II, MS_Bruker_Daltonics_micrOTOF_series}, {MS_maXis, MS_Bruker_Daltonics_maXis_series}, {MS_amaZon_ETD, MS_Bruker_Daltonics_amaZon_series}, {MS_microflex_LRF, MS_Bruker_Daltonics_flex_series}, {MS_ultrafleXtreme, MS_Bruker_Daltonics_flex_series}, {MS_Bruker_Daltonics_amaZon_series, MS_Bruker_Daltonics_instrument_model}, {MS_amaZon_X, MS_Bruker_Daltonics_amaZon_series}, {MS_Bruker_Daltonics_maXis_series, MS_Bruker_Daltonics_instrument_model}, {MS_Bruker_Daltonics_solarix_series, MS_Bruker_Daltonics_instrument_model}, {MS_solariX, MS_Bruker_Daltonics_solarix_series}, {MS_microflex_II, MS_Bruker_Daltonics_flex_series}, {MS_autoflex_II_TOF_TOF, MS_Bruker_Daltonics_flex_series}, {MS_autoflex_III_TOF_TOF_smartbeam, MS_Bruker_Daltonics_flex_series}, {MS_autoflex, MS_Bruker_Daltonics_flex_series}, {MS_Bruker_Daltonics_apex_series, MS_Bruker_Daltonics_instrument_model}, {MS_Shimadzu_Corporation_software, MS_software}, {MS_MALDI_Solutions, MS_acquisition_software}, {MS_MALDI_Solutions, MS_analysis_software}, {MS_MALDI_Solutions, MS_data_processing_software}, {MS_MALDI_Solutions, MS_Shimadzu_Corporation_software}, {MS_SCIEX_TOF_TOF_T2D_nativeID_format, MS_native_spectrum_identifier_format}, {MS_SCIEX_TOF_TOF_T2D_format, MS_mass_spectrometer_file_format}, {MS_Scaffold, MS_analysis_software}, {MS_Scaffold_nativeID_format, MS_native_spectrum_identifier_format}, {MS_SEQUEST_SQT_format, MS_intermediate_analysis_format}, {MS_Discoverer_MSF_format, MS_intermediate_analysis_format}, {MS_IdentityE_XML_format, MS_intermediate_analysis_format}, {MS_ProteinLynx_XML_format, MS_intermediate_analysis_format}, {MS_SpectrumMill_directories, MS_intermediate_analysis_format}, {MS_Scaffold_Peptide_Probability, MS_search_engine_specific_score_for_PSMs}, {MS_Scaffold_Peptide_Probability, MS_search_engine_specific_score}, {MS_IdentityE_Score, MS_search_engine_specific_score_for_PSMs}, {MS_IdentityE_Score, MS_search_engine_specific_score}, {MS_ProteinLynx_Log_Likelihood, MS_search_engine_specific_score_for_PSMs}, {MS_ProteinLynx_Log_Likelihood, MS_search_engine_specific_score}, {MS_ProteinLynx_Ladder_Score, MS_search_engine_specific_score_for_PSMs}, {MS_ProteinLynx_Ladder_Score, MS_search_engine_specific_score}, {MS_SpectrumMill_Score, MS_search_engine_specific_score_for_PSMs}, {MS_SpectrumMill_Score, MS_search_engine_specific_score}, {MS_SpectrumMill_SPI, MS_search_engine_specific_score_for_PSMs}, {MS_SpectrumMill_SPI, MS_search_engine_specific_score}, {MS_report_only_spectra_assigned_to_identified_proteins, MS_quality_estimation_method_details}, {MS_Scaffold__Minimum_Peptide_Count, MS_Scaffold_input_parameter}, {MS_Scaffold__Minimum_Protein_Probability, MS_Scaffold_input_parameter}, {MS_Scaffold__Minimum_Peptide_Probability, MS_Scaffold_input_parameter}, {MS_minimum_number_of_enzymatic_termini, MS_common_search_engine_input_parameter}, {MS_Scaffold_Protein_Probability, MS_single_protein_result_details}, {MS_Scaffold_Protein_Probability, MS_search_engine_specific_score}, {MS_SpectrumMill_Discriminant_Score, MS_search_engine_specific_score_for_PSMs}, {MS_SpectrumMill_Discriminant_Score, MS_search_engine_specific_score}, {MS_FAIMS_compensation_voltage, MS_scan_attribute}, {MS_XCMS, MS_analysis_software}, {MS_XCMS, MS_data_processing_software}, {MS_MaxQuant, MS_quantitation_software_name}, {MS_MaxQuant, MS_analysis_software}, {MS_combined_pmf___ms_ms_search, MS_search_type}, {MS_MyriMatch, MS_analysis_software}, {MS_DirecTag, MS_analysis_software}, {MS_TagRecon, MS_analysis_software}, {MS_Pepitome, MS_analysis_software}, {MS_MyriMatch_MVH, MS_search_engine_specific_score_for_PSMs}, {MS_MyriMatch_MVH, MS_search_engine_specific_score}, {MS_MyriMatch_mzFidelity, MS_search_engine_specific_score_for_PSMs}, {MS_MyriMatch_mzFidelity, MS_search_engine_specific_score}, {MS_anchor_protein, MS_protein_group_or_subset_relationship}, {MS_family_member_protein, MS_protein_group_or_subset_relationship}, {MS_group_member_with_undefined_relationship_OR_ortholog_protein, MS_protein_group_or_subset_relationship}, {MS_sequence_same_set_protein, MS_protein_group_or_subset_relationship}, {MS_spectrum_same_set_protein, MS_protein_group_or_subset_relationship}, {MS_sequence_sub_set_protein, MS_protein_group_or_subset_relationship}, {MS_spectrum_sub_set_protein, MS_protein_group_or_subset_relationship}, {MS_sequence_subsumable_protein, MS_protein_group_or_subset_relationship}, {MS_spectrum_subsumable_protein, MS_protein_group_or_subset_relationship}, {MS_protein_inference_confidence_category, MS_protein_group_or_subset_relationship}, {MS_ProteomeDiscoverer_Spectrum_Files_Raw_File_names_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SRF_File_Selector_SRF_File_Path_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Selector_Ionization_Source_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Activation_Type_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Selector_Lower_RT_Limit, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mass_Analyzer_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Max_Precursor_Mass, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Min_Precursor_Mass, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Selector_Minimum_Peak_Count, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_MS_Order_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Polarity_Mode_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Selector_Precursor_Selection, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SN_Threshold, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Scan_Type_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Selector_Total_Intensity_Threshold, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Selector_Unrecognized_Activation_Type_Replacements, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Selector_Unrecognized_Charge_Replacements, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Selector_Unrecognized_Mass_Analyzer_Replacements, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Selector_Unrecognized_MS_Order_Replacements, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Selector_Unrecognized_Polarity_Replacements, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Selector_Upper_RT_Limit, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Non_Fragment_Filter_Mass_Window_Offset, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Non_Fragment_Filter_Maximum_Neutral_Loss_Mass, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Non_Fragment_Filter_Remove_Charge_Reduced_Precursor, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Non_Fragment_Filter_Remove_Neutral_Loss_Peaks, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Non_Fragment_Filter_Remove_Only_Known_Masses, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Non_Fragment_Filter_Remove_Precursor_Overtones, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Non_Fragment_Filter_Remove_Precursor_Peak, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Grouper_Allow_Mass_Analyzer_Mismatch, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Grouper_Allow_MS_Order_Mismatch, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Grouper_Max_RT_Difference_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Grouper_Precursor_Mass_Criterion, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Xtract_Highest_Charge, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Xtract_Highest_MZ_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Xtract_Lowest_Charge, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Xtract_Lowest_MZ_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Xtract_Monoisotopic_Mass_Only, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Xtract_Overlapping_Remainder, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Xtract_Required_Fitting_Accuracy, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Xtract_Resolution_At_400, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Lowest_Charge_State, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Highest_Charge_State, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Score_Filter_Let_Pass_Above_Scores, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Dynamic_Modification, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Static_Modification, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_Decoy_Search_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_Error_tolerant_Search, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_Max_MGF_File_Size, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_Mascot_Server_URL, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_Number_of_attempts_to_submit_the_search, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_X_Static_Modification, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_User_Name_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_Time_interval_between_attempts_to_submit_a_search, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Enzyme_Name_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Fragment_Mass_Tolerance_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_Mascot_Instrument, MS_Mascot_input_parameter}, {MS_ProteomeDiscoverer_Maximum_Missed_Cleavage_Sites, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_Peptide_CutOff_Score, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Precursor_Mass_Tolerance_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_Protein_CutOff_Score, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Protein_Database_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_Protein_Relevance_Factor, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Target_FDR_Relaxed, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Target_FDR_Strict, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_Taxonomy_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Use_Average_Precursor_Mass_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_Mascot_use_MudPIT_scoring_OBSOLETE, MS_Mascot_input_parameter}, {MS_ProteomeDiscoverer_Absolute_XCorr_Threshold, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Calculate_Probability_Score, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_CTerminal_Modification, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Fragment_Ion_Cutoff_Percentage, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Max_Identical_Modifications_Per_Peptide, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Max_Modifications_Per_Peptide, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Maximum_Peptides_Considered, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Maximum_Peptides_Output, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Maximum_Protein_References_Per_Peptide, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_NTerminal_Modification, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Peptide_CTerminus, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Peptide_NTerminus, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Peptide_Relevance_Factor, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Protein_Relevance_Threshold, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Search_Against_Decoy_Database_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Use_Average_Fragment_Masses, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Use_Neutral_Loss_a_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Use_Neutral_Loss_b_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Use_Neutral_Loss_y_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Use_Neutral_Loss_z_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Weight_of_a_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Weight_of_b_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Weight_of_c_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Weight_of_d_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Weight_of_v_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Weight_of_w_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Weight_of_x_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Weight_of_y_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Weight_of_z_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_ZCore_Protein_Score_Cutoff, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Reporter_Ions_Quantizer_Integration_Method, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Reporter_Ions_Quantizer_Integration_Window_Tolerance, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Reporter_Ions_Quantizer_Quantitation_Method, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Exporter_Export_Format_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Exporter_File_name, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Search_Modifications_Only_For_Identified_Proteins, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Std_High_Confidence_XCorr_Charge1, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Std_High_Confidence_XCorr_Charge2, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Std_High_Confidence_XCorr_Charge3, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Std_High_Confidence_XCorr_Charge4, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Std_Medium_Confidence_XCorr_Charge1, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Std_Medium_Confidence_XCorr_Charge2, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Std_Medium_Confidence_XCorr_Charge3, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Std_Medium_Confidence_XCorr_Charge4, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_FT_High_Confidence_XCorr_Charge1, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_FT_High_Confidence_XCorr_Charge2, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_FT_High_Confidence_XCorr_Charge3, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_FT_High_Confidence_XCorr_Charge4, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_FT_Medium_Confidence_XCorr_Charge1, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_FT_Medium_Confidence_XCorr_Charge2, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_FT_Medium_Confidence_XCorr_Charge3, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_FT_Medium_Confidence_XCorr_Charge4, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_1__Dynamic_Modification_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_2__Dynamic_Modification_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_3__Dynamic_Modification_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_4__Dynamic_Modification_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Static_Modification_for_X, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Initial_minimal_peptide_probability, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Minimal_peptide_probability, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Minimal_peptide_weight, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Number_of_input1_spectra, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Number_of_input2_spectra, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Number_of_input3_spectra, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Number_of_input4_spectra, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Number_of_input5_spectra, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Number_of_predicted_correct_proteins, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Organism_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Reference_Database_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Residue_substitution_list, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Source_file_extension_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Source_Files_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Source_Files_old_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_WinCyg_reference_database, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_WinCyg_source_files, MS_ProteomeDiscoverer_input_parameter}, {MS_LTQ_Orbitrap_Velos, MS_Thermo_Scientific_instrument_model}, {MS_ProteomeDiscoverer_Mascot_Weight_of_A_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_Weight_of_B_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_Weight_of_C_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_Weight_of_D_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_Weight_of_V_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_Weight_of_W_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_Weight_of_X_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_Weight_of_Y_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_Weight_of_Z_Ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Selector_Use_New_Precursor_Reevaluation, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Selector_SN_Threshold_FTonly, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_Please_Do_not_Touch_this, MS_ProteomeDiscoverer_input_parameter}, {MS_contact_phone_number, MS_contact_attribute}, {MS_contact_fax_number, MS_contact_attribute}, {MS_contact_toll_free_phone_number, MS_contact_attribute}, {MS_Mascot_SigThresholdType, MS_Mascot_input_parameter}, {MS_Mascot_ProteinGrouping, MS_Mascot_input_parameter}, {MS_Percolator_features, MS_Percolator_input_parameter}, {MS_ACQUITY_UPLC, MS_Waters_instrument_model}, {MS_ACQUITY_UPLC_H_Class, MS_Waters_instrument_model}, {MS_ACQUITY_UPLC_H_Class_Bio, MS_Waters_instrument_model}, {MS_ACQUITY_UPLC_I_Class, MS_Waters_instrument_model}, {MS_ACQUITY_UPLC_Systems_with_2D_Technology, MS_Waters_instrument_model}, {MS_nanoACQUITY_UPLC, MS_Waters_instrument_model}, {MS_nanoACQUITY_UPLC_System_with_Technology, MS_Waters_instrument_model}, {MS_nanoACQUITY_UPLC_with_HDX_Technology, MS_Waters_instrument_model}, {MS_TRIZAIC_UPLC_nanoTile, MS_Waters_instrument_model}, {MS_GCT_Premier, MS_Waters_instrument_model}, {MS_MALDI_Synapt_G2_HDMS, MS_Waters_instrument_model}, {MS_MALDI_Synapt_G2_MS, MS_Waters_instrument_model}, {MS_MALDI_Synapt_G2_S_HDMS, MS_Waters_instrument_model}, {MS_MALDI_Synapt_G2_S_MS, MS_Waters_instrument_model}, {MS_MALDI_Synapt_HDMS, MS_Waters_instrument_model}, {MS_MALDI_Synapt_MS, MS_Waters_instrument_model}, {MS_Synapt_G2_HDMS, MS_Waters_instrument_model}, {MS_Synapt_G2_MS, MS_Waters_instrument_model}, {MS_Synapt_G2_S_HDMS, MS_Waters_instrument_model}, {MS_Synapt_G2_S_MS, MS_Waters_instrument_model}, {MS_Synapt_HDMS, MS_Waters_instrument_model}, {MS_Synapt_MS, MS_Waters_instrument_model}, {MS_Xevo_G2_Q_Tof, MS_Waters_instrument_model}, {MS_Xevo_G2_Tof, MS_Waters_instrument_model}, {MS_Xevo_Q_Tof, MS_Waters_instrument_model}, {MS_3100, MS_Waters_instrument_model}, {MS_Acquity_SQD, MS_Waters_instrument_model}, {MS_Acquity_TQD, MS_Waters_instrument_model}, {MS_Quattro_micro_GC, MS_Waters_instrument_model}, {MS_Xevo_TQ_MS, MS_Waters_instrument_model}, {MS_Xevo_TQD, MS_Waters_instrument_model}, {MS_Xevo_TQ_S, MS_Waters_instrument_model}, {MS_Mascot_PreferredTaxonomy, MS_Mascot_input_parameter}, {MS_Empower, MS_Waters_software}, {MS_Empower, MS_analysis_software}, {MS_Empower, MS_data_processing_software}, {MS_Unify, MS_Waters_software}, {MS_Unify, MS_analysis_software}, {MS_Unify, MS_data_processing_software}, {MS_LECO_software, MS_software}, {MS_ChromaTOF_software, MS_acquisition_software}, {MS_ChromaTOF_software, MS_analysis_software}, {MS_ChromaTOF_software, MS_data_processing_software}, {MS_ChromaTOF_software, MS_LECO_software}, {MS_LECO_instrument_model, MS_instrument_model}, {MS_Pegasus_HRT, MS_LECO_instrument_model}, {MS_Citius_HRT, MS_LECO_instrument_model}, {MS_Pegasus, MS_LECO_instrument_model}, {MS_TruTOF, MS_LECO_instrument_model}, {MS_quantification_datatype, MS_quantification_information}, {MS_quantification_object_attribute, MS_quantification_information}, {MS_study_variable_attribute, MS_quantification_object_attribute}, {MS_technical_replicate, MS_study_variable_attribute}, {MS_biological_replicate, MS_study_variable_attribute}, {MS_experimental_condition__case_, MS_study_variable_attribute}, {MS_experimental_condition__control_, MS_study_variable_attribute}, {MS_experimental_condition__disease_, MS_study_variable_attribute}, {MS_experimental_condition__healthy_, MS_study_variable_attribute}, {MS_generic_experimental_condition, MS_study_variable_attribute}, {MS_time_series__time_point_X, MS_study_variable_attribute}, {MS_dilution_series__concentration_X, MS_study_variable_attribute}, {MS_raw_file_attribute, MS_quantification_object_attribute}, {MS_one_sample_run, MS_raw_file_attribute}, {MS_two_sample_run, MS_raw_file_attribute}, {MS_three_sample_run, MS_raw_file_attribute}, {MS_four_sample_run, MS_raw_file_attribute}, {MS_eight_sample_run, MS_raw_file_attribute}, {MS_raw_files_group_attribute, MS_quantification_object_attribute}, {MS_merge_of_runs_of_1D_gel_bands, MS_raw_files_group_attribute}, {MS_feature_list_attribute, MS_quantification_object_attribute}, {MS_mass_trace_reporting__rectangles, MS_feature_list_attribute}, {MS_mass_trace_reporting__polygons, MS_feature_list_attribute}, {MS_feature_attribute, MS_quantification_object_attribute}, {MS_SRM_transition_ID, MS_feature_attribute}, {MS_Progenesis_LC_MS, MS_quantitation_software_name}, {MS_SILACAnalyzer, MS_quantitation_software_name}, {MS_SILACAnalyzer, MS_TOPP_software}, {MS_quantitation_software_comment_or_customizations, MS_quantification_information}, {MS_quantitation_analysis_summary, MS_quantification_information}, {MS_LC_MS_label_free_quantitation_analysis, MS_quantitation_analysis_summary}, {MS_SILAC_quantitation_analysis, MS_quantitation_analysis_summary}, {MS_spectral_counting_quantitation_analysis, MS_quantitation_analysis_summary}, {MS_iTRAQ_quantitation_analysis, MS_isobaric_label_quantitation_analysis}, {MS_SRM_quantitation_analysis, MS_quantitation_analysis_summary}, {MS_metabolic_labeling_14N___15N_quantitation_analysis, MS_quantitation_analysis_summary}, {MS_LC_MS_feature_intensity, MS_quantification_datatype}, {MS_LC_MS_feature_volume, MS_quantification_datatype}, {MS_peptide_PSM_count, MS_quantification_datatype}, {MS_MS1_feature_maximum_intensity, MS_quantification_datatype}, {MS_MS1_feature_area, MS_quantification_datatype}, {MS_peak_area_OBSOLETE, MS_quantification_datatype}, {MS_isotopic_pattern_area, MS_quantification_datatype}, {MS_reporter_ion_intensity, MS_quantification_datatype}, {MS_simple_ratio_of_two_values, MS_ratio_calculation_method}, {MS_sum_of_MatchedFeature_values_OBSOLETE, MS_quantification_datatype}, {MS_normalized_peptide_value, MS_quantification_datatype}, {MS_protein_value__sum_of_peptide_values, MS_quantification_datatype}, {MS_normalized_protein_value, MS_quantification_datatype}, {MS_max_fold_change, MS_quantification_datatype}, {MS_ANOVA_p_value, MS_p_value}, {MS_t_test_p_value, MS_p_value}, {MS_reporter_ion_raw_value, MS_quantification_datatype}, {MS_reporter_ion_normalized_value, MS_quantification_datatype}, {MS_XIC_area, MS_quantification_datatype}, {MS_normalized_XIC_area, MS_quantification_datatype}, {MS_protein_value__mean_of_peptide_ratios, MS_quantification_datatype}, {MS_normalization_to_mean_of_sum_of_all_proteins, MS_quantification_data_processing}, {MS_quantile_normalization__proteins, MS_quantification_data_processing}, {MS_quantile_normalization__peptides, MS_quantification_data_processing}, {MS_Progenesis_automatic_alignment, MS_quantification_data_processing}, {MS_Progenesis_manual_alignment, MS_quantification_data_processing}, {MS_Progenesis_normalization, MS_quantification_data_processing}, {MS_distinct_peptide_level_q_value, MS_peptide_level_statistical_threshold}, {MS_protein_level_q_value, MS_protein_identification_confidence_metric}, {MS_distinct_peptide_level_p_value, MS_PSM_level_identification_confidence_metric}, {MS_protein_level_p_value, MS_protein_identification_confidence_metric}, {MS_distinct_peptide_level_e_value, MS_PSM_level_identification_confidence_metric}, {MS_protein_level_e_value, MS_protein_identification_confidence_metric}, {MS_FDRScore_OBSOLETE, MS_search_engine_specific_score_for_PSMs}, {MS_FDRScore_OBSOLETE, MS_search_engine_specific_score}, {MS_modification_motif, MS_modification_specificity_rule}, {MS_modification_probability, MS_modification_specificity_rule}, {MS_ChromaTOF_HRT_software, MS_acquisition_software}, {MS_ChromaTOF_HRT_software, MS_analysis_software}, {MS_ChromaTOF_HRT_software, MS_data_processing_software}, {MS_ChromaTOF_HRT_software, MS_LECO_software}, {MS_MALDI_Solutions_Microbial_Identification, MS_acquisition_software}, {MS_MALDI_Solutions_Microbial_Identification, MS_analysis_software}, {MS_MALDI_Solutions_Microbial_Identification, MS_data_processing_software}, {MS_MALDI_Solutions_Microbial_Identification, MS_MALDI_Solutions}, {MS_offset_voltage, MS_source_attribute}, {MS_in_source_collision_induced_dissociation, MS_dissociation_method}, {MS_mz5_format, MS_mass_spectrometer_file_format}, {MS_coefficient_of_variation, MS_transition_validation_attribute}, {MS_signal_to_noise_ratio, MS_transition_validation_attribute}, {MS_command_line_parameters, MS_data_processing_parameter}, {MS_SQID, MS_analysis_software}, {MS_SQID, MS_data_processing_software}, {MS_SQID_score, MS_search_engine_specific_score_for_PSMs}, {MS_SQID_score, MS_search_engine_specific_score}, {MS_SQID_deltaScore, MS_search_engine_specific_score_for_PSMs}, {MS_SQID_deltaScore, MS_search_engine_specific_score}, {MS_SQID_protein_score, MS_single_protein_result_details}, {MS_SQID_protein_score, MS_search_engine_specific_score}, {MS_Progenesis_protein_normalised_abundance, MS_quantification_datatype}, {MS_Progenesis_peptide_normalised_abundance, MS_quantification_datatype}, {MS_Progenesis_protein_raw_abundance, MS_quantification_datatype}, {MS_Progenesis_peptide_raw_abundance, MS_quantification_datatype}, {MS_Progenesis_confidence_score, MS_quantification_datatype}, {MS_Progenesis_peptide_count, MS_quantification_datatype}, {MS_Progenesis_feature_intensity, MS_quantification_datatype}, {MS_MaxQuant_peptide_counts__unique_, MS_quantification_datatype}, {MS_MaxQuant_peptide_counts__all_, MS_quantification_datatype}, {MS_MaxQuant_peptide_counts__razor_unique_, MS_quantification_datatype}, {MS_MaxQuant_sequence_length, MS_quantification_datatype}, {MS_MaxQuant_PEP, MS_quantification_datatype}, {MS_MaxQuant_LFQ_intensity, MS_quantification_datatype}, {MS_MaxQuant_feature_intensity, MS_quantification_datatype}, {MS_MaxQuant_MS_MS_count, MS_quantification_datatype}, {MS_emPAI_value, MS_quantification_datatype}, {MS_APEX_value, MS_quantification_datatype}, {MS_retention_time_window_width, MS_retention_time_window_attribute}, {MS_ISQ, MS_Thermo_Scientific_instrument_model}, {MS_Velos_Plus, MS_Thermo_Scientific_instrument_model}, {MS_LTQ_Orbitrap_Elite, MS_Thermo_Scientific_instrument_model}, {MS_Q_Exactive, MS_Thermo_Scientific_instrument_model}, {MS_PinPoint, MS_Thermo_Finnigan_software}, {MS_PinPoint, MS_analysis_software}, {MS_PinPoint, MS_data_processing_software}, {MS_S_lens_voltage, MS_source_attribute}, {MS_pymzML, MS_data_processing_software}, {MS_leukocyte_elastase, MS_cleavage_agent_name}, {MS_proline_endopeptidase, MS_cleavage_agent_name}, {MS_glutamyl_endopeptidase, MS_cleavage_agent_name}, {MS_2_iodobenzoate, MS_cleavage_agent_name}, {MS_ProteomeXchange_accession_number, MS_external_reference_identifier}, {MS_ProteomeXchange_accession_number_version_number, MS_external_reference_identifier}, {MS_Digital_Object_Identifier__DOI_, MS_external_reference_identifier}, {MS_external_reference_keyword, MS_external_reference_identifier}, {MS_journal_article_keyword, MS_external_reference_keyword}, {MS_submitter_keyword, MS_external_reference_keyword}, {MS_curator_keyword, MS_external_reference_keyword}, {MS_Tranche_file_hash, MS_external_reference_identifier}, {MS_Tranche_project_hash, MS_external_reference_identifier}, {MS_PRIDE_experiment_URI, MS_external_reference_identifier}, {MS_PRIDE_project_URI, MS_external_reference_identifier}, {MS_stainless_steel_plate, MS_sample_plate_type}, {MS_coated_glass_plate, MS_sample_plate_type}, {MS_static_supply_electrospray, MS_electrospray_supply_type}, {MS_fed_supply_electrospray, MS_electrospray_supply_type}, {MS_Collision_cell_exit_potential, MS_precursor_activation_attribute}, {MS_Pegasus_4D, MS_LECO_instrument_model}, {MS_PEAKS_Studio, MS_quantitation_software_name}, {MS_PEAKS_Studio, MS_analysis_software}, {MS_PEAKS_Studio, MS_data_processing_software}, {MS_PEAKS_Online, MS_quantitation_software_name}, {MS_PEAKS_Online, MS_analysis_software}, {MS_PEAKS_Online, MS_data_processing_software}, {MS_PEAKS_Node, MS_quantitation_software_name}, {MS_PEAKS_Node, MS_analysis_software}, {MS_PEAKS_Node, MS_data_processing_software}, {MS_BSI_software, MS_software}, {MS_PEAKS_peptideScore, MS_search_engine_specific_score_for_PSMs}, {MS_PEAKS_peptideScore, MS_search_engine_specific_score}, {MS_PEAKS_proteinScore, MS_single_protein_result_details}, {MS_PEAKS_proteinScore, MS_search_engine_specific_score}, {MS_ZCore_probScore, MS_search_engine_specific_score_for_PSMs}, {MS_ZCore_probScore, MS_search_engine_specific_score}, {MS_no_cleavage, MS_cleavage_agent_name}, {MS_unspecific_cleavage, MS_cleavage_agent_name}, {MS______ALIV_____P_, MS_Cleavage_agent_regular_expression}, {MS______HKR_P____P_, MS_Cleavage_agent_regular_expression}, {MS_______E_E_, MS_Cleavage_agent_regular_expression}, {MS_____W_, MS_Cleavage_agent_regular_expression}, {MS_Mascot_C13_counts, MS_Mascot_input_parameter}, {MS_ProteinExtractor_Weighting, MS_ProteinExtractor_input_parameter}, {MS_ProteinScape_second_round_Mascot, MS_ProteinScape_input_parameter}, {MS_ProteinScape_second_round_Phenyx, MS_ProteinScape_input_parameter}, {MS_product_ion_mobility, MS_fragmentation_information}, {MS_product_ion_drift_time_OBSOLETE, MS_SRM_transition_attribute}, {MS_PSM_level_PTM_localization_score, MS_spectrum_identification_result_details}, {MS_phosphoRS_score, MS_PSM_level_PTM_localization_score}, {MS_phosphoRS_sequence_probability, MS_PSM_level_PTM_localization_score}, {MS_phosphoRS_site_probability, MS_PSM_level_PTM_localization_score}, {MS_PTM_scoring_algorithm_version, MS_peptide_modification_details}, {MS_DeBunker, MS_analysis_software}, {MS_DeBunker_score, MS_search_engine_specific_score}, {MS_DeBunker_score, MS_search_engine_specific_score_for_PSMs}, {MS_DeBunker_score, MS_PSM_level_PTM_localization_score}, {MS_delta_m_z, MS_spectrum_identification_result_details}, {MS_delta_M, MS_spectrum_identification_result_details}, {MS_MSQuant, MS_analysis_software}, {MS_MSQuant_PTM_score, MS_search_engine_specific_score}, {MS_MSQuant_PTM_score, MS_search_engine_specific_score_for_PSMs}, {MS_MSQuant_PTM_score, MS_PSM_level_PTM_localization_score}, {MS_MaxQuant_PTM_Score, MS_search_engine_specific_score}, {MS_MaxQuant_PTM_Score, MS_search_engine_specific_score_for_PSMs}, {MS_MaxQuant_PTM_Score, MS_PSM_level_PTM_localization_score}, {MS_MaxQuant_Phospho__STY__Probabilities, MS_search_engine_specific_score}, {MS_MaxQuant_Phospho__STY__Probabilities, MS_search_engine_specific_score_for_PSMs}, {MS_MaxQuant_Phospho__STY__Probabilities, MS_spectrum_identification_result_details}, {MS_MaxQuant_Phospho__STY__Probabilities, MS_PSM_level_PTM_localization_score}, {MS_MaxQuant_Phospho__STY__Score_Diffs, MS_search_engine_specific_score}, {MS_MaxQuant_Phospho__STY__Score_Diffs, MS_search_engine_specific_score_for_PSMs}, {MS_MaxQuant_Phospho__STY__Score_Diffs, MS_spectrum_identification_result_details}, {MS_MaxQuant_Phospho__STY__Score_Diffs, MS_PSM_level_PTM_localization_score}, {MS_MaxQuant_P_site_localization_probability, MS_search_engine_specific_score}, {MS_MaxQuant_P_site_localization_probability, MS_search_engine_specific_score_for_PSMs}, {MS_MaxQuant_P_site_localization_probability, MS_spectrum_identification_result_details}, {MS_MaxQuant_P_site_localization_probability, MS_PSM_level_PTM_localization_score}, {MS_MaxQuant_PTM_Delta_Score, MS_search_engine_specific_score}, {MS_MaxQuant_PTM_Delta_Score, MS_search_engine_specific_score_for_PSMs}, {MS_MaxQuant_PTM_Delta_Score, MS_PSM_level_PTM_localization_score}, {MS_Ascore_1001984, MS_analysis_software}, {MS_Ascore_1001985, MS_search_engine_specific_score}, {MS_Ascore_1001985, MS_search_engine_specific_score_for_PSMs}, {MS_Ascore_1001985, MS_PSM_level_PTM_localization_score}, {MS_H_Score, MS_PSM_level_PTM_localization_score}, {MS_vacuum_drying_MALDI_sample_preparation, MS_matrix_application_type}, {MS_crushed_crystal_MALDI_sample_preparation, MS_matrix_application_type}, {MS_fast_evaporation_MALDI_sample_preparation, MS_matrix_application_type}, {MS_overlayer_MALDI_sample_preparation, MS_matrix_application_type}, {MS_sandwich_MALDI_sample_preparation, MS_matrix_application_type}, {MS_spin_coating_MALDI_sample_preparation, MS_matrix_application_type}, {MS_quick_and_dirty_MALDI_sample_preparation, MS_matrix_application_type}, {MS_top_hat_baseline_reduction, MS_baseline_reduction}, {MS_convex_hull_baseline_reduction, MS_baseline_reduction}, {MS_median_baseline_reduction, MS_baseline_reduction}, {MS_wavelet_transformation_smoothing, MS_smoothing}, {MS_sophisticated_numerical_annotation_procedure, MS_area_peak_picking}, {MS_area_normalization, MS_intensity_normalization}, {MS_LIFT, MS_dissociation_method}, {MS_MS1_label_based_raw_feature_quantitation, MS_MS1_label_based_analysis}, {MS_MS1_label_based_peptide_level_quantitation, MS_MS1_label_based_analysis}, {MS_MS1_label_based_protein_level_quantitation, MS_MS1_label_based_analysis}, {MS_MS1_label_based_proteingroup_level_quantitation, MS_MS1_label_based_analysis}, {MS_iRT_retention_time_normalization_standard, MS_retention_time_normalization_standard}, {MS_target_SRM_transition, MS_SRM_transition_type}, {MS_decoy_SRM_transition, MS_SRM_transition_type}, {MS_isobaric_label_quantitation_analysis, MS_quantitation_analysis_summary}, {MS_TMT_quantitation_analysis, MS_quantitation_analysis_summary}, {MS_TMT_quantitation_analysis, MS_isobaric_label_quantitation_analysis}, {MS_desorption_electrospray_ionization, MS_atmospheric_pressure_ionization}, {MS_Mascot_PTM_site_assignment_confidence, MS_search_engine_specific_score}, {MS_Mascot_PTM_site_assignment_confidence, MS_search_engine_specific_score_for_PSMs}, {MS_Mascot_PTM_site_assignment_confidence, MS_spectrum_identification_result_details}, {MS_Mascot_PTM_site_assignment_confidence, MS_PSM_level_PTM_localization_score}, {MS_collision_energy_ramp_start, MS_collision_energy}, {MS_collision_energy_ramp_end, MS_collision_energy}, {MS_spectral_count_peptide_level_quantitation, MS_spectral_counting_quantitation_analysis}, {MS_spectral_count_protein_level_quantitation, MS_spectral_counting_quantitation_analysis}, {MS_spectral_count_proteingroup_level_quantitation, MS_spectral_counting_quantitation_analysis}, {MS_MS1_label_based_analysis, MS_quantitation_analysis_summary}, {MS_label_free_raw_feature_quantitation, MS_LC_MS_label_free_quantitation_analysis}, {MS_label_free_peptide_level_quantitation, MS_LC_MS_label_free_quantitation_analysis}, {MS_label_free_protein_level_quantitation, MS_LC_MS_label_free_quantitation_analysis}, {MS_label_free_proteingroup_level_quantitation, MS_LC_MS_label_free_quantitation_analysis}, {MS_MS2_tag_based_analysis, MS_quantitation_analysis_summary}, {MS_MS2_tag_based_feature_level_quantitation, MS_MS2_tag_based_analysis}, {MS_MS2_tag_based_peptide_level_quantitation, MS_MS2_tag_based_analysis}, {MS_MS2_tag_based_protein_level_quantitation, MS_MS2_tag_based_analysis}, {MS_MS2_tag_based_proteingroup_level_quantitation, MS_MS2_tag_based_analysis}, {MS_nucleic_acid_base_modification, MS_peptide_modification_details}, {MS_original_nucleic_acid_sequence, MS_peptide_modification_details}, {MS_modified_nucleic_acid_sequence, MS_peptide_modification_details}, {MS_PASSEL_transition_group_browser_URI, MS_external_reference_identifier}, {MS_PeptideAtlas_dataset_URI, MS_external_reference_identifier}, {MS_contact_role, MS_contact_attribute}, {MS_first_author, MS_contact_role}, {MS_senior_author, MS_contact_role}, {MS_co_author, MS_contact_role}, {MS_dataset_submitter, MS_contact_role}, {MS_unlabeled_sample, MS_sample_attribute}, {MS_inlet_attribute, MS_object_attribute}, {MS_inlet_temperature, MS_source_attribute}, {MS_inlet_temperature, MS_inlet_attribute}, {MS_source_temperature, MS_source_attribute}, {MS_modulation_time, MS_run_attribute}, {MS_ProteinProspector, MS_analysis_software}, {MS_ProteinProspector_score, MS_search_engine_specific_score_for_PSMs}, {MS_ProteinProspector_score, MS_search_engine_specific_score}, {MS_ProteinProspector_expectation_value, MS_search_engine_specific_score_for_PSMs}, {MS_ProteinProspector_expectation_value, MS_search_engine_specific_score}, {MS_native_source_path, MS_spectrum_generation_information}, {MS_MS_GF, MS_analysis_software}, {MS_MS_GF_, MS_analysis_software}, {MS_MS_GF_RawScore, MS_search_engine_specific_score_for_PSMs}, {MS_MS_GF_RawScore, MS_search_engine_specific_score}, {MS_MS_GF_DeNovoScore, MS_search_engine_specific_score}, {MS_MS_GF_Energy, MS_search_engine_specific_score_for_PSMs}, {MS_MS_GF_Energy, MS_search_engine_specific_score}, {MS_MS_GF_SpecEValue, MS_search_engine_specific_score_for_PSMs}, {MS_MS_GF_SpecEValue, MS_search_engine_specific_score}, {MS_MS_GF_SpecEValue, MS_PSM_level_e_value}, {MS_MS_GF_EValue, MS_search_engine_specific_score_for_PSMs}, {MS_MS_GF_EValue, MS_search_engine_specific_score}, {MS_MS_GF_EValue, MS_PSM_level_e_value}, {MS_MS_GF_QValue, MS_search_engine_specific_score_for_PSMs}, {MS_MS_GF_QValue, MS_search_engine_specific_score}, {MS_MS_GF_QValue, MS_PSM_level_q_value}, {MS_MS_GF_PepQValue, MS_search_engine_specific_score_for_PSMs}, {MS_MS_GF_PepQValue, MS_search_engine_specific_score}, {MS_MS_GF_PepQValue, MS_distinct_peptide_level_q_value}, {MS_MS_GF_PEP, MS_search_engine_specific_score_for_PSMs}, {MS_MS_GF_PEP, MS_search_engine_specific_score}, {MS_modification_specificity_protein_N_term, MS_modification_specificity_rule}, {MS_modification_specificity_protein_C_term, MS_modification_specificity_rule}, {MS_Microsoft_Excel, MS_quantitation_software_name}, {MS_database_UniProtKB_TrEMBL, MS_database_UniProtKB}, {MS_metabolic_labelling__natural_N__mainly_14N_, MS_modification_parameters}, {MS_FindPairs, MS_quantitation_software_name}, {MS_peptide_consensus_RT, MS_quantification_datatype}, {MS_peptide_consensus_m_z, MS_quantification_datatype}, {MS_ratio_calculation_method, MS_quantification_datatype}, {MS_protein_value__median_of_peptide_ratios, MS_quantification_datatype}, {MS_metabolic_labelling__heavy_N__mainly_15N_, MS_modification_parameters}, {MS_metabolic_labelling__labelling_purity, MS_modification_parameters}, {MS_t_test, MS_quantification_data_processing}, {MS_ANOVA_test, MS_quantification_data_processing}, {MS_p_value, MS_quantification_datatype}, {MS_mzIdentML_format, MS_intermediate_analysis_format}, {MS_quantification_file_format, MS_file_format}, {MS_mzQuantML_format, MS_quantification_file_format}, {MS_PAnalyzer, MS_analysis_software}, {MS_impact, MS_Bruker_Daltonics_micrOTOF_series}, {MS_ProteomeDiscoverer_1__Static_Modification_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_2__Static_Modification_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Selector_Precursor_Clipping_Range_Before, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Spectrum_Selector_Precursor_Clipping_Range_After, MS_ProteomeDiscoverer_input_parameter}, {MS_first_column_elution_time, MS_scan_attribute}, {MS_second_column_elution_time, MS_scan_attribute}, {MS_multidimensional_chromatography_modulation_description, MS_run_attribute}, {MS_two_dimensional_gas_chromatography_with_fixed_modulation_time, MS_multidimensional_chromatography_modulation_description}, {MS_two_dimensional_gas_chromatography_with_discrete_modulation_time_steps, MS_multidimensional_chromatography_modulation_description}, {MS_two_dimensional_liquid_chromatography_with_fixed_modulation_time, MS_multidimensional_chromatography_modulation_description}, {MS_two_dimensional_liquid_chromatography_with_discrete_modulation_time_steps, MS_multidimensional_chromatography_modulation_description}, {MS_ProteomeDiscoverer_Peptide_Without_Protein_XCorr_Threshold, MS_ProteomeDiscoverer_input_parameter}, {MS_Calculate_Probability_Scores, MS_common_search_engine_input_parameter}, {MS_ProteomeDiscoverer_Maximum_Delta_Cn, MS_ProteomeDiscoverer_input_parameter}, {MS_Percolator_Validation_based_on, MS_Percolator_input_parameter}, {MS_search_engine_input_parameter, MS_search_input_details}, {MS_common_search_engine_input_parameter, MS_search_engine_input_parameter}, {MS_Mascot_input_parameter, MS_search_engine_specific_input_parameter}, {MS_SEQUEST_input_parameter, MS_search_engine_specific_input_parameter}, {MS_Phenyx_input_parameter, MS_search_engine_specific_input_parameter}, {MS_ProteinExtractor_input_parameter, MS_search_engine_specific_input_parameter}, {MS_OMSSA_input_parameter, MS_search_engine_specific_input_parameter}, {MS_ProteinScape_input_parameter, MS_search_engine_specific_input_parameter}, {MS_ProteomeDiscoverer_input_parameter, MS_search_engine_specific_input_parameter}, {MS_software_input_parameter, MS_search_input_details}, {MS_common_software_input_parameter, MS_software_input_parameter}, {MS_software_specific_input_parameter, MS_software_input_parameter}, {MS_Scaffold_input_parameter, MS_software_specific_input_parameter}, {MS_Percolator_input_parameter, MS_software_specific_input_parameter}, {MS_assay_attribute, MS_quantification_object_attribute}, {MS_assay_label_attribute, MS_quantification_object_attribute}, {MS_protein_group_list_attribute, MS_quantification_object_attribute}, {MS_protein_group_attribute, MS_quantification_object_attribute}, {MS_protein_list_attribute, MS_quantification_object_attribute}, {MS_peptide_consensus_list_attribute, MS_quantification_object_attribute}, {MS_peptide_consensus_attribute, MS_quantification_object_attribute}, {MS_small_molecule_list_attribute, MS_quantification_object_attribute}, {MS_small_molecule_attribute, MS_quantification_object_attribute}, {MS_small_molecule_modification_attribute, MS_quantification_object_attribute}, {MS_experiment_name, MS_quantification_object_attribute}, {MS_spectral_count_feature, MS_feature_attribute}, {MS_counts_reporting, MS_feature_list_attribute}, {MS_x_Tracker, MS_quantitation_software_name}, {MS_ProteoSuite, MS_quantitation_software_name}, {MS_combined_FDRScore_OBSOLETE, MS_search_engine_specific_score_for_PSMs}, {MS_combined_FDRScore_OBSOLETE, MS_search_engine_specific_score}, {MS_database_UniProtKB, MS_database_name}, {MS_identification_file_attribute, MS_quantification_object_attribute}, {MS_method_file_format, MS_file_format}, {MS_ITRAQAnalyzer, MS_quantitation_software_name}, {MS_ITRAQAnalyzer, MS_TOPP_software}, {MS_identification_file_format, MS_file_format}, {MS_TOPP_noise_filter, MS_TOPP_software}, {MS_TOPP_NoiseFilterGaussian, MS_TOPP_noise_filter}, {MS_TOPP_NoiseFilterSGolay, MS_TOPP_noise_filter}, {MS_TOPP_peak_picker, MS_TOPP_software}, {MS_TOPP_PeakPickerHiRes, MS_TOPP_peak_picker}, {MS_TOPP_PeakPickerWavelet, MS_TOPP_peak_picker}, {MS_TOPP_spectra_filter, MS_TOPP_software}, {MS_TOPP_SpectraFilterBernNorm, MS_TOPP_spectra_filter}, {MS_TOPP_SpectraFilterMarkerMower, MS_TOPP_spectra_filter}, {MS_TOPP_SpectraFilterNLargest, MS_TOPP_spectra_filter}, {MS_TOPP_SpectraFilterNormalizer, MS_TOPP_spectra_filter}, {MS_TOPP_SpectraFilterParentPeakMower, MS_TOPP_spectra_filter}, {MS_TOPP_SpectraFilterScaler, MS_TOPP_spectra_filter}, {MS_TOPP_SpectraFilterSqrtMower, MS_TOPP_spectra_filter}, {MS_TOPP_SpectraFilterThresholdMower, MS_TOPP_spectra_filter}, {MS_TOPP_SpectraFilterWindowMower, MS_TOPP_spectra_filter}, {MS_TOPP_map_aligner, MS_TOPP_software}, {MS_TOPP_MapAlignerIdentification, MS_TOPP_map_aligner}, {MS_TOPP_MapAlignerPoseClustering, MS_TOPP_map_aligner}, {MS_TOPP_MapAlignerSpectrum, MS_TOPP_map_aligner}, {MS_numerator_data_type_attribute, MS_quantification_object_attribute}, {MS_denominator_data_type_attribute, MS_quantification_object_attribute}, {MS_protein_level_PSM_counts, MS_quantification_datatype}, {MS_TOPP_DTAExtractor, MS_TOPP_software}, {MS_TOPP_IDMerger, MS_TOPP_software}, {MS_TOPP_IDFileConverter, MS_TOPP_software}, {MS_TOPP_SpectraMerger, MS_TOPP_software}, {MS_TOPP_MzTabExporter, MS_TOPP_software}, {MS_TOPP_MassTraceExtractor, MS_TOPP_software}, {MS_TOPP_PrecursorMassCorrector, MS_TOPP_software}, {MS_TOPP_HighResPrecursorMassCorrector, MS_TOPP_software}, {MS_TOPP_AdditiveSeries, MS_TOPP_software}, {MS_TOPP_Decharger, MS_TOPP_software}, {MS_TOPP_EICExtractor, MS_TOPP_software}, {MS_TOPP_feature_finder, MS_TOPP_software}, {MS_TOPP_FeatureFinderCentroided, MS_TOPP_feature_finder}, {MS_TOPP_FeatureFinderRaw, MS_TOPP_feature_finder}, {MS_TOPP_FeatureFinderIsotopeWavelet, MS_TOPP_feature_finder}, {MS_TOPP_FeatureFinderMetabo, MS_TOPP_feature_finder}, {MS_TOPP_FeatureFinderMRM, MS_TOPP_feature_finder}, {MS_TOPP_ProteinQuantifier, MS_TOPP_software}, {MS_TOPP_ConsensusMapNormalizer, MS_TOPP_software}, {MS_TOPP_MapRTTransformer, MS_TOPP_software}, {MS_TOPP_feature_linker, MS_TOPP_software}, {MS_TOPP_FeatureLinkerLabeled, MS_TOPP_feature_linker}, {MS_TOPP_FeatureLinkerUnlabeled, MS_TOPP_feature_linker}, {MS_TOPP_FeatureLinkerUnlabeledQT, MS_TOPP_feature_linker}, {MS_TOPP_CompNovo, MS_TOPP_software}, {MS_TOPP_CompNovoCID, MS_TOPP_software}, {MS_TOPP_software_adaptor, MS_TOPP_software}, {MS_TOPP_InspectAdapter, MS_TOPP_software_adaptor}, {MS_TOPP_MascotAdapter, MS_TOPP_software_adaptor}, {MS_TOPP_MascotAdapterOnline, MS_TOPP_software_adaptor}, {MS_TOPP_OMSSAAdapter, MS_TOPP_software_adaptor}, {MS_TOPP_PepNovoAdapter, MS_TOPP_software_adaptor}, {MS_TOPP_XTandemAdapter, MS_TOPP_software_adaptor}, {MS_TOPP_SpecLibSearcher, MS_TOPP_software}, {MS_TOPP_ConsensusID, MS_TOPP_software}, {MS_TOPP_IDConflictResolver, MS_TOPP_software}, {MS_TOPP_IDFilter, MS_TOPP_software}, {MS_TOPP_IDMapper, MS_TOPP_software}, {MS_TOPP_IDPosteriorErrorProbability, MS_TOPP_software}, {MS_TOPP_IDRTCalibration, MS_TOPP_software}, {MS_TOPP_PeptideIndexer, MS_TOPP_software}, {MS_TOPP_PrecursorIonSelector, MS_TOPP_software}, {MS_TOPP_MRMMapper, MS_TOPP_software}, {MS_TOPP_OpenSwath_component, MS_TOPP_software}, {MS_TOPP_OpenSwathAnalyzer, MS_TOPP_OpenSwath_component}, {MS_TOPP_OpenSwathChromatogramExtractor, MS_TOPP_OpenSwath_component}, {MS_TOPP_OpenSwathDecoyGenerator, MS_TOPP_OpenSwath_component}, {MS_TOPP_OpenSwathFeatureXMLToTSV, MS_TOPP_OpenSwath_component}, {MS_TOPP_OpenSwathRTNormalizer, MS_TOPP_OpenSwath_component}, {MS_TOPP_ProteinInference, MS_TOPP_software}, {MS_TOPP_FalseDiscoveryRate, MS_TOPP_software}, {MS_ProteoWizard_msconvert, MS_ProteoWizard_software}, {MS_ProteoWizard_idconvert, MS_ProteoWizard_software}, {MS_ProteoWizard_chainsaw, MS_ProteoWizard_software}, {MS_ProteoWizard_msaccess, MS_ProteoWizard_software}, {MS_ProteoWizard_SeeMS, MS_ProteoWizard_software}, {MS_IsobariQ, MS_quantitation_software_name}, {MS_IsobariQ, MS_analysis_software}, {MS_Variance_stabilizing_normalization, MS_quantification_data_processing}, {MS_IPTL_quantitation_analysis, MS_isobaric_label_quantitation_analysis}, {MS_PAnalyzer_conclusive_protein, MS_protein_inference_confidence_category}, {MS_PAnalyzer_indistinguishable_protein, MS_protein_inference_confidence_category}, {MS_PAnalyzer_non_conclusive_protein, MS_protein_inference_confidence_category}, {MS_PAnalyzer_ambiguous_group_member, MS_protein_inference_confidence_category}, {MS_decoy_peptide, MS_peptide_result_details}, {MS_percent_collision_energy_ramp_start, MS_normalized_collision_energy}, {MS_percent_collision_energy_ramp_end, MS_normalized_collision_energy}, {MS_MRMaid, MS_SRM_software}, {MS_MRMaid_peptide_score, MS_search_engine_specific_score_for_PSMs}, {MS_MRMaid_peptide_score, MS_search_engine_specific_score}, {MS_SRM_transition_attribute, MS_ion_selection_attribute}, {MS_precursor_ion_detection_probability, MS_SRM_transition_attribute}, {MS_product_ion_detection_probability, MS_SRM_transition_attribute}, {MS_average_product_ion_intensity, MS_product_ion_intensity}, {MS_product_ion_intensity_standard_deviation, MS_product_ion_intensity}, {MS_number_of_product_ion_observations, MS_SRM_transition_attribute}, {MS_number_of_precursor_ion_observations, MS_SRM_transition_attribute}, {MS_ProteomeDiscoverer_Mascot_Significance_Middle, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Mascot_Significance_High, MS_ProteomeDiscoverer_input_parameter}, {MS_regular_expressions_for_a_GUID, MS_regular_expression}, {MS_ProteomeDiscoverer_Default_FDR_calculator, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_SEQUEST_Low_resolution_spectra_contained, MS_ProteomeDiscoverer_input_parameter}, {MS_selected_precursor_m_z, MS_ion_selection_attribute}, {MS_ProteoGrouper_PDH_score, MS_single_protein_result_details}, {MS_ProteoGrouper_PAG_score, MS_protein_ambiguity_group_result_details}, {MS_mzidLib, MS_analysis_software}, {MS_mzidLib_Omssa2Mzid, MS_mzidLib}, {MS_mzidLib_Tandem2Mzid, MS_mzidLib}, {MS_mzidLib_Csv2Mzid, MS_mzidLib}, {MS_mzidLib_ProteoGrouper, MS_mzidLib}, {MS_mzidLib_Thresholder, MS_mzidLib}, {MS_mzidLib_Perform_emPAI_on_mzid, MS_mzidLib}, {MS_mzidLib_FalseDiscoveryRate, MS_mzidLib}, {MS_mzidLib_Mzidentml2Csv, MS_mzidLib}, {MS_mzidLib_CombineSearchEngines, MS_mzidLib}, {MS_mzidLib_InsertMetaDataFromFasta, MS_mzidLib}, {MS_SEQUEST_spscore, MS_search_engine_specific_score_for_PSMs}, {MS_SEQUEST_spscore, MS_search_engine_specific_score}, {MS_SEQUEST_sprank, MS_search_engine_specific_score_for_PSMs}, {MS_SEQUEST_sprank, MS_search_engine_specific_score}, {MS_SEQUEST_deltacnstar, MS_search_engine_specific_score_for_PSMs}, {MS_SEQUEST_deltacnstar, MS_search_engine_specific_score}, {MS_Comet, MS_analysis_software}, {MS_Comet_xcorr, MS_search_engine_specific_score_for_PSMs}, {MS_Comet_xcorr, MS_search_engine_specific_score}, {MS_Comet_deltacn, MS_search_engine_specific_score_for_PSMs}, {MS_Comet_deltacn, MS_search_engine_specific_score}, {MS_Comet_deltacnstar, MS_search_engine_specific_score_for_PSMs}, {MS_Comet_deltacnstar, MS_search_engine_specific_score}, {MS_Comet_spscore, MS_search_engine_specific_score_for_PSMs}, {MS_Comet_spscore, MS_search_engine_specific_score}, {MS_Comet_sprank, MS_search_engine_specific_score_for_PSMs}, {MS_Comet_sprank, MS_search_engine_specific_score}, {MS_Comet_expectation_value, MS_search_engine_specific_score}, {MS_Comet_matched_ions, MS_search_engine_specific_score_for_PSMs}, {MS_Comet_matched_ions, MS_search_engine_specific_score}, {MS_Comet_total_ions, MS_search_engine_specific_score_for_PSMs}, {MS_Comet_total_ions, MS_search_engine_specific_score}, {MS_PSM_FDR_threshold, MS_PSM_level_statistical_threshold}, {MS_Byonic, MS_analysis_software}, {MS_Byonic_Score, MS_search_engine_specific_score_for_PSMs}, {MS_Byonic_Score, MS_search_engine_specific_score}, {MS_Byonic_Delta_Score, MS_search_engine_specific_score_for_PSMs}, {MS_Byonic_Delta_Score, MS_search_engine_specific_score}, {MS_Byonic_DeltaMod_Score, MS_search_engine_specific_score_for_PSMs}, {MS_Byonic_DeltaMod_Score, MS_search_engine_specific_score}, {MS_Byonic_PEP, MS_search_engine_specific_score_for_PSMs}, {MS_Byonic_PEP, MS_search_engine_specific_score}, {MS_Byonic_Peptide_LogProb, MS_search_engine_specific_score_for_PSMs}, {MS_Byonic_Peptide_LogProb, MS_search_engine_specific_score}, {MS_Byonic_Protein_LogProb, MS_single_protein_result_details}, {MS_Byonic_Protein_LogProb, MS_search_engine_specific_score}, {MS_Byonic_Best_LogProb, MS_single_protein_result_details}, {MS_Byonic_Best_LogProb, MS_search_engine_specific_score}, {MS_Byonic_Best_Score, MS_single_protein_result_details}, {MS_Byonic_Best_Score, MS_search_engine_specific_score}, {MS_chromatography_separation, MS_run_attribute}, {MS_liquid_chromatography_separation, MS_chromatography_separation}, {MS_gas_chromatography_separation, MS_chromatography_separation}, {MS_detector_potential, MS_detector_attribute}, {MS_SQ_Detector_2, MS_Waters_instrument_model}, {MS_Xevo_G2_S_Tof, MS_Waters_instrument_model}, {MS_Xevo_G2_S_QTof, MS_Waters_instrument_model}, {MS_AutoSpec_Premier, MS_Waters_instrument_model}, {MS_Pegasus_III, MS_LECO_instrument_model}, {MS_maXis_4G, MS_Bruker_Daltonics_maXis_series}, {MS_compact, MS_Bruker_Daltonics_micrOTOF_series}, {MS_SRM_feature_level_quantitation, MS_SRM_quantitation_analysis}, {MS_SRM_peptide_level_quantitation, MS_SRM_quantitation_analysis}, {MS_SRM_protein_level_quantitation, MS_SRM_quantitation_analysis}, {MS_SRM_proteingroup_level_quantitation, MS_SRM_quantitation_analysis}, {MS_Trans_Proteomic_Pipeline, MS_analysis_software}, {MS_Trans_Proteomic_Pipeline_software, MS_analysis_software}, {MS_PeptideProphet, MS_Trans_Proteomic_Pipeline_software}, {MS_iProphet, MS_Trans_Proteomic_Pipeline_software}, {MS_ProteinProphet, MS_Trans_Proteomic_Pipeline_software}, {MS_XPRESS, MS_Trans_Proteomic_Pipeline_software}, {MS_Libra, MS_Trans_Proteomic_Pipeline_software}, {MS_PTMProphet, MS_Trans_Proteomic_Pipeline_software}, {MS_Bruker_Daltonics_SCION_series, MS_Bruker_Daltonics_instrument_model}, {MS_Bruker_Daltonics_EVOQ_series, MS_Bruker_Daltonics_instrument_model}, {MS_SCION_SQ, MS_Bruker_Daltonics_SCION_series}, {MS_SCION_TQ, MS_Bruker_Daltonics_SCION_series}, {MS_EVOQ_Elite, MS_Bruker_Daltonics_EVOQ_series}, {MS_EVOQ_Qube, MS_Bruker_Daltonics_EVOQ_series}, {MS_micrOTOF_Q_III, MS_Bruker_Daltonics_micrOTOF_series}, {MS_amaZon_Speed_ETD, MS_Bruker_Daltonics_amaZon_series}, {MS_amaZon_Speed, MS_Bruker_Daltonics_amaZon_series}, {MS_Bruker_Container_format, MS_mass_spectrometer_file_format}, {MS_Bruker_Container_nativeID_format, MS_native_spectrum_identifier_format}, {MS_value_between_0_and_1_inclusive, MS_domain_range}, {MS_value_greater_than_zero, MS_domain_range}, {MS_fragmentation_ion_type, MS_fragmentation_information}, {MS_fluorescence_detector, MS_detector_type}, {MS_Byonic__Peptide_AbsLogProb, MS_search_engine_specific_score_for_PSMs}, {MS_Byonic__Peptide_AbsLogProb, MS_search_engine_specific_score}, {MS_Byonic__Protein_AbsLogProb, MS_single_protein_result_details}, {MS_Byonic__Protein_AbsLogProb, MS_search_engine_specific_score}, {MS_Byonic__Peptide_AbsLogProb2D, MS_search_engine_specific_score_for_PSMs}, {MS_Byonic__Peptide_AbsLogProb2D, MS_search_engine_specific_score}, {MS_MS_Numpress_linear_prediction_compression, MS_binary_data_compression_type}, {MS_MS_Numpress_positive_integer_compression, MS_binary_data_compression_type}, {MS_MS_Numpress_short_logged_float_compression, MS_binary_data_compression_type}, {MS_consensus_result, MS_spectrum_identification_result_details}, {MS_ProteomeDiscoverer_Amanda_high_confidence_threshold, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Amanda_middle_confidence_threshold, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_automatic_workload, MS_ProteomeDiscoverer_input_parameter}, {MS_Amanda_AmandaScore, MS_search_engine_specific_score_for_PSMs}, {MS_Amanda_AmandaScore, MS_search_engine_specific_score}, {MS_ProteomeDiscoverer_max_differential_modifications, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_max_equal_modifications, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_min_peptide_length, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_max_peptide_length, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_max_number_neutral_loss, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_max_number_neutral_loss_modifications, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_use_flanking_ions, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_max_number_of_same_modifs, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_perform_deisotoping, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_ion_settings, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_3__Static_Modification_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_5__Dynamic_Modification_OBSOLETE, MS_ProteomeDiscoverer_input_parameter}, {MS_lab_head, MS_contact_role}, {MS_conversion_software, MS_data_processing_software}, {MS_ProCon, MS_conversion_software}, {MS_ProCon, MS_data_processing_software}, {MS_PRIDE_Converter2, MS_conversion_software}, {MS_PRIDE_Converter2, MS_data_processing_software}, {MS_Amanda, MS_analysis_software}, {MS_Andromeda, MS_analysis_software}, {MS_Andromeda_score, MS_search_engine_specific_score_for_PSMs}, {MS_Andromeda_score, MS_search_engine_specific_score}, {MS_site_global_FDR, MS_spectrum_identification_result_details}, {MS_ProteomeXchange_project_tag, MS_external_reference_identifier}, {MS_second_pass_peptide_identification, MS_peptide_result_details}, {MS_MZmine, MS_analysis_software}, {MS_MZmine, MS_data_processing_software}, {MS_Maltcms, MS_analysis_software}, {MS_Maltcms, MS_data_processing_software}, {MS_PSM_level_result_details, MS_spectrum_identification_result_details}, {MS_protein_group_level_result_details, MS_spectrum_identification_result_details}, {MS_PSM_level_identification_confidence_metric, MS_PSM_level_result_details}, {MS_protein_group_level_identification_confidence_metric, MS_protein_group_level_result_details}, {MS_value_greater_than_zero_but_less_than_or_equal_to_one, MS_domain_range}, {MS_PSM_level_global_FDR, MS_PSM_level_result_details}, {MS_PSM_level_global_FDR, MS_PSM_level_statistical_threshold}, {MS_PSM_level_local_FDR, MS_PSM_level_result_details}, {MS_PSM_level_local_FDR, MS_PSM_level_statistical_threshold}, {MS_PSM_level_p_value, MS_PSM_level_identification_confidence_metric}, {MS_PSM_level_e_value, MS_PSM_level_identification_confidence_metric}, {MS_PSM_level_q_value, MS_PSM_level_identification_confidence_metric}, {MS_PSM_level_FDRScore, MS_search_engine_specific_score_for_PSMs}, {MS_PSM_level_FDRScore, MS_search_engine_specific_score}, {MS_PSM_level_combined_FDRScore, MS_search_engine_specific_score_for_PSMs}, {MS_PSM_level_combined_FDRScore, MS_search_engine_specific_score}, {MS_PSM_level_probability, MS_PSM_level_identification_confidence_metric}, {MS_search_engine_specific_score_for_distinct_peptides, MS_peptide_result_details}, {MS_distinct_peptide_level_local_FDR, MS_peptide_result_details}, {MS_distinct_peptide_level_local_FDR, MS_peptide_level_statistical_threshold}, {MS_distinct_peptide_level_FDRScore, MS_search_engine_specific_score_for_distinct_peptides}, {MS_distinct_peptide_level_FDRScore, MS_search_engine_specific_score}, {MS_distinct_peptide_level_combined_FDRScore, MS_search_engine_specific_score_for_distinct_peptides}, {MS_distinct_peptide_level_combined_FDRScore, MS_search_engine_specific_score}, {MS_distinct_peptide_level_probability, MS_peptide_identification_confidence_metric}, {MS_search_engine_specific_score_for_proteins, MS_single_protein_result_details}, {MS_protein_level_local_FDR, MS_single_protein_result_details}, {MS_FDRScore_for_proteins, MS_search_engine_specific_score_for_proteins}, {MS_FDRScore_for_proteins, MS_search_engine_specific_score}, {MS_combined_FDRScore_for_proteins, MS_search_engine_specific_score_for_proteins}, {MS_combined_FDRScore_for_proteins, MS_search_engine_specific_score}, {MS_probability_for_proteins, MS_protein_identification_confidence_metric}, {MS_search_engine_specific_score_for_protein_groups, MS_protein_group_level_result_details}, {MS_protein_group_level_global_FDR, MS_protein_group_level_result_details}, {MS_protein_group_level_global_FDR, MS_protein_group_level_statistical_threshold}, {MS_protein_group_level_local_FDR, MS_protein_group_level_result_details}, {MS_protein_group_level_local_FDR, MS_protein_group_level_statistical_threshold}, {MS_protein_group_level_p_value, MS_protein_group_level_identification_confidence_metric}, {MS_protein_group_level_e_value, MS_protein_group_level_identification_confidence_metric}, {MS_protein_group_level_q_value, MS_protein_group_level_identification_confidence_metric}, {MS_protein_group_level_FDRScore, MS_search_engine_specific_score_for_protein_groups}, {MS_protein_group_level_FDRScore, MS_search_engine_specific_score}, {MS_protein_group_level_combined_FDRScore, MS_search_engine_specific_score_for_protein_groups}, {MS_protein_group_level_combined_FDRScore, MS_search_engine_specific_score}, {MS_protein_group_level_probability, MS_search_engine_specific_score_for_protein_groups}, {MS_ProteomeDiscoverer_Relaxed_Score_Threshold, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Strict_Score_Threshold, MS_ProteomeDiscoverer_input_parameter}, {MS_ProteomeDiscoverer_Peptide_Without_Protein_Cut_Off_Score, MS_ProteomeDiscoverer_input_parameter}, {MS_false_localization_rate, MS_spectrum_identification_result_details}, {MS_MALDI_Solutions_LC_MALDI, MS_acquisition_software}, {MS_MALDI_Solutions_LC_MALDI, MS_analysis_software}, {MS_MALDI_Solutions_LC_MALDI, MS_data_processing_software}, {MS_MALDI_Solutions_LC_MALDI, MS_Shimadzu_Corporation_software}, {MS_Shimadzu_MALDI_7090, MS_Shimadzu_MALDI_TOF_instrument_model}, {MS_SCiLS_software, MS_software}, {MS_SCiLS_Lab, MS_SCiLS_software}, {MS_SCiLS_Lab, MS_analysis_software}, {MS_SCiLS_Lab, MS_data_processing_software}, {MS_SCiLS_Lab_format, MS_mass_spectrometer_file_format}, {MS_preprocessing_software, MS_data_processing_software}, {MS_PIA, MS_postprocessing_software}, {MS_PIA, MS_analysis_software}, {MS_PIA, MS_data_processing_software}, {MS_PIA_XML_format, MS_intermediate_analysis_format}, {MS_PIA_workflow_parameter, MS_software_specific_input_parameter}, {MS_PIA_FDRScore_calculated, MS_PIA_workflow_parameter}, {MS_PIA_Combined_FDRScore_calculated, MS_PIA_workflow_parameter}, {MS_PIA_PSM_sets_created, MS_PIA_workflow_parameter}, {MS_PIA_used_top_identifications_for_FDR, MS_PIA_workflow_parameter}, {MS_PIA_protein_score, MS_single_protein_result_details}, {MS_PIA_protein_inference, MS_PIA_workflow_parameter}, {MS_PIA_protein_inference_filter, MS_PIA_workflow_parameter}, {MS_PIA_protein_inference_scoring, MS_PIA_workflow_parameter}, {MS_PIA_protein_inference_used_score, MS_PIA_workflow_parameter}, {MS_PIA_protein_inference_used_PSMs, MS_PIA_workflow_parameter}, {MS_PIA_filter, MS_PIA_workflow_parameter}, {MS_leading_protein, MS_protein_group_or_subset_relationship}, {MS_non_leading_protein, MS_protein_group_or_subset_relationship}, {MS_group_representative, MS_protein_group_or_subset_relationship}, {MS_count_of_identified_proteins, MS_protein_result_details}, {MS_protein_cluster_details, MS_protein_result_details}, {MS_count_of_identified_clusters, MS_protein_cluster_details}, {MS_cluster_identifier, MS_protein_ambiguity_group_result_details}, {MS_number_of_distinct_protein_sequences, MS_protein_cluster_details}, {MS_marginally_distinguished_protein, MS_protein_group_or_subset_relationship}, {MS_Anubis, MS_SRM_software}, {MS_Anubis, MS_quantitation_software_name}, {MS_TraML_format, MS_method_file_format}, {MS_total_XIC_area, MS_quantification_datatype}, {MS_product_background, MS_quantification_datatype}, {MS_postprocessing_software, MS_data_processing_software}, {MS_protein_group_passes_threshold, MS_protein_ambiguity_group_result_details}, {MS_Orbitrap_Fusion, MS_Thermo_Scientific_instrument_model}, {MS_Orbitrap_Fusion_ETD, MS_Thermo_Scientific_instrument_model}, {MS_TSQ_Quantiva, MS_Thermo_Scientific_instrument_model}, {MS_TSQ_Endura, MS_Thermo_Scientific_instrument_model}, {MS_PASSEL_experiment_URI, MS_external_reference_identifier}, {MS_Paragon_input_parameter, MS_search_engine_specific_input_parameter}, {MS_Paragon__sample_type, MS_Paragon_input_parameter}, {MS_Paragon__cysteine_alkylation, MS_Paragon_input_parameter}, {MS_Paragon__instrument_setting, MS_Paragon_input_parameter}, {MS_Paragon__search_effort, MS_Paragon_input_parameter}, {MS_Paragon__ID_focus, MS_Paragon_input_parameter}, {MS_Paragon__FDR_analysis, MS_Paragon_input_parameter}, {MS_Paragon__quantitation, MS_Paragon_input_parameter}, {MS_Paragon__background_correction, MS_Paragon_input_parameter}, {MS_Paragon__bias_correction, MS_Paragon_input_parameter}, {MS_Paragon__channel_to_use_as_denominator_in_ratios, MS_Paragon_input_parameter}, {MS_search_engine_specific_input_metadata, MS_search_input_details}, {MS_Paragon__modified_data_dictionary_or_parameter_translation, MS_search_engine_specific_input_metadata}, {MS_number_of_spectra_searched, MS_search_input_details}, {MS_data_processing_start_time, MS_data_processing_parameter}, {MS_Paragon__digestion, MS_search_input_details}, {MS_number_of_decoy_sequences, MS_search_database_details}, {MS_final_PSM_list, MS_spectrum_identification_list_result_details}, {MS_intermediate_PSM_list, MS_spectrum_identification_list_result_details}, {MS_Andi_MS_format, MS_mass_spectrometer_file_format}, {MS_chromatograph_file_format, MS_file_format}, {MS_Andi_CHROM_format, MS_chromatograph_file_format}, {MS_6420_Triple_Quadrupole_LC_MS, MS_Agilent_instrument_model}, {MS_6460_Triple_Quadrupole_LC_MS, MS_Agilent_instrument_model}, {MS_6490_Triple_Quadrupole_LC_MS, MS_Agilent_instrument_model}, {MS_Paragon_special_factor, MS_Paragon_input_parameter}, {MS_PEAKS_inChorusPeptideScore, MS_search_engine_specific_score_for_PSMs}, {MS_PEAKS_inChorusPeptideScore, MS_search_engine_specific_score}, {MS_PEAKS_inChorusProteinScore, MS_single_protein_result_details}, {MS_PEAKS_inChorusProteinScore, MS_search_engine_specific_score}, {MS_param__b_ion_H3PO4_DEPRECATED, MS_ions_series_considered_in_search}, {MS_param__y_ion_H3PO4_DEPRECATED, MS_ions_series_considered_in_search}, {MS_Maui, MS_analysis_software}, {MS_Maui, MS_data_processing_software}, {MS_No_fixed_modifications_searched, MS_common_search_engine_input_parameter}, {MS_No_variable_modifications_searched, MS_common_search_engine_input_parameter}, {MS_H2O_neutral_loss, MS_neutral_loss}, {MS_H2O_neutral_loss, MS_ion_series_considered_in_search}, {MS_NH3_neutral_loss, MS_neutral_loss}, {MS_NH3_neutral_loss, MS_ion_series_considered_in_search}, {MS_H3PO4_neutral_loss, MS_neutral_loss}, {MS_H3PO4_neutral_loss, MS_ion_series_considered_in_search}, {MS_PeptideShaker, MS_analysis_software}, {MS_MS_Amanda_csv_format, MS_intermediate_analysis_format}, {MS_protein_group_level_global_FNR, MS_protein_group_level_result_details}, {MS_protein_group_level_global_FNR, MS_protein_group_level_statistical_threshold}, {MS_protein_group_level_confidence, MS_protein_group_level_result_details}, {MS_distinct_peptide_level_global_FNR, MS_peptide_result_details}, {MS_distinct_peptide_level_global_FNR, MS_peptide_level_statistical_threshold}, {MS_distinct_peptide_level_global_confidence, MS_peptide_result_details}, {MS_PSM_level_global_FNR, MS_PSM_level_result_details}, {MS_PSM_level_global_FNR, MS_PSM_level_statistical_threshold}, {MS_PSM_level_global_confidence, MS_PSM_level_result_details}, {MS_PeptideShaker_PSM_score, MS_search_engine_specific_score}, {MS_PeptideShaker_PSM_score, MS_search_engine_specific_score_for_PSMs}, {MS_PeptideShaker_PSM_confidence, MS_search_engine_specific_score}, {MS_PeptideShaker_PSM_confidence, MS_search_engine_specific_score_for_PSMs}, {MS_PeptideShaker_peptide_score, MS_search_engine_specific_score}, {MS_PeptideShaker_peptide_score, MS_search_engine_specific_score_for_distinct_peptides}, {MS_PeptideShaker_peptide_confidence, MS_search_engine_specific_score}, {MS_PeptideShaker_protein_group_score, MS_search_engine_specific_score}, {MS_PeptideShaker_protein_group_score, MS_search_engine_specific_score_for_protein_groups}, {MS_PeptideShaker_protein_group_confidence, MS_search_engine_specific_score}, {MS_trap_type_collision_induced_dissociation, MS_collision_induced_dissociation}, {MS_ion_series_considered_in_search, MS_search_input_details}, {MS_ProteoAnnotator_non_canonical_gene_model_score, MS_protein_ambiguity_group_result_details}, {MS_ProteoAnnotator_count_alternative_peptides, MS_protein_ambiguity_group_result_details}, {MS_ion_mobility_drift_time, MS_ion_selection_attribute}, {MS_mean_drift_time_array, MS_binary_data_array}, {MS_mean_charge_array, MS_binary_data_array}, {MS_regular_expression_for_a_digital_object_identifier__DOI_, MS_regular_expression}, {MS_higher_energy_beam_type_collision_induced_dissociation, MS_beam_type_collision_induced_dissociation}, {MS_statistical_threshold, MS_quality_estimation_method_details}, {MS_PSM_level_statistical_threshold, MS_spectrum_identification_statistical_threshold}, {MS_peptide_level_statistical_threshold, MS_spectrum_identification_statistical_threshold}, {MS_protein_level_statistical_threshold, MS_protein_detection_statistical_threshold}, {MS_protein_group_level_statistical_threshold, MS_protein_detection_statistical_threshold}, {MS_MassIVE_dataset_identifier, MS_external_reference_identifier}, {MS_MassIVE_dataset_URI, MS_external_reference_identifier}, {MS_special_processing, MS_search_type}, {MS_peptide_level_scoring, MS_special_processing}, {MS_modification_localization_scoring, MS_special_processing}, {MS_consensus_scoring, MS_special_processing}, {MS_sample_pre_fractionation, MS_special_processing}, {MS_cross_linking_search, MS_special_processing}, {MS_no_special_processing, MS_special_processing}, {MS_group_PSMs_by_sequence, MS_PSM_level_result_details}, {MS_group_PSMs_by_sequence_with_modifications, MS_PSM_level_result_details}, {MS_group_PSMs_by_sequence_with_modifications_and_charge, MS_PSM_level_result_details}, {MS_peptide_level_score, MS_search_engine_specific_score_for_distinct_peptides}, {MS_peptide_passes_threshold, MS_peptide_result_details}, {MS_no_PSM_threshold, MS_PSM_level_result_details}, {MS_no_peptide_level_threshold, MS_peptide_result_details}, {MS_PSM_is_used_for_peptide_level_scoring, MS_peptide_result_details}, {MS_modification_index, MS_modification_parameters}, {MS_regular_expression_for_modification_localization_scoring, MS_regular_expression}, {MS_modification_position_score, MS_modification_parameters}, {MS_modification_rescoring_false_localization_rate, MS_modification_position_score}, {MS_cross_linking_attribute, MS_peptide_result_details}, {MS_cross_link_donor, MS_cross_linking_attribute}, {MS_cross_link_receiver, MS_cross_linking_attribute}, {MS_cross_link_spectrum_identification_item, MS_cross_linking_attribute}, {MS_cross_linking_score, MS_search_engine_specific_score}, {MS_molecules_per_cell, MS_quantification_datatype}, {MS_absolute_quantitation_analysis, MS_quantitation_analysis_summary}, {MS_internal_peptide_reference_used, MS_quantitation_software_comment_or_customizations}, {MS_internal_protein_reference_used, MS_quantitation_software_comment_or_customizations}, {MS_internal_reference_abundance, MS_quantification_datatype}, {MS_Progenesis_protein_group_normalised_abundance, MS_quantification_datatype}, {MS_Progenesis_protein_group_raw_abundance, MS_quantification_datatype}, {MS_peptide_group_ID, MS_peptide_result_details}, {MS_mass_spectrometry_imaging, MS_run_attribute}, {MS_ProteomeDiscoverer_1__Static_Terminal_Modification, MS_ProteomeDiscoverer_input_parameter}, {MS_Q_Exactive_HF, MS_Thermo_Scientific_instrument_model}, {MS_PepFinder, MS_data_processing_software}, {MS_TSQ_8000_Evo, MS_Thermo_Scientific_instrument_model}, {MS_Exactive_Plus, MS_Thermo_Scientific_instrument_model}, {MS_instrument_specific_scan_attribute, MS_scan_attribute}, {MS_synchronous_prefilter_selection, MS_instrument_specific_scan_attribute}, {MS_resolution_array, MS_binary_data_array}, {MS_baseline_array, MS_binary_data_array}, {MS_UIMF_format, MS_mass_spectrometer_file_format}, {MS_UIMF_nativeID_format, MS_native_spectrum_identifier_format}, {MS_TripleTOF_6600, MS_SCIEX_instrument_model}, {MS_ProLuCID_xcorr, MS_search_engine_specific_score_for_PSMs}, {MS_ProLuCID_xcorr, MS_search_engine_specific_score}, {MS_ProLuCID_deltacn, MS_search_engine_specific_score_for_PSMs}, {MS_ProLuCID_deltacn, MS_search_engine_specific_score}, {MS_D_Score, MS_PSM_level_PTM_localization_score}, {MS_MD_Score, MS_PSM_level_PTM_localization_score}, {MS_PTM_localization_confidence_metric, MS_spectrum_identification_result_details}, {MS_PeptideShaker_PTM_confidence_type, MS_PTM_localization_confidence_metric}, {MS_PeptideShaker_PSM_confidence_type, MS_PSM_level_identification_confidence_metric}, {MS_PeptideShaker_peptide_confidence_type, MS_peptide_identification_confidence_metric}, {MS_PeptideShaker_protein_confidence_type, MS_protein_identification_confidence_metric}, {MS_xiFDR, MS_analysis_software}, {MS_xi, MS_analysis_software}, {MS_xi_score, MS_search_engine_specific_score_for_PSMs}, {MS_xi_score, MS_search_engine_specific_score}, {MS_Skyline_mzQuantML_converter, MS_quantitation_software_name}, {MS_Skyline_mzQuantML_converter, MS_analysis_software}, {MS_normalized_spectral_abundance_factor, MS_quantification_datatype}, {MS_distributed_normalized_spectral_abundance_factor, MS_quantification_datatype}, {MS_peptide_level_PTM_localization_score, MS_spectrum_identification_result_details}, {MS_peptide_phosphoRS_score, MS_peptide_level_PTM_localization_score}, {MS_peptide_Ascore, MS_peptide_level_PTM_localization_score}, {MS_peptide_H_Score, MS_peptide_level_PTM_localization_score}, {MS_peptide_D_Score, MS_peptide_level_PTM_localization_score}, {MS_peptide_MD_Score, MS_peptide_level_PTM_localization_score}, {MS_PTM_localization_score_threshold, MS_spectrum_identification_result_details}, {MS_Ascore_threshold, MS_PTM_localization_score_threshold}, {MS_D_Score_threshold, MS_PTM_localization_score_threshold}, {MS_MD_Score_threshold, MS_PTM_localization_score_threshold}, {MS_H_Score_threshold, MS_PTM_localization_score_threshold}, {MS_Mascot_PTM_site_assignment_confidence_threshold, MS_PTM_localization_score_threshold}, {MS_MSQuant_PTM_score_threshold, MS_PTM_localization_score_threshold}, {MS_MaxQuant_PTM_Score_threshold, MS_PTM_localization_score_threshold}, {MS_MaxQuant_P_site_localization_probability_threshold, MS_PTM_localization_score_threshold}, {MS_MaxQuant_PTM_Delta_Score_threshold, MS_PTM_localization_score_threshold}, {MS_MaxQuant_Phospho__STY__Probabilities_threshold, MS_PTM_localization_score_threshold}, {MS_phosphoRS_score_threshold, MS_PTM_localization_score_threshold}, {MS_phosphoRS_site_probability_threshold, MS_PTM_localization_score_threshold}, {MS_ProteomeDiscoverer_Number_of_Spectra_Processed_At_Once, MS_ProteomeDiscoverer_input_parameter}, {MS_sequence_multiply_subsumable_protein, MS_protein_group_or_subset_relationship}, {MS_spectrum_multiply_subsumable_protein, MS_protein_group_or_subset_relationship}, {MS_protein_detection_statistical_threshold, MS_statistical_threshold}, {MS_spectrum_identification_statistical_threshold, MS_statistical_threshold}, {MS_ASAPRatio, MS_Trans_Proteomic_Pipeline_software}, {MS_Tide, MS_analysis_software}, {MS_Andromeda_result_file, MS_intermediate_analysis_format}, {MS_2000_QTRAP, MS_SCIEX_instrument_model}, {MS_2500_QTRAP, MS_SCIEX_instrument_model}, {MS_3500_QTRAP, MS_SCIEX_instrument_model}, {MS_QTRAP_4500, MS_SCIEX_instrument_model}, {MS_QTRAP_6500, MS_SCIEX_instrument_model}, {MS_QTRAP_6500_, MS_SCIEX_instrument_model}, {MS_TripleTOF_4600, MS_SCIEX_instrument_model}, {MS_TripleTOF_5600_, MS_SCIEX_instrument_model}, {MS_API_100, MS_SCIEX_instrument_model}, {MS_API_100LC, MS_SCIEX_instrument_model}, {MS_API_165, MS_SCIEX_instrument_model}, {MS_API_300, MS_SCIEX_instrument_model}, {MS_API_350, MS_SCIEX_instrument_model}, {MS_API_365, MS_SCIEX_instrument_model}, {MS_Triple_Quad_3500, MS_SCIEX_instrument_model}, {MS_Triple_Quad_4500, MS_SCIEX_instrument_model}, {MS_Triple_Quad_5500, MS_SCIEX_instrument_model}, {MS_Triple_Quad_6500, MS_SCIEX_instrument_model}, {MS_Triple_Quad_6500_, MS_SCIEX_instrument_model}, {MS_DeBunker_score_threshold, MS_PTM_localization_score_threshold}, {UNIMOD_Acetyl, UNIMOD_unimod_root_node}, {UNIMOD_Amidated, UNIMOD_unimod_root_node}, {UNIMOD_Biotin, UNIMOD_unimod_root_node}, {UNIMOD_Carbamidomethyl, UNIMOD_unimod_root_node}, {UNIMOD_Carbamyl, UNIMOD_unimod_root_node}, {UNIMOD_Carboxymethyl, UNIMOD_unimod_root_node}, {UNIMOD_Deamidated, UNIMOD_unimod_root_node}, {UNIMOD_ICAT_G, UNIMOD_unimod_root_node}, {UNIMOD_ICAT_G_2H_8_, UNIMOD_unimod_root_node}, {UNIMOD_Met__Hse, UNIMOD_unimod_root_node}, {UNIMOD_Met__Hsl, UNIMOD_unimod_root_node}, {UNIMOD_ICAT_D_2H_8_, UNIMOD_unimod_root_node}, {UNIMOD_ICAT_D, UNIMOD_unimod_root_node}, {UNIMOD_NIPCAM, UNIMOD_unimod_root_node}, {UNIMOD_PEO_Iodoacetyl_LC_Biotin, UNIMOD_unimod_root_node}, {UNIMOD_Phospho, UNIMOD_unimod_root_node}, {UNIMOD_Dehydrated, UNIMOD_unimod_root_node}, {UNIMOD_Propionamide, UNIMOD_unimod_root_node}, {UNIMOD_Pyridylacetyl, UNIMOD_unimod_root_node}, {UNIMOD_Pyro_carbamidomethyl, UNIMOD_unimod_root_node}, {UNIMOD_Glu__pyro_Glu, UNIMOD_unimod_root_node}, {UNIMOD_Gln__pyro_Glu, UNIMOD_unimod_root_node}, {UNIMOD_SMA, UNIMOD_unimod_root_node}, {UNIMOD_Cation_Na, UNIMOD_unimod_root_node}, {UNIMOD_Pyridylethyl, UNIMOD_unimod_root_node}, {UNIMOD_Methyl, UNIMOD_unimod_root_node}, {UNIMOD_Oxidation, UNIMOD_unimod_root_node}, {UNIMOD_Dimethyl, UNIMOD_unimod_root_node}, {UNIMOD_Trimethyl, UNIMOD_unimod_root_node}, {UNIMOD_Methylthio, UNIMOD_unimod_root_node}, {UNIMOD_Sulfo, UNIMOD_unimod_root_node}, {UNIMOD_Hex, UNIMOD_unimod_root_node}, {UNIMOD_Lipoyl, UNIMOD_unimod_root_node}, {UNIMOD_HexNAc, UNIMOD_unimod_root_node}, {UNIMOD_Farnesyl, UNIMOD_unimod_root_node}, {UNIMOD_Myristoyl, UNIMOD_unimod_root_node}, {UNIMOD_PyridoxalPhosphate, UNIMOD_unimod_root_node}, {UNIMOD_Palmitoyl, UNIMOD_unimod_root_node}, {UNIMOD_GeranylGeranyl, UNIMOD_unimod_root_node}, {UNIMOD_Phosphopantetheine, UNIMOD_unimod_root_node}, {UNIMOD_FAD, UNIMOD_unimod_root_node}, {UNIMOD_Tripalmitate, UNIMOD_unimod_root_node}, {UNIMOD_Guanidinyl, UNIMOD_unimod_root_node}, {UNIMOD_HNE, UNIMOD_unimod_root_node}, {UNIMOD_Glucuronyl, UNIMOD_unimod_root_node}, {UNIMOD_Glutathione, UNIMOD_unimod_root_node}, {UNIMOD_Acetyl_2H_3_, UNIMOD_unimod_root_node}, {UNIMOD_Propionyl, UNIMOD_unimod_root_node}, {UNIMOD_Propionyl_13C_3_, UNIMOD_unimod_root_node}, {UNIMOD_GIST_Quat, UNIMOD_unimod_root_node}, {UNIMOD_GIST_Quat_2H_3_, UNIMOD_unimod_root_node}, {UNIMOD_GIST_Quat_2H_6_, UNIMOD_unimod_root_node}, {UNIMOD_GIST_Quat_2H_9_, UNIMOD_unimod_root_node}, {UNIMOD_Succinyl, UNIMOD_unimod_root_node}, {UNIMOD_Succinyl_2H_4_, UNIMOD_unimod_root_node}, {UNIMOD_Succinyl_13C_4_, UNIMOD_unimod_root_node}, {UNIMOD_Iminobiotin, UNIMOD_unimod_root_node}, {UNIMOD_ESP, UNIMOD_unimod_root_node}, {UNIMOD_ESP_2H_10_, UNIMOD_unimod_root_node}, {UNIMOD_NHS_LC_Biotin, UNIMOD_unimod_root_node}, {UNIMOD_EDT_maleimide_PEO_biotin, UNIMOD_unimod_root_node}, {UNIMOD_IMID, UNIMOD_unimod_root_node}, {UNIMOD_IMID_2H_4_, UNIMOD_unimod_root_node}, {UNIMOD_Propionamide_2H_3_, UNIMOD_unimod_root_node}, {UNIMOD_ICAT_C, UNIMOD_unimod_root_node}, {UNIMOD_ICAT_C_13C_9_, UNIMOD_unimod_root_node}, {UNIMOD_FormylMet, UNIMOD_unimod_root_node}, {UNIMOD_Nethylmaleimide, UNIMOD_unimod_root_node}, {UNIMOD_OxLysBiotinRed, UNIMOD_unimod_root_node}, {UNIMOD_OxLysBiotin, UNIMOD_unimod_root_node}, {UNIMOD_OxProBiotinRed, UNIMOD_unimod_root_node}, {UNIMOD_OxProBiotin, UNIMOD_unimod_root_node}, {UNIMOD_OxArgBiotin, UNIMOD_unimod_root_node}, {UNIMOD_OxArgBiotinRed, UNIMOD_unimod_root_node}, {UNIMOD_EDT_iodoacetyl_PEO_biotin, UNIMOD_unimod_root_node}, {UNIMOD_IBTP, UNIMOD_unimod_root_node}, {UNIMOD_GG, UNIMOD_unimod_root_node}, {UNIMOD_Formyl, UNIMOD_unimod_root_node}, {UNIMOD_ICAT_H, UNIMOD_unimod_root_node}, {UNIMOD_ICAT_H_13C_6_, UNIMOD_unimod_root_node}, {UNIMOD_Thioacyl, UNIMOD_unimod_root_node}, {UNIMOD_Fluoro, UNIMOD_unimod_root_node}, {UNIMOD_Fluorescein, UNIMOD_unimod_root_node}, {UNIMOD_Iodo, UNIMOD_unimod_root_node}, {UNIMOD_Diiodo, UNIMOD_unimod_root_node}, {UNIMOD_Triiodo, UNIMOD_unimod_root_node}, {UNIMOD_Myristoleyl, UNIMOD_unimod_root_node}, {UNIMOD_Myristoyl_Delta_H__4_, UNIMOD_unimod_root_node}, {UNIMOD_Benzoyl, UNIMOD_unimod_root_node}, {UNIMOD_Hex_5_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_Dansyl, UNIMOD_unimod_root_node}, {UNIMOD_a_type_ion, UNIMOD_unimod_root_node}, {UNIMOD_Amidine, UNIMOD_unimod_root_node}, {UNIMOD_HexNAc_1_dHex_1_, UNIMOD_unimod_root_node}, {UNIMOD_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_, UNIMOD_unimod_root_node}, {UNIMOD_HexNAc_1_dHex_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_, UNIMOD_unimod_root_node}, {UNIMOD_HexNAc_2_dHex_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_HexNAc_2_dHex_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_2_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_1_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_2_dHex_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_2_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_2_dHex_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_2_Phos_1_, UNIMOD_unimod_root_node}, {UNIMOD_Delta_S__1_Se_1_, UNIMOD_unimod_root_node}, {UNIMOD_Delta_H_1_N__1_18O_1_, UNIMOD_unimod_root_node}, {UNIMOD_NBS_13C_6_, UNIMOD_unimod_root_node}, {UNIMOD_NBS, UNIMOD_unimod_root_node}, {UNIMOD_BHT, UNIMOD_unimod_root_node}, {UNIMOD_DAET, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_9_, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_9__Phospho, UNIMOD_unimod_root_node}, {UNIMOD_HPG, UNIMOD_unimod_root_node}, {UNIMOD_2HPG, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_6_, UNIMOD_unimod_root_node}, {UNIMOD_Label_18O_2_, UNIMOD_unimod_root_node}, {UNIMOD_AccQTag, UNIMOD_unimod_root_node}, {UNIMOD_QAT, UNIMOD_unimod_root_node}, {UNIMOD_QAT_2H_3_, UNIMOD_unimod_root_node}, {UNIMOD_EQAT, UNIMOD_unimod_root_node}, {UNIMOD_EQAT_2H_5_, UNIMOD_unimod_root_node}, {UNIMOD_Dimethyl_2H_4_, UNIMOD_unimod_root_node}, {UNIMOD_Ethanedithiol, UNIMOD_unimod_root_node}, {UNIMOD_Delta_H_6_C_6_O_1_, UNIMOD_unimod_root_node}, {UNIMOD_Delta_H_4_C_3_O_1_, UNIMOD_unimod_root_node}, {UNIMOD_Delta_H_2_C_3_, UNIMOD_unimod_root_node}, {UNIMOD_Delta_H_4_C_6_, UNIMOD_unimod_root_node}, {UNIMOD_Delta_H_8_C_6_O_2_, UNIMOD_unimod_root_node}, {UNIMOD_NEIAA, UNIMOD_unimod_root_node}, {UNIMOD_NEIAA_2H_5_, UNIMOD_unimod_root_node}, {UNIMOD_ADP_Ribosyl, UNIMOD_unimod_root_node}, {UNIMOD_iTRAQ4plex, UNIMOD_unimod_root_node}, {UNIMOD_IGBP, UNIMOD_unimod_root_node}, {UNIMOD_Crotonaldehyde, UNIMOD_unimod_root_node}, {UNIMOD_Delta_H_2_C_2_, UNIMOD_unimod_root_node}, {UNIMOD_Delta_H_4_C_2_, UNIMOD_unimod_root_node}, {UNIMOD_Delta_H_4_C_3_, UNIMOD_unimod_root_node}, {UNIMOD_Label_18O_1_, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_6_15N_2_, UNIMOD_unimod_root_node}, {UNIMOD_Thiophospho, UNIMOD_unimod_root_node}, {UNIMOD_SPITC, UNIMOD_unimod_root_node}, {UNIMOD_Label_2H_3_, UNIMOD_unimod_root_node}, {UNIMOD_PET, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_6_15N_4_, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_5_15N_1_, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_9_15N_1_, UNIMOD_unimod_root_node}, {UNIMOD_Cytopiloyne, UNIMOD_unimod_root_node}, {UNIMOD_Cytopiloyne_water, UNIMOD_unimod_root_node}, {UNIMOD_CAF, UNIMOD_unimod_root_node}, {UNIMOD_Xlink_SSD, UNIMOD_unimod_root_node}, {UNIMOD_Nitrosyl, UNIMOD_unimod_root_node}, {UNIMOD_AEBS, UNIMOD_unimod_root_node}, {UNIMOD_Ethanolyl, UNIMOD_unimod_root_node}, {UNIMOD_Ethyl, UNIMOD_unimod_root_node}, {UNIMOD_CoenzymeA, UNIMOD_unimod_root_node}, {UNIMOD_Methyl_2H_2_, UNIMOD_unimod_root_node}, {UNIMOD_SulfanilicAcid, UNIMOD_unimod_root_node}, {UNIMOD_SulfanilicAcid_13C_6_, UNIMOD_unimod_root_node}, {UNIMOD_Trp__Oxolactone, UNIMOD_unimod_root_node}, {UNIMOD_Biotin_PEO_Amine, UNIMOD_unimod_root_node}, {UNIMOD_Biotin_HPDP, UNIMOD_unimod_root_node}, {UNIMOD_Delta_Hg_1_, UNIMOD_unimod_root_node}, {UNIMOD_IodoU_AMP, UNIMOD_unimod_root_node}, {UNIMOD_CAMthiopropanoyl, UNIMOD_unimod_root_node}, {UNIMOD_IED_Biotin, UNIMOD_unimod_root_node}, {UNIMOD_dHex, UNIMOD_unimod_root_node}, {UNIMOD_Methyl_2H_3_, UNIMOD_unimod_root_node}, {UNIMOD_Carboxy, UNIMOD_unimod_root_node}, {UNIMOD_Bromobimane, UNIMOD_unimod_root_node}, {UNIMOD_Menadione, UNIMOD_unimod_root_node}, {UNIMOD_DeStreak, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_5_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_Cysteinyl, UNIMOD_unimod_root_node}, {UNIMOD_Lys_loss, UNIMOD_unimod_root_node}, {UNIMOD_Nmethylmaleimide, UNIMOD_unimod_root_node}, {UNIMOD_DimethylpyrroleAdduct, UNIMOD_unimod_root_node}, {UNIMOD_Delta_H_2_C_5_, UNIMOD_unimod_root_node}, {UNIMOD_Delta_H_2_C_3_O_1_, UNIMOD_unimod_root_node}, {UNIMOD_Nethylmaleimide_water, UNIMOD_unimod_root_node}, {UNIMOD_Xlink_B10621, UNIMOD_unimod_root_node}, {UNIMOD_DTBP, UNIMOD_unimod_root_node}, {UNIMOD_FP_Biotin, UNIMOD_unimod_root_node}, {UNIMOD_Delta_H_4_C_2_O__1_S_1_, UNIMOD_unimod_root_node}, {UNIMOD_Methyl_2H_3_13C_1_, UNIMOD_unimod_root_node}, {UNIMOD_Dimethyl_2H_6_13C_2_, UNIMOD_unimod_root_node}, {UNIMOD_Thiophos_S_S_biotin, UNIMOD_unimod_root_node}, {UNIMOD_Can_FP_biotin, UNIMOD_unimod_root_node}, {UNIMOD_HNE_Delta_H_2_, UNIMOD_unimod_root_node}, {UNIMOD_Methylamine, UNIMOD_unimod_root_node}, {UNIMOD_Bromo, UNIMOD_unimod_root_node}, {UNIMOD_Amino, UNIMOD_unimod_root_node}, {UNIMOD_Argbiotinhydrazide, UNIMOD_unimod_root_node}, {UNIMOD_Arg__GluSA, UNIMOD_unimod_root_node}, {UNIMOD_Trioxidation, UNIMOD_unimod_root_node}, {UNIMOD_His__Asn, UNIMOD_unimod_root_node}, {UNIMOD_His__Asp, UNIMOD_unimod_root_node}, {UNIMOD_Trp__Hydroxykynurenin, UNIMOD_unimod_root_node}, {UNIMOD_Trp__Kynurenin, UNIMOD_unimod_root_node}, {UNIMOD_Lys__Allysine, UNIMOD_unimod_root_node}, {UNIMOD_Lysbiotinhydrazide, UNIMOD_unimod_root_node}, {UNIMOD_Nitro, UNIMOD_unimod_root_node}, {UNIMOD_probiotinhydrazide, UNIMOD_unimod_root_node}, {UNIMOD_Pro__pyro_Glu, UNIMOD_unimod_root_node}, {UNIMOD_Pro__Pyrrolidinone, UNIMOD_unimod_root_node}, {UNIMOD_Thrbiotinhydrazide, UNIMOD_unimod_root_node}, {UNIMOD_Diisopropylphosphate, UNIMOD_unimod_root_node}, {UNIMOD_Isopropylphospho, UNIMOD_unimod_root_node}, {UNIMOD_ICPL_13C_6_, UNIMOD_unimod_root_node}, {UNIMOD_ICPL, UNIMOD_unimod_root_node}, {UNIMOD_Deamidated_18O_1_, UNIMOD_unimod_root_node}, {UNIMOD_Cys__Dha, UNIMOD_unimod_root_node}, {UNIMOD_Pro__Pyrrolidone, UNIMOD_unimod_root_node}, {UNIMOD_HMVK, UNIMOD_unimod_root_node}, {UNIMOD_Arg__Orn, UNIMOD_unimod_root_node}, {UNIMOD_Dehydro, UNIMOD_unimod_root_node}, {UNIMOD_Diphthamide, UNIMOD_unimod_root_node}, {UNIMOD_Hydroxyfarnesyl, UNIMOD_unimod_root_node}, {UNIMOD_Diacylglycerol, UNIMOD_unimod_root_node}, {UNIMOD_Carboxyethyl, UNIMOD_unimod_root_node}, {UNIMOD_Hypusine, UNIMOD_unimod_root_node}, {UNIMOD_Retinylidene, UNIMOD_unimod_root_node}, {UNIMOD_Lys__AminoadipicAcid, UNIMOD_unimod_root_node}, {UNIMOD_Cys__PyruvicAcid, UNIMOD_unimod_root_node}, {UNIMOD_Ammonia_loss, UNIMOD_unimod_root_node}, {UNIMOD_Phycocyanobilin, UNIMOD_unimod_root_node}, {UNIMOD_Phycoerythrobilin, UNIMOD_unimod_root_node}, {UNIMOD_Phytochromobilin, UNIMOD_unimod_root_node}, {UNIMOD_Heme, UNIMOD_unimod_root_node}, {UNIMOD_Molybdopterin, UNIMOD_unimod_root_node}, {UNIMOD_Quinone, UNIMOD_unimod_root_node}, {UNIMOD_Glucosylgalactosyl, UNIMOD_unimod_root_node}, {UNIMOD_GPIanchor, UNIMOD_unimod_root_node}, {UNIMOD_PhosphoribosyldephosphoCoA, UNIMOD_unimod_root_node}, {UNIMOD_GlycerylPE, UNIMOD_unimod_root_node}, {UNIMOD_Triiodothyronine, UNIMOD_unimod_root_node}, {UNIMOD_Thyroxine, UNIMOD_unimod_root_node}, {UNIMOD_Tyr__Dha, UNIMOD_unimod_root_node}, {UNIMOD_Didehydro, UNIMOD_unimod_root_node}, {UNIMOD_Cys__Oxoalanine, UNIMOD_unimod_root_node}, {UNIMOD_Ser__LacticAcid, UNIMOD_unimod_root_node}, {UNIMOD_Phosphoadenosine, UNIMOD_unimod_root_node}, {UNIMOD_Hydroxycinnamyl, UNIMOD_unimod_root_node}, {UNIMOD_Glycosyl, UNIMOD_unimod_root_node}, {UNIMOD_FMNH, UNIMOD_unimod_root_node}, {UNIMOD_Archaeol, UNIMOD_unimod_root_node}, {UNIMOD_Phenylisocyanate, UNIMOD_unimod_root_node}, {UNIMOD_Phenylisocyanate_2H_5_, UNIMOD_unimod_root_node}, {UNIMOD_Phosphoguanosine, UNIMOD_unimod_root_node}, {UNIMOD_Hydroxymethyl, UNIMOD_unimod_root_node}, {UNIMOD_MolybdopterinGD_Delta_S__1_Se_1_, UNIMOD_unimod_root_node}, {UNIMOD_Dipyrrolylmethanemethyl, UNIMOD_unimod_root_node}, {UNIMOD_PhosphoUridine, UNIMOD_unimod_root_node}, {UNIMOD_Glycerophospho, UNIMOD_unimod_root_node}, {UNIMOD_Carboxy__Thiocarboxy, UNIMOD_unimod_root_node}, {UNIMOD_Sulfide, UNIMOD_unimod_root_node}, {UNIMOD_PyruvicAcidIminyl, UNIMOD_unimod_root_node}, {UNIMOD_Delta_Se_1_, UNIMOD_unimod_root_node}, {UNIMOD_MolybdopterinGD, UNIMOD_unimod_root_node}, {UNIMOD_Dioxidation, UNIMOD_unimod_root_node}, {UNIMOD_Octanoyl, UNIMOD_unimod_root_node}, {UNIMOD_PhosphoHexNAc, UNIMOD_unimod_root_node}, {UNIMOD_PhosphoHex, UNIMOD_unimod_root_node}, {UNIMOD_Palmitoleyl, UNIMOD_unimod_root_node}, {UNIMOD_Cholesterol, UNIMOD_unimod_root_node}, {UNIMOD_Didehydroretinylidene, UNIMOD_unimod_root_node}, {UNIMOD_CHDH, UNIMOD_unimod_root_node}, {UNIMOD_Methylpyrroline, UNIMOD_unimod_root_node}, {UNIMOD_Hydroxyheme, UNIMOD_unimod_root_node}, {UNIMOD_MicrocinC7, UNIMOD_unimod_root_node}, {UNIMOD_Cyano, UNIMOD_unimod_root_node}, {UNIMOD_Diironsubcluster, UNIMOD_unimod_root_node}, {UNIMOD_Amidino, UNIMOD_unimod_root_node}, {UNIMOD_FMN, UNIMOD_unimod_root_node}, {UNIMOD_FMNC, UNIMOD_unimod_root_node}, {UNIMOD_CuSMo, UNIMOD_unimod_root_node}, {UNIMOD_Hydroxytrimethyl, UNIMOD_unimod_root_node}, {UNIMOD_Deoxy, UNIMOD_unimod_root_node}, {UNIMOD_Microcin, UNIMOD_unimod_root_node}, {UNIMOD_Decanoyl, UNIMOD_unimod_root_node}, {UNIMOD_Glu, UNIMOD_unimod_root_node}, {UNIMOD_GluGlu, UNIMOD_unimod_root_node}, {UNIMOD_GluGluGlu, UNIMOD_unimod_root_node}, {UNIMOD_GluGluGluGlu, UNIMOD_unimod_root_node}, {UNIMOD_HexN, UNIMOD_unimod_root_node}, {UNIMOD_Xlink_DMP_s, UNIMOD_unimod_root_node}, {UNIMOD_Xlink_DMP, UNIMOD_unimod_root_node}, {UNIMOD_NDA, UNIMOD_unimod_root_node}, {UNIMOD_SPITC_13C_6_, UNIMOD_unimod_root_node}, {UNIMOD_AEC_MAEC, UNIMOD_unimod_root_node}, {UNIMOD_TMAB, UNIMOD_unimod_root_node}, {UNIMOD_TMAB_2H_9_, UNIMOD_unimod_root_node}, {UNIMOD_FTC, UNIMOD_unimod_root_node}, {UNIMOD_Label_2H_4_, UNIMOD_unimod_root_node}, {UNIMOD_DHP, UNIMOD_unimod_root_node}, {UNIMOD_Hep, UNIMOD_unimod_root_node}, {UNIMOD_BADGE, UNIMOD_unimod_root_node}, {UNIMOD_CyDye_Cy3, UNIMOD_unimod_root_node}, {UNIMOD_CyDye_Cy5, UNIMOD_unimod_root_node}, {UNIMOD_BHTOH, UNIMOD_unimod_root_node}, {UNIMOD_IGBP_13C_2_, UNIMOD_unimod_root_node}, {UNIMOD_Nmethylmaleimide_water, UNIMOD_unimod_root_node}, {UNIMOD_PyMIC, UNIMOD_unimod_root_node}, {UNIMOD_LG_lactam_K, UNIMOD_unimod_root_node}, {UNIMOD_LG_Hlactam_K, UNIMOD_unimod_root_node}, {UNIMOD_LG_lactam_R, UNIMOD_unimod_root_node}, {UNIMOD_LG_Hlactam_R, UNIMOD_unimod_root_node}, {UNIMOD_Dimethyl_2H_4_13C_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_, UNIMOD_unimod_root_node}, {UNIMOD_C8_QAT, UNIMOD_unimod_root_node}, {UNIMOD_PropylNAGthiazoline, UNIMOD_unimod_root_node}, {UNIMOD_FNEM, UNIMOD_unimod_root_node}, {UNIMOD_Diethyl, UNIMOD_unimod_root_node}, {UNIMOD_BisANS, UNIMOD_unimod_root_node}, {UNIMOD_Piperidine, UNIMOD_unimod_root_node}, {UNIMOD_Maleimide_PEO2_Biotin, UNIMOD_unimod_root_node}, {UNIMOD_Sulfo_NHS_LC_LC_Biotin, UNIMOD_unimod_root_node}, {UNIMOD_CLIP_TRAQ_2, UNIMOD_unimod_root_node}, {UNIMOD_Dethiomethyl, UNIMOD_unimod_root_node}, {UNIMOD_Methyl_Deamidated, UNIMOD_unimod_root_node}, {UNIMOD_Delta_H_5_C_2_, UNIMOD_unimod_root_node}, {UNIMOD_Cation_K, UNIMOD_unimod_root_node}, {UNIMOD_Cation_Cu_I_, UNIMOD_unimod_root_node}, {UNIMOD_iTRAQ4plex114, UNIMOD_unimod_root_node}, {UNIMOD_iTRAQ4plex115, UNIMOD_unimod_root_node}, {UNIMOD_Dibromo, UNIMOD_unimod_root_node}, {UNIMOD_LRGG, UNIMOD_unimod_root_node}, {UNIMOD_CLIP_TRAQ_3, UNIMOD_unimod_root_node}, {UNIMOD_CLIP_TRAQ_4, UNIMOD_unimod_root_node}, {UNIMOD_Biotin_Cayman_10141, UNIMOD_unimod_root_node}, {UNIMOD_Biotin_Cayman_10013, UNIMOD_unimod_root_node}, {UNIMOD_Ala__Ser, UNIMOD_unimod_root_node}, {UNIMOD_Ala__Thr, UNIMOD_unimod_root_node}, {UNIMOD_Ala__Asp, UNIMOD_unimod_root_node}, {UNIMOD_Ala__Pro, UNIMOD_unimod_root_node}, {UNIMOD_Ala__Gly, UNIMOD_unimod_root_node}, {UNIMOD_Ala__Glu, UNIMOD_unimod_root_node}, {UNIMOD_Ala__Val, UNIMOD_unimod_root_node}, {UNIMOD_Cys__Phe, UNIMOD_unimod_root_node}, {UNIMOD_Cys__Ser, UNIMOD_unimod_root_node}, {UNIMOD_Cys__Trp, UNIMOD_unimod_root_node}, {UNIMOD_Cys__Tyr, UNIMOD_unimod_root_node}, {UNIMOD_Cys__Arg, UNIMOD_unimod_root_node}, {UNIMOD_Cys__Gly, UNIMOD_unimod_root_node}, {UNIMOD_Asp__Ala, UNIMOD_unimod_root_node}, {UNIMOD_Asp__His, UNIMOD_unimod_root_node}, {UNIMOD_Asp__Asn, UNIMOD_unimod_root_node}, {UNIMOD_Asp__Gly, UNIMOD_unimod_root_node}, {UNIMOD_Asp__Tyr, UNIMOD_unimod_root_node}, {UNIMOD_Asp__Glu, UNIMOD_unimod_root_node}, {UNIMOD_Asp__Val, UNIMOD_unimod_root_node}, {UNIMOD_Glu__Ala, UNIMOD_unimod_root_node}, {UNIMOD_Glu__Gln, UNIMOD_unimod_root_node}, {UNIMOD_Glu__Asp, UNIMOD_unimod_root_node}, {UNIMOD_Glu__Lys, UNIMOD_unimod_root_node}, {UNIMOD_Glu__Gly, UNIMOD_unimod_root_node}, {UNIMOD_Glu__Val, UNIMOD_unimod_root_node}, {UNIMOD_Phe__Ser, UNIMOD_unimod_root_node}, {UNIMOD_Phe__Cys, UNIMOD_unimod_root_node}, {UNIMOD_Phe__Xle, UNIMOD_unimod_root_node}, {UNIMOD_Phe__Tyr, UNIMOD_unimod_root_node}, {UNIMOD_Phe__Val, UNIMOD_unimod_root_node}, {UNIMOD_Gly__Ala, UNIMOD_unimod_root_node}, {UNIMOD_Gly__Ser, UNIMOD_unimod_root_node}, {UNIMOD_Gly__Trp, UNIMOD_unimod_root_node}, {UNIMOD_Gly__Glu, UNIMOD_unimod_root_node}, {UNIMOD_Gly__Val, UNIMOD_unimod_root_node}, {UNIMOD_Gly__Asp, UNIMOD_unimod_root_node}, {UNIMOD_Gly__Cys, UNIMOD_unimod_root_node}, {UNIMOD_Gly__Arg, UNIMOD_unimod_root_node}, {UNIMOD_His__Pro, UNIMOD_unimod_root_node}, {UNIMOD_His__Tyr, UNIMOD_unimod_root_node}, {UNIMOD_His__Gln, UNIMOD_unimod_root_node}, {UNIMOD_His__Arg, UNIMOD_unimod_root_node}, {UNIMOD_His__Xle, UNIMOD_unimod_root_node}, {UNIMOD_Xle__Thr, UNIMOD_unimod_root_node}, {UNIMOD_Xle__Asn, UNIMOD_unimod_root_node}, {UNIMOD_Xle__Lys, UNIMOD_unimod_root_node}, {UNIMOD_Lys__Thr, UNIMOD_unimod_root_node}, {UNIMOD_Lys__Asn, UNIMOD_unimod_root_node}, {UNIMOD_Lys__Glu, UNIMOD_unimod_root_node}, {UNIMOD_Lys__Gln, UNIMOD_unimod_root_node}, {UNIMOD_Lys__Met, UNIMOD_unimod_root_node}, {UNIMOD_Lys__Arg, UNIMOD_unimod_root_node}, {UNIMOD_Lys__Xle, UNIMOD_unimod_root_node}, {UNIMOD_Xle__Ser, UNIMOD_unimod_root_node}, {UNIMOD_Xle__Phe, UNIMOD_unimod_root_node}, {UNIMOD_Xle__Trp, UNIMOD_unimod_root_node}, {UNIMOD_Xle__Pro, UNIMOD_unimod_root_node}, {UNIMOD_Xle__Val, UNIMOD_unimod_root_node}, {UNIMOD_Xle__His, UNIMOD_unimod_root_node}, {UNIMOD_Xle__Gln, UNIMOD_unimod_root_node}, {UNIMOD_Xle__Met, UNIMOD_unimod_root_node}, {UNIMOD_Xle__Arg, UNIMOD_unimod_root_node}, {UNIMOD_Met__Thr, UNIMOD_unimod_root_node}, {UNIMOD_Met__Arg, UNIMOD_unimod_root_node}, {UNIMOD_Met__Lys, UNIMOD_unimod_root_node}, {UNIMOD_Met__Xle, UNIMOD_unimod_root_node}, {UNIMOD_Met__Val, UNIMOD_unimod_root_node}, {UNIMOD_Asn__Ser, UNIMOD_unimod_root_node}, {UNIMOD_Asn__Thr, UNIMOD_unimod_root_node}, {UNIMOD_Asn__Lys, UNIMOD_unimod_root_node}, {UNIMOD_Asn__Tyr, UNIMOD_unimod_root_node}, {UNIMOD_Asn__His, UNIMOD_unimod_root_node}, {UNIMOD_Asn__Asp, UNIMOD_unimod_root_node}, {UNIMOD_Asn__Xle, UNIMOD_unimod_root_node}, {UNIMOD_Pro__Ser, UNIMOD_unimod_root_node}, {UNIMOD_Pro__Ala, UNIMOD_unimod_root_node}, {UNIMOD_Pro__His, UNIMOD_unimod_root_node}, {UNIMOD_Pro__Gln, UNIMOD_unimod_root_node}, {UNIMOD_Pro__Thr, UNIMOD_unimod_root_node}, {UNIMOD_Pro__Arg, UNIMOD_unimod_root_node}, {UNIMOD_Pro__Xle, UNIMOD_unimod_root_node}, {UNIMOD_Gln__Pro, UNIMOD_unimod_root_node}, {UNIMOD_Gln__Lys, UNIMOD_unimod_root_node}, {UNIMOD_Gln__Glu, UNIMOD_unimod_root_node}, {UNIMOD_Gln__His, UNIMOD_unimod_root_node}, {UNIMOD_Gln__Arg, UNIMOD_unimod_root_node}, {UNIMOD_Gln__Xle, UNIMOD_unimod_root_node}, {UNIMOD_Arg__Ser, UNIMOD_unimod_root_node}, {UNIMOD_Arg__Trp, UNIMOD_unimod_root_node}, {UNIMOD_Arg__Thr, UNIMOD_unimod_root_node}, {UNIMOD_Arg__Pro, UNIMOD_unimod_root_node}, {UNIMOD_Arg__Lys, UNIMOD_unimod_root_node}, {UNIMOD_Arg__His, UNIMOD_unimod_root_node}, {UNIMOD_Arg__Gln, UNIMOD_unimod_root_node}, {UNIMOD_Arg__Met, UNIMOD_unimod_root_node}, {UNIMOD_Arg__Cys, UNIMOD_unimod_root_node}, {UNIMOD_Arg__Xle, UNIMOD_unimod_root_node}, {UNIMOD_Arg__Gly, UNIMOD_unimod_root_node}, {UNIMOD_Ser__Phe, UNIMOD_unimod_root_node}, {UNIMOD_Ser__Ala, UNIMOD_unimod_root_node}, {UNIMOD_Ser__Trp, UNIMOD_unimod_root_node}, {UNIMOD_Ser__Thr, UNIMOD_unimod_root_node}, {UNIMOD_Ser__Asn, UNIMOD_unimod_root_node}, {UNIMOD_Ser__Pro, UNIMOD_unimod_root_node}, {UNIMOD_Ser__Tyr, UNIMOD_unimod_root_node}, {UNIMOD_Ser__Cys, UNIMOD_unimod_root_node}, {UNIMOD_Ser__Arg, UNIMOD_unimod_root_node}, {UNIMOD_Ser__Xle, UNIMOD_unimod_root_node}, {UNIMOD_Ser__Gly, UNIMOD_unimod_root_node}, {UNIMOD_Thr__Ser, UNIMOD_unimod_root_node}, {UNIMOD_Thr__Ala, UNIMOD_unimod_root_node}, {UNIMOD_Thr__Asn, UNIMOD_unimod_root_node}, {UNIMOD_Thr__Lys, UNIMOD_unimod_root_node}, {UNIMOD_Thr__Pro, UNIMOD_unimod_root_node}, {UNIMOD_Thr__Met, UNIMOD_unimod_root_node}, {UNIMOD_Thr__Xle, UNIMOD_unimod_root_node}, {UNIMOD_Thr__Arg, UNIMOD_unimod_root_node}, {UNIMOD_Val__Phe, UNIMOD_unimod_root_node}, {UNIMOD_Val__Ala, UNIMOD_unimod_root_node}, {UNIMOD_Val__Glu, UNIMOD_unimod_root_node}, {UNIMOD_Val__Met, UNIMOD_unimod_root_node}, {UNIMOD_Val__Asp, UNIMOD_unimod_root_node}, {UNIMOD_Val__Xle, UNIMOD_unimod_root_node}, {UNIMOD_Val__Gly, UNIMOD_unimod_root_node}, {UNIMOD_Trp__Ser, UNIMOD_unimod_root_node}, {UNIMOD_Trp__Cys, UNIMOD_unimod_root_node}, {UNIMOD_Trp__Arg, UNIMOD_unimod_root_node}, {UNIMOD_Trp__Gly, UNIMOD_unimod_root_node}, {UNIMOD_Trp__Xle, UNIMOD_unimod_root_node}, {UNIMOD_Tyr__Phe, UNIMOD_unimod_root_node}, {UNIMOD_Tyr__Ser, UNIMOD_unimod_root_node}, {UNIMOD_Tyr__Asn, UNIMOD_unimod_root_node}, {UNIMOD_Tyr__His, UNIMOD_unimod_root_node}, {UNIMOD_Tyr__Asp, UNIMOD_unimod_root_node}, {UNIMOD_Tyr__Cys, UNIMOD_unimod_root_node}, {UNIMOD_BDMAPP, UNIMOD_unimod_root_node}, {UNIMOD_NA_LNO2, UNIMOD_unimod_root_node}, {UNIMOD_NA_OA_NO2, UNIMOD_unimod_root_node}, {UNIMOD_ICPL_2H_4_, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_6_15N_1_, UNIMOD_unimod_root_node}, {UNIMOD_Label_2H_9_13C_6_15N_2_, UNIMOD_unimod_root_node}, {UNIMOD_NIC, UNIMOD_unimod_root_node}, {UNIMOD_dNIC, UNIMOD_unimod_root_node}, {UNIMOD_HNE_Delta_H_2_O, UNIMOD_unimod_root_node}, {UNIMOD_4_ONE, UNIMOD_unimod_root_node}, {UNIMOD_O_Dimethylphosphate, UNIMOD_unimod_root_node}, {UNIMOD_O_Methylphosphate, UNIMOD_unimod_root_node}, {UNIMOD_Diethylphosphate, UNIMOD_unimod_root_node}, {UNIMOD_Ethylphosphate, UNIMOD_unimod_root_node}, {UNIMOD_O_pinacolylmethylphosphonate, UNIMOD_unimod_root_node}, {UNIMOD_Methylphosphonate, UNIMOD_unimod_root_node}, {UNIMOD_O_Isopropylmethylphosphonate, UNIMOD_unimod_root_node}, {UNIMOD_iTRAQ8plex, UNIMOD_unimod_root_node}, {UNIMOD_iTRAQ8plex_13C_6_15N_2_, UNIMOD_unimod_root_node}, {UNIMOD_Ethanolamine, UNIMOD_unimod_root_node}, {UNIMOD_DTT_ST, UNIMOD_unimod_root_node}, {UNIMOD_DTT_C, UNIMOD_unimod_root_node}, {UNIMOD_TMT6plex, UNIMOD_unimod_root_node}, {UNIMOD_TMT2plex, UNIMOD_unimod_root_node}, {UNIMOD_TMT, UNIMOD_unimod_root_node}, {UNIMOD_ExacTagThiol, UNIMOD_unimod_root_node}, {UNIMOD_ExacTagAmine, UNIMOD_unimod_root_node}, {UNIMOD_4_ONE_Delta_H__2_O__1_, UNIMOD_unimod_root_node}, {UNIMOD_NO_SMX_SEMD, UNIMOD_unimod_root_node}, {UNIMOD_NO_SMX_SMCT, UNIMOD_unimod_root_node}, {UNIMOD_NO_SMX_SIMD, UNIMOD_unimod_root_node}, {UNIMOD_Malonyl, UNIMOD_unimod_root_node}, {UNIMOD_3sulfo, UNIMOD_unimod_root_node}, {UNIMOD_trifluoro, UNIMOD_unimod_root_node}, {UNIMOD_TNBS, UNIMOD_unimod_root_node}, {UNIMOD_IDEnT, UNIMOD_unimod_root_node}, {UNIMOD_DTT_ST_2H_6_, UNIMOD_unimod_root_node}, {UNIMOD_DTT_C_2H_6_, UNIMOD_unimod_root_node}, {UNIMOD_Met_loss, UNIMOD_unimod_root_node}, {UNIMOD_Met_loss_Acetyl, UNIMOD_unimod_root_node}, {UNIMOD_Menadione_HQ, UNIMOD_unimod_root_node}, {UNIMOD_Methyl_Acetyl_2H_3_, UNIMOD_unimod_root_node}, {UNIMOD_lapachenole, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_5_, UNIMOD_unimod_root_node}, {UNIMOD_maleimide, UNIMOD_unimod_root_node}, {UNIMOD_Biotin_phenacyl, UNIMOD_unimod_root_node}, {UNIMOD_Carboxymethyl_13C_2_, UNIMOD_unimod_root_node}, {UNIMOD_NEM_2H_5_, UNIMOD_unimod_root_node}, {UNIMOD_AEC_MAEC_2H_4_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_6__GG, UNIMOD_unimod_root_node}, {UNIMOD_Biotin_Thermo_21345, UNIMOD_unimod_root_node}, {UNIMOD_Pentylamine, UNIMOD_unimod_root_node}, {UNIMOD_Biotin_Thermo_21360, UNIMOD_unimod_root_node}, {UNIMOD_Cy3b_maleimide, UNIMOD_unimod_root_node}, {UNIMOD_Gly_loss_Amide, UNIMOD_unimod_root_node}, {UNIMOD_BMOE, UNIMOD_unimod_root_node}, {UNIMOD_DFDNB, UNIMOD_unimod_root_node}, {UNIMOD_TMPP_Ac, UNIMOD_unimod_root_node}, {UNIMOD_Dihydroxyimidazolidine, UNIMOD_unimod_root_node}, {UNIMOD_Label_2H_4__Acetyl, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_6__Acetyl, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_6_15N_2__Acetyl, UNIMOD_unimod_root_node}, {UNIMOD_Arg__Npo, UNIMOD_unimod_root_node}, {UNIMOD_EQIGG, UNIMOD_unimod_root_node}, {UNIMOD_Arg2PG, UNIMOD_unimod_root_node}, {UNIMOD_cGMP, UNIMOD_unimod_root_node}, {UNIMOD_cGMP_RMP_loss, UNIMOD_unimod_root_node}, {UNIMOD_Label_2H_4__GG, UNIMOD_unimod_root_node}, {UNIMOD_MG_H1, UNIMOD_unimod_root_node}, {UNIMOD_G_H1, UNIMOD_unimod_root_node}, {UNIMOD_ZGB, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_1_2H_3_, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_6_15N_2__GG, UNIMOD_unimod_root_node}, {UNIMOD_ICPL_13C_6_2H_4_, UNIMOD_unimod_root_node}, {UNIMOD_QEQTGG, UNIMOD_unimod_root_node}, {UNIMOD_QQQTGG, UNIMOD_unimod_root_node}, {UNIMOD_Bodipy, UNIMOD_unimod_root_node}, {UNIMOD_Biotin_Thermo_21325, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_1_2H_3__Oxidation, UNIMOD_unimod_root_node}, {UNIMOD_HydroxymethylOP, UNIMOD_unimod_root_node}, {UNIMOD_MDCC, UNIMOD_unimod_root_node}, {UNIMOD_mTRAQ, UNIMOD_unimod_root_node}, {UNIMOD_mTRAQ_13C_3_15N_1_, UNIMOD_unimod_root_node}, {UNIMOD_DyLight_maleimide, UNIMOD_unimod_root_node}, {UNIMOD_Methyl_PEO12_Maleimide, UNIMOD_unimod_root_node}, {UNIMOD_CarbamidomethylDTT, UNIMOD_unimod_root_node}, {UNIMOD_CarboxymethylDTT, UNIMOD_unimod_root_node}, {UNIMOD_Biotin_PEG_PRA, UNIMOD_unimod_root_node}, {UNIMOD_Met__Aha, UNIMOD_unimod_root_node}, {UNIMOD_Label_15N_4_, UNIMOD_unimod_root_node}, {UNIMOD_pyrophospho, UNIMOD_unimod_root_node}, {UNIMOD_Met__Hpg, UNIMOD_unimod_root_node}, {UNIMOD_4AcAllylGal, UNIMOD_unimod_root_node}, {UNIMOD_DimethylArsino, UNIMOD_unimod_root_node}, {UNIMOD_Lys__CamCys, UNIMOD_unimod_root_node}, {UNIMOD_Phe__CamCys, UNIMOD_unimod_root_node}, {UNIMOD_Leu__MetOx, UNIMOD_unimod_root_node}, {UNIMOD_Lys__MetOx, UNIMOD_unimod_root_node}, {UNIMOD_Galactosyl, UNIMOD_unimod_root_node}, {UNIMOD_SMCC_maleimide, UNIMOD_unimod_root_node}, {UNIMOD_Bacillosamine, UNIMOD_unimod_root_node}, {UNIMOD_MTSL, UNIMOD_unimod_root_node}, {UNIMOD_HNE_BAHAH, UNIMOD_unimod_root_node}, {UNIMOD_Methylmalonylation, UNIMOD_unimod_root_node}, {UNIMOD_Ethoxyformyl, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_4_15N_2__GG, UNIMOD_unimod_root_node}, {UNIMOD_ethylamino, UNIMOD_unimod_root_node}, {UNIMOD_MercaptoEthanol, UNIMOD_unimod_root_node}, {UNIMOD_Ethyl_Deamidated, UNIMOD_unimod_root_node}, {UNIMOD_VFQQQTGG, UNIMOD_unimod_root_node}, {UNIMOD_VIEVYQEQTGG, UNIMOD_unimod_root_node}, {UNIMOD_AMTzHexNAc2, UNIMOD_unimod_root_node}, {UNIMOD_Atto495Maleimide, UNIMOD_unimod_root_node}, {UNIMOD_Chlorination, UNIMOD_unimod_root_node}, {UNIMOD_dichlorination, UNIMOD_unimod_root_node}, {UNIMOD_AROD, UNIMOD_unimod_root_node}, {UNIMOD_Cys__methylaminoAla, UNIMOD_unimod_root_node}, {UNIMOD_Cys__ethylaminoAla, UNIMOD_unimod_root_node}, {UNIMOD_DNPS, UNIMOD_unimod_root_node}, {UNIMOD_SulfoGMBS, UNIMOD_unimod_root_node}, {UNIMOD_DimethylamineGMBS, UNIMOD_unimod_root_node}, {UNIMOD_Label_15N_2_2H_9_, UNIMOD_unimod_root_node}, {UNIMOD_LG_anhydrolactam, UNIMOD_unimod_root_node}, {UNIMOD_LG_pyrrole, UNIMOD_unimod_root_node}, {UNIMOD_LG_anhyropyrrole, UNIMOD_unimod_root_node}, {UNIMOD_3_deoxyglucosone, UNIMOD_unimod_root_node}, {UNIMOD_Cation_Li, UNIMOD_unimod_root_node}, {UNIMOD_Cation_Ca_II_, UNIMOD_unimod_root_node}, {UNIMOD_Cation_Fe_II_, UNIMOD_unimod_root_node}, {UNIMOD_Cation_Ni_II_, UNIMOD_unimod_root_node}, {UNIMOD_Cation_Zn_II_, UNIMOD_unimod_root_node}, {UNIMOD_Cation_Ag, UNIMOD_unimod_root_node}, {UNIMOD_Cation_Mg_II_, UNIMOD_unimod_root_node}, {UNIMOD_2_succinyl, UNIMOD_unimod_root_node}, {UNIMOD_Propargylamine, UNIMOD_unimod_root_node}, {UNIMOD_Phosphopropargyl, UNIMOD_unimod_root_node}, {UNIMOD_SUMO2135, UNIMOD_unimod_root_node}, {UNIMOD_SUMO3549, UNIMOD_unimod_root_node}, {UNIMOD_thioacylPA, UNIMOD_unimod_root_node}, {UNIMOD_maleimide3, UNIMOD_unimod_root_node}, {UNIMOD_maleimide5, UNIMOD_unimod_root_node}, {UNIMOD_Puromycin, UNIMOD_unimod_root_node}, {UNIMOD_Chlorpyrifos, UNIMOD_unimod_root_node}, {UNIMOD_Carbofuran, UNIMOD_unimod_root_node}, {UNIMOD_BITC, UNIMOD_unimod_root_node}, {UNIMOD_PEITC, UNIMOD_unimod_root_node}, {UNIMOD_glucosone, UNIMOD_unimod_root_node}, {UNIMOD_cysTMT, UNIMOD_unimod_root_node}, {UNIMOD_cysTMT6plex, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_6__Dimethyl, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_6_15N_2__Dimethyl, UNIMOD_unimod_root_node}, {UNIMOD_Ammonium, UNIMOD_unimod_root_node}, {UNIMOD_ISD_z_2_ion, UNIMOD_unimod_root_node}, {UNIMOD_Biotin_Sigma_B1267, UNIMOD_unimod_root_node}, {UNIMOD_Label_15N_1_, UNIMOD_unimod_root_node}, {UNIMOD_Label_15N_2_, UNIMOD_unimod_root_node}, {UNIMOD_Label_15N_3_, UNIMOD_unimod_root_node}, {UNIMOD_sulfo_amino, UNIMOD_unimod_root_node}, {UNIMOD_BHAc, UNIMOD_unimod_root_node}, {UNIMOD_AHA_Alkyne, UNIMOD_unimod_root_node}, {UNIMOD_AHA_Alkyne_KDDDD, UNIMOD_unimod_root_node}, {UNIMOD_EGCG1, UNIMOD_unimod_root_node}, {UNIMOD_EGCG2, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_6_15N_4__Methyl, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_6_15N_4__Dimethyl, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_6_15N_4__Methyl_2H_3_13C_1_, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_6_15N_4__Dimethyl_2H_6_13C_2_, UNIMOD_unimod_root_node}, {UNIMOD_SecCarbamidomethyl, UNIMOD_unimod_root_node}, {UNIMOD_Thiazolidine, UNIMOD_unimod_root_node}, {UNIMOD_DEDGFLYMVYASQETFG, UNIMOD_unimod_root_node}, {UNIMOD_Biotin_Invitrogen_M1602, UNIMOD_unimod_root_node}, {UNIMOD_glycidamide, UNIMOD_unimod_root_node}, {UNIMOD_Ahx2_Hsl, UNIMOD_unimod_root_node}, {UNIMOD_DMPO, UNIMOD_unimod_root_node}, {UNIMOD_ICDID, UNIMOD_unimod_root_node}, {UNIMOD_ICDID_2H_6_, UNIMOD_unimod_root_node}, {UNIMOD_Xlink_DSS, UNIMOD_unimod_root_node}, {UNIMOD_Xlink_EGS, UNIMOD_unimod_root_node}, {UNIMOD_Xlink_DST, UNIMOD_unimod_root_node}, {UNIMOD_Xlink_DTSSP, UNIMOD_unimod_root_node}, {UNIMOD_Xlink_SMCC, UNIMOD_unimod_root_node}, {UNIMOD_Xlink_DMP_de, UNIMOD_unimod_root_node}, {UNIMOD_Xlink_EGScleaved, UNIMOD_unimod_root_node}, {UNIMOD_Biotin_Thermo_88310, UNIMOD_unimod_root_node}, {UNIMOD_2_nitrobenzyl, UNIMOD_unimod_root_node}, {UNIMOD_SecNEM, UNIMOD_unimod_root_node}, {UNIMOD_SecNEM_2H_5_, UNIMOD_unimod_root_node}, {UNIMOD_Thiadiazole, UNIMOD_unimod_root_node}, {UNIMOD_Withaferin, UNIMOD_unimod_root_node}, {UNIMOD_Biotin_Thermo_88317, UNIMOD_unimod_root_node}, {UNIMOD_TAMRA_FP, UNIMOD_unimod_root_node}, {UNIMOD_Biotin_Thermo_21901_H2O, UNIMOD_unimod_root_node}, {UNIMOD_Deoxyhypusine, UNIMOD_unimod_root_node}, {UNIMOD_Acetyldeoxyhypusine, UNIMOD_unimod_root_node}, {UNIMOD_Acetylhypusine, UNIMOD_unimod_root_node}, {UNIMOD_Ala__Cys, UNIMOD_unimod_root_node}, {UNIMOD_Ala__Phe, UNIMOD_unimod_root_node}, {UNIMOD_Ala__His, UNIMOD_unimod_root_node}, {UNIMOD_Ala__Xle, UNIMOD_unimod_root_node}, {UNIMOD_Ala__Lys, UNIMOD_unimod_root_node}, {UNIMOD_Ala__Met, UNIMOD_unimod_root_node}, {UNIMOD_Ala__Asn, UNIMOD_unimod_root_node}, {UNIMOD_Ala__Gln, UNIMOD_unimod_root_node}, {UNIMOD_Ala__Arg, UNIMOD_unimod_root_node}, {UNIMOD_Ala__Trp, UNIMOD_unimod_root_node}, {UNIMOD_Ala__Tyr, UNIMOD_unimod_root_node}, {UNIMOD_Cys__Ala, UNIMOD_unimod_root_node}, {UNIMOD_Cys__Asp, UNIMOD_unimod_root_node}, {UNIMOD_Cys__Glu, UNIMOD_unimod_root_node}, {UNIMOD_Cys__His, UNIMOD_unimod_root_node}, {UNIMOD_Cys__Xle, UNIMOD_unimod_root_node}, {UNIMOD_Cys__Lys, UNIMOD_unimod_root_node}, {UNIMOD_Cys__Met, UNIMOD_unimod_root_node}, {UNIMOD_Cys__Asn, UNIMOD_unimod_root_node}, {UNIMOD_Cys__Pro, UNIMOD_unimod_root_node}, {UNIMOD_Cys__Gln, UNIMOD_unimod_root_node}, {UNIMOD_Cys__Thr, UNIMOD_unimod_root_node}, {UNIMOD_Cys__Val, UNIMOD_unimod_root_node}, {UNIMOD_Asp__Cys, UNIMOD_unimod_root_node}, {UNIMOD_Asp__Phe, UNIMOD_unimod_root_node}, {UNIMOD_Asp__Xle, UNIMOD_unimod_root_node}, {UNIMOD_Asp__Lys, UNIMOD_unimod_root_node}, {UNIMOD_Asp__Met, UNIMOD_unimod_root_node}, {UNIMOD_Asp__Pro, UNIMOD_unimod_root_node}, {UNIMOD_Asp__Gln, UNIMOD_unimod_root_node}, {UNIMOD_Asp__Arg, UNIMOD_unimod_root_node}, {UNIMOD_Asp__Ser, UNIMOD_unimod_root_node}, {UNIMOD_Asp__Thr, UNIMOD_unimod_root_node}, {UNIMOD_Asp__Trp, UNIMOD_unimod_root_node}, {UNIMOD_Glu__Cys, UNIMOD_unimod_root_node}, {UNIMOD_Glu__Phe, UNIMOD_unimod_root_node}, {UNIMOD_Glu__His, UNIMOD_unimod_root_node}, {UNIMOD_Glu__Xle, UNIMOD_unimod_root_node}, {UNIMOD_Glu__Met, UNIMOD_unimod_root_node}, {UNIMOD_Glu__Asn, UNIMOD_unimod_root_node}, {UNIMOD_Glu__Pro, UNIMOD_unimod_root_node}, {UNIMOD_Glu__Arg, UNIMOD_unimod_root_node}, {UNIMOD_Glu__Ser, UNIMOD_unimod_root_node}, {UNIMOD_Glu__Thr, UNIMOD_unimod_root_node}, {UNIMOD_Glu__Trp, UNIMOD_unimod_root_node}, {UNIMOD_Glu__Tyr, UNIMOD_unimod_root_node}, {UNIMOD_Phe__Ala, UNIMOD_unimod_root_node}, {UNIMOD_Phe__Asp, UNIMOD_unimod_root_node}, {UNIMOD_Phe__Glu, UNIMOD_unimod_root_node}, {UNIMOD_Phe__Gly, UNIMOD_unimod_root_node}, {UNIMOD_Phe__His, UNIMOD_unimod_root_node}, {UNIMOD_Phe__Lys, UNIMOD_unimod_root_node}, {UNIMOD_Phe__Met, UNIMOD_unimod_root_node}, {UNIMOD_Phe__Asn, UNIMOD_unimod_root_node}, {UNIMOD_Phe__Pro, UNIMOD_unimod_root_node}, {UNIMOD_Phe__Gln, UNIMOD_unimod_root_node}, {UNIMOD_Phe__Arg, UNIMOD_unimod_root_node}, {UNIMOD_Phe__Thr, UNIMOD_unimod_root_node}, {UNIMOD_Phe__Trp, UNIMOD_unimod_root_node}, {UNIMOD_Gly__Phe, UNIMOD_unimod_root_node}, {UNIMOD_Gly__His, UNIMOD_unimod_root_node}, {UNIMOD_Gly__Xle, UNIMOD_unimod_root_node}, {UNIMOD_Gly__Lys, UNIMOD_unimod_root_node}, {UNIMOD_Gly__Met, UNIMOD_unimod_root_node}, {UNIMOD_Gly__Asn, UNIMOD_unimod_root_node}, {UNIMOD_Gly__Pro, UNIMOD_unimod_root_node}, {UNIMOD_Gly__Gln, UNIMOD_unimod_root_node}, {UNIMOD_Gly__Thr, UNIMOD_unimod_root_node}, {UNIMOD_Gly__Tyr, UNIMOD_unimod_root_node}, {UNIMOD_His__Ala, UNIMOD_unimod_root_node}, {UNIMOD_His__Cys, UNIMOD_unimod_root_node}, {UNIMOD_His__Glu, UNIMOD_unimod_root_node}, {UNIMOD_His__Phe, UNIMOD_unimod_root_node}, {UNIMOD_His__Gly, UNIMOD_unimod_root_node}, {UNIMOD_His__Lys, UNIMOD_unimod_root_node}, {UNIMOD_His__Met, UNIMOD_unimod_root_node}, {UNIMOD_His__Ser, UNIMOD_unimod_root_node}, {UNIMOD_His__Thr, UNIMOD_unimod_root_node}, {UNIMOD_His__Val, UNIMOD_unimod_root_node}, {UNIMOD_His__Trp, UNIMOD_unimod_root_node}, {UNIMOD_Xle__Ala, UNIMOD_unimod_root_node}, {UNIMOD_Xle__Cys, UNIMOD_unimod_root_node}, {UNIMOD_Xle__Asp, UNIMOD_unimod_root_node}, {UNIMOD_Xle__Glu, UNIMOD_unimod_root_node}, {UNIMOD_Xle__Gly, UNIMOD_unimod_root_node}, {UNIMOD_Xle__Tyr, UNIMOD_unimod_root_node}, {UNIMOD_Lys__Ala, UNIMOD_unimod_root_node}, {UNIMOD_Lys__Cys, UNIMOD_unimod_root_node}, {UNIMOD_Lys__Asp, UNIMOD_unimod_root_node}, {UNIMOD_Lys__Phe, UNIMOD_unimod_root_node}, {UNIMOD_Lys__Gly, UNIMOD_unimod_root_node}, {UNIMOD_Lys__His, UNIMOD_unimod_root_node}, {UNIMOD_Lys__Pro, UNIMOD_unimod_root_node}, {UNIMOD_Lys__Ser, UNIMOD_unimod_root_node}, {UNIMOD_Lys__Val, UNIMOD_unimod_root_node}, {UNIMOD_Lys__Trp, UNIMOD_unimod_root_node}, {UNIMOD_Lys__Tyr, UNIMOD_unimod_root_node}, {UNIMOD_Met__Ala, UNIMOD_unimod_root_node}, {UNIMOD_Met__Cys, UNIMOD_unimod_root_node}, {UNIMOD_Met__Asp, UNIMOD_unimod_root_node}, {UNIMOD_Met__Glu, UNIMOD_unimod_root_node}, {UNIMOD_Met__Phe, UNIMOD_unimod_root_node}, {UNIMOD_Met__Gly, UNIMOD_unimod_root_node}, {UNIMOD_Met__His, UNIMOD_unimod_root_node}, {UNIMOD_Met__Asn, UNIMOD_unimod_root_node}, {UNIMOD_Met__Pro, UNIMOD_unimod_root_node}, {UNIMOD_Met__Gln, UNIMOD_unimod_root_node}, {UNIMOD_Met__Ser, UNIMOD_unimod_root_node}, {UNIMOD_Met__Trp, UNIMOD_unimod_root_node}, {UNIMOD_Met__Tyr, UNIMOD_unimod_root_node}, {UNIMOD_Asn__Ala, UNIMOD_unimod_root_node}, {UNIMOD_Asn__Cys, UNIMOD_unimod_root_node}, {UNIMOD_Asn__Glu, UNIMOD_unimod_root_node}, {UNIMOD_Asn__Phe, UNIMOD_unimod_root_node}, {UNIMOD_Asn__Gly, UNIMOD_unimod_root_node}, {UNIMOD_Asn__Met, UNIMOD_unimod_root_node}, {UNIMOD_Asn__Pro, UNIMOD_unimod_root_node}, {UNIMOD_Asn__Gln, UNIMOD_unimod_root_node}, {UNIMOD_Asn__Arg, UNIMOD_unimod_root_node}, {UNIMOD_Asn__Val, UNIMOD_unimod_root_node}, {UNIMOD_Asn__Trp, UNIMOD_unimod_root_node}, {UNIMOD_Pro__Cys, UNIMOD_unimod_root_node}, {UNIMOD_Pro__Asp, UNIMOD_unimod_root_node}, {UNIMOD_Pro__Glu, UNIMOD_unimod_root_node}, {UNIMOD_Pro__Phe, UNIMOD_unimod_root_node}, {UNIMOD_Pro__Gly, UNIMOD_unimod_root_node}, {UNIMOD_Pro__Lys, UNIMOD_unimod_root_node}, {UNIMOD_Pro__Met, UNIMOD_unimod_root_node}, {UNIMOD_Pro__Asn, UNIMOD_unimod_root_node}, {UNIMOD_Pro__Val, UNIMOD_unimod_root_node}, {UNIMOD_Pro__Trp, UNIMOD_unimod_root_node}, {UNIMOD_Pro__Tyr, UNIMOD_unimod_root_node}, {UNIMOD_Gln__Ala, UNIMOD_unimod_root_node}, {UNIMOD_Gln__Cys, UNIMOD_unimod_root_node}, {UNIMOD_Gln__Asp, UNIMOD_unimod_root_node}, {UNIMOD_Gln__Phe, UNIMOD_unimod_root_node}, {UNIMOD_Gln__Gly, UNIMOD_unimod_root_node}, {UNIMOD_Gln__Met, UNIMOD_unimod_root_node}, {UNIMOD_Gln__Asn, UNIMOD_unimod_root_node}, {UNIMOD_Gln__Ser, UNIMOD_unimod_root_node}, {UNIMOD_Gln__Thr, UNIMOD_unimod_root_node}, {UNIMOD_Gln__Val, UNIMOD_unimod_root_node}, {UNIMOD_Gln__Trp, UNIMOD_unimod_root_node}, {UNIMOD_Gln__Tyr, UNIMOD_unimod_root_node}, {UNIMOD_Arg__Ala, UNIMOD_unimod_root_node}, {UNIMOD_Arg__Asp, UNIMOD_unimod_root_node}, {UNIMOD_Arg__Glu, UNIMOD_unimod_root_node}, {UNIMOD_Arg__Asn, UNIMOD_unimod_root_node}, {UNIMOD_Arg__Val, UNIMOD_unimod_root_node}, {UNIMOD_Arg__Tyr, UNIMOD_unimod_root_node}, {UNIMOD_Arg__Phe, UNIMOD_unimod_root_node}, {UNIMOD_Ser__Asp, UNIMOD_unimod_root_node}, {UNIMOD_Ser__Glu, UNIMOD_unimod_root_node}, {UNIMOD_Ser__His, UNIMOD_unimod_root_node}, {UNIMOD_Ser__Lys, UNIMOD_unimod_root_node}, {UNIMOD_Ser__Met, UNIMOD_unimod_root_node}, {UNIMOD_Ser__Gln, UNIMOD_unimod_root_node}, {UNIMOD_Ser__Val, UNIMOD_unimod_root_node}, {UNIMOD_Thr__Cys, UNIMOD_unimod_root_node}, {UNIMOD_Thr__Asp, UNIMOD_unimod_root_node}, {UNIMOD_Thr__Glu, UNIMOD_unimod_root_node}, {UNIMOD_Thr__Phe, UNIMOD_unimod_root_node}, {UNIMOD_Thr__Gly, UNIMOD_unimod_root_node}, {UNIMOD_Thr__His, UNIMOD_unimod_root_node}, {UNIMOD_Thr__Gln, UNIMOD_unimod_root_node}, {UNIMOD_Thr__Val, UNIMOD_unimod_root_node}, {UNIMOD_Thr__Trp, UNIMOD_unimod_root_node}, {UNIMOD_Thr__Tyr, UNIMOD_unimod_root_node}, {UNIMOD_Val__Cys, UNIMOD_unimod_root_node}, {UNIMOD_Val__His, UNIMOD_unimod_root_node}, {UNIMOD_Val__Lys, UNIMOD_unimod_root_node}, {UNIMOD_Val__Asn, UNIMOD_unimod_root_node}, {UNIMOD_Val__Pro, UNIMOD_unimod_root_node}, {UNIMOD_Val__Gln, UNIMOD_unimod_root_node}, {UNIMOD_Val__Arg, UNIMOD_unimod_root_node}, {UNIMOD_Val__Ser, UNIMOD_unimod_root_node}, {UNIMOD_Val__Thr, UNIMOD_unimod_root_node}, {UNIMOD_Val__Trp, UNIMOD_unimod_root_node}, {UNIMOD_Val__Tyr, UNIMOD_unimod_root_node}, {UNIMOD_Trp__Ala, UNIMOD_unimod_root_node}, {UNIMOD_Trp__Asp, UNIMOD_unimod_root_node}, {UNIMOD_Trp__Glu, UNIMOD_unimod_root_node}, {UNIMOD_Trp__Phe, UNIMOD_unimod_root_node}, {UNIMOD_Trp__His, UNIMOD_unimod_root_node}, {UNIMOD_Trp__Lys, UNIMOD_unimod_root_node}, {UNIMOD_Trp__Met, UNIMOD_unimod_root_node}, {UNIMOD_Trp__Asn, UNIMOD_unimod_root_node}, {UNIMOD_Trp__Pro, UNIMOD_unimod_root_node}, {UNIMOD_Trp__Gln, UNIMOD_unimod_root_node}, {UNIMOD_Trp__Thr, UNIMOD_unimod_root_node}, {UNIMOD_Trp__Val, UNIMOD_unimod_root_node}, {UNIMOD_Trp__Tyr, UNIMOD_unimod_root_node}, {UNIMOD_Tyr__Ala, UNIMOD_unimod_root_node}, {UNIMOD_Tyr__Glu, UNIMOD_unimod_root_node}, {UNIMOD_Tyr__Gly, UNIMOD_unimod_root_node}, {UNIMOD_Tyr__Lys, UNIMOD_unimod_root_node}, {UNIMOD_Tyr__Met, UNIMOD_unimod_root_node}, {UNIMOD_Tyr__Pro, UNIMOD_unimod_root_node}, {UNIMOD_Tyr__Gln, UNIMOD_unimod_root_node}, {UNIMOD_Tyr__Arg, UNIMOD_unimod_root_node}, {UNIMOD_Tyr__Thr, UNIMOD_unimod_root_node}, {UNIMOD_Tyr__Val, UNIMOD_unimod_root_node}, {UNIMOD_Tyr__Trp, UNIMOD_unimod_root_node}, {UNIMOD_Tyr__Xle, UNIMOD_unimod_root_node}, {UNIMOD_AHA_SS, UNIMOD_unimod_root_node}, {UNIMOD_AHA_SS_CAM, UNIMOD_unimod_root_node}, {UNIMOD_Biotin_Thermo_33033, UNIMOD_unimod_root_node}, {UNIMOD_Biotin_Thermo_33033_H, UNIMOD_unimod_root_node}, {UNIMOD_2_monomethylsuccinyl, UNIMOD_unimod_root_node}, {UNIMOD_Saligenin, UNIMOD_unimod_root_node}, {UNIMOD_Cresylphosphate, UNIMOD_unimod_root_node}, {UNIMOD_CresylSaligeninPhosphate, UNIMOD_unimod_root_node}, {UNIMOD_Ub_Br2, UNIMOD_unimod_root_node}, {UNIMOD_Ub_VME, UNIMOD_unimod_root_node}, {UNIMOD_Ub_amide, UNIMOD_unimod_root_node}, {UNIMOD_Ub_fluorescein, UNIMOD_unimod_root_node}, {UNIMOD_2_dimethylsuccinyl, UNIMOD_unimod_root_node}, {UNIMOD_Gly, UNIMOD_unimod_root_node}, {UNIMOD_pupylation, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_4_, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_4__Oxidation, UNIMOD_unimod_root_node}, {UNIMOD_HCysThiolactone, UNIMOD_unimod_root_node}, {UNIMOD_HCysteinyl, UNIMOD_unimod_root_node}, {UNIMOD_UgiJoullie, UNIMOD_unimod_root_node}, {UNIMOD_Dipyridyl, UNIMOD_unimod_root_node}, {UNIMOD_Furan, UNIMOD_unimod_root_node}, {UNIMOD_Difuran, UNIMOD_unimod_root_node}, {UNIMOD_BMP_piperidinol, UNIMOD_unimod_root_node}, {UNIMOD_UgiJoullieProGly, UNIMOD_unimod_root_node}, {UNIMOD_UgiJoullieProGlyProGly, UNIMOD_unimod_root_node}, {UNIMOD_IMEHex_2_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Arg_loss, UNIMOD_unimod_root_node}, {UNIMOD_Arg, UNIMOD_unimod_root_node}, {UNIMOD_Butyryl, UNIMOD_unimod_root_node}, {UNIMOD_Dicarbamidomethyl, UNIMOD_unimod_root_node}, {UNIMOD_Dimethyl_2H_6_, UNIMOD_unimod_root_node}, {UNIMOD_GGQ, UNIMOD_unimod_root_node}, {UNIMOD_QTGG, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_3_, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_3_15N_1_, UNIMOD_unimod_root_node}, {UNIMOD_Label_13C_4_15N_1_, UNIMOD_unimod_root_node}, {UNIMOD_Label_2H_10_, UNIMOD_unimod_root_node}, {UNIMOD_Label_2H_4_13C_1_, UNIMOD_unimod_root_node}, {UNIMOD_Lys, UNIMOD_unimod_root_node}, {UNIMOD_mTRAQ_13C_6_15N_2_, UNIMOD_unimod_root_node}, {UNIMOD_NeuAc, UNIMOD_unimod_root_node}, {UNIMOD_NeuGc, UNIMOD_unimod_root_node}, {UNIMOD_Propyl, UNIMOD_unimod_root_node}, {UNIMOD_Propyl_2H_6_, UNIMOD_unimod_root_node}, {UNIMOD_Propiophenone, UNIMOD_unimod_root_node}, {UNIMOD_Delta_H_6_C_3_O_1_, UNIMOD_unimod_root_node}, {UNIMOD_Delta_H_8_C_6_O_1_, UNIMOD_unimod_root_node}, {UNIMOD_biotinAcrolein298, UNIMOD_unimod_root_node}, {UNIMOD_MM_diphenylpentanone, UNIMOD_unimod_root_node}, {UNIMOD_EHD_diphenylpentanone, UNIMOD_unimod_root_node}, {UNIMOD_Biotin_Thermo_21901_2H2O, UNIMOD_unimod_root_node}, {UNIMOD_DiLeu4plex115, UNIMOD_unimod_root_node}, {UNIMOD_DiLeu4plex, UNIMOD_unimod_root_node}, {UNIMOD_DiLeu4plex117, UNIMOD_unimod_root_node}, {UNIMOD_DiLeu4plex118, UNIMOD_unimod_root_node}, {UNIMOD_NEMsulfur, UNIMOD_unimod_root_node}, {UNIMOD_SulfurDioxide, UNIMOD_unimod_root_node}, {UNIMOD_NEMsulfurWater, UNIMOD_unimod_root_node}, {UNIMOD_bisANS_sulfonates, UNIMOD_unimod_root_node}, {UNIMOD_DNCB_hapten, UNIMOD_unimod_root_node}, {UNIMOD_Biotin_Thermo_21911, UNIMOD_unimod_root_node}, {UNIMOD_iodoTMT, UNIMOD_unimod_root_node}, {UNIMOD_iodoTMT6plex, UNIMOD_unimod_root_node}, {UNIMOD_Gluconoylation, UNIMOD_unimod_root_node}, {UNIMOD_Phosphogluconoylation, UNIMOD_unimod_root_node}, {UNIMOD_PS_Hapten, UNIMOD_unimod_root_node}, {UNIMOD_Cy3_maleimide, UNIMOD_unimod_root_node}, {UNIMOD_benzylguanidine, UNIMOD_unimod_root_node}, {UNIMOD_CarboxymethylDMAP, UNIMOD_unimod_root_node}, {UNIMOD_azole, UNIMOD_unimod_root_node}, {UNIMOD_phosphoRibosyl, UNIMOD_unimod_root_node}, {UNIMOD_NEM_2H_5__H2O, UNIMOD_unimod_root_node}, {UNIMOD_Crotonyl, UNIMOD_unimod_root_node}, {UNIMOD_O_Et_N_diMePhospho, UNIMOD_unimod_root_node}, {UNIMOD_N_dimethylphosphate, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_1_, UNIMOD_unimod_root_node}, {UNIMOD_Methyl_2H_3__Acetyl_2H_3_, UNIMOD_unimod_root_node}, {UNIMOD_Label_2H_3__Oxidation, UNIMOD_unimod_root_node}, {UNIMOD_Trimethyl_2H_9_, UNIMOD_unimod_root_node}, {UNIMOD_Acetyl_13C_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_4_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_5_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_6_, UNIMOD_unimod_root_node}, {UNIMOD_methylsulfonylethyl, UNIMOD_unimod_root_node}, {UNIMOD_ethylsulfonylethyl, UNIMOD_unimod_root_node}, {UNIMOD_phenylsulfonylethyl, UNIMOD_unimod_root_node}, {UNIMOD_PyridoxalPhosphateH2, UNIMOD_unimod_root_node}, {UNIMOD_Homocysteic_acid, UNIMOD_unimod_root_node}, {UNIMOD_Hydroxamic_acid, UNIMOD_unimod_root_node}, {UNIMOD_3_phosphoglyceryl, UNIMOD_unimod_root_node}, {UNIMOD_HN2_mustard, UNIMOD_unimod_root_node}, {UNIMOD_HN3_mustard, UNIMOD_unimod_root_node}, {UNIMOD_Oxidation_NEM, UNIMOD_unimod_root_node}, {UNIMOD_NHS_fluorescein, UNIMOD_unimod_root_node}, {UNIMOD_DiART6plex, UNIMOD_unimod_root_node}, {UNIMOD_DiART6plex115, UNIMOD_unimod_root_node}, {UNIMOD_DiART6plex116_119, UNIMOD_unimod_root_node}, {UNIMOD_DiART6plex117, UNIMOD_unimod_root_node}, {UNIMOD_DiART6plex118, UNIMOD_unimod_root_node}, {UNIMOD_Iodoacetanilide, UNIMOD_unimod_root_node}, {UNIMOD_Iodoacetanilide_13C_6_, UNIMOD_unimod_root_node}, {UNIMOD_Dap_DSP, UNIMOD_unimod_root_node}, {UNIMOD_MurNAc, UNIMOD_unimod_root_node}, {UNIMOD_Label_2H_7_15N_4_, UNIMOD_unimod_root_node}, {UNIMOD_Label_2H_6_15N_1_, UNIMOD_unimod_root_node}, {UNIMOD_EEEDVIEVYQEQTGG, UNIMOD_unimod_root_node}, {UNIMOD_EDEDTIDVFQQQTGG, UNIMOD_unimod_root_node}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_NeuAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_s_GlcNAc, UNIMOD_unimod_root_node}, {UNIMOD_PhosphoHex_2_, UNIMOD_unimod_root_node}, {UNIMOD_Trimethyl_13C_3_2H_9_, UNIMOD_unimod_root_node}, {UNIMOD_15N_oxobutanoic, UNIMOD_unimod_root_node}, {UNIMOD_spermine, UNIMOD_unimod_root_node}, {UNIMOD_spermidine, UNIMOD_unimod_root_node}, {UNIMOD_Biotin_Thermo_21330, UNIMOD_unimod_root_node}, {UNIMOD_Pentose, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexA_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_Pent_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_1_Phos_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_HexNAc_1_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_HexNAc_1_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexA_1_HexNAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_1_Me_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_Phos_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_NeuAc_1_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexA_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_2_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_2_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_4_HexNAc_1_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_2_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_2_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_3_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_5_HexNAc_2_Phos_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_7_HexNAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_2_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_5_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_4_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_6_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_3_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_5_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_4_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_6_HexNAc_2_Phos_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_5_HexNAc_2_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_8_HexNAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_6_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_4_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_7_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_5_HexNAc_3_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_3_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_5_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_6_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_4_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_4_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_7_HexNAc_2_Phos_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_4_Me_2_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_Pent_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_6_HexNAc_3_Phos_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_5_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_7_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_7_HexNAc_2_Phos_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_5_HexNAc_4_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_8_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_6_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_3_Hex_3_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_5_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_7_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_5_HexNAc_4_Me_2_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_6_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_6_HexNAc_3_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_4_HexNAc_5_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_5_HexA_1_HexNAc_3_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_7_HexNAc_3_Phos_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_6_HexNAc_4_Me_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_5_HexNAc_3_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_Pent_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_6_Sulf_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_9_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_6_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_3_Hex_3_HexNAc_4_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_4_HexNAc_5_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_5_HexA_1_HexNAc_3_Sulf_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_7_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_5_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_NeuAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Sulf_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Me_2_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_5_HexNAc_4_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_6_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_7_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuGc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_5_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_6_HexNAc_4_Me_3_Pent_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_Phos_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_5_HexNAc_5_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_7_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_6_HexNAc_5_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_6_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_3_HexNAc_6_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_HexNAc_3_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_1_Kdn_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_HexNAc_2_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_HexNAc_1_Kdn_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_1_Me_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexA_1_Pent_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_HexNAc_2_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_Phos_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexA_1_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_Kdn_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_HexNAc_2_NeuAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_3_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexA_1_HexNAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_2_HexA_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_2_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_5_, UNIMOD_unimod_root_node}, {UNIMOD_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_HexNAc_1_NeuGc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_2_HexNAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_3_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_2_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_5_Phos_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_1_HexNAc_1_Kdn_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_4_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_HexNAc_2_Kdn_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Kdn_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexA_1_NeuAc_1_Pent_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_3_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_5_HexNAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_HexNAc_5_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_2_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_5_Phos_3_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_6_Phos_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_3_HexNAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_1_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_3_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_1_HexA_1_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_Kdn_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_1_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_4_HexNAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_HexNAc_5_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_3_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_6_Phos_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_3_Hex_1_HexNAc_2_Kdn_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Kdn_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_2_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_3_HexNAc_3_Kdn_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_HexNAc_5_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_5_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_7_Phos_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexA_2_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_4_Hex_1_HexNAc_2_Kdn_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_Kdn_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_3_Hex_2_HexA_1_HexNAc_2_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_4_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_2_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_2_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_4_HexNAc_3_Kdn_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_4_Hex_1_HexNAc_1_Kdn_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_3_Hex_1_HexNAc_3_Kdn_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_2_NeuAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_3_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_4_Hex_2_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_8_Phos_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_4_Hex_2_HexNAc_2_Kdn_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_3_Hex_2_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_4_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_4_Hex_1_HexNAc_3_Kdn_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_4_Sulf_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_Kdn_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_2_HexNAc_5_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_3_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_3_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_4_Hex_3_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuGc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_9_Phos_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_HexNAc_7_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_4_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_3_HexNAc_5_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_4_HexA_1_HexNAc_3_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_NeuAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_3_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_10_Phos_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_5_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_4_NeuGc_1_Sulf_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Sulf_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_4_HexNAc_2_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_5_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_3_HexNAc_6_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_6_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_5_HexNAc_5_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_NeuAc_1_, UNIMOD_unimod_root_node}, {UNIMOD_dHex_2_Hex_4_HexNAc_5_, UNIMOD_unimod_root_node}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Ac_1_, UNIMOD_unimod_root_node}, {UO_length_unit, UO_unit}, {UO_mass_unit, UO_unit}, {UO_time_unit, UO_unit}, {UO_electric_current_unit, UO_unit}, {UO_temperature_unit, UO_unit}, {UO_substance_unit, UO_unit}, {UO_luminous_intensity_unit, UO_light_unit}, {UO_meter, UO_length_unit}, {UO_meter, UO_base_unit}, {UO_kilogram, UO_mass_unit}, {UO_kilogram, UO_base_unit}, {UO_second, UO_time_unit}, {UO_second, UO_base_unit}, {UO_ampere, UO_electric_current_unit}, {UO_ampere, UO_base_unit}, {UO_kelvin, UO_temperature_unit}, {UO_kelvin, UO_base_unit}, {UO_mole, UO_substance_unit}, {UO_mole, UO_base_unit}, {UO_candela, UO_luminous_intensity_unit}, {UO_candela, UO_base_unit}, {UO_centimeter, UO_length_unit}, {UO_millimeter, UO_length_unit}, {UO_micrometer, UO_length_unit}, {UO_nanometer, UO_length_unit}, {UO_angstrom, UO_length_unit}, {UO_picometer, UO_length_unit}, {UO_gram, UO_mass_unit}, {UO_milligram, UO_mass_unit}, {UO_microgram, UO_mass_unit}, {UO_nanogram, UO_mass_unit}, {UO_picogram, UO_mass_unit}, {UO_femtogram, UO_mass_unit}, {UO_degree_celsius, UO_temperature_unit}, {UO_millisecond, UO_time_unit}, {UO_microsecond, UO_time_unit}, {UO_picosecond, UO_time_unit}, {UO_minute, UO_time_unit}, {UO_hour, UO_time_unit}, {UO_day, UO_time_unit}, {UO_week, UO_time_unit}, {UO_month, UO_time_unit}, {UO_year, UO_time_unit}, {UO_milliampere, UO_electric_current_unit}, {UO_microampere, UO_electric_current_unit}, {UO_micromole, UO_substance_unit}, {UO_millimole, UO_substance_unit}, {UO_nanomole, UO_substance_unit}, {UO_picomole, UO_substance_unit}, {UO_femtomole, UO_substance_unit}, {UO_attomole, UO_substance_unit}, {UO_base_unit, UO_unit}, {UO_area_unit, UO_unit}, {UO_acceleration_unit, UO_unit}, {UO_angular_velocity_unit, UO_unit}, {UO_angular_acceleration_unit, UO_unit}, {UO_concentration_unit, UO_unit}, {UO_mass_density_unit, UO_density_unit}, {UO_luminance_unit, UO_light_unit}, {UO_area_density_unit, UO_density_unit}, {UO_molar_mass_unit, UO_mass_unit}, {UO_molar_volume_unit, UO_volume_unit}, {UO_momentum_unit, UO_unit}, {UO_rotational_frequency_unit, UO_frequency_unit}, {UO_specific_volume_unit, UO_volume_unit}, {UO_speed_velocity_unit, UO_unit}, {UO_unit_of_molarity, UO_concentration_unit}, {UO_molar, UO_unit_of_molarity}, {UO_millimolar, UO_unit_of_molarity}, {UO_micromolar, UO_unit_of_molarity}, {UO_nanomolar, UO_unit_of_molarity}, {UO_picomolar, UO_unit_of_molarity}, {UO_unit_of_molality, UO_concentration_unit}, {UO_molal, UO_unit_of_molality}, {UO_millimolal, UO_unit_of_molality}, {UO_micromolal, UO_unit_of_molality}, {UO_nanomolal, UO_unit_of_molality}, {UO_picomolal, UO_unit_of_molality}, {UO_femtomolar, UO_unit_of_molarity}, {UO_unit_of_normality, UO_concentration_unit}, {UO_normal, UO_unit_of_normality}, {UO_mole_fraction, UO_concentration_unit}, {UO_mole_fraction, UO_fraction}, {UO_meter_per_second_per_second, UO_acceleration_unit}, {UO_radian_per_second_per_second, UO_angular_acceleration_unit}, {UO_radian_per_second, UO_angular_velocity_unit}, {UO_square_meter, UO_area_unit}, {UO_square_centimeter, UO_area_unit}, {UO_square_millimeter, UO_area_unit}, {UO_kilogram_per_cubic_meter, UO_mass_density_unit}, {UO_gram_per_cubic_centimeter, UO_mass_density_unit}, {UO_candela_per_square_meter, UO_luminance_unit}, {UO_kilogram_per_square_meter, UO_area_density_unit}, {UO_kilogram_per_mole, UO_molar_mass_unit}, {UO_gram_per_mole, UO_molar_mass_unit}, {UO_cubic_meter_per_mole, UO_molar_volume_unit}, {UO_cubic_centimeter_per_mole, UO_molar_volume_unit}, {UO_kilogram_meter_per_second, UO_momentum_unit}, {UO_turns_per_second, UO_rotational_frequency_unit}, {UO_cubic_meter_per_kilogram, UO_specific_volume_unit}, {UO_meter_per_second, UO_speed_velocity_unit}, {UO_volume_unit, UO_unit}, {UO_cubic_meter, UO_volume_unit}, {UO_cubic_centimeter, UO_volume_unit}, {UO_milliliter, UO_volume_unit}, {UO_liter, UO_volume_unit}, {UO_cubic_decimeter, UO_volume_unit}, {UO_microliter, UO_volume_unit}, {UO_nanoliter, UO_volume_unit}, {UO_picoliter, UO_volume_unit}, {UO_femtoliter, UO_volume_unit}, {UO_frequency_unit, UO_unit}, {UO_hertz, UO_frequency_unit}, {UO_force_unit, UO_unit}, {UO_newton, UO_force_unit}, {UO_pressure_unit, UO_unit}, {UO_pascal, UO_pressure_unit}, {UO_energy_unit, UO_unit}, {UO_joule, UO_energy_unit}, {UO_power_unit, UO_unit}, {UO_watt, UO_power_unit}, {UO_illuminance_unit, UO_light_unit}, {UO_lux, UO_illuminance_unit}, {UO_luminous_flux_unit, UO_light_unit}, {UO_lumen, UO_luminous_flux_unit}, {UO_catalytic_activity_unit, UO_unit}, {UO_katal, UO_catalytic_activity_unit}, {UO_angle_unit, UO_unit}, {UO_plane_angle_unit, UO_angle_unit}, {UO_radian, UO_plane_angle_unit}, {UO_solid_angle_unit, UO_angle_unit}, {UO_steradian, UO_solid_angle_unit}, {UO_radiation_unit, UO_unit}, {UO_activity__of_a_radionuclide__unit, UO_radiation_unit}, {UO_absorbed_dose_unit, UO_radiation_unit}, {UO_dose_equivalent_unit, UO_radiation_unit}, {UO_exposure_unit, UO_radiation_unit}, {UO_becquerel, UO_activity__of_a_radionuclide__unit}, {UO_curie, UO_activity__of_a_radionuclide__unit}, {UO_gray, UO_absorbed_dose_unit}, {UO_rad, UO_absorbed_dose_unit}, {UO_roentgen, UO_exposure_unit}, {UO_sievert, UO_dose_equivalent_unit}, {UO_millisievert, UO_dose_equivalent_unit}, {UO_microsievert, UO_dose_equivalent_unit}, {UO_Roentgen_equivalent_man, UO_dose_equivalent_unit}, {UO_microgray, UO_absorbed_dose_unit}, {UO_milligray, UO_absorbed_dose_unit}, {UO_nanogray, UO_absorbed_dose_unit}, {UO_nanosievert, UO_dose_equivalent_unit}, {UO_millicurie, UO_activity__of_a_radionuclide__unit}, {UO_microcurie, UO_activity__of_a_radionuclide__unit}, {UO_disintegrations_per_minute, UO_activity__of_a_radionuclide__unit}, {UO_counts_per_minute, UO_activity__of_a_radionuclide__unit}, {UO_nanosecond, UO_time_unit}, {UO_century, UO_time_unit}, {UO_half_life, UO_time_unit}, {UO_foot_candle, UO_illuminance_unit}, {UO_irradiance_unit, UO_light_unit}, {UO_watt_per_square_meter, UO_irradiance_unit}, {UO_einstein_per_square_meter_per_second, UO_irradiance_unit}, {UO_light_unit, UO_unit}, {UO_watt_per_steradian_per_square_meter, UO_radiance_unit}, {UO_radiant_intensity_unit, UO_light_unit}, {UO_microeinstein_per_square_meter_per_second, UO_irradiance_unit}, {UO_radiance_unit, UO_light_unit}, {UO_watt_per_steradian, UO_radiant_intensity_unit}, {UO_mass_percentage, UO_concentration_unit}, {UO_mass_percentage, UO_percent}, {UO_mass_volume_percentage, UO_concentration_unit}, {UO_mass_volume_percentage, UO_percent}, {UO_volume_percentage, UO_percent}, {UO_volume_percentage, UO_volume_per_unit_volume}, {UO_parts_per_notation_unit, UO_dimensionless_unit}, {UO_parts_per_hundred, UO_parts_per_notation_unit}, {UO_parts_per_thousand, UO_parts_per_notation_unit}, {UO_parts_per_million, UO_parts_per_notation_unit}, {UO_parts_per_billion, UO_parts_per_notation_unit}, {UO_parts_per_trillion, UO_parts_per_notation_unit}, {UO_parts_per_quadrillion, UO_parts_per_notation_unit}, {UO_gram_per_milliliter, UO_mass_density_unit}, {UO_kilogram_per_liter, UO_mass_density_unit}, {UO_gram_per_liter, UO_mass_density_unit}, {UO_milligram_per_milliliter, UO_mass_density_unit}, {UO_unit_per_volume_unit, UO_concentration_unit}, {UO_unit_per_milliliter, UO_unit_per_volume_unit}, {UO_unit_per_liter, UO_unit_per_volume_unit}, {UO_mass_per_unit_volume, UO_concentration_unit}, {UO_enzyme_unit, UO_catalytic_activity_unit}, {UO_density_unit, UO_unit}, {UO_linear_density_unit, UO_density_unit}, {UO_kilogram_per_meter, UO_linear_density_unit}, {UO_degree, UO_plane_angle_unit}, {UO_dimensionless_unit, UO_unit}, {UO_percent, UO_ratio}, {UO_pi, UO_dimensionless_unit}, {UO_count_unit, UO_dimensionless_unit}, {UO_ratio, UO_dimensionless_unit}, {UO_fraction, UO_ratio}, {UO_molecule_count, UO_count_unit}, {UO_purity_percentage, UO_percent}, {UO_confluence_percentage, UO_percent}, {UO_degree_fahrenheit, UO_temperature_unit}, {UO_pH, UO_concentration_unit}, {UO_pH, UO_dimensionless_unit}, {UO_liter_per_kilogram, UO_specific_volume_unit}, {UO_milliliter_per_kilogram, UO_specific_volume_unit}, {UO_microliter_per_kilogram, UO_specific_volume_unit}, {UO_cell_concentration_unit, UO_concentration_unit}, {UO_cells_per_milliliter, UO_cell_concentration_unit}, {UO_catalytic__activity__concentration_unit, UO_concentration_unit}, {UO_katal_per_cubic_meter, UO_catalytic__activity__concentration_unit}, {UO_katal_per_liter, UO_catalytic__activity__concentration_unit}, {UO_volume_per_unit_volume, UO_concentration_unit}, {UO_milliliter_per_cubic_meter, UO_volume_per_unit_volume}, {UO_milliliter_per_liter, UO_volume_per_unit_volume}, {UO_gram_per_deciliter, UO_mass_density_unit}, {UO_deciliter, UO_volume_unit}, {UO_colony_forming_unit, UO_count_unit}, {UO_plaque_forming_unit, UO_count_unit}, {UO_colony_forming_unit_per_volume, UO_concentration_unit}, {UO_colony_forming_unit_per_milliliter, UO_colony_forming_unit_per_volume}, {UO_plaque_forming_unit_per_volume, UO_concentration_unit}, {UO_plaque_forming_unit_per_milliliter, UO_plaque_forming_unit_per_volume}, {UO_disintegrations_per_second, UO_activity__of_a_radionuclide__unit}, {UO_electric_potential_difference_unit, UO_unit}, {UO_volt, UO_electric_potential_difference_unit}, {UO_electric_charge, UO_unit}, {UO_coulomb, UO_electric_charge}, {UO_dalton, UO_mass_unit}, {UO_kilodalton, UO_mass_unit}, {UO_watt_hour, UO_energy_unit}, {UO_kilowatt_hour, UO_energy_unit}, {UO_magnetic_flux_unit, UO_unit}, {UO_weber, UO_magnetic_flux_unit}, {UO_magnetic_flux_density_unit, UO_unit}, {UO_tesla, UO_magnetic_flux_density_unit}, {UO_volt_hour, UO_magnetic_flux_unit}, {UO_kilovolt_hour, UO_magnetic_flux_unit}, {UO_information_unit, UO_unit}, {UO_bit, UO_information_unit}, {UO_byte, UO_information_unit}, {UO_kilobyte, UO_information_unit}, {UO_megabyte, UO_information_unit}, {UO_image_resolution_unit, UO_information_unit}, {UO_chroma_sampling_unit, UO_image_resolution_unit}, {UO_dynamic_range_unit, UO_image_resolution_unit}, {UO_spatial_resolution_unit, UO_image_resolution_unit}, {UO_dots_per_inch, UO_spatial_resolution_unit}, {UO_micron_pixel, UO_spatial_resolution_unit}, {UO_pixels_per_inch, UO_spatial_resolution_unit}, {UO_pixels_per_millimeter, UO_spatial_resolution_unit}, {UO_base_pair, UO_count_unit}, {UO_kibibyte, UO_information_unit}, {UO_mebibyte, UO_information_unit}, {UO_millivolt, UO_electric_potential_difference_unit}, {UO_kilovolt, UO_electric_potential_difference_unit}, {UO_microvolt, UO_electric_potential_difference_unit}, {UO_nanovolt, UO_electric_potential_difference_unit}, {UO_picovolt, UO_electric_potential_difference_unit}, {UO_megavolt, UO_electric_potential_difference_unit}, {UO_surface_tension_unit, UO_unit}, {UO_newton_per_meter, UO_surface_tension_unit}, {UO_dyne_per_cm, UO_surface_tension_unit}, {UO_viscosity_unit, UO_unit}, {UO_pascal_second, UO_viscosity_unit}, {UO_poise, UO_viscosity_unit}, {UO_decibel, UO_ratio}, {UO_effective_dose_unit, UO_radiation_unit}, {UO_conduction_unit, UO_unit}, {UO_electrical_conduction_unit, UO_conduction_unit}, {UO_heat_conduction_unit, UO_conduction_unit}, {UO_siemens, UO_electrical_conduction_unit}, {UO_watt_per_meter_kelvin, UO_heat_conduction_unit}, {UO_electronvolt, UO_energy_unit}, {UO_electric_field_strength_unit, UO_unit}, {UO_volt_per_meter, UO_electric_field_strength_unit}, {UO_absorbance_unit, UO_dimensionless_unit}, {UO_volumetric_flow_rate_unit, UO_unit}, {UO_microliters_per_minute, UO_volumetric_flow_rate_unit}, {UO_millimetres_of_mercury, UO_pressure_unit}, {UO_milligram_per_liter, UO_mass_density_unit}, {UO_microgram_per_milliliter, UO_mass_density_unit}, {UO_nanogram_per_milliliter, UO_mass_density_unit}, {UO_amount_per_container, UO_concentration_unit}, {UO_ug_disk, UO_amount_per_container}, {UO_nmole_disk, UO_amount_per_container}, {UO_milliunits_per_milliliter, UO_unit_per_volume_unit}, {UO_rate_unit, UO_unit}, {UO_count_per_nanomolar_second, UO_rate_unit}, {UO_count_per_molar_second, UO_rate_unit}, {UO_kilogram_per_hectare, UO_area_density_unit}, {UO_count_per_nanomolar, UO_rate_unit}, {UO_count_per_molar, UO_rate_unit}, {UO_microgram_per_liter, UO_mass_density_unit}, }; // relationsIsA_ const size_t relationsIsASize_ = sizeof(relationsIsA_)/sizeof(CVIDPair); CVIDPair relationsPartOf_[] = { {MS_inlet_type, MS_source}, {MS_ionization_type, MS_source}, {MS_scan_direction, MS_scan}, {MS_scan_law, MS_scan}, {MS_detector_type, MS_detector}, {MS_detector_acquisition_mode, MS_detector}, {MS_instrument_model, MS_instrument}, {MS_peak_intensity, MS_peak}, {MS_dissociation_method, MS_precursor_activation}, {MS_peak, MS_spectrum}, {MS_scan, MS_spectrum_generation_information}, {MS_spectrum, MS_spectrum_generation_information}, {MS_mass_analyzer_type, MS_mass_analyzer}, {MS_mass_analyzer, MS_instrument}, {MS_data_transformation, MS_spectrum_generation_information}, {MS_detector, MS_instrument}, {MS_ion_selection_attribute, MS_spectrum}, {MS_precursor_activation, MS_spectrum}, {MS_sample, MS_spectrum_generation_information}, {MS_source, MS_instrument}, {MS_unit_OBSOLETE, MS_spectrum_generation_information}, {MS_ion_optics, MS_instrument}, {MS_instrument, MS_spectrum_generation_information}, {MS_scan_polarity, MS_scan}, {MS_mass_analyzer_attribute, MS_mass_analyzer}, {MS_detector_attribute, MS_detector}, {MS_source_attribute, MS_source}, {MS_instrument_attribute, MS_instrument}, {MS_spectrum_attribute, MS_spectrum}, {MS_scan_attribute, MS_scan}, {MS_precursor_activation_attribute, MS_precursor_activation}, {MS_binary_data_array, MS_spectrum}, {MS_binary_data_array, MS_chromatogram}, {MS_binary_data_type, MS_spectrum}, {MS_binary_data_type, MS_chromatogram}, {MS_data_file_content, MS_raw_data_file}, {MS_spectrum_representation, MS_spectrum}, {MS_software, MS_Proteomics_Standards_Initiative_Mass_Spectrometry_Vocabularies}, {MS_object_attribute, MS_spectrum_generation_information}, {MS_sample_attribute, MS_sample}, {MS_selection_window_attribute, MS_scan}, {MS_spectrum_type, MS_spectrum}, {MS_data_file_checksum_type, MS_raw_data_file}, {MS_spectra_combination, MS_spectrum}, {MS_binary_data_compression_type, MS_spectrum}, {MS_binary_data_compression_type, MS_chromatogram}, {MS_raw_data_file, MS_spectrum_generation_information}, {MS_contact_attribute, MS_Proteomics_Standards_Initiative_Mass_Spectrometry_Vocabularies}, {MS_measurement_method, MS_spectrum_generation_information}, {MS_chromatogram, MS_spectrum_generation_information}, {MS_chromatogram_type, MS_chromatogram}, {MS_data_processing_parameter, MS_spectrum_generation_information}, {MS_native_spectrum_identifier_format, MS_raw_data_file}, {MS_isolation_window_attribute, MS_scan}, {MS_chromatogram_attribute, MS_chromatogram}, {MS_sample_preparation, MS_sample_attribute}, {MS_MALDI_matrix_application, MS_sample_preparation}, {MS_matrix_application_type, MS_MALDI_matrix_application}, {MS_laser, MS_source_attribute}, {MS_laser_attribute, MS_laser}, {MS_laser_type, MS_laser}, {MS_molecule, MS_chemical_compound}, {MS_chemical_compound_attribute, MS_chemical_compound}, {MS_chemical_compound_formula, MS_chemical_compound}, {MS_external_reference_identifier, MS_Proteomics_Standards_Initiative_Mass_Spectrometry_Vocabularies}, {MS_chemical_compound, MS_Proteomics_Standards_Initiative_Mass_Spectrometry_Vocabularies}, {MS_protein_attribute, MS_protein}, {MS_peptide_attribute, MS_peptide}, {MS_standard, MS_Proteomics_Standards_Initiative_Mass_Spectrometry_Vocabularies}, {MS_peak_intensity_rank, MS_peak}, {MS_peak_targeting_suitability_rank, MS_peak}, {MS_transition, MS_spectrum_generation_information}, {MS_transition_validation_method, MS_transition}, {MS_retention_time_window_attribute, MS_retention_time}, {MS_target_list, MS_spectrum_generation_information}, {MS_target_inclusion_exclusion_priority, MS_target_list}, {MS_spectrum_interpretation, MS_Proteomics_Standards_Initiative_Mass_Spectrometry_Vocabularies}, {MS_modification_parameters, MS_spectrum_interpretation}, {MS_quantification_information, MS_spectrum_interpretation}, {MS_Cleavage_agent_regular_expression, MS_cleavage_agent_details}, {MS_search_input_details, MS_spectrum_interpretation}, {MS_mass_table_options, MS_spectrum_interpretation}, {MS_ambiguous_residues, MS_spectrum_interpretation}, {MS_spectrum_identification_result_details, MS_spectrum_interpretation}, {MS_spectrum_generation_information, MS_Proteomics_Standards_Initiative_Mass_Spectrometry_Vocabularies}, {MS_file_format, MS_Proteomics_Standards_Initiative_Mass_Spectrometry_Vocabularies}, {MS_peptide_modification_details, MS_spectrum_interpretation}, {MS_quantification_data_processing, MS_spectrum_interpretation}, {MS_transition_validation_attribute, MS_transition}, {MS_source_interface, MS_source}, {MS_source_interface_model, MS_source_interface}, {MS_source_sprayer, MS_source}, {MS_source_sprayer_type, MS_source_sprayer}, {MS_source_sprayer_manufacturer, MS_source_sprayer}, {MS_source_sprayer_model, MS_source_sprayer}, {MS_sample_plate, MS_source}, {MS_sample_plate_type, MS_sample_plate}, {MS_electrospray_supply_type, MS_source}, {MS_source_interface_manufacturer, MS_source_interface}, {MS_acquisition_parameter, MS_spectrum_generation_information}, {MS_peptide_spectrum_match_scoring_algorithm, MS_spectrum_generation_information}, {MS_SRM_transition_type, MS_transition}, {MS_inlet_attribute, MS_source}, {MS_higher_score_better, MS_search_engine_specific_score}, {MS_lower_score_better, MS_search_engine_specific_score}, {MS_SRM_transition_attribute, MS_transition}, {MS_Trans_Proteomic_Pipeline_software, MS_Trans_Proteomic_Pipeline}, {MS_domain_range, MS_Proteomics_Standards_Initiative_Mass_Spectrometry_Vocabularies}, {MS_spectrum_identification_list_result_details, MS_spectrum_interpretation}, {MS_regular_expression, MS_Proteomics_Standards_Initiative_Mass_Spectrometry_Vocabularies}, {MS_special_processing, MS_spectrum_interpretation}, }; // relationsPartOf_ const size_t relationsPartOfSize_ = sizeof(relationsPartOf_)/sizeof(CVIDPair); struct OtherRelationPair { CVID subject; const char* relation; CVID object; }; OtherRelationPair relationsOther_[] = { {CVID_Unknown, "Unknown", CVID_Unknown}, {MS_sample_mass, "has_units", UO_gram}, {MS_sample_volume, "has_units", UO_milliliter}, {MS_sample_concentration, "has_units", UO_gram_per_liter}, {MS_accuracy, "has_units", MS_m_z}, {MS_accuracy, "has_units", UO_parts_per_million}, {MS_scan_rate, "has_units", MS_Th_s}, {MS_scan_start_time, "has_units", UO_second}, {MS_scan_start_time, "has_units", UO_minute}, {MS_TOF_Total_Path_Length, "has_units", UO_meter}, {MS_isolation_width_OBSOLETE, "has_units", MS_m_z}, {MS_magnetic_field_strength, "has_units", UO_tesla}, {MS_sampling_frequency, "has_units", UO_hertz}, {MS_peak_intensity, "has_units", MS_number_of_detector_counts}, {MS_peak_intensity, "has_units", MS_percent_of_base_peak}, {MS_peak_intensity, "has_units", MS_counts_per_second}, {MS_peak_intensity, "has_units", MS_percent_of_base_peak_times_100}, {MS_peak_intensity, "has_units", UO_absorbance_unit}, {MS_collision_energy, "has_units", UO_electronvolt}, {MS_normalized_collision_energy, "has_units", UO_percent}, {MS_accurate_mass_OBSOLETE, "has_units", UO_mass_unit}, {MS_average_mass_OBSOLETE, "has_units", UO_mass_unit}, {MS_appearance_energy_OBSOLETE, "has_units", UO_electronvolt}, {MS_exact_mass_OBSOLETE, "has_units", UO_mass_unit}, {MS_ionization_energy_OBSOLETE, "has_units", UO_electronvolt}, {MS_mass_defect_OBSOLETE, "has_units", UO_mass_unit}, {MS_molecular_mass_OBSOLETE, "has_units", UO_mass_unit}, {MS_monoisotopic_mass_OBSOLETE, "has_units", UO_mass_unit}, {MS_nominal_mass_OBSOLETE, "has_units", UO_mass_unit}, {MS_accelerating_voltage, "has_units", UO_volt}, {MS_electric_field_strength, "has_units", UO_volt_per_meter}, {MS_source_potential, "has_units", UO_volt}, {MS_scan_window_upper_limit, "has_units", MS_m_z}, {MS_scan_window_lower_limit, "has_units", MS_m_z}, {MS_dwell_time, "has_units", UO_second}, {MS_dwell_time, "has_units", UO_minute}, {MS_base_peak_m_z, "has_units", MS_m_z}, {MS_base_peak_intensity, "has_units", MS_number_of_detector_counts}, {MS_base_peak_intensity, "has_units", MS_percent_of_base_peak}, {MS_base_peak_intensity, "has_units", MS_counts_per_second}, {MS_base_peak_intensity, "has_units", MS_percent_of_base_peak_times_100}, {MS_base_peak_intensity, "has_units", UO_absorbance_unit}, {MS_activation_energy, "has_units", UO_electronvolt}, {MS_m_z_array, "has_units", MS_m_z}, {MS_intensity_array, "has_units", MS_number_of_detector_counts}, {MS_intensity_array, "has_units", MS_percent_of_base_peak}, {MS_intensity_array, "has_units", MS_counts_per_second}, {MS_intensity_array, "has_units", MS_percent_of_base_peak_times_100}, {MS_intensity_array, "has_units", UO_absorbance_unit}, {MS_highest_observed_m_z, "has_units", MS_m_z}, {MS_lowest_observed_m_z, "has_units", MS_m_z}, {MS_time_array, "has_units", UO_second}, {MS_time_array, "has_units", UO_minute}, {MS_wavelength_array, "has_units", UO_nanometer}, {MS_highest_observed_wavelength, "has_units", UO_nanometer}, {MS_lowest_observed_wavelength, "has_units", UO_nanometer}, {MS_low_intensity_threshold, "has_units", MS_number_of_detector_counts}, {MS_low_intensity_threshold, "has_units", MS_percent_of_base_peak}, {MS_low_intensity_threshold, "has_units", MS_counts_per_second}, {MS_low_intensity_threshold, "has_units", MS_percent_of_base_peak_times_100}, {MS_low_intensity_threshold, "has_units", UO_absorbance_unit}, {MS_high_intensity_threshold, "has_units", MS_number_of_detector_counts}, {MS_high_intensity_threshold, "has_units", MS_percent_of_base_peak}, {MS_high_intensity_threshold, "has_units", MS_counts_per_second}, {MS_high_intensity_threshold, "has_units", MS_percent_of_base_peak_times_100}, {MS_high_intensity_threshold, "has_units", UO_absorbance_unit}, {MS_selected_ion_m_z, "has_units", MS_m_z}, {MS_inclusive_low_intensity_threshold, "has_units", MS_number_of_detector_counts}, {MS_inclusive_low_intensity_threshold, "has_units", MS_percent_of_base_peak}, {MS_inclusive_low_intensity_threshold, "has_units", MS_counts_per_second}, {MS_inclusive_low_intensity_threshold, "has_units", MS_percent_of_base_peak_times_100}, {MS_inclusive_low_intensity_threshold, "has_units", UO_absorbance_unit}, {MS_inclusive_high_intensity_threshold, "has_units", MS_number_of_detector_counts}, {MS_inclusive_high_intensity_threshold, "has_units", MS_percent_of_base_peak}, {MS_inclusive_high_intensity_threshold, "has_units", MS_counts_per_second}, {MS_inclusive_high_intensity_threshold, "has_units", MS_percent_of_base_peak_times_100}, {MS_inclusive_high_intensity_threshold, "has_units", UO_absorbance_unit}, {MS_isolation_window_upper_limit_OBSOLETE, "has_units", MS_m_z}, {MS_isolation_window_lower_limit_OBSOLETE, "has_units", MS_m_z}, {MS_analyzer_scan_offset, "has_units", MS_m_z}, {MS_pressure_array, "has_units", UO_pascal}, {MS_temperature_array, "has_units", UO_kelvin}, {MS_elution_time, "has_units", UO_second}, {MS_elution_time, "has_units", UO_minute}, {MS_isolation_window_target_m_z, "has_units", MS_m_z}, {MS_isolation_window_lower_offset, "has_units", MS_m_z}, {MS_isolation_window_upper_offset, "has_units", MS_m_z}, {MS_matrix_solution_concentration, "has_units", UO_gram_per_liter}, {MS_wavelength_OBSOLETE, "has_units", UO_nanometer}, {MS_focus_diameter_x, "has_units", UO_micrometer}, {MS_focus_diameter_y, "has_units", UO_micrometer}, {MS_pulse_energy, "has_units", UO_joule}, {MS_pulse_duration, "has_units", UO_nanosecond}, {MS_attenuation, "has_units", UO_percent}, {MS_impact_angle, "has_units", UO_degree}, {MS_collision_gas_pressure, "has_units", UO_pascal}, {MS_declustering_potential, "has_units", UO_volt}, {MS_cone_voltage, "has_units", UO_volt}, {MS_tube_lens_voltage, "has_units", UO_volt}, {MS_interchannel_delay, "has_units", UO_second}, {MS_retention_time, "has_units", UO_second}, {MS_retention_time, "has_units", UO_minute}, {MS_local_retention_time, "has_units", UO_second}, {MS_local_retention_time, "has_units", UO_minute}, {MS_normalized_retention_time, "has_units", UO_second}, {MS_normalized_retention_time, "has_units", UO_minute}, {MS_predicted_retention_time, "has_units", UO_second}, {MS_predicted_retention_time, "has_units", UO_minute}, {MS_product_ion_m_z_delta, "has_units", MS_m_z}, {MS_retention_time_window_lower_offset, "has_units", UO_second}, {MS_retention_time_window_lower_offset, "has_units", UO_minute}, {MS_retention_time_window_upper_offset, "has_units", UO_second}, {MS_retention_time_window_upper_offset, "has_units", UO_minute}, {MS_ion_injection_time, "has_units", UO_millisecond}, {MS_retention_time_s__OBSOLETE, "has_units", UO_second}, {MS_retention_time_s__OBSOLETE, "has_units", UO_minute}, {MS_theoretical_mass, "has_units", UO_dalton}, {MS_SEQUEST_xcorr, "has_order", MS_higher_score_better}, {MS_DB_MW_filter_maximum, "has_units", UO_dalton}, {MS_DB_MW_filter_maximum, "has_units", UO_kilodalton}, {MS_DB_MW_filter_minimum, "has_units", UO_dalton}, {MS_DB_MW_filter_minimum, "has_units", UO_kilodalton}, {MS_protein_level_global_FDR, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_product_ion_m_z, "has_units", MS_m_z}, {MS_product_ion_intensity, "has_units", MS_number_of_detector_counts}, {MS_product_ion_intensity, "has_units", MS_percent_of_base_peak}, {MS_product_ion_intensity, "has_units", MS_counts_per_second}, {MS_product_ion_intensity, "has_units", MS_percent_of_base_peak_times_100}, {MS_product_ion_m_z_error, "has_units", MS_m_z}, {MS_product_ion_m_z_error, "has_units", UO_parts_per_notation_unit}, {MS_local_FDR, "has_units", UO_parts_per_notation_unit}, {MS_local_FDR, "has_units", UO_percent}, {MS_Trypsin, "has_regexp", MS______KR_____P_}, {MS_Arg_C, "has_regexp", MS_____R____P_}, {MS_Asp_N, "has_regexp", MS_____BD__}, {MS_Asp_N_ambic, "has_regexp", MS_____DE__}, {MS_Chymotrypsin, "has_regexp", MS______FYWL_____P_}, {MS_CNBr, "has_regexp", MS_____M_}, {MS_Formic_acid, "has_regexp", MS______D_______D__}, {MS_Lys_C, "has_regexp", MS_____K____P_}, {MS_Lys_C_P, "has_regexp", MS_____K_}, {MS_PepsinA, "has_regexp", MS______FL__}, {MS_TrypChymo, "has_regexp", MS______FYWLKR_____P_}, {MS_Trypsin_P, "has_regexp", MS______KR__}, {MS_V8_DE, "has_regexp", MS______BDEZ_____P_}, {MS_V8_E, "has_regexp", MS______EZ_____P_}, {MS_alternate_mass, "has_units", UO_dalton}, {MS_distinct_peptide_level_global_FDR, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_search_tolerance_plus_value, "has_units", UO_parts_per_notation_unit}, {MS_search_tolerance_plus_value, "has_units", UO_percent}, {MS_search_tolerance_plus_value, "has_units", UO_dalton}, {MS_search_tolerance_minus_value, "has_units", UO_parts_per_notation_unit}, {MS_search_tolerance_minus_value, "has_units", UO_percent}, {MS_search_tolerance_minus_value, "has_units", UO_dalton}, {MS_fragment_neutral_loss, "has_units", UO_dalton}, {MS_precursor_neutral_loss, "has_units", UO_dalton}, {MS_distinct_peptide_level_q_value, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_distinct_peptide_level_q_value, "has_units", UO_parts_per_notation_unit}, {MS_distinct_peptide_level_q_value, "has_units", UO_percent}, {MS_protein_level_q_value, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_protein_level_q_value, "has_units", UO_parts_per_notation_unit}, {MS_protein_level_q_value, "has_units", UO_percent}, {MS_distinct_peptide_level_p_value, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_protein_level_p_value, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_distinct_peptide_level_e_value, "has_domain", MS_value_greater_than_zero}, {MS_protein_level_e_value, "has_domain", MS_value_greater_than_zero}, {MS_offset_voltage, "has_units", UO_volt}, {MS_retention_time_window_width, "has_units", UO_second}, {MS_retention_time_window_width, "has_units", UO_minute}, {MS_S_lens_voltage, "has_units", UO_volt}, {MS_leukocyte_elastase, "has_regexp", MS______ALIV_____P_}, {MS_proline_endopeptidase, "has_regexp", MS______HKR_P____P_}, {MS_glutamyl_endopeptidase, "has_regexp", MS_______E_E_}, {MS_2_iodobenzoate, "has_regexp", MS_____W_}, {MS_Digital_Object_Identifier__DOI_, "has_regexp", MS_regular_expression_for_a_digital_object_identifier__DOI_}, {MS_Collision_cell_exit_potential, "has_units", UO_volt}, {MS_product_ion_drift_time_OBSOLETE, "has_units", UO_millisecond}, {MS_phosphoRS_score, "has_regexp", MS_regular_expression_for_modification_localization_scoring}, {MS_phosphoRS_sequence_probability, "has_regexp", MS_regular_expression_for_modification_localization_scoring}, {MS_phosphoRS_site_probability, "has_regexp", MS_regular_expression_for_modification_localization_scoring}, {MS_DeBunker_score, "has_regexp", MS_regular_expression_for_modification_localization_scoring}, {MS_delta_m_z, "has_units", UO_parts_per_notation_unit}, {MS_delta_m_z, "has_units", UO_percent}, {MS_delta_m_z, "has_units", UO_dalton}, {MS_delta_M, "has_units", UO_parts_per_notation_unit}, {MS_delta_M, "has_units", UO_percent}, {MS_delta_M, "has_units", UO_dalton}, {MS_MSQuant_PTM_score, "has_regexp", MS_regular_expression_for_modification_localization_scoring}, {MS_MaxQuant_PTM_Score, "has_regexp", MS_regular_expression_for_modification_localization_scoring}, {MS_MaxQuant_Phospho__STY__Probabilities, "has_regexp", MS_regular_expression_for_modification_localization_scoring}, {MS_MaxQuant_P_site_localization_probability, "has_regexp", MS_regular_expression_for_modification_localization_scoring}, {MS_MaxQuant_PTM_Delta_Score, "has_regexp", MS_regular_expression_for_modification_localization_scoring}, {MS_Ascore_1001985, "has_regexp", MS_regular_expression_for_modification_localization_scoring}, {MS_H_Score, "has_regexp", MS_regular_expression_for_modification_localization_scoring}, {MS_Mascot_PTM_site_assignment_confidence, "has_units", UO_percent}, {MS_collision_energy_ramp_start, "has_units", UO_electronvolt}, {MS_collision_energy_ramp_end, "has_units", UO_electronvolt}, {MS_inlet_temperature, "has_units", UO_kelvin}, {MS_inlet_temperature, "has_units", UO_degree_celsius}, {MS_source_temperature, "has_units", UO_kelvin}, {MS_source_temperature, "has_units", UO_degree_celsius}, {MS_modulation_time, "has_units", UO_second}, {MS_modulation_time, "has_units", UO_minute}, {MS_MS_GF_SpecEValue, "has_order", MS_lower_score_better}, {MS_MS_GF_EValue, "has_order", MS_lower_score_better}, {MS_p_value, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_ProteomeDiscoverer_Spectrum_Selector_Precursor_Clipping_Range_Before, "has_units", UO_dalton}, {MS_ProteomeDiscoverer_Spectrum_Selector_Precursor_Clipping_Range_After, "has_units", UO_dalton}, {MS_first_column_elution_time, "has_units", UO_second}, {MS_first_column_elution_time, "has_units", UO_minute}, {MS_second_column_elution_time, "has_units", UO_second}, {MS_second_column_elution_time, "has_units", UO_minute}, {MS_percent_collision_energy_ramp_start, "has_units", UO_percent}, {MS_percent_collision_energy_ramp_end, "has_units", UO_percent}, {MS_ProteomeDiscoverer_Default_FDR_calculator, "has_regexp", MS_regular_expressions_for_a_GUID}, {MS_selected_precursor_m_z, "has_units", MS_m_z}, {MS_Comet_xcorr, "has_order", MS_higher_score_better}, {MS_Byonic_Score, "has_order", MS_higher_score_better}, {MS_Byonic_Delta_Score, "has_order", MS_higher_score_better}, {MS_Byonic_DeltaMod_Score, "has_order", MS_higher_score_better}, {MS_Byonic_PEP, "has_order", MS_lower_score_better}, {MS_Byonic_Peptide_LogProb, "has_order", MS_lower_score_better}, {MS_Byonic_Protein_LogProb, "has_order", MS_lower_score_better}, {MS_Byonic_Best_LogProb, "has_order", MS_lower_score_better}, {MS_Byonic_Best_Score, "has_order", MS_higher_score_better}, {MS_detector_potential, "has_units", UO_volt}, {MS_Byonic__Peptide_AbsLogProb, "has_order", MS_higher_score_better}, {MS_Byonic__Protein_AbsLogProb, "has_order", MS_higher_score_better}, {MS_Byonic__Peptide_AbsLogProb2D, "has_order", MS_higher_score_better}, {MS_Andromeda_score, "has_order", MS_higher_score_better}, {MS_PSM_level_global_FDR, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_PSM_level_local_FDR, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_PSM_level_p_value, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_PSM_level_e_value, "has_domain", MS_value_greater_than_zero}, {MS_PSM_level_q_value, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_PSM_level_q_value, "has_units", UO_parts_per_notation_unit}, {MS_PSM_level_q_value, "has_units", UO_percent}, {MS_PSM_level_FDRScore, "has_domain", MS_value_greater_than_zero_but_less_than_or_equal_to_one}, {MS_PSM_level_combined_FDRScore, "has_domain", MS_value_greater_than_zero_but_less_than_or_equal_to_one}, {MS_PSM_level_probability, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_distinct_peptide_level_local_FDR, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_distinct_peptide_level_FDRScore, "has_domain", MS_value_greater_than_zero_but_less_than_or_equal_to_one}, {MS_distinct_peptide_level_combined_FDRScore, "has_domain", MS_value_greater_than_zero_but_less_than_or_equal_to_one}, {MS_distinct_peptide_level_probability, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_FDRScore_for_proteins, "has_domain", MS_value_greater_than_zero_but_less_than_or_equal_to_one}, {MS_combined_FDRScore_for_proteins, "has_domain", MS_value_greater_than_zero_but_less_than_or_equal_to_one}, {MS_probability_for_proteins, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_protein_group_level_p_value, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_protein_group_level_e_value, "has_domain", MS_value_greater_than_zero}, {MS_protein_group_level_q_value, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_protein_group_level_q_value, "has_units", UO_parts_per_notation_unit}, {MS_protein_group_level_q_value, "has_units", UO_percent}, {MS_protein_group_level_FDRScore, "has_domain", MS_value_greater_than_zero_but_less_than_or_equal_to_one}, {MS_protein_group_level_combined_FDRScore, "has_domain", MS_value_greater_than_zero_but_less_than_or_equal_to_one}, {MS_protein_group_level_probability, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_PIA_protein_score, "has_order", MS_higher_score_better}, {MS_protein_group_level_global_FNR, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_distinct_peptide_level_global_FNR, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_PSM_level_global_FNR, "has_domain", MS_value_between_0_and_1_inclusive}, {MS_PeptideShaker_PSM_score, "has_order", MS_higher_score_better}, {MS_PeptideShaker_PSM_confidence, "has_order", MS_higher_score_better}, {MS_PeptideShaker_peptide_score, "has_order", MS_higher_score_better}, {MS_PeptideShaker_peptide_confidence, "has_order", MS_higher_score_better}, {MS_PeptideShaker_protein_group_score, "has_order", MS_higher_score_better}, {MS_PeptideShaker_protein_group_confidence, "has_order", MS_higher_score_better}, {MS_ProteoAnnotator_non_canonical_gene_model_score, "has_order", MS_higher_score_better}, {MS_ion_mobility_drift_time, "has_units", UO_millisecond}, {MS_mean_drift_time_array, "has_units", UO_millisecond}, {MS_mean_drift_time_array, "has_units", UO_second}, {MS_modification_rescoring_false_localization_rate, "has_regexp", MS_regular_expression_for_modification_localization_scoring}, {MS_ProLuCID_xcorr, "has_order", MS_higher_score_better}, {MS_D_Score, "has_regexp", MS_regular_expression_for_modification_localization_scoring}, {MS_MD_Score, "has_regexp", MS_regular_expression_for_modification_localization_scoring}, {MS_xi_score, "has_order", MS_higher_score_better}, {MS_peptide_phosphoRS_score, "has_regexp", MS_regular_expression_for_modification_localization_scoring}, {MS_peptide_Ascore, "has_regexp", MS_regular_expression_for_modification_localization_scoring}, {MS_peptide_H_Score, "has_regexp", MS_regular_expression_for_modification_localization_scoring}, {MS_peptide_D_Score, "has_regexp", MS_regular_expression_for_modification_localization_scoring}, {MS_peptide_MD_Score, "has_regexp", MS_regular_expression_for_modification_localization_scoring}, }; // relationsOther_ const size_t relationsOtherSize_ = sizeof(relationsOther_)/sizeof(OtherRelationPair); struct CVIDStringPair { CVID first; const char* second; }; CVIDStringPair relationsExactSynonym_[] = { {CVID_Unknown, "Unknown"}, {MS_magnetic_field_strength, "B"}, {MS_m_z, "mass-to-charge ratio"}, {MS_m_z, "Th"}, {MS_m_z, "thomson"}, {MS_charge_state, "z"}, {MS_continuous_flow_fast_atom_bombardment, "CF-FAB"}, {MS_atmospheric_pressure_chemical_ionization, "APCI"}, {MS_chemical_ionization, "CI"}, {MS_Electronic_Ionization_OBSOLETE, "EI"}, {MS_electrospray_ionization, "ESI"}, {MS_fast_atom_bombardment_ionization, "FAB"}, {MS_matrix_assisted_laser_desorption_ionization, "MALDI"}, {MS_fourier_transform_ion_cyclotron_resonance_mass_spectrometer, "FT_ICR"}, {MS_quadrupole_ion_trap, "Paul Ion trap"}, {MS_quadrupole_ion_trap, "QIT"}, {MS_quadrupole_ion_trap, "Quistor"}, {MS_time_of_flight, "TOF"}, {MS_full_width_at_half_maximum, "FWHM"}, {MS_multiple_reaction_monitoring_OBSOLETE, "MRM"}, {MS_channeltron, "Channeltron Detector"}, {MS_daly_detector, "Daly"}, {MS_electron_multiplier_tube, "EMT"}, {MS_microchannel_plate_detector, "multichannel plate"}, {MS_photomultiplier, "PMT"}, {MS_analog_digital_converter, "ADC"}, {MS_time_digital_converter, "TDC"}, {MS_centroid_spectrum, "Discrete Mass Spectrum"}, {MS_profile_spectrum, "continuous mass spectrum"}, {MS_profile_spectrum, "Continuum Mass Spectrum"}, {MS_collision_induced_dissociation, "CID"}, {MS_collision_induced_dissociation, "CAD"}, {MS_collision_induced_dissociation, "collisionally activated dissociation"}, {MS_plasma_desorption, "PD"}, {MS_post_source_decay, "PSD"}, {MS_surface_induced_dissociation, "SID"}, {MS_electron_volt_OBSOLETE, "eV"}, {MS_selected_ion_monitoring, "Multiple Ion Monitoring"}, {MS_selected_ion_monitoring, "SIM"}, {MS_selected_reaction_monitoring, "SRM"}, {MS_appearance_energy_OBSOLETE, "AE"}, {MS_base_peak, "BP"}, {MS_OBSOLETE_charge_number_OBSOLETE, "z"}, {MS_dalton_OBSOLETE, "Da"}, {MS_electron_affinity_OBSOLETE, "EA"}, {MS_field_free_region, "FFR"}, {MS_ionization_energy_OBSOLETE, "IE"}, {MS_isotope_dilution_mass_spectrometry_OBSOLETE, "IDMS"}, {MS_molecular_beam_mass_spectrometry_OBSOLETE, "MBMS"}, {MS_multiphoton_ionization, "MPI"}, {MS_proton_affinity_OBSOLETE, "PA"}, {MS_total_ion_current_chromatogram, "TIC chromatogram"}, {MS_unified_atomic_mass_unit_OBSOLETE, "u"}, {MS_accelerator_mass_spectrometry_OBSOLETE, "AMS"}, {MS_atmospheric_pressure_matrix_assisted_laser_desorption_ionization, "AP MALDI"}, {MS_atmospheric_pressure_ionization, "API"}, {MS_Atmostpheric_Pressure_Photoionization_OBSOLETE, "APPI"}, {MS_blackbody_infrared_radiative_dissociation, "BIRD"}, {MS_charge_remote_fragmentation_OBSOLETE, "CRF"}, {MS_consecutive_reaction_monitoring_OBSOLETE_1000244, "CRM"}, {MS_charge_stripping, "CS"}, {MS_delayed_extraction, "DE"}, {MS_desorption_ionization, "DI"}, {MS_direct_insertion_probe, "DIP"}, {MS_direct_liquid_introduction, "DLI"}, {MS_electron_capture_dissociation, "ECD"}, {MS_even_electron_ion_OBSOLETE, "EE"}, {MS_electron_induced_excitation_in_organics_OBSOLETE, "EIEIO"}, {MS_electron_multiplier, "EM"}, {MS_electrostatic_energy_analyzer, "ESA"}, {MS_flowing_afterglow, "FA"}, {MS_high_field_asymmetric_waveform_ion_mobility_spectrometry_OBSOLETE, "FAIMS"}, {MS_field_desorption, "FD"}, {MS_field_ionization, "FI"}, {MS_glow_discharge_ionization, "GD-MS"}, {MS_ion_kinetic_energy_spectrometry_OBSOLETE, "IKES"}, {MS_ion_mobility_spectrometry_OBSOLETE, "IMS"}, {MS_infrared_multiphoton_dissociation, "IRMPD"}, {MS_isotope_ratio_mass_spectrometry_OBSOLETE, "IRMS"}, {MS_ion_trap, "IT"}, {MS_kinetic_energy_release_distribution_OBSOLETE, "KERD"}, {MS_Laser_Desorption_OBSOLETE, "Laser Ionization MERGE"}, {MS_Laser_Desorption_OBSOLETE, "LD"}, {MS_mass_analyzed_ion_kinetic_energy_spectrometry_OBSOLETE, "MIKES"}, {MS_mass_spectrometry_OBSOLETE, "MS"}, {MS_mass_spectrometry_mass_spectrometry_OBSOLETE, "MS/MS"}, {MS_multiple_stage_mass_spectrometry_OBSOLETE, "MSn"}, {MS_Negative_Ion_chemical_ionization, "NICI"}, {MS_neutralization_reionization_mass_spectrometry, "NRMS"}, {MS_photoionization, "PI"}, {MS_pyrolysis_mass_spectrometry, "PyMS"}, {MS_collision_quadrupole, "q"}, {MS_resonance_enhanced_multiphoton_ionization, "REMPI"}, {MS_residual_gas_analyzer_OBSOLETE, "RGA"}, {MS_surface_enhanced_laser_desorption_ionization, "SELDI"}, {MS_surface_enhanced_neat_desorption, "SEND"}, {MS_suface_ionization_OBSOLETE, "SI"}, {MS_selected_ion_flow_tube, "SIFT"}, {MS_sustained_off_resonance_irradiation, "SORI"}, {MS_Spark_Source_Mass_Spectrometry_OBSOLETE, "SSMS"}, {MS_stored_waveform_inverse_fourier_transform, "SWIFT"}, {MS_total_ion_current, "TIC"}, {MS_time_lag_focusing, "TLF"}, {MS_time_of_flight_mass_spectrometer_OBSOLETE, "TOF-MS"}, {MS_constant_neutral_gain_scan_OBSOLETE, "Constant Neutral Mass Gain Scan"}, {MS_constant_neutral_gain_spectrum, "constant neutral mass gain spectrum"}, {MS_constant_neutral_loss_spectrum, "constant neutral mass loss spectrum"}, {MS_progeny_ion_OBSOLETE, "Progeny Fragment Ion"}, {MS_nanoelectrospray, "nanospray"}, {MS_beam_type_collision_induced_dissociation, "HCD"}, {MS_photodissociation, "multiphoton dissociation"}, {MS_photodissociation, "MPD"}, {MS_fast_ion_bombardment, "FIB"}, {MS_mass_analyzer, "analyzer"}, {MS_data_transformation, "data processing"}, {MS_precursor_activation, "activation"}, {MS_instrument, "instrument configuration"}, {MS_6410_Triple_Quadrupole_LC_MS, "6410 Triple Quad LC/MS"}, {MS_Applied_Biosystems_instrument_model, "ABI"}, {MS_zoom_scan, "enhanced resolution scan"}, {MS_massWolf, "wolf"}, {MS_raw_data_file, "source file"}, {MS_MS1_spectrum, "full spectrum"}, {MS_MS1_spectrum, "Q1 spectrum"}, {MS_MS1_spectrum, "Q3 spectrum"}, {MS_MS1_spectrum, "Single-Stage Mass Spectrometry"}, {MS_MSn_spectrum, "multiple-stage mass spectrometry spectrum"}, {MS_MSn_spectrum, "nth generation product ion spectrum"}, {MS_MSn_spectrum, "product ion spectrum"}, {MS_SIM_spectrum, "MIM spectrum"}, {MS_SIM_spectrum, "multiple ion monitoring spectrum"}, {MS_SIM_spectrum, "selected ion monitoring spectrum"}, {MS_SRM_spectrum, "MRM spectrum"}, {MS_SRM_spectrum, "multiple reaction monitoring spectrum"}, {MS_SRM_spectrum, "selected reaction monitoring spectrum"}, {MS_low_intensity_data_point_removal, "thresholding"}, {MS_electron_transfer_dissociation, "ETD"}, {MS_pulsed_q_dissociation, "PQD"}, {MS_ProteoWizard_software, "pwiz"}, {MS_photodiode_array_detector, "PDA"}, {MS_inductive_detector, "image current detector"}, {MS_selected_ion_current_chromatogram, "SIC chromatogram"}, {MS_native_spectrum_identifier_format, "nativeID format"}, {MS_Gaussian_smoothing, "binomial smoothing"}, {MS_Gaussian_smoothing, "Weierstrass transform"}, {MS_moving_average_smoothing, "box smoothing"}, {MS_moving_average_smoothing, "boxcar smoothing"}, {MS_moving_average_smoothing, "sliding average smoothing"}, {MS_area_peak_picking, "sum peak picking"}, {MS_height_peak_picking, "max peak picking"}, {MS_electromagnetic_radiation_spectrum, "EMR spectrum"}, {MS_electromagnetic_radiation_chromatogram, "EMR radiation chromatogram"}, {MS_isoelectric_point, "pI"}, {MS_predicted_isoelectric_point, "predicted pI"}, {MS_unlabeled_peptide, "light labeled peptide"}, {MS_transition, "reaction"}, {MS_product_ion_m_z, "fragment ion m/z"}, {MS_product_ion_intensity, "fragment ion intensity"}, {MS_Arg_C, "Clostripain"}, {MS_selected_ion_monitoring_chromatogram, "SIM chromatogram"}, {MS_selected_reaction_monitoring_chromatogram, "SRM chromatogram"}, {MS_consecutive_reaction_monitoring_chromatogram_OBSOLETE, "CRM chromatogram"}, {MS_FAIMS_compensation_voltage, "FAIMS CV"}, {MS_MyriMatch_MVH, "Pepitome:MVH"}, {MS_MyriMatch_MVH, "TagRecon:MVH"}, {MS_MyriMatch_mzFidelity, "Pepitome:mzFidelity"}, {MS_MyriMatch_mzFidelity, "TagRecon:mzFidelity"}, {MS_travelling_wave_ion_mobility_mass_spectrometer_OBSOLETE, "TWIMS"}, {MS_glutamyl_endopeptidase, "staphylococcal protease"}, {MS_glutamyl_endopeptidase, "Glu-C"}, {MS_Digital_Object_Identifier__DOI_, "doi"}, {MS_Collision_cell_exit_potential, "CXP"}, {MS_delta_m_z, "m/z difference"}, {MS_delta_M, "mass difference"}, {MS_sophisticated_numerical_annotation_procedure, "SNAP"}, {MS_SRM_transition_type, "MRM transition type"}, {MS_target_SRM_transition, "target MRM transition"}, {MS_decoy_SRM_transition, "decoy MRM transition"}, {MS_desorption_electrospray_ionization, "DESI"}, {MS_unlabeled_sample, "light labeled sample"}, {MS_MS_GF_, "MS-GFDB"}, {MS_Trans_Proteomic_Pipeline, "TPP"}, {MS_synchronous_prefilter_selection, "SPS"}, {UO_time_unit, "time derived unit"}, {UO_temperature_unit, "temperature derived unit"}, {UO_meter, "m"}, {UO_kilogram, "kg"}, {UO_second, "s"}, {UO_ampere, "A"}, {UO_kelvin, "K"}, {UO_mole, "mol"}, {UO_candela, "cd"}, {UO_centimeter, "cm"}, {UO_millimeter, "mm"}, {UO_micrometer, "micron"}, {UO_micrometer, "um"}, {UO_nanometer, "nm"}, {UO_angstrom, "A"}, {UO_picometer, "pm"}, {UO_gram, "g"}, {UO_milligram, "mg"}, {UO_microgram, "ug"}, {UO_nanogram, "ng"}, {UO_picogram, "pg"}, {UO_femtogram, "fg"}, {UO_degree_celsius, "C"}, {UO_millisecond, "ms"}, {UO_microsecond, "us"}, {UO_picosecond, "ps"}, {UO_minute, "min"}, {UO_hour, "h"}, {UO_milliampere, "mA"}, {UO_microampere, "uA"}, {UO_micromole, "umol"}, {UO_millimole, "mmol"}, {UO_nanomole, "nmol"}, {UO_picomole, "pmol"}, {UO_femtomole, "fmol"}, {UO_attomole, "amol"}, {UO_mass_density_unit, "mass per unit volume"}, {UO_area_density_unit, "mass per unit area unit"}, {UO_molar, "M"}, {UO_millimolar, "mM"}, {UO_micromolar, "uM"}, {UO_nanomolar, "nM"}, {UO_picomolar, "pM"}, {UO_molal, "m"}, {UO_millimolal, "mm"}, {UO_micromolal, "um"}, {UO_nanomolal, "nm"}, {UO_picomolal, "pm"}, {UO_femtomolar, "fM"}, {UO_normal, "N"}, {UO_mole_fraction, "(x)"}, {UO_mole_fraction, "chi"}, {UO_meter_per_second_per_second, "m/s^[2]"}, {UO_radian_per_second_per_second, "alpha"}, {UO_radian_per_second_per_second, "rad/s^[2]"}, {UO_radian_per_second, "rad/s"}, {UO_square_meter, "m^[2]"}, {UO_square_centimeter, "cm^[2]"}, {UO_square_millimeter, "mm^[2]"}, {UO_kilogram_per_cubic_meter, "kg/m^[3]"}, {UO_gram_per_cubic_centimeter, "g/cm^[3]"}, {UO_candela_per_square_meter, "cd/m^[2]"}, {UO_kilogram_per_square_meter, "Body Mass Index (BMI)"}, {UO_kilogram_per_square_meter, "kg/m^[2]"}, {UO_kilogram_per_mole, "kg/mol"}, {UO_gram_per_mole, "g/mol"}, {UO_cubic_meter_per_mole, "m^[3]/mol"}, {UO_cubic_centimeter_per_mole, "cm^[3]/mol"}, {UO_kilogram_meter_per_second, "kg.m/s"}, {UO_turns_per_second, "1/s"}, {UO_cubic_meter_per_kilogram, "m^[3]/kg"}, {UO_meter_per_second, "m/s"}, {UO_cubic_meter, "m^[3]"}, {UO_cubic_centimeter, "cc"}, {UO_cubic_centimeter, "cm^3"}, {UO_milliliter, "ml"}, {UO_liter, "l"}, {UO_liter, "L"}, {UO_cubic_decimeter, "dm^[3]"}, {UO_microliter, "ul"}, {UO_nanoliter, "nl"}, {UO_picoliter, "pl"}, {UO_femtoliter, "fl"}, {UO_hertz, "Hz"}, {UO_hertz, "s^1"}, {UO_newton, "N"}, {UO_pascal, "Pa"}, {UO_joule, "J"}, {UO_watt, "W"}, {UO_lux, "lx"}, {UO_lumen, "lm"}, {UO_katal, "kat"}, {UO_radian, "rad"}, {UO_steradian, "sr"}, {UO_becquerel, "Bq"}, {UO_curie, "Ci"}, {UO_gray, "Gy"}, {UO_roentgen, "R"}, {UO_sievert, "Sv"}, {UO_millisievert, "mSv"}, {UO_microsievert, "uSv"}, {UO_Roentgen_equivalent_man, "rem"}, {UO_microgray, "uGy"}, {UO_milligray, "mGy"}, {UO_nanogray, "nGy"}, {UO_nanosievert, "nSv"}, {UO_millicurie, "mCi"}, {UO_microcurie, "uCi"}, {UO_disintegrations_per_minute, "dpm"}, {UO_counts_per_minute, "cpm"}, {UO_nanosecond, "ns"}, {UO_foot_candle, "ft-c"}, {UO_watt_per_square_meter, "W/m^[2]"}, {UO_einstein_per_square_meter_per_second, "einstein/sm^[2]"}, {UO_einstein_per_square_meter_per_second, "mole per second and square meter mol/sm^2"}, {UO_watt_per_steradian_per_square_meter, "W/sr m^[2]"}, {UO_microeinstein_per_square_meter_per_second, "micromole per second and square meter mmol/sm^2"}, {UO_microeinstein_per_square_meter_per_second, "umicroeinstein/sm^[2]"}, {UO_watt_per_steradian, "W/sr"}, {UO_mass_percentage, "w/w"}, {UO_mass_percentage, "weight-weight percentage"}, {UO_mass_volume_percentage, "(w/v)"}, {UO_mass_volume_percentage, "weight-volume percentage"}, {UO_volume_percentage, "% (v/v)"}, {UO_parts_per_hundred, "10^[-2]"}, {UO_parts_per_hundred, "pph"}, {UO_parts_per_thousand, "10^[-3]"}, {UO_parts_per_thousand, "ppth"}, {UO_parts_per_million, "10^[-6]"}, {UO_parts_per_million, "ppm"}, {UO_parts_per_billion, "10^[-9]"}, {UO_parts_per_billion, "ppb"}, {UO_parts_per_trillion, "10^[-12]"}, {UO_parts_per_trillion, "ppt"}, {UO_parts_per_quadrillion, "10^[-15]"}, {UO_parts_per_quadrillion, "ppq"}, {UO_gram_per_milliliter, "g/ml"}, {UO_kilogram_per_liter, "kg/L"}, {UO_gram_per_liter, "g/L"}, {UO_milligram_per_milliliter, "mg/ml"}, {UO_unit_per_milliliter, "U/ml"}, {UO_unit_per_liter, "U/l"}, {UO_enzyme_unit, "U"}, {UO_kilogram_per_meter, "kg/m"}, {UO_percent, "%"}, {UO_count_unit, "count"}, {UO_degree_fahrenheit, "F"}, {UO_liter_per_kilogram, "l/kg"}, {UO_milliliter_per_kilogram, "ml/kg"}, {UO_microliter_per_kilogram, "ul/kg"}, {UO_cells_per_milliliter, "cells per ml"}, {UO_katal_per_cubic_meter, "kat/m^[3]"}, {UO_katal_per_liter, "kat/l"}, {UO_milliliter_per_cubic_meter, "ml/m^[3]"}, {UO_milliliter_per_liter, "ml/l"}, {UO_gram_per_deciliter, "g/dl"}, {UO_deciliter, "dl"}, {UO_colony_forming_unit, "cfu"}, {UO_plaque_forming_unit, "pfu"}, {UO_colony_forming_unit_per_milliliter, "cfu/ml"}, {UO_plaque_forming_unit_per_milliliter, "pfu/ml"}, {UO_disintegrations_per_second, "dps"}, {UO_volt, "V"}, {UO_coulomb, "C"}, {UO_dalton, "Da"}, {UO_dalton, "u"}, {UO_dalton, "unified atomic mass unit"}, {UO_kilodalton, "kDa"}, {UO_watt_hour, "Wh"}, {UO_weber, "V s"}, {UO_weber, "Wb"}, {UO_magnetic_flux_density_unit, "B"}, {UO_tesla, "T"}, {UO_tesla, "Wb/m2"}, {UO_volt_hour, "Vh"}, {UO_kilovolt_hour, "kVh"}, {UO_byte, "B"}, {UO_kilobyte, "kB"}, {UO_megabyte, "MB"}, {UO_dots_per_inch, "dpi"}, {UO_micron_pixel, "micrometer pixel"}, {UO_pixels_per_inch, "pixel density"}, {UO_pixels_per_inch, "ppi"}, {UO_base_pair, "bp"}, {UO_kibibyte, "KiB"}, {UO_mebibyte, "MiB"}, {UO_millivolt, "mV"}, {UO_kilovolt, "kV"}, {UO_microvolt, "uV"}, {UO_nanovolt, "nV"}, {UO_picovolt, "pV"}, {UO_megavolt, "MV"}, {UO_newton_per_meter, "N/m"}, {UO_dyne_per_cm, "dyn/cm"}, {UO_pascal_second, "Pa s"}, {UO_poise, "dyne s/cm^2"}, {UO_poise, "P"}, {UO_decibel, "dB"}, {UO_siemens, "A V^-1"}, {UO_watt_per_meter_kelvin, "W/m K"}, {UO_electronvolt, "electron volt"}, {UO_electronvolt, "eV"}, {UO_electric_field_strength_unit, "E-field strength "}, {UO_volt_per_meter, "V/m"}, {UO_absorbance_unit, "AU"}, {UO_microliters_per_minute, "uL/min"}, {UO_millimetres_of_mercury, "mmHg"}, {UO_milligram_per_liter, "mg/L"}, {UO_microgram_per_milliliter, "ug/ml"}, {UO_nanogram_per_milliliter, "ng/ml"}, {UO_milliunits_per_milliliter, "mU/ml"}, {UO_count_per_nanomolar_second, "nM^-1 s^-1"}, {UO_count_per_molar_second, "M^-1 s^-1"}, {UO_count_per_nanomolar, "nM^-1"}, {UO_count_per_nanomolar, "1/nM"}, {UO_count_per_molar, "M^-1"}, {UO_count_per_molar, "1/M"}, {UO_microgram_per_liter, "ug/L"}, }; // relationsExactSynonym_ const size_t relationsExactSynonymSize_ = sizeof(relationsExactSynonym_)/sizeof(CVIDStringPair); struct PropertyValuePair { CVID term; const char* name; const char* value; }; PropertyValuePair propertyValue_[] = { {CVID_Unknown, "Unknown", "Unknown"}, {UNIMOD_Acetyl, "approved", "1"}, {UNIMOD_Acetyl, "delta_composition", "H(2) C(2) O"}, {UNIMOD_Acetyl, "spec_1_classification", "Multiple"}, {UNIMOD_Acetyl, "spec_1_hidden", "0"}, {UNIMOD_Acetyl, "spec_1_position", "Anywhere"}, {UNIMOD_Acetyl, "spec_1_site", "K"}, {UNIMOD_Acetyl, "spec_2_classification", "Multiple"}, {UNIMOD_Acetyl, "spec_2_hidden", "0"}, {UNIMOD_Acetyl, "spec_2_position", "Any N-term"}, {UNIMOD_Acetyl, "spec_2_site", "N-term"}, {UNIMOD_Acetyl, "spec_3_classification", "Post-translational"}, {UNIMOD_Acetyl, "spec_3_hidden", "1"}, {UNIMOD_Acetyl, "spec_3_position", "Anywhere"}, {UNIMOD_Acetyl, "spec_3_site", "C"}, {UNIMOD_Acetyl, "spec_4_classification", "Post-translational"}, {UNIMOD_Acetyl, "spec_4_hidden", "1"}, {UNIMOD_Acetyl, "spec_4_position", "Anywhere"}, {UNIMOD_Acetyl, "spec_4_site", "S"}, {UNIMOD_Acetyl, "spec_5_classification", "Post-translational"}, {UNIMOD_Acetyl, "spec_5_hidden", "0"}, {UNIMOD_Acetyl, "spec_5_position", "Protein N-term"}, {UNIMOD_Acetyl, "spec_5_site", "N-term"}, {UNIMOD_Acetyl, "spec_6_classification", "Post-translational"}, {UNIMOD_Acetyl, "spec_6_hidden", "1"}, {UNIMOD_Acetyl, "spec_6_position", "Anywhere"}, {UNIMOD_Acetyl, "spec_6_site", "T"}, {UNIMOD_Acetyl, "spec_7_classification", "Chemical derivative"}, {UNIMOD_Acetyl, "spec_7_hidden", "1"}, {UNIMOD_Acetyl, "spec_7_position", "Anywhere"}, {UNIMOD_Acetyl, "spec_7_site", "Y"}, {UNIMOD_Acetyl, "spec_8_classification", "Chemical derivative"}, {UNIMOD_Acetyl, "spec_8_hidden", "1"}, {UNIMOD_Acetyl, "spec_8_position", "Anywhere"}, {UNIMOD_Acetyl, "spec_8_site", "H"}, {UNIMOD_Amidated, "approved", "1"}, {UNIMOD_Amidated, "delta_composition", "H N O(-1)"}, {UNIMOD_Amidated, "spec_1_classification", "Post-translational"}, {UNIMOD_Amidated, "spec_1_hidden", "0"}, {UNIMOD_Amidated, "spec_1_position", "Protein C-term"}, {UNIMOD_Amidated, "spec_1_site", "C-term"}, {UNIMOD_Amidated, "spec_2_classification", "Artefact"}, {UNIMOD_Amidated, "spec_2_hidden", "0"}, {UNIMOD_Amidated, "spec_2_position", "Any C-term"}, {UNIMOD_Amidated, "spec_2_site", "C-term"}, {UNIMOD_Biotin, "approved", "1"}, {UNIMOD_Biotin, "delta_composition", "H(14) C(10) N(2) O(2) S"}, {UNIMOD_Biotin, "spec_1_classification", "Post-translational"}, {UNIMOD_Biotin, "spec_1_hidden", "0"}, {UNIMOD_Biotin, "spec_1_position", "Anywhere"}, {UNIMOD_Biotin, "spec_1_site", "K"}, {UNIMOD_Biotin, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Biotin, "spec_2_hidden", "0"}, {UNIMOD_Biotin, "spec_2_position", "Any N-term"}, {UNIMOD_Biotin, "spec_2_site", "N-term"}, {UNIMOD_Carbamidomethyl, "approved", "1"}, {UNIMOD_Carbamidomethyl, "delta_composition", "H(3) C(2) N O"}, {UNIMOD_Carbamidomethyl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Carbamidomethyl, "spec_1_hidden", "0"}, {UNIMOD_Carbamidomethyl, "spec_1_position", "Anywhere"}, {UNIMOD_Carbamidomethyl, "spec_1_site", "C"}, {UNIMOD_Carbamidomethyl, "spec_2_classification", "Artefact"}, {UNIMOD_Carbamidomethyl, "spec_2_hidden", "1"}, {UNIMOD_Carbamidomethyl, "spec_2_position", "Anywhere"}, {UNIMOD_Carbamidomethyl, "spec_2_site", "K"}, {UNIMOD_Carbamidomethyl, "spec_3_classification", "Artefact"}, {UNIMOD_Carbamidomethyl, "spec_3_hidden", "1"}, {UNIMOD_Carbamidomethyl, "spec_3_position", "Any N-term"}, {UNIMOD_Carbamidomethyl, "spec_3_site", "N-term"}, {UNIMOD_Carbamidomethyl, "spec_4_classification", "Artefact"}, {UNIMOD_Carbamidomethyl, "spec_4_hidden", "1"}, {UNIMOD_Carbamidomethyl, "spec_4_position", "Anywhere"}, {UNIMOD_Carbamidomethyl, "spec_4_site", "H"}, {UNIMOD_Carbamidomethyl, "spec_5_classification", "Artefact"}, {UNIMOD_Carbamidomethyl, "spec_5_hidden", "1"}, {UNIMOD_Carbamidomethyl, "spec_5_position", "Anywhere"}, {UNIMOD_Carbamidomethyl, "spec_5_site", "D"}, {UNIMOD_Carbamidomethyl, "spec_6_classification", "Artefact"}, {UNIMOD_Carbamidomethyl, "spec_6_hidden", "1"}, {UNIMOD_Carbamidomethyl, "spec_6_position", "Anywhere"}, {UNIMOD_Carbamidomethyl, "spec_6_site", "E"}, {UNIMOD_Carbamidomethyl, "spec_7_classification", "Artefact"}, {UNIMOD_Carbamidomethyl, "spec_7_hidden", "1"}, {UNIMOD_Carbamidomethyl, "spec_7_position", "Anywhere"}, {UNIMOD_Carbamidomethyl, "spec_7_site", "S"}, {UNIMOD_Carbamidomethyl, "spec_8_classification", "Artefact"}, {UNIMOD_Carbamidomethyl, "spec_8_hidden", "1"}, {UNIMOD_Carbamidomethyl, "spec_8_position", "Anywhere"}, {UNIMOD_Carbamidomethyl, "spec_8_site", "T"}, {UNIMOD_Carbamidomethyl, "spec_9_classification", "Artefact"}, {UNIMOD_Carbamidomethyl, "spec_9_hidden", "1"}, {UNIMOD_Carbamidomethyl, "spec_9_position", "Anywhere"}, {UNIMOD_Carbamidomethyl, "spec_9_site", "Y"}, {UNIMOD_Carbamyl, "approved", "0"}, {UNIMOD_Carbamyl, "delta_composition", "H C N O"}, {UNIMOD_Carbamyl, "spec_1_classification", "Multiple"}, {UNIMOD_Carbamyl, "spec_1_hidden", "0"}, {UNIMOD_Carbamyl, "spec_1_position", "Anywhere"}, {UNIMOD_Carbamyl, "spec_1_site", "K"}, {UNIMOD_Carbamyl, "spec_2_classification", "Multiple"}, {UNIMOD_Carbamyl, "spec_2_hidden", "0"}, {UNIMOD_Carbamyl, "spec_2_position", "Any N-term"}, {UNIMOD_Carbamyl, "spec_2_site", "N-term"}, {UNIMOD_Carbamyl, "spec_3_classification", "Artefact"}, {UNIMOD_Carbamyl, "spec_3_hidden", "1"}, {UNIMOD_Carbamyl, "spec_3_position", "Anywhere"}, {UNIMOD_Carbamyl, "spec_3_site", "R"}, {UNIMOD_Carbamyl, "spec_4_classification", "Artefact"}, {UNIMOD_Carbamyl, "spec_4_hidden", "1"}, {UNIMOD_Carbamyl, "spec_4_position", "Anywhere"}, {UNIMOD_Carbamyl, "spec_4_site", "C"}, {UNIMOD_Carbamyl, "spec_5_classification", "Artefact"}, {UNIMOD_Carbamyl, "spec_5_hidden", "1"}, {UNIMOD_Carbamyl, "spec_5_position", "Anywhere"}, {UNIMOD_Carbamyl, "spec_5_site", "M"}, {UNIMOD_Carbamyl, "spec_6_classification", "Chemical derivative"}, {UNIMOD_Carbamyl, "spec_6_hidden", "1"}, {UNIMOD_Carbamyl, "spec_6_position", "Anywhere"}, {UNIMOD_Carbamyl, "spec_6_site", "S"}, {UNIMOD_Carbamyl, "spec_7_classification", "Chemical derivative"}, {UNIMOD_Carbamyl, "spec_7_hidden", "1"}, {UNIMOD_Carbamyl, "spec_7_position", "Anywhere"}, {UNIMOD_Carbamyl, "spec_7_site", "T"}, {UNIMOD_Carbamyl, "spec_8_classification", "Chemical derivative"}, {UNIMOD_Carbamyl, "spec_8_hidden", "1"}, {UNIMOD_Carbamyl, "spec_8_position", "Anywhere"}, {UNIMOD_Carbamyl, "spec_8_site", "Y"}, {UNIMOD_Carbamyl, "spec_9_classification", "Post-translational"}, {UNIMOD_Carbamyl, "spec_9_hidden", "1"}, {UNIMOD_Carbamyl, "spec_9_position", "Protein N-term"}, {UNIMOD_Carbamyl, "spec_9_site", "N-term"}, {UNIMOD_Carboxymethyl, "approved", "1"}, {UNIMOD_Carboxymethyl, "delta_composition", "H(2) C(2) O(2)"}, {UNIMOD_Carboxymethyl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Carboxymethyl, "spec_1_hidden", "0"}, {UNIMOD_Carboxymethyl, "spec_1_position", "Anywhere"}, {UNIMOD_Carboxymethyl, "spec_1_site", "C"}, {UNIMOD_Carboxymethyl, "spec_2_classification", "Artefact"}, {UNIMOD_Carboxymethyl, "spec_2_hidden", "1"}, {UNIMOD_Carboxymethyl, "spec_2_position", "Anywhere"}, {UNIMOD_Carboxymethyl, "spec_2_site", "K"}, {UNIMOD_Carboxymethyl, "spec_3_classification", "Artefact"}, {UNIMOD_Carboxymethyl, "spec_3_hidden", "1"}, {UNIMOD_Carboxymethyl, "spec_3_position", "Any N-term"}, {UNIMOD_Carboxymethyl, "spec_3_site", "N-term"}, {UNIMOD_Carboxymethyl, "spec_4_classification", "Chemical derivative"}, {UNIMOD_Carboxymethyl, "spec_4_hidden", "1"}, {UNIMOD_Carboxymethyl, "spec_4_position", "Anywhere"}, {UNIMOD_Carboxymethyl, "spec_4_site", "W"}, {UNIMOD_Deamidated, "approved", "0"}, {UNIMOD_Deamidated, "delta_composition", "H(-1) N(-1) O"}, {UNIMOD_Deamidated, "spec_1_classification", "Artefact"}, {UNIMOD_Deamidated, "spec_1_classification", "Artefact"}, {UNIMOD_Deamidated, "spec_1_hidden", "0"}, {UNIMOD_Deamidated, "spec_1_hidden", "0"}, {UNIMOD_Deamidated, "spec_1_position", "Anywhere"}, {UNIMOD_Deamidated, "spec_1_position", "Anywhere"}, {UNIMOD_Deamidated, "spec_1_site", "Q"}, {UNIMOD_Deamidated, "spec_1_site", "N"}, {UNIMOD_Deamidated, "spec_2_classification", "Post-translational"}, {UNIMOD_Deamidated, "spec_2_hidden", "1"}, {UNIMOD_Deamidated, "spec_2_position", "Anywhere"}, {UNIMOD_Deamidated, "spec_2_site", "R"}, {UNIMOD_Deamidated, "spec_3_classification", "Post-translational"}, {UNIMOD_Deamidated, "spec_3_hidden", "1"}, {UNIMOD_Deamidated, "spec_3_position", "Protein N-term"}, {UNIMOD_Deamidated, "spec_3_site", "F"}, {UNIMOD_ICAT_G, "approved", "1"}, {UNIMOD_ICAT_G, "delta_composition", "H(38) C(22) N(4) O(6) S"}, {UNIMOD_ICAT_G, "spec_1_classification", "Isotopic label"}, {UNIMOD_ICAT_G, "spec_1_hidden", "1"}, {UNIMOD_ICAT_G, "spec_1_position", "Anywhere"}, {UNIMOD_ICAT_G, "spec_1_site", "C"}, {UNIMOD_ICAT_G_2H_8_, "approved", "1"}, {UNIMOD_ICAT_G_2H_8_, "delta_composition", "H(30) 2H(8) C(22) N(4) O(6) S"}, {UNIMOD_ICAT_G_2H_8_, "spec_1_classification", "Isotopic label"}, {UNIMOD_ICAT_G_2H_8_, "spec_1_hidden", "1"}, {UNIMOD_ICAT_G_2H_8_, "spec_1_position", "Anywhere"}, {UNIMOD_ICAT_G_2H_8_, "spec_1_site", "C"}, {UNIMOD_Met__Hse, "approved", "1"}, {UNIMOD_Met__Hse, "delta_composition", "H(-2) C(-1) O S(-1)"}, {UNIMOD_Met__Hse, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Met__Hse, "spec_1_hidden", "0"}, {UNIMOD_Met__Hse, "spec_1_position", "Any C-term"}, {UNIMOD_Met__Hse, "spec_1_site", "M"}, {UNIMOD_Met__Hsl, "approved", "0"}, {UNIMOD_Met__Hsl, "delta_composition", "H(-4) C(-1) S(-1)"}, {UNIMOD_Met__Hsl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Met__Hsl, "spec_1_hidden", "0"}, {UNIMOD_Met__Hsl, "spec_1_position", "Any C-term"}, {UNIMOD_Met__Hsl, "spec_1_site", "M"}, {UNIMOD_ICAT_D_2H_8_, "approved", "1"}, {UNIMOD_ICAT_D_2H_8_, "delta_composition", "H(26) 2H(8) C(20) N(4) O(5) S"}, {UNIMOD_ICAT_D_2H_8_, "spec_1_classification", "Isotopic label"}, {UNIMOD_ICAT_D_2H_8_, "spec_1_hidden", "1"}, {UNIMOD_ICAT_D_2H_8_, "spec_1_position", "Anywhere"}, {UNIMOD_ICAT_D_2H_8_, "spec_1_site", "C"}, {UNIMOD_ICAT_D, "approved", "1"}, {UNIMOD_ICAT_D, "delta_composition", "H(34) C(20) N(4) O(5) S"}, {UNIMOD_ICAT_D, "spec_1_classification", "Isotopic label"}, {UNIMOD_ICAT_D, "spec_1_hidden", "1"}, {UNIMOD_ICAT_D, "spec_1_position", "Anywhere"}, {UNIMOD_ICAT_D, "spec_1_site", "C"}, {UNIMOD_NIPCAM, "approved", "1"}, {UNIMOD_NIPCAM, "delta_composition", "H(9) C(5) N O"}, {UNIMOD_NIPCAM, "spec_1_classification", "Chemical derivative"}, {UNIMOD_NIPCAM, "spec_1_hidden", "0"}, {UNIMOD_NIPCAM, "spec_1_position", "Anywhere"}, {UNIMOD_NIPCAM, "spec_1_site", "C"}, {UNIMOD_PEO_Iodoacetyl_LC_Biotin, "approved", "0"}, {UNIMOD_PEO_Iodoacetyl_LC_Biotin, "delta_composition", "H(30) C(18) N(4) O(5) S"}, {UNIMOD_PEO_Iodoacetyl_LC_Biotin, "spec_1_classification", "Chemical derivative"}, {UNIMOD_PEO_Iodoacetyl_LC_Biotin, "spec_1_hidden", "1"}, {UNIMOD_PEO_Iodoacetyl_LC_Biotin, "spec_1_position", "Anywhere"}, {UNIMOD_PEO_Iodoacetyl_LC_Biotin, "spec_1_site", "C"}, {UNIMOD_Phospho, "approved", "1"}, {UNIMOD_Phospho, "delta_composition", "H O(3) P"}, {UNIMOD_Phospho, "spec_1_classification", "Post-translational"}, {UNIMOD_Phospho, "spec_1_classification", "Post-translational"}, {UNIMOD_Phospho, "spec_1_hidden", "0"}, {UNIMOD_Phospho, "spec_1_hidden", "0"}, {UNIMOD_Phospho, "spec_1_position", "Anywhere"}, {UNIMOD_Phospho, "spec_1_position", "Anywhere"}, {UNIMOD_Phospho, "spec_1_site", "T"}, {UNIMOD_Phospho, "spec_1_site", "S"}, {UNIMOD_Phospho, "spec_2_classification", "Post-translational"}, {UNIMOD_Phospho, "spec_2_hidden", "0"}, {UNIMOD_Phospho, "spec_2_position", "Anywhere"}, {UNIMOD_Phospho, "spec_2_site", "Y"}, {UNIMOD_Phospho, "spec_3_classification", "Post-translational"}, {UNIMOD_Phospho, "spec_3_hidden", "1"}, {UNIMOD_Phospho, "spec_3_position", "Anywhere"}, {UNIMOD_Phospho, "spec_3_site", "D"}, {UNIMOD_Phospho, "spec_4_classification", "Post-translational"}, {UNIMOD_Phospho, "spec_4_hidden", "1"}, {UNIMOD_Phospho, "spec_4_position", "Anywhere"}, {UNIMOD_Phospho, "spec_4_site", "H"}, {UNIMOD_Phospho, "spec_5_classification", "Post-translational"}, {UNIMOD_Phospho, "spec_5_hidden", "1"}, {UNIMOD_Phospho, "spec_5_position", "Anywhere"}, {UNIMOD_Phospho, "spec_5_site", "C"}, {UNIMOD_Phospho, "spec_6_classification", "Post-translational"}, {UNIMOD_Phospho, "spec_6_hidden", "1"}, {UNIMOD_Phospho, "spec_6_position", "Anywhere"}, {UNIMOD_Phospho, "spec_6_site", "R"}, {UNIMOD_Phospho, "spec_7_classification", "Other"}, {UNIMOD_Phospho, "spec_7_hidden", "1"}, {UNIMOD_Phospho, "spec_7_position", "Anywhere"}, {UNIMOD_Phospho, "spec_7_site", "K"}, {UNIMOD_Dehydrated, "approved", "0"}, {UNIMOD_Dehydrated, "delta_composition", "H(-2) O(-1)"}, {UNIMOD_Dehydrated, "spec_1_classification", "Post-translational"}, {UNIMOD_Dehydrated, "spec_1_hidden", "1"}, {UNIMOD_Dehydrated, "spec_1_position", "Protein C-term"}, {UNIMOD_Dehydrated, "spec_1_site", "N"}, {UNIMOD_Dehydrated, "spec_2_classification", "Post-translational"}, {UNIMOD_Dehydrated, "spec_2_hidden", "1"}, {UNIMOD_Dehydrated, "spec_2_position", "Protein C-term"}, {UNIMOD_Dehydrated, "spec_2_site", "Q"}, {UNIMOD_Dehydrated, "spec_3_classification", "Post-translational"}, {UNIMOD_Dehydrated, "spec_3_hidden", "1"}, {UNIMOD_Dehydrated, "spec_3_position", "Anywhere"}, {UNIMOD_Dehydrated, "spec_3_site", "S"}, {UNIMOD_Dehydrated, "spec_4_classification", "Post-translational"}, {UNIMOD_Dehydrated, "spec_4_hidden", "1"}, {UNIMOD_Dehydrated, "spec_4_position", "Anywhere"}, {UNIMOD_Dehydrated, "spec_4_site", "T"}, {UNIMOD_Dehydrated, "spec_5_classification", "Post-translational"}, {UNIMOD_Dehydrated, "spec_5_hidden", "1"}, {UNIMOD_Dehydrated, "spec_5_position", "Anywhere"}, {UNIMOD_Dehydrated, "spec_5_site", "Y"}, {UNIMOD_Dehydrated, "spec_6_classification", "Chemical derivative"}, {UNIMOD_Dehydrated, "spec_6_hidden", "1"}, {UNIMOD_Dehydrated, "spec_6_position", "Anywhere"}, {UNIMOD_Dehydrated, "spec_6_site", "D"}, {UNIMOD_Dehydrated, "spec_7_classification", "Artefact"}, {UNIMOD_Dehydrated, "spec_7_hidden", "0"}, {UNIMOD_Dehydrated, "spec_7_position", "Any N-term"}, {UNIMOD_Dehydrated, "spec_7_site", "C"}, {UNIMOD_Propionamide, "approved", "1"}, {UNIMOD_Propionamide, "delta_composition", "H(5) C(3) N O"}, {UNIMOD_Propionamide, "spec_1_classification", "Artefact"}, {UNIMOD_Propionamide, "spec_1_hidden", "0"}, {UNIMOD_Propionamide, "spec_1_position", "Anywhere"}, {UNIMOD_Propionamide, "spec_1_site", "C"}, {UNIMOD_Propionamide, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Propionamide, "spec_2_hidden", "1"}, {UNIMOD_Propionamide, "spec_2_position", "Anywhere"}, {UNIMOD_Propionamide, "spec_2_site", "K"}, {UNIMOD_Propionamide, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Propionamide, "spec_3_hidden", "1"}, {UNIMOD_Propionamide, "spec_3_position", "Any N-term"}, {UNIMOD_Propionamide, "spec_3_site", "N-term"}, {UNIMOD_Pyridylacetyl, "approved", "1"}, {UNIMOD_Pyridylacetyl, "delta_composition", "H(5) C(7) N O"}, {UNIMOD_Pyridylacetyl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Pyridylacetyl, "spec_1_hidden", "1"}, {UNIMOD_Pyridylacetyl, "spec_1_position", "Anywhere"}, {UNIMOD_Pyridylacetyl, "spec_1_site", "K"}, {UNIMOD_Pyridylacetyl, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Pyridylacetyl, "spec_2_hidden", "1"}, {UNIMOD_Pyridylacetyl, "spec_2_position", "Any N-term"}, {UNIMOD_Pyridylacetyl, "spec_2_site", "N-term"}, {UNIMOD_Pyro_carbamidomethyl, "approved", "0"}, {UNIMOD_Pyro_carbamidomethyl, "delta_composition", "C(2) O"}, {UNIMOD_Pyro_carbamidomethyl, "spec_1_classification", "Artefact"}, {UNIMOD_Pyro_carbamidomethyl, "spec_1_hidden", "0"}, {UNIMOD_Pyro_carbamidomethyl, "spec_1_position", "Any N-term"}, {UNIMOD_Pyro_carbamidomethyl, "spec_1_site", "C"}, {UNIMOD_Glu__pyro_Glu, "approved", "1"}, {UNIMOD_Glu__pyro_Glu, "delta_composition", "H(-2) O(-1)"}, {UNIMOD_Glu__pyro_Glu, "spec_1_classification", "Artefact"}, {UNIMOD_Glu__pyro_Glu, "spec_1_hidden", "0"}, {UNIMOD_Glu__pyro_Glu, "spec_1_position", "Any N-term"}, {UNIMOD_Glu__pyro_Glu, "spec_1_site", "E"}, {UNIMOD_Gln__pyro_Glu, "approved", "1"}, {UNIMOD_Gln__pyro_Glu, "delta_composition", "H(-3) N(-1)"}, {UNIMOD_Gln__pyro_Glu, "spec_1_classification", "Artefact"}, {UNIMOD_Gln__pyro_Glu, "spec_1_hidden", "0"}, {UNIMOD_Gln__pyro_Glu, "spec_1_position", "Any N-term"}, {UNIMOD_Gln__pyro_Glu, "spec_1_site", "Q"}, {UNIMOD_SMA, "approved", "1"}, {UNIMOD_SMA, "delta_composition", "H(9) C(6) N O(2)"}, {UNIMOD_SMA, "spec_1_classification", "Chemical derivative"}, {UNIMOD_SMA, "spec_1_hidden", "1"}, {UNIMOD_SMA, "spec_1_position", "Anywhere"}, {UNIMOD_SMA, "spec_1_site", "K"}, {UNIMOD_SMA, "spec_2_classification", "Chemical derivative"}, {UNIMOD_SMA, "spec_2_hidden", "1"}, {UNIMOD_SMA, "spec_2_position", "Any N-term"}, {UNIMOD_SMA, "spec_2_site", "N-term"}, {UNIMOD_Cation_Na, "approved", "1"}, {UNIMOD_Cation_Na, "delta_composition", "H(-1) Na"}, {UNIMOD_Cation_Na, "spec_1_classification", "Artefact"}, {UNIMOD_Cation_Na, "spec_1_hidden", "0"}, {UNIMOD_Cation_Na, "spec_1_position", "Any C-term"}, {UNIMOD_Cation_Na, "spec_1_site", "C-term"}, {UNIMOD_Cation_Na, "spec_2_classification", "Artefact"}, {UNIMOD_Cation_Na, "spec_2_classification", "Artefact"}, {UNIMOD_Cation_Na, "spec_2_hidden", "0"}, {UNIMOD_Cation_Na, "spec_2_hidden", "0"}, {UNIMOD_Cation_Na, "spec_2_position", "Anywhere"}, {UNIMOD_Cation_Na, "spec_2_position", "Anywhere"}, {UNIMOD_Cation_Na, "spec_2_site", "D"}, {UNIMOD_Cation_Na, "spec_2_site", "E"}, {UNIMOD_Pyridylethyl, "approved", "1"}, {UNIMOD_Pyridylethyl, "delta_composition", "H(7) C(7) N"}, {UNIMOD_Pyridylethyl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Pyridylethyl, "spec_1_hidden", "0"}, {UNIMOD_Pyridylethyl, "spec_1_position", "Anywhere"}, {UNIMOD_Pyridylethyl, "spec_1_site", "C"}, {UNIMOD_Methyl, "approved", "1"}, {UNIMOD_Methyl, "delta_composition", "H(2) C"}, {UNIMOD_Methyl, "spec_10_classification", "Post-translational"}, {UNIMOD_Methyl, "spec_10_hidden", "1"}, {UNIMOD_Methyl, "spec_10_position", "Protein N-term"}, {UNIMOD_Methyl, "spec_10_site", "N-term"}, {UNIMOD_Methyl, "spec_11_classification", "Multiple"}, {UNIMOD_Methyl, "spec_11_hidden", "0"}, {UNIMOD_Methyl, "spec_11_position", "Any C-term"}, {UNIMOD_Methyl, "spec_11_site", "C-term"}, {UNIMOD_Methyl, "spec_12_classification", "Post-translational"}, {UNIMOD_Methyl, "spec_12_classification", "Post-translational"}, {UNIMOD_Methyl, "spec_12_hidden", "0"}, {UNIMOD_Methyl, "spec_12_hidden", "0"}, {UNIMOD_Methyl, "spec_12_position", "Anywhere"}, {UNIMOD_Methyl, "spec_12_position", "Anywhere"}, {UNIMOD_Methyl, "spec_12_site", "E"}, {UNIMOD_Methyl, "spec_12_site", "D"}, {UNIMOD_Methyl, "spec_13_classification", "Post-translational"}, {UNIMOD_Methyl, "spec_13_hidden", "1"}, {UNIMOD_Methyl, "spec_13_position", "Anywhere"}, {UNIMOD_Methyl, "spec_13_site", "S"}, {UNIMOD_Methyl, "spec_14_classification", "Post-translational"}, {UNIMOD_Methyl, "spec_14_hidden", "1"}, {UNIMOD_Methyl, "spec_14_position", "Anywhere"}, {UNIMOD_Methyl, "spec_14_site", "T"}, {UNIMOD_Methyl, "spec_1_classification", "Post-translational"}, {UNIMOD_Methyl, "spec_1_hidden", "1"}, {UNIMOD_Methyl, "spec_1_position", "Anywhere"}, {UNIMOD_Methyl, "spec_1_site", "C"}, {UNIMOD_Methyl, "spec_2_classification", "Post-translational"}, {UNIMOD_Methyl, "spec_2_hidden", "1"}, {UNIMOD_Methyl, "spec_2_position", "Anywhere"}, {UNIMOD_Methyl, "spec_2_site", "H"}, {UNIMOD_Methyl, "spec_3_classification", "Post-translational"}, {UNIMOD_Methyl, "spec_3_hidden", "1"}, {UNIMOD_Methyl, "spec_3_position", "Anywhere"}, {UNIMOD_Methyl, "spec_3_site", "K"}, {UNIMOD_Methyl, "spec_4_classification", "Post-translational"}, {UNIMOD_Methyl, "spec_4_hidden", "1"}, {UNIMOD_Methyl, "spec_4_position", "Anywhere"}, {UNIMOD_Methyl, "spec_4_site", "N"}, {UNIMOD_Methyl, "spec_5_classification", "Chemical derivative"}, {UNIMOD_Methyl, "spec_5_hidden", "1"}, {UNIMOD_Methyl, "spec_5_position", "Any N-term"}, {UNIMOD_Methyl, "spec_5_site", "N-term"}, {UNIMOD_Methyl, "spec_6_classification", "Post-translational"}, {UNIMOD_Methyl, "spec_6_hidden", "1"}, {UNIMOD_Methyl, "spec_6_position", "Anywhere"}, {UNIMOD_Methyl, "spec_6_site", "Q"}, {UNIMOD_Methyl, "spec_7_classification", "Post-translational"}, {UNIMOD_Methyl, "spec_7_hidden", "1"}, {UNIMOD_Methyl, "spec_7_position", "Anywhere"}, {UNIMOD_Methyl, "spec_7_site", "R"}, {UNIMOD_Methyl, "spec_8_classification", "Post-translational"}, {UNIMOD_Methyl, "spec_8_hidden", "1"}, {UNIMOD_Methyl, "spec_8_position", "Anywhere"}, {UNIMOD_Methyl, "spec_8_site", "I"}, {UNIMOD_Methyl, "spec_9_classification", "Post-translational"}, {UNIMOD_Methyl, "spec_9_hidden", "1"}, {UNIMOD_Methyl, "spec_9_position", "Anywhere"}, {UNIMOD_Methyl, "spec_9_site", "L"}, {UNIMOD_Oxidation, "approved", "0"}, {UNIMOD_Oxidation, "delta_composition", "O"}, {UNIMOD_Oxidation, "spec_10_classification", "Artefact"}, {UNIMOD_Oxidation, "spec_10_classification", "Artefact"}, {UNIMOD_Oxidation, "spec_10_hidden", "0"}, {UNIMOD_Oxidation, "spec_10_hidden", "0"}, {UNIMOD_Oxidation, "spec_10_position", "Anywhere"}, {UNIMOD_Oxidation, "spec_10_position", "Anywhere"}, {UNIMOD_Oxidation, "spec_10_site", "W"}, {UNIMOD_Oxidation, "spec_10_site", "H"}, {UNIMOD_Oxidation, "spec_11_classification", "Pre-translational"}, {UNIMOD_Oxidation, "spec_11_hidden", "1"}, {UNIMOD_Oxidation, "spec_11_position", "Any C-term"}, {UNIMOD_Oxidation, "spec_11_site", "G"}, {UNIMOD_Oxidation, "spec_1_classification", "Post-translational"}, {UNIMOD_Oxidation, "spec_1_hidden", "1"}, {UNIMOD_Oxidation, "spec_1_position", "Anywhere"}, {UNIMOD_Oxidation, "spec_1_site", "D"}, {UNIMOD_Oxidation, "spec_2_classification", "Post-translational"}, {UNIMOD_Oxidation, "spec_2_hidden", "1"}, {UNIMOD_Oxidation, "spec_2_position", "Anywhere"}, {UNIMOD_Oxidation, "spec_2_site", "K"}, {UNIMOD_Oxidation, "spec_3_classification", "Post-translational"}, {UNIMOD_Oxidation, "spec_3_hidden", "1"}, {UNIMOD_Oxidation, "spec_3_position", "Anywhere"}, {UNIMOD_Oxidation, "spec_3_site", "N"}, {UNIMOD_Oxidation, "spec_4_classification", "Post-translational"}, {UNIMOD_Oxidation, "spec_4_hidden", "1"}, {UNIMOD_Oxidation, "spec_4_position", "Anywhere"}, {UNIMOD_Oxidation, "spec_4_site", "P"}, {UNIMOD_Oxidation, "spec_5_classification", "Artefact"}, {UNIMOD_Oxidation, "spec_5_hidden", "1"}, {UNIMOD_Oxidation, "spec_5_position", "Anywhere"}, {UNIMOD_Oxidation, "spec_5_site", "F"}, {UNIMOD_Oxidation, "spec_6_classification", "Post-translational"}, {UNIMOD_Oxidation, "spec_6_hidden", "1"}, {UNIMOD_Oxidation, "spec_6_position", "Anywhere"}, {UNIMOD_Oxidation, "spec_6_site", "Y"}, {UNIMOD_Oxidation, "spec_7_classification", "Post-translational"}, {UNIMOD_Oxidation, "spec_7_hidden", "1"}, {UNIMOD_Oxidation, "spec_7_position", "Anywhere"}, {UNIMOD_Oxidation, "spec_7_site", "R"}, {UNIMOD_Oxidation, "spec_8_classification", "Artefact"}, {UNIMOD_Oxidation, "spec_8_hidden", "0"}, {UNIMOD_Oxidation, "spec_8_position", "Anywhere"}, {UNIMOD_Oxidation, "spec_8_site", "M"}, {UNIMOD_Oxidation, "spec_9_classification", "Post-translational"}, {UNIMOD_Oxidation, "spec_9_hidden", "1"}, {UNIMOD_Oxidation, "spec_9_position", "Anywhere"}, {UNIMOD_Oxidation, "spec_9_site", "C"}, {UNIMOD_Dimethyl, "approved", "1"}, {UNIMOD_Dimethyl, "delta_composition", "H(4) C(2)"}, {UNIMOD_Dimethyl, "spec_1_classification", "Multiple"}, {UNIMOD_Dimethyl, "spec_1_hidden", "1"}, {UNIMOD_Dimethyl, "spec_1_position", "Anywhere"}, {UNIMOD_Dimethyl, "spec_1_site", "K"}, {UNIMOD_Dimethyl, "spec_2_classification", "Post-translational"}, {UNIMOD_Dimethyl, "spec_2_hidden", "1"}, {UNIMOD_Dimethyl, "spec_2_position", "Anywhere"}, {UNIMOD_Dimethyl, "spec_2_site", "R"}, {UNIMOD_Dimethyl, "spec_3_classification", "Isotopic label"}, {UNIMOD_Dimethyl, "spec_3_hidden", "1"}, {UNIMOD_Dimethyl, "spec_3_position", "Any N-term"}, {UNIMOD_Dimethyl, "spec_3_site", "N-term"}, {UNIMOD_Dimethyl, "spec_4_classification", "Post-translational"}, {UNIMOD_Dimethyl, "spec_4_hidden", "1"}, {UNIMOD_Dimethyl, "spec_4_position", "Anywhere"}, {UNIMOD_Dimethyl, "spec_4_site", "N"}, {UNIMOD_Dimethyl, "spec_5_classification", "Post-translational"}, {UNIMOD_Dimethyl, "spec_5_hidden", "1"}, {UNIMOD_Dimethyl, "spec_5_position", "Protein N-term"}, {UNIMOD_Dimethyl, "spec_5_site", "P"}, {UNIMOD_Dimethyl, "spec_6_classification", "Isotopic label"}, {UNIMOD_Dimethyl, "spec_6_hidden", "1"}, {UNIMOD_Dimethyl, "spec_6_position", "Protein N-term"}, {UNIMOD_Dimethyl, "spec_6_site", "N-term"}, {UNIMOD_Trimethyl, "approved", "1"}, {UNIMOD_Trimethyl, "delta_composition", "H(6) C(3)"}, {UNIMOD_Trimethyl, "spec_1_classification", "Post-translational"}, {UNIMOD_Trimethyl, "spec_1_hidden", "1"}, {UNIMOD_Trimethyl, "spec_1_position", "Anywhere"}, {UNIMOD_Trimethyl, "spec_1_site", "K"}, {UNIMOD_Trimethyl, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Trimethyl, "spec_2_hidden", "1"}, {UNIMOD_Trimethyl, "spec_2_position", "Anywhere"}, {UNIMOD_Trimethyl, "spec_2_site", "R"}, {UNIMOD_Trimethyl, "spec_3_classification", "Post-translational"}, {UNIMOD_Trimethyl, "spec_3_hidden", "1"}, {UNIMOD_Trimethyl, "spec_3_position", "Protein N-term"}, {UNIMOD_Trimethyl, "spec_3_site", "A"}, {UNIMOD_Methylthio, "approved", "0"}, {UNIMOD_Methylthio, "delta_composition", "H(2) C S"}, {UNIMOD_Methylthio, "spec_1_classification", "Post-translational"}, {UNIMOD_Methylthio, "spec_1_hidden", "1"}, {UNIMOD_Methylthio, "spec_1_position", "Anywhere"}, {UNIMOD_Methylthio, "spec_1_site", "D"}, {UNIMOD_Methylthio, "spec_2_classification", "Post-translational"}, {UNIMOD_Methylthio, "spec_2_hidden", "1"}, {UNIMOD_Methylthio, "spec_2_position", "Anywhere"}, {UNIMOD_Methylthio, "spec_2_site", "N"}, {UNIMOD_Methylthio, "spec_3_classification", "Multiple"}, {UNIMOD_Methylthio, "spec_3_hidden", "0"}, {UNIMOD_Methylthio, "spec_3_position", "Anywhere"}, {UNIMOD_Methylthio, "spec_3_site", "C"}, {UNIMOD_Methylthio, "spec_4_classification", "Artefact"}, {UNIMOD_Methylthio, "spec_4_hidden", "1"}, {UNIMOD_Methylthio, "spec_4_position", "Any N-term"}, {UNIMOD_Methylthio, "spec_4_site", "N-term"}, {UNIMOD_Methylthio, "spec_5_classification", "Artefact"}, {UNIMOD_Methylthio, "spec_5_hidden", "1"}, {UNIMOD_Methylthio, "spec_5_position", "Anywhere"}, {UNIMOD_Methylthio, "spec_5_site", "K"}, {UNIMOD_Sulfo, "approved", "1"}, {UNIMOD_Sulfo, "delta_composition", "O(3) S"}, {UNIMOD_Sulfo, "spec_1_classification", "Post-translational"}, {UNIMOD_Sulfo, "spec_1_classification", "Post-translational"}, {UNIMOD_Sulfo, "spec_1_classification", "Post-translational"}, {UNIMOD_Sulfo, "spec_1_hidden", "0"}, {UNIMOD_Sulfo, "spec_1_hidden", "0"}, {UNIMOD_Sulfo, "spec_1_hidden", "0"}, {UNIMOD_Sulfo, "spec_1_position", "Anywhere"}, {UNIMOD_Sulfo, "spec_1_position", "Anywhere"}, {UNIMOD_Sulfo, "spec_1_position", "Anywhere"}, {UNIMOD_Sulfo, "spec_1_site", "S"}, {UNIMOD_Sulfo, "spec_1_site", "T"}, {UNIMOD_Sulfo, "spec_1_site", "Y"}, {UNIMOD_Sulfo, "spec_2_classification", "Post-translational"}, {UNIMOD_Sulfo, "spec_2_hidden", "1"}, {UNIMOD_Sulfo, "spec_2_position", "Anywhere"}, {UNIMOD_Sulfo, "spec_2_site", "C"}, {UNIMOD_Hex, "approved", "1"}, {UNIMOD_Hex, "delta_composition", "Hex"}, {UNIMOD_Hex, "spec_1_classification", "Other glycosylation"}, {UNIMOD_Hex, "spec_1_hidden", "1"}, {UNIMOD_Hex, "spec_1_position", "Anywhere"}, {UNIMOD_Hex, "spec_1_site", "K"}, {UNIMOD_Hex, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_Hex, "spec_2_hidden", "1"}, {UNIMOD_Hex, "spec_2_position", "Anywhere"}, {UNIMOD_Hex, "spec_2_site", "N"}, {UNIMOD_Hex, "spec_3_classification", "Other glycosylation"}, {UNIMOD_Hex, "spec_3_hidden", "1"}, {UNIMOD_Hex, "spec_3_position", "Any N-term"}, {UNIMOD_Hex, "spec_3_site", "N-term"}, {UNIMOD_Hex, "spec_4_classification", "O-linked glycosylation"}, {UNIMOD_Hex, "spec_4_classification", "O-linked glycosylation"}, {UNIMOD_Hex, "spec_4_hidden", "1"}, {UNIMOD_Hex, "spec_4_hidden", "1"}, {UNIMOD_Hex, "spec_4_position", "Anywhere"}, {UNIMOD_Hex, "spec_4_position", "Anywhere"}, {UNIMOD_Hex, "spec_4_site", "T"}, {UNIMOD_Hex, "spec_4_site", "S"}, {UNIMOD_Hex, "spec_5_classification", "Other glycosylation"}, {UNIMOD_Hex, "spec_5_hidden", "1"}, {UNIMOD_Hex, "spec_5_position", "Anywhere"}, {UNIMOD_Hex, "spec_5_site", "W"}, {UNIMOD_Hex, "spec_6_classification", "Other glycosylation"}, {UNIMOD_Hex, "spec_6_hidden", "1"}, {UNIMOD_Hex, "spec_6_position", "Anywhere"}, {UNIMOD_Hex, "spec_6_site", "C"}, {UNIMOD_Hex, "spec_7_classification", "N-linked glycosylation"}, {UNIMOD_Hex, "spec_7_hidden", "1"}, {UNIMOD_Hex, "spec_7_position", "Anywhere"}, {UNIMOD_Hex, "spec_7_site", "R"}, {UNIMOD_Hex, "spec_8_classification", "O-linked glycosylation"}, {UNIMOD_Hex, "spec_8_hidden", "1"}, {UNIMOD_Hex, "spec_8_position", "Anywhere"}, {UNIMOD_Hex, "spec_8_site", "Y"}, {UNIMOD_Lipoyl, "approved", "1"}, {UNIMOD_Lipoyl, "delta_composition", "H(12) C(8) O S(2)"}, {UNIMOD_Lipoyl, "spec_1_classification", "Post-translational"}, {UNIMOD_Lipoyl, "spec_1_hidden", "1"}, {UNIMOD_Lipoyl, "spec_1_position", "Anywhere"}, {UNIMOD_Lipoyl, "spec_1_site", "K"}, {UNIMOD_HexNAc, "approved", "1"}, {UNIMOD_HexNAc, "delta_composition", "HexNAc"}, {UNIMOD_HexNAc, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_HexNAc, "spec_1_hidden", "1"}, {UNIMOD_HexNAc, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc, "spec_1_site", "N"}, {UNIMOD_HexNAc, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc, "spec_2_hidden", "1"}, {UNIMOD_HexNAc, "spec_2_hidden", "1"}, {UNIMOD_HexNAc, "spec_2_position", "Anywhere"}, {UNIMOD_HexNAc, "spec_2_position", "Anywhere"}, {UNIMOD_HexNAc, "spec_2_site", "T"}, {UNIMOD_HexNAc, "spec_2_site", "S"}, {UNIMOD_Farnesyl, "approved", "1"}, {UNIMOD_Farnesyl, "delta_composition", "H(24) C(15)"}, {UNIMOD_Farnesyl, "spec_1_classification", "Post-translational"}, {UNIMOD_Farnesyl, "spec_1_hidden", "1"}, {UNIMOD_Farnesyl, "spec_1_position", "Anywhere"}, {UNIMOD_Farnesyl, "spec_1_site", "C"}, {UNIMOD_Myristoyl, "approved", "1"}, {UNIMOD_Myristoyl, "delta_composition", "H(26) C(14) O"}, {UNIMOD_Myristoyl, "spec_1_classification", "Post-translational"}, {UNIMOD_Myristoyl, "spec_1_hidden", "1"}, {UNIMOD_Myristoyl, "spec_1_position", "Any N-term"}, {UNIMOD_Myristoyl, "spec_1_site", "G"}, {UNIMOD_Myristoyl, "spec_2_classification", "Post-translational"}, {UNIMOD_Myristoyl, "spec_2_hidden", "1"}, {UNIMOD_Myristoyl, "spec_2_position", "Anywhere"}, {UNIMOD_Myristoyl, "spec_2_site", "K"}, {UNIMOD_Myristoyl, "spec_3_classification", "Post-translational"}, {UNIMOD_Myristoyl, "spec_3_hidden", "1"}, {UNIMOD_Myristoyl, "spec_3_position", "Anywhere"}, {UNIMOD_Myristoyl, "spec_3_site", "C"}, {UNIMOD_PyridoxalPhosphate, "approved", "1"}, {UNIMOD_PyridoxalPhosphate, "delta_composition", "H(8) C(8) N O(5) P"}, {UNIMOD_PyridoxalPhosphate, "spec_1_classification", "Post-translational"}, {UNIMOD_PyridoxalPhosphate, "spec_1_hidden", "1"}, {UNIMOD_PyridoxalPhosphate, "spec_1_position", "Anywhere"}, {UNIMOD_PyridoxalPhosphate, "spec_1_site", "K"}, {UNIMOD_Palmitoyl, "approved", "1"}, {UNIMOD_Palmitoyl, "delta_composition", "H(30) C(16) O"}, {UNIMOD_Palmitoyl, "spec_1_classification", "Post-translational"}, {UNIMOD_Palmitoyl, "spec_1_hidden", "1"}, {UNIMOD_Palmitoyl, "spec_1_position", "Anywhere"}, {UNIMOD_Palmitoyl, "spec_1_site", "C"}, {UNIMOD_Palmitoyl, "spec_2_classification", "Post-translational"}, {UNIMOD_Palmitoyl, "spec_2_hidden", "1"}, {UNIMOD_Palmitoyl, "spec_2_position", "Anywhere"}, {UNIMOD_Palmitoyl, "spec_2_site", "K"}, {UNIMOD_Palmitoyl, "spec_3_classification", "Post-translational"}, {UNIMOD_Palmitoyl, "spec_3_hidden", "1"}, {UNIMOD_Palmitoyl, "spec_3_position", "Anywhere"}, {UNIMOD_Palmitoyl, "spec_3_site", "S"}, {UNIMOD_Palmitoyl, "spec_4_classification", "Post-translational"}, {UNIMOD_Palmitoyl, "spec_4_hidden", "1"}, {UNIMOD_Palmitoyl, "spec_4_position", "Anywhere"}, {UNIMOD_Palmitoyl, "spec_4_site", "T"}, {UNIMOD_Palmitoyl, "spec_5_classification", "Post-translational"}, {UNIMOD_Palmitoyl, "spec_5_hidden", "1"}, {UNIMOD_Palmitoyl, "spec_5_position", "Protein N-term"}, {UNIMOD_Palmitoyl, "spec_5_site", "N-term"}, {UNIMOD_GeranylGeranyl, "approved", "1"}, {UNIMOD_GeranylGeranyl, "delta_composition", "H(32) C(20)"}, {UNIMOD_GeranylGeranyl, "spec_1_classification", "Post-translational"}, {UNIMOD_GeranylGeranyl, "spec_1_hidden", "1"}, {UNIMOD_GeranylGeranyl, "spec_1_position", "Anywhere"}, {UNIMOD_GeranylGeranyl, "spec_1_site", "C"}, {UNIMOD_Phosphopantetheine, "approved", "1"}, {UNIMOD_Phosphopantetheine, "delta_composition", "H(21) C(11) N(2) O(6) P S"}, {UNIMOD_Phosphopantetheine, "spec_1_classification", "Post-translational"}, {UNIMOD_Phosphopantetheine, "spec_1_hidden", "1"}, {UNIMOD_Phosphopantetheine, "spec_1_position", "Anywhere"}, {UNIMOD_Phosphopantetheine, "spec_1_site", "S"}, {UNIMOD_FAD, "approved", "1"}, {UNIMOD_FAD, "delta_composition", "H(31) C(27) N(9) O(15) P(2)"}, {UNIMOD_FAD, "spec_1_classification", "Post-translational"}, {UNIMOD_FAD, "spec_1_hidden", "1"}, {UNIMOD_FAD, "spec_1_position", "Anywhere"}, {UNIMOD_FAD, "spec_1_site", "C"}, {UNIMOD_FAD, "spec_2_classification", "Post-translational"}, {UNIMOD_FAD, "spec_2_hidden", "1"}, {UNIMOD_FAD, "spec_2_position", "Anywhere"}, {UNIMOD_FAD, "spec_2_site", "H"}, {UNIMOD_FAD, "spec_3_classification", "Post-translational"}, {UNIMOD_FAD, "spec_3_hidden", "1"}, {UNIMOD_FAD, "spec_3_position", "Anywhere"}, {UNIMOD_FAD, "spec_3_site", "Y"}, {UNIMOD_Tripalmitate, "approved", "1"}, {UNIMOD_Tripalmitate, "delta_composition", "H(96) C(51) O(5)"}, {UNIMOD_Tripalmitate, "spec_1_classification", "Post-translational"}, {UNIMOD_Tripalmitate, "spec_1_hidden", "1"}, {UNIMOD_Tripalmitate, "spec_1_position", "Protein N-term"}, {UNIMOD_Tripalmitate, "spec_1_site", "C"}, {UNIMOD_Guanidinyl, "approved", "1"}, {UNIMOD_Guanidinyl, "delta_composition", "H(2) C N(2)"}, {UNIMOD_Guanidinyl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Guanidinyl, "spec_1_hidden", "0"}, {UNIMOD_Guanidinyl, "spec_1_position", "Anywhere"}, {UNIMOD_Guanidinyl, "spec_1_site", "K"}, {UNIMOD_Guanidinyl, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Guanidinyl, "spec_2_hidden", "1"}, {UNIMOD_Guanidinyl, "spec_2_position", "Any N-term"}, {UNIMOD_Guanidinyl, "spec_2_site", "N-term"}, {UNIMOD_HNE, "approved", "1"}, {UNIMOD_HNE, "delta_composition", "H(16) C(9) O(2)"}, {UNIMOD_HNE, "spec_1_classification", "Post-translational"}, {UNIMOD_HNE, "spec_1_hidden", "1"}, {UNIMOD_HNE, "spec_1_position", "Anywhere"}, {UNIMOD_HNE, "spec_1_site", "C"}, {UNIMOD_HNE, "spec_2_classification", "Post-translational"}, {UNIMOD_HNE, "spec_2_hidden", "1"}, {UNIMOD_HNE, "spec_2_position", "Anywhere"}, {UNIMOD_HNE, "spec_2_site", "H"}, {UNIMOD_HNE, "spec_3_classification", "Post-translational"}, {UNIMOD_HNE, "spec_3_hidden", "1"}, {UNIMOD_HNE, "spec_3_position", "Anywhere"}, {UNIMOD_HNE, "spec_3_site", "K"}, {UNIMOD_HNE, "spec_4_classification", "Post-translational"}, {UNIMOD_HNE, "spec_4_hidden", "1"}, {UNIMOD_HNE, "spec_4_position", "Anywhere"}, {UNIMOD_HNE, "spec_4_site", "A"}, {UNIMOD_HNE, "spec_5_classification", "Post-translational"}, {UNIMOD_HNE, "spec_5_hidden", "1"}, {UNIMOD_HNE, "spec_5_position", "Anywhere"}, {UNIMOD_HNE, "spec_5_site", "L"}, {UNIMOD_Glucuronyl, "approved", "1"}, {UNIMOD_Glucuronyl, "delta_composition", "HexA"}, {UNIMOD_Glucuronyl, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Glucuronyl, "spec_1_hidden", "1"}, {UNIMOD_Glucuronyl, "spec_1_position", "Protein N-term"}, {UNIMOD_Glucuronyl, "spec_1_site", "N-term"}, {UNIMOD_Glucuronyl, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Glucuronyl, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Glucuronyl, "spec_2_hidden", "1"}, {UNIMOD_Glucuronyl, "spec_2_hidden", "1"}, {UNIMOD_Glucuronyl, "spec_2_position", "Anywhere"}, {UNIMOD_Glucuronyl, "spec_2_position", "Anywhere"}, {UNIMOD_Glucuronyl, "spec_2_site", "T"}, {UNIMOD_Glucuronyl, "spec_2_site", "S"}, {UNIMOD_Glutathione, "approved", "1"}, {UNIMOD_Glutathione, "delta_composition", "H(15) C(10) N(3) O(6) S"}, {UNIMOD_Glutathione, "spec_1_classification", "Post-translational"}, {UNIMOD_Glutathione, "spec_1_hidden", "1"}, {UNIMOD_Glutathione, "spec_1_position", "Anywhere"}, {UNIMOD_Glutathione, "spec_1_site", "C"}, {UNIMOD_Acetyl_2H_3_, "approved", "1"}, {UNIMOD_Acetyl_2H_3_, "delta_composition", "H(-1) 2H(3) C(2) O"}, {UNIMOD_Acetyl_2H_3_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Acetyl_2H_3_, "spec_1_hidden", "1"}, {UNIMOD_Acetyl_2H_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Acetyl_2H_3_, "spec_1_site", "K"}, {UNIMOD_Acetyl_2H_3_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Acetyl_2H_3_, "spec_2_hidden", "1"}, {UNIMOD_Acetyl_2H_3_, "spec_2_position", "Any N-term"}, {UNIMOD_Acetyl_2H_3_, "spec_2_site", "N-term"}, {UNIMOD_Acetyl_2H_3_, "spec_3_classification", "Isotopic label"}, {UNIMOD_Acetyl_2H_3_, "spec_3_hidden", "1"}, {UNIMOD_Acetyl_2H_3_, "spec_3_position", "Anywhere"}, {UNIMOD_Acetyl_2H_3_, "spec_3_site", "H"}, {UNIMOD_Acetyl_2H_3_, "spec_4_classification", "Isotopic label"}, {UNIMOD_Acetyl_2H_3_, "spec_4_hidden", "1"}, {UNIMOD_Acetyl_2H_3_, "spec_4_position", "Anywhere"}, {UNIMOD_Acetyl_2H_3_, "spec_4_site", "S"}, {UNIMOD_Acetyl_2H_3_, "spec_5_classification", "Isotopic label"}, {UNIMOD_Acetyl_2H_3_, "spec_5_hidden", "1"}, {UNIMOD_Acetyl_2H_3_, "spec_5_position", "Anywhere"}, {UNIMOD_Acetyl_2H_3_, "spec_5_site", "T"}, {UNIMOD_Acetyl_2H_3_, "spec_6_classification", "Isotopic label"}, {UNIMOD_Acetyl_2H_3_, "spec_6_hidden", "1"}, {UNIMOD_Acetyl_2H_3_, "spec_6_position", "Anywhere"}, {UNIMOD_Acetyl_2H_3_, "spec_6_site", "Y"}, {UNIMOD_Acetyl_2H_3_, "spec_7_classification", "Isotopic label"}, {UNIMOD_Acetyl_2H_3_, "spec_7_hidden", "1"}, {UNIMOD_Acetyl_2H_3_, "spec_7_position", "Protein N-term"}, {UNIMOD_Acetyl_2H_3_, "spec_7_site", "N-term"}, {UNIMOD_Propionyl, "approved", "1"}, {UNIMOD_Propionyl, "delta_composition", "H(4) C(3) O"}, {UNIMOD_Propionyl, "spec_1_classification", "Isotopic label"}, {UNIMOD_Propionyl, "spec_1_hidden", "1"}, {UNIMOD_Propionyl, "spec_1_position", "Anywhere"}, {UNIMOD_Propionyl, "spec_1_site", "K"}, {UNIMOD_Propionyl, "spec_2_classification", "Isotopic label"}, {UNIMOD_Propionyl, "spec_2_hidden", "1"}, {UNIMOD_Propionyl, "spec_2_position", "Any N-term"}, {UNIMOD_Propionyl, "spec_2_site", "N-term"}, {UNIMOD_Propionyl, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Propionyl, "spec_3_hidden", "1"}, {UNIMOD_Propionyl, "spec_3_position", "Anywhere"}, {UNIMOD_Propionyl, "spec_3_site", "S"}, {UNIMOD_Propionyl, "spec_4_classification", "Isotopic label"}, {UNIMOD_Propionyl, "spec_4_hidden", "1"}, {UNIMOD_Propionyl, "spec_4_position", "Anywhere"}, {UNIMOD_Propionyl, "spec_4_site", "T"}, {UNIMOD_Propionyl, "spec_5_classification", "Multiple"}, {UNIMOD_Propionyl, "spec_5_hidden", "1"}, {UNIMOD_Propionyl, "spec_5_position", "Protein N-term"}, {UNIMOD_Propionyl, "spec_5_site", "N-term"}, {UNIMOD_Propionyl_13C_3_, "approved", "1"}, {UNIMOD_Propionyl_13C_3_, "delta_composition", "H(4) 13C(3) O"}, {UNIMOD_Propionyl_13C_3_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Propionyl_13C_3_, "spec_1_hidden", "1"}, {UNIMOD_Propionyl_13C_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Propionyl_13C_3_, "spec_1_site", "K"}, {UNIMOD_Propionyl_13C_3_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Propionyl_13C_3_, "spec_2_hidden", "1"}, {UNIMOD_Propionyl_13C_3_, "spec_2_position", "Any N-term"}, {UNIMOD_Propionyl_13C_3_, "spec_2_site", "N-term"}, {UNIMOD_GIST_Quat, "approved", "1"}, {UNIMOD_GIST_Quat, "delta_composition", "H(13) C(7) N O"}, {UNIMOD_GIST_Quat, "spec_1_classification", "Isotopic label"}, {UNIMOD_GIST_Quat, "spec_1_hidden", "1"}, {UNIMOD_GIST_Quat, "spec_1_position", "Anywhere"}, {UNIMOD_GIST_Quat, "spec_1_site", "K"}, {UNIMOD_GIST_Quat, "spec_2_classification", "Isotopic label"}, {UNIMOD_GIST_Quat, "spec_2_hidden", "1"}, {UNIMOD_GIST_Quat, "spec_2_position", "Any N-term"}, {UNIMOD_GIST_Quat, "spec_2_site", "N-term"}, {UNIMOD_GIST_Quat_2H_3_, "approved", "1"}, {UNIMOD_GIST_Quat_2H_3_, "delta_composition", "H(10) 2H(3) C(7) N O"}, {UNIMOD_GIST_Quat_2H_3_, "spec_1_classification", "Isotopic label"}, {UNIMOD_GIST_Quat_2H_3_, "spec_1_hidden", "1"}, {UNIMOD_GIST_Quat_2H_3_, "spec_1_position", "Anywhere"}, {UNIMOD_GIST_Quat_2H_3_, "spec_1_site", "K"}, {UNIMOD_GIST_Quat_2H_3_, "spec_2_classification", "Isotopic label"}, {UNIMOD_GIST_Quat_2H_3_, "spec_2_hidden", "1"}, {UNIMOD_GIST_Quat_2H_3_, "spec_2_position", "Any N-term"}, {UNIMOD_GIST_Quat_2H_3_, "spec_2_site", "N-term"}, {UNIMOD_GIST_Quat_2H_6_, "approved", "1"}, {UNIMOD_GIST_Quat_2H_6_, "delta_composition", "H(7) 2H(6) C(7) N O"}, {UNIMOD_GIST_Quat_2H_6_, "spec_1_classification", "Isotopic label"}, {UNIMOD_GIST_Quat_2H_6_, "spec_1_hidden", "1"}, {UNIMOD_GIST_Quat_2H_6_, "spec_1_position", "Anywhere"}, {UNIMOD_GIST_Quat_2H_6_, "spec_1_site", "K"}, {UNIMOD_GIST_Quat_2H_6_, "spec_2_classification", "Isotopic label"}, {UNIMOD_GIST_Quat_2H_6_, "spec_2_hidden", "1"}, {UNIMOD_GIST_Quat_2H_6_, "spec_2_position", "Any N-term"}, {UNIMOD_GIST_Quat_2H_6_, "spec_2_site", "N-term"}, {UNIMOD_GIST_Quat_2H_9_, "approved", "1"}, {UNIMOD_GIST_Quat_2H_9_, "delta_composition", "H(4) 2H(9) C(7) N O"}, {UNIMOD_GIST_Quat_2H_9_, "spec_1_classification", "Isotopic label"}, {UNIMOD_GIST_Quat_2H_9_, "spec_1_hidden", "1"}, {UNIMOD_GIST_Quat_2H_9_, "spec_1_position", "Anywhere"}, {UNIMOD_GIST_Quat_2H_9_, "spec_1_site", "K"}, {UNIMOD_GIST_Quat_2H_9_, "spec_2_classification", "Isotopic label"}, {UNIMOD_GIST_Quat_2H_9_, "spec_2_hidden", "1"}, {UNIMOD_GIST_Quat_2H_9_, "spec_2_position", "Any N-term"}, {UNIMOD_GIST_Quat_2H_9_, "spec_2_site", "N-term"}, {UNIMOD_Succinyl, "approved", "1"}, {UNIMOD_Succinyl, "delta_composition", "H(4) C(4) O(3)"}, {UNIMOD_Succinyl, "spec_1_classification", "Isotopic label"}, {UNIMOD_Succinyl, "spec_1_hidden", "1"}, {UNIMOD_Succinyl, "spec_1_position", "Anywhere"}, {UNIMOD_Succinyl, "spec_1_site", "K"}, {UNIMOD_Succinyl, "spec_2_classification", "Isotopic label"}, {UNIMOD_Succinyl, "spec_2_hidden", "1"}, {UNIMOD_Succinyl, "spec_2_position", "Any N-term"}, {UNIMOD_Succinyl, "spec_2_site", "N-term"}, {UNIMOD_Succinyl, "spec_3_classification", "Post-translational"}, {UNIMOD_Succinyl, "spec_3_hidden", "1"}, {UNIMOD_Succinyl, "spec_3_position", "Protein N-term"}, {UNIMOD_Succinyl, "spec_3_site", "N-term"}, {UNIMOD_Succinyl_2H_4_, "approved", "1"}, {UNIMOD_Succinyl_2H_4_, "delta_composition", "2H(4) C(4) O(3)"}, {UNIMOD_Succinyl_2H_4_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Succinyl_2H_4_, "spec_1_hidden", "1"}, {UNIMOD_Succinyl_2H_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Succinyl_2H_4_, "spec_1_site", "K"}, {UNIMOD_Succinyl_2H_4_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Succinyl_2H_4_, "spec_2_hidden", "1"}, {UNIMOD_Succinyl_2H_4_, "spec_2_position", "Any N-term"}, {UNIMOD_Succinyl_2H_4_, "spec_2_site", "N-term"}, {UNIMOD_Succinyl_13C_4_, "approved", "1"}, {UNIMOD_Succinyl_13C_4_, "delta_composition", "H(4) 13C(4) O(3)"}, {UNIMOD_Succinyl_13C_4_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Succinyl_13C_4_, "spec_1_hidden", "1"}, {UNIMOD_Succinyl_13C_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Succinyl_13C_4_, "spec_1_site", "K"}, {UNIMOD_Succinyl_13C_4_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Succinyl_13C_4_, "spec_2_hidden", "1"}, {UNIMOD_Succinyl_13C_4_, "spec_2_position", "Any N-term"}, {UNIMOD_Succinyl_13C_4_, "spec_2_site", "N-term"}, {UNIMOD_Iminobiotin, "approved", "1"}, {UNIMOD_Iminobiotin, "delta_composition", "H(15) C(10) N(3) O S"}, {UNIMOD_Iminobiotin, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Iminobiotin, "spec_1_hidden", "1"}, {UNIMOD_Iminobiotin, "spec_1_position", "Anywhere"}, {UNIMOD_Iminobiotin, "spec_1_site", "K"}, {UNIMOD_Iminobiotin, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Iminobiotin, "spec_2_hidden", "1"}, {UNIMOD_Iminobiotin, "spec_2_position", "Any N-term"}, {UNIMOD_Iminobiotin, "spec_2_site", "N-term"}, {UNIMOD_ESP, "approved", "1"}, {UNIMOD_ESP, "delta_composition", "H(26) C(16) N(4) O(2) S"}, {UNIMOD_ESP, "spec_1_classification", "Isotopic label"}, {UNIMOD_ESP, "spec_1_hidden", "1"}, {UNIMOD_ESP, "spec_1_position", "Anywhere"}, {UNIMOD_ESP, "spec_1_site", "K"}, {UNIMOD_ESP, "spec_2_classification", "Isotopic label"}, {UNIMOD_ESP, "spec_2_hidden", "1"}, {UNIMOD_ESP, "spec_2_position", "Any N-term"}, {UNIMOD_ESP, "spec_2_site", "N-term"}, {UNIMOD_ESP_2H_10_, "approved", "1"}, {UNIMOD_ESP_2H_10_, "delta_composition", "H(16) 2H(10) C(16) N(4) O(2) S"}, {UNIMOD_ESP_2H_10_, "spec_1_classification", "Isotopic label"}, {UNIMOD_ESP_2H_10_, "spec_1_hidden", "1"}, {UNIMOD_ESP_2H_10_, "spec_1_position", "Anywhere"}, {UNIMOD_ESP_2H_10_, "spec_1_site", "K"}, {UNIMOD_ESP_2H_10_, "spec_2_classification", "Isotopic label"}, {UNIMOD_ESP_2H_10_, "spec_2_hidden", "1"}, {UNIMOD_ESP_2H_10_, "spec_2_position", "Any N-term"}, {UNIMOD_ESP_2H_10_, "spec_2_site", "N-term"}, {UNIMOD_NHS_LC_Biotin, "approved", "0"}, {UNIMOD_NHS_LC_Biotin, "delta_composition", "H(25) C(16) N(3) O(3) S"}, {UNIMOD_NHS_LC_Biotin, "spec_1_classification", "Chemical derivative"}, {UNIMOD_NHS_LC_Biotin, "spec_1_hidden", "1"}, {UNIMOD_NHS_LC_Biotin, "spec_1_position", "Anywhere"}, {UNIMOD_NHS_LC_Biotin, "spec_1_site", "K"}, {UNIMOD_NHS_LC_Biotin, "spec_2_classification", "Chemical derivative"}, {UNIMOD_NHS_LC_Biotin, "spec_2_hidden", "1"}, {UNIMOD_NHS_LC_Biotin, "spec_2_position", "Any N-term"}, {UNIMOD_NHS_LC_Biotin, "spec_2_site", "N-term"}, {UNIMOD_EDT_maleimide_PEO_biotin, "approved", "0"}, {UNIMOD_EDT_maleimide_PEO_biotin, "delta_composition", "H(39) C(25) N(5) O(6) S(3)"}, {UNIMOD_EDT_maleimide_PEO_biotin, "spec_1_classification", "Chemical derivative"}, {UNIMOD_EDT_maleimide_PEO_biotin, "spec_1_hidden", "1"}, {UNIMOD_EDT_maleimide_PEO_biotin, "spec_1_position", "Anywhere"}, {UNIMOD_EDT_maleimide_PEO_biotin, "spec_1_site", "S"}, {UNIMOD_EDT_maleimide_PEO_biotin, "spec_2_classification", "Chemical derivative"}, {UNIMOD_EDT_maleimide_PEO_biotin, "spec_2_hidden", "1"}, {UNIMOD_EDT_maleimide_PEO_biotin, "spec_2_position", "Anywhere"}, {UNIMOD_EDT_maleimide_PEO_biotin, "spec_2_site", "T"}, {UNIMOD_IMID, "approved", "1"}, {UNIMOD_IMID, "delta_composition", "H(4) C(3) N(2)"}, {UNIMOD_IMID, "spec_1_classification", "Isotopic label"}, {UNIMOD_IMID, "spec_1_hidden", "1"}, {UNIMOD_IMID, "spec_1_position", "Anywhere"}, {UNIMOD_IMID, "spec_1_site", "K"}, {UNIMOD_IMID_2H_4_, "approved", "1"}, {UNIMOD_IMID_2H_4_, "delta_composition", "2H(4) C(3) N(2)"}, {UNIMOD_IMID_2H_4_, "spec_1_classification", "Isotopic label"}, {UNIMOD_IMID_2H_4_, "spec_1_hidden", "1"}, {UNIMOD_IMID_2H_4_, "spec_1_position", "Anywhere"}, {UNIMOD_IMID_2H_4_, "spec_1_site", "K"}, {UNIMOD_Propionamide_2H_3_, "approved", "1"}, {UNIMOD_Propionamide_2H_3_, "delta_composition", "H(2) 2H(3) C(3) N O"}, {UNIMOD_Propionamide_2H_3_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Propionamide_2H_3_, "spec_1_hidden", "1"}, {UNIMOD_Propionamide_2H_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Propionamide_2H_3_, "spec_1_site", "C"}, {UNIMOD_ICAT_C, "approved", "1"}, {UNIMOD_ICAT_C, "delta_composition", "H(17) C(10) N(3) O(3)"}, {UNIMOD_ICAT_C, "spec_1_classification", "Isotopic label"}, {UNIMOD_ICAT_C, "spec_1_hidden", "0"}, {UNIMOD_ICAT_C, "spec_1_position", "Anywhere"}, {UNIMOD_ICAT_C, "spec_1_site", "C"}, {UNIMOD_ICAT_C_13C_9_, "approved", "1"}, {UNIMOD_ICAT_C_13C_9_, "delta_composition", "H(17) C 13C(9) N(3) O(3)"}, {UNIMOD_ICAT_C_13C_9_, "spec_1_classification", "Isotopic label"}, {UNIMOD_ICAT_C_13C_9_, "spec_1_hidden", "0"}, {UNIMOD_ICAT_C_13C_9_, "spec_1_position", "Anywhere"}, {UNIMOD_ICAT_C_13C_9_, "spec_1_site", "C"}, {UNIMOD_FormylMet, "approved", "1"}, {UNIMOD_FormylMet, "delta_composition", "H(9) C(6) N O(2) S"}, {UNIMOD_FormylMet, "spec_1_classification", "Pre-translational"}, {UNIMOD_FormylMet, "spec_1_hidden", "1"}, {UNIMOD_FormylMet, "spec_1_position", "Protein N-term"}, {UNIMOD_FormylMet, "spec_1_site", "N-term"}, {UNIMOD_Nethylmaleimide, "approved", "1"}, {UNIMOD_Nethylmaleimide, "delta_composition", "H(7) C(6) N O(2)"}, {UNIMOD_Nethylmaleimide, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Nethylmaleimide, "spec_1_hidden", "1"}, {UNIMOD_Nethylmaleimide, "spec_1_position", "Anywhere"}, {UNIMOD_Nethylmaleimide, "spec_1_site", "C"}, {UNIMOD_OxLysBiotinRed, "approved", "0"}, {UNIMOD_OxLysBiotinRed, "delta_composition", "H(26) C(16) N(4) O(3) S"}, {UNIMOD_OxLysBiotinRed, "spec_1_classification", "Chemical derivative"}, {UNIMOD_OxLysBiotinRed, "spec_1_hidden", "1"}, {UNIMOD_OxLysBiotinRed, "spec_1_position", "Anywhere"}, {UNIMOD_OxLysBiotinRed, "spec_1_site", "K"}, {UNIMOD_OxLysBiotin, "approved", "0"}, {UNIMOD_OxLysBiotin, "delta_composition", "H(24) C(16) N(4) O(3) S"}, {UNIMOD_OxLysBiotin, "spec_1_classification", "Chemical derivative"}, {UNIMOD_OxLysBiotin, "spec_1_hidden", "1"}, {UNIMOD_OxLysBiotin, "spec_1_position", "Anywhere"}, {UNIMOD_OxLysBiotin, "spec_1_site", "K"}, {UNIMOD_OxProBiotinRed, "approved", "0"}, {UNIMOD_OxProBiotinRed, "delta_composition", "H(29) C(16) N(5) O(3) S"}, {UNIMOD_OxProBiotinRed, "spec_1_classification", "Chemical derivative"}, {UNIMOD_OxProBiotinRed, "spec_1_hidden", "1"}, {UNIMOD_OxProBiotinRed, "spec_1_position", "Anywhere"}, {UNIMOD_OxProBiotinRed, "spec_1_site", "P"}, {UNIMOD_OxProBiotin, "approved", "0"}, {UNIMOD_OxProBiotin, "delta_composition", "H(27) C(16) N(5) O(3) S"}, {UNIMOD_OxProBiotin, "spec_1_classification", "Chemical derivative"}, {UNIMOD_OxProBiotin, "spec_1_hidden", "1"}, {UNIMOD_OxProBiotin, "spec_1_position", "Anywhere"}, {UNIMOD_OxProBiotin, "spec_1_site", "P"}, {UNIMOD_OxArgBiotin, "approved", "0"}, {UNIMOD_OxArgBiotin, "delta_composition", "H(22) C(15) N(2) O(3) S"}, {UNIMOD_OxArgBiotin, "spec_1_classification", "Chemical derivative"}, {UNIMOD_OxArgBiotin, "spec_1_hidden", "1"}, {UNIMOD_OxArgBiotin, "spec_1_position", "Anywhere"}, {UNIMOD_OxArgBiotin, "spec_1_site", "R"}, {UNIMOD_OxArgBiotinRed, "approved", "0"}, {UNIMOD_OxArgBiotinRed, "delta_composition", "H(24) C(15) N(2) O(3) S"}, {UNIMOD_OxArgBiotinRed, "spec_1_classification", "Chemical derivative"}, {UNIMOD_OxArgBiotinRed, "spec_1_hidden", "1"}, {UNIMOD_OxArgBiotinRed, "spec_1_position", "Anywhere"}, {UNIMOD_OxArgBiotinRed, "spec_1_site", "R"}, {UNIMOD_EDT_iodoacetyl_PEO_biotin, "approved", "1"}, {UNIMOD_EDT_iodoacetyl_PEO_biotin, "delta_composition", "H(34) C(20) N(4) O(4) S(3)"}, {UNIMOD_EDT_iodoacetyl_PEO_biotin, "spec_1_classification", "Chemical derivative"}, {UNIMOD_EDT_iodoacetyl_PEO_biotin, "spec_1_hidden", "1"}, {UNIMOD_EDT_iodoacetyl_PEO_biotin, "spec_1_position", "Anywhere"}, {UNIMOD_EDT_iodoacetyl_PEO_biotin, "spec_1_site", "S"}, {UNIMOD_EDT_iodoacetyl_PEO_biotin, "spec_2_classification", "Chemical derivative"}, {UNIMOD_EDT_iodoacetyl_PEO_biotin, "spec_2_hidden", "1"}, {UNIMOD_EDT_iodoacetyl_PEO_biotin, "spec_2_position", "Anywhere"}, {UNIMOD_EDT_iodoacetyl_PEO_biotin, "spec_2_site", "T"}, {UNIMOD_IBTP, "approved", "1"}, {UNIMOD_IBTP, "delta_composition", "H(21) C(22) P"}, {UNIMOD_IBTP, "spec_1_classification", "Chemical derivative"}, {UNIMOD_IBTP, "spec_1_hidden", "1"}, {UNIMOD_IBTP, "spec_1_position", "Anywhere"}, {UNIMOD_IBTP, "spec_1_site", "C"}, {UNIMOD_GG, "approved", "1"}, {UNIMOD_GG, "delta_composition", "H(6) C(4) N(2) O(2)"}, {UNIMOD_GG, "spec_1_classification", "Other"}, {UNIMOD_GG, "spec_1_hidden", "1"}, {UNIMOD_GG, "spec_1_position", "Anywhere"}, {UNIMOD_GG, "spec_1_site", "K"}, {UNIMOD_GG, "spec_2_classification", "Other"}, {UNIMOD_GG, "spec_2_hidden", "1"}, {UNIMOD_GG, "spec_2_position", "Anywhere"}, {UNIMOD_GG, "spec_2_site", "S"}, {UNIMOD_GG, "spec_3_classification", "Other"}, {UNIMOD_GG, "spec_3_hidden", "1"}, {UNIMOD_GG, "spec_3_position", "Anywhere"}, {UNIMOD_GG, "spec_3_site", "T"}, {UNIMOD_GG, "spec_4_classification", "Other"}, {UNIMOD_GG, "spec_4_hidden", "1"}, {UNIMOD_GG, "spec_4_position", "Anywhere"}, {UNIMOD_GG, "spec_4_site", "C"}, {UNIMOD_Formyl, "approved", "1"}, {UNIMOD_Formyl, "delta_composition", "C O"}, {UNIMOD_Formyl, "spec_1_classification", "Artefact"}, {UNIMOD_Formyl, "spec_1_hidden", "1"}, {UNIMOD_Formyl, "spec_1_position", "Anywhere"}, {UNIMOD_Formyl, "spec_1_site", "K"}, {UNIMOD_Formyl, "spec_2_classification", "Artefact"}, {UNIMOD_Formyl, "spec_2_hidden", "0"}, {UNIMOD_Formyl, "spec_2_position", "Any N-term"}, {UNIMOD_Formyl, "spec_2_site", "N-term"}, {UNIMOD_Formyl, "spec_3_classification", "Artefact"}, {UNIMOD_Formyl, "spec_3_hidden", "1"}, {UNIMOD_Formyl, "spec_3_position", "Anywhere"}, {UNIMOD_Formyl, "spec_3_site", "S"}, {UNIMOD_Formyl, "spec_4_classification", "Artefact"}, {UNIMOD_Formyl, "spec_4_hidden", "1"}, {UNIMOD_Formyl, "spec_4_position", "Anywhere"}, {UNIMOD_Formyl, "spec_4_site", "T"}, {UNIMOD_Formyl, "spec_5_classification", "Post-translational"}, {UNIMOD_Formyl, "spec_5_hidden", "0"}, {UNIMOD_Formyl, "spec_5_position", "Protein N-term"}, {UNIMOD_Formyl, "spec_5_site", "N-term"}, {UNIMOD_ICAT_H, "approved", "1"}, {UNIMOD_ICAT_H, "delta_composition", "H(20) C(15) N O(6) Cl"}, {UNIMOD_ICAT_H, "spec_1_classification", "Isotopic label"}, {UNIMOD_ICAT_H, "spec_1_hidden", "1"}, {UNIMOD_ICAT_H, "spec_1_position", "Anywhere"}, {UNIMOD_ICAT_H, "spec_1_site", "C"}, {UNIMOD_ICAT_H_13C_6_, "approved", "1"}, {UNIMOD_ICAT_H_13C_6_, "delta_composition", "H(20) C(9) 13C(6) N O(6) Cl"}, {UNIMOD_ICAT_H_13C_6_, "spec_1_classification", "Isotopic label"}, {UNIMOD_ICAT_H_13C_6_, "spec_1_hidden", "1"}, {UNIMOD_ICAT_H_13C_6_, "spec_1_position", "Anywhere"}, {UNIMOD_ICAT_H_13C_6_, "spec_1_site", "C"}, {UNIMOD_Thioacyl, "approved", "1"}, {UNIMOD_Thioacyl, "delta_composition", "H(4) C(3) O S"}, {UNIMOD_Thioacyl, "spec_1_classification", "Other"}, {UNIMOD_Thioacyl, "spec_1_hidden", "1"}, {UNIMOD_Thioacyl, "spec_1_position", "Anywhere"}, {UNIMOD_Thioacyl, "spec_1_site", "K"}, {UNIMOD_Thioacyl, "spec_2_classification", "Other"}, {UNIMOD_Thioacyl, "spec_2_hidden", "1"}, {UNIMOD_Thioacyl, "spec_2_position", "Anywhere"}, {UNIMOD_Thioacyl, "spec_2_site", "N-term"}, {UNIMOD_Fluoro, "approved", "1"}, {UNIMOD_Fluoro, "delta_composition", "H(-1) F"}, {UNIMOD_Fluoro, "spec_1_classification", "Non-standard residue"}, {UNIMOD_Fluoro, "spec_1_hidden", "1"}, {UNIMOD_Fluoro, "spec_1_position", "Anywhere"}, {UNIMOD_Fluoro, "spec_1_site", "F"}, {UNIMOD_Fluoro, "spec_2_classification", "Non-standard residue"}, {UNIMOD_Fluoro, "spec_2_hidden", "1"}, {UNIMOD_Fluoro, "spec_2_position", "Anywhere"}, {UNIMOD_Fluoro, "spec_2_site", "W"}, {UNIMOD_Fluoro, "spec_3_classification", "Non-standard residue"}, {UNIMOD_Fluoro, "spec_3_hidden", "1"}, {UNIMOD_Fluoro, "spec_3_position", "Anywhere"}, {UNIMOD_Fluoro, "spec_3_site", "Y"}, {UNIMOD_Fluoro, "spec_4_classification", "Chemical derivative"}, {UNIMOD_Fluoro, "spec_4_hidden", "1"}, {UNIMOD_Fluoro, "spec_4_position", "Anywhere"}, {UNIMOD_Fluoro, "spec_4_site", "A"}, {UNIMOD_Fluorescein, "approved", "1"}, {UNIMOD_Fluorescein, "delta_composition", "H(14) C(22) N O(6)"}, {UNIMOD_Fluorescein, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Fluorescein, "spec_1_hidden", "1"}, {UNIMOD_Fluorescein, "spec_1_position", "Anywhere"}, {UNIMOD_Fluorescein, "spec_1_site", "C"}, {UNIMOD_Iodo, "approved", "1"}, {UNIMOD_Iodo, "delta_composition", "H(-1) I"}, {UNIMOD_Iodo, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Iodo, "spec_1_hidden", "1"}, {UNIMOD_Iodo, "spec_1_position", "Anywhere"}, {UNIMOD_Iodo, "spec_1_site", "Y"}, {UNIMOD_Iodo, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Iodo, "spec_2_hidden", "1"}, {UNIMOD_Iodo, "spec_2_position", "Anywhere"}, {UNIMOD_Iodo, "spec_2_site", "H"}, {UNIMOD_Diiodo, "approved", "1"}, {UNIMOD_Diiodo, "delta_composition", "H(-2) I(2)"}, {UNIMOD_Diiodo, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Diiodo, "spec_1_hidden", "1"}, {UNIMOD_Diiodo, "spec_1_position", "Anywhere"}, {UNIMOD_Diiodo, "spec_1_site", "Y"}, {UNIMOD_Diiodo, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Diiodo, "spec_2_hidden", "1"}, {UNIMOD_Diiodo, "spec_2_position", "Anywhere"}, {UNIMOD_Diiodo, "spec_2_site", "H"}, {UNIMOD_Triiodo, "approved", "1"}, {UNIMOD_Triiodo, "delta_composition", "H(-3) I(3)"}, {UNIMOD_Triiodo, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Triiodo, "spec_1_hidden", "1"}, {UNIMOD_Triiodo, "spec_1_position", "Anywhere"}, {UNIMOD_Triiodo, "spec_1_site", "Y"}, {UNIMOD_Myristoleyl, "approved", "1"}, {UNIMOD_Myristoleyl, "delta_composition", "H(24) C(14) O"}, {UNIMOD_Myristoleyl, "spec_1_classification", "Co-translational"}, {UNIMOD_Myristoleyl, "spec_1_hidden", "1"}, {UNIMOD_Myristoleyl, "spec_1_position", "Protein N-term"}, {UNIMOD_Myristoleyl, "spec_1_site", "G"}, {UNIMOD_Myristoyl_Delta_H__4_, "approved", "1"}, {UNIMOD_Myristoyl_Delta_H__4_, "delta_composition", "H(22) C(14) O"}, {UNIMOD_Myristoyl_Delta_H__4_, "spec_1_classification", "Co-translational"}, {UNIMOD_Myristoyl_Delta_H__4_, "spec_1_hidden", "1"}, {UNIMOD_Myristoyl_Delta_H__4_, "spec_1_position", "Protein N-term"}, {UNIMOD_Myristoyl_Delta_H__4_, "spec_1_site", "G"}, {UNIMOD_Benzoyl, "approved", "1"}, {UNIMOD_Benzoyl, "delta_composition", "H(4) C(7) O"}, {UNIMOD_Benzoyl, "spec_1_classification", "Isotopic label"}, {UNIMOD_Benzoyl, "spec_1_hidden", "1"}, {UNIMOD_Benzoyl, "spec_1_position", "Anywhere"}, {UNIMOD_Benzoyl, "spec_1_site", "K"}, {UNIMOD_Benzoyl, "spec_2_classification", "Isotopic label"}, {UNIMOD_Benzoyl, "spec_2_hidden", "1"}, {UNIMOD_Benzoyl, "spec_2_position", "Any N-term"}, {UNIMOD_Benzoyl, "spec_2_site", "N-term"}, {UNIMOD_Hex_5_HexNAc_2_, "approved", "1"}, {UNIMOD_Hex_5_HexNAc_2_, "delta_composition", "Hex(5) HexNAc(2)"}, {UNIMOD_Hex_5_HexNAc_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_5_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_HexNAc_2_, "spec_1_site", "N"}, {UNIMOD_Dansyl, "approved", "1"}, {UNIMOD_Dansyl, "delta_composition", "H(11) C(12) N O(2) S"}, {UNIMOD_Dansyl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Dansyl, "spec_1_hidden", "1"}, {UNIMOD_Dansyl, "spec_1_position", "Anywhere"}, {UNIMOD_Dansyl, "spec_1_site", "K"}, {UNIMOD_Dansyl, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Dansyl, "spec_2_hidden", "1"}, {UNIMOD_Dansyl, "spec_2_position", "Any N-term"}, {UNIMOD_Dansyl, "spec_2_site", "N-term"}, {UNIMOD_a_type_ion, "approved", "0"}, {UNIMOD_a_type_ion, "delta_composition", "H(-2) C(-1) O(-2)"}, {UNIMOD_a_type_ion, "spec_1_classification", "Other"}, {UNIMOD_a_type_ion, "spec_1_hidden", "1"}, {UNIMOD_a_type_ion, "spec_1_position", "Any C-term"}, {UNIMOD_a_type_ion, "spec_1_site", "C-term"}, {UNIMOD_Amidine, "approved", "1"}, {UNIMOD_Amidine, "delta_composition", "H(3) C(2) N"}, {UNIMOD_Amidine, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Amidine, "spec_1_hidden", "1"}, {UNIMOD_Amidine, "spec_1_position", "Anywhere"}, {UNIMOD_Amidine, "spec_1_site", "K"}, {UNIMOD_Amidine, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Amidine, "spec_2_hidden", "1"}, {UNIMOD_Amidine, "spec_2_position", "Any N-term"}, {UNIMOD_Amidine, "spec_2_site", "N-term"}, {UNIMOD_HexNAc_1_dHex_1_, "approved", "1"}, {UNIMOD_HexNAc_1_dHex_1_, "delta_composition", "dHex HexNAc"}, {UNIMOD_HexNAc_1_dHex_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_HexNAc_1_dHex_1_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_1_dHex_1_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_1_dHex_1_, "spec_1_site", "N"}, {UNIMOD_HexNAc_1_dHex_1_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_1_dHex_1_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_1_dHex_1_, "spec_2_hidden", "1"}, {UNIMOD_HexNAc_1_dHex_1_, "spec_2_hidden", "1"}, {UNIMOD_HexNAc_1_dHex_1_, "spec_2_position", "Anywhere"}, {UNIMOD_HexNAc_1_dHex_1_, "spec_2_position", "Anywhere"}, {UNIMOD_HexNAc_1_dHex_1_, "spec_2_site", "T"}, {UNIMOD_HexNAc_1_dHex_1_, "spec_2_site", "S"}, {UNIMOD_HexNAc_2_, "approved", "1"}, {UNIMOD_HexNAc_2_, "delta_composition", "HexNAc(2)"}, {UNIMOD_HexNAc_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_2_, "spec_1_site", "N"}, {UNIMOD_HexNAc_2_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_2_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_2_, "spec_2_hidden", "1"}, {UNIMOD_HexNAc_2_, "spec_2_hidden", "1"}, {UNIMOD_HexNAc_2_, "spec_2_position", "Anywhere"}, {UNIMOD_HexNAc_2_, "spec_2_position", "Anywhere"}, {UNIMOD_HexNAc_2_, "spec_2_site", "T"}, {UNIMOD_HexNAc_2_, "spec_2_site", "S"}, {UNIMOD_Hex_3_, "approved", "1"}, {UNIMOD_Hex_3_, "delta_composition", "Hex(3)"}, {UNIMOD_Hex_3_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_, "spec_1_site", "N"}, {UNIMOD_Hex_3_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_, "spec_2_hidden", "1"}, {UNIMOD_Hex_3_, "spec_2_hidden", "1"}, {UNIMOD_Hex_3_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_3_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_3_, "spec_2_site", "T"}, {UNIMOD_Hex_3_, "spec_2_site", "S"}, {UNIMOD_HexNAc_1_dHex_2_, "approved", "1"}, {UNIMOD_HexNAc_1_dHex_2_, "delta_composition", "dHex(2) HexNAc"}, {UNIMOD_HexNAc_1_dHex_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_HexNAc_1_dHex_2_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_1_dHex_2_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_1_dHex_2_, "spec_1_site", "N"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_, "approved", "1"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_, "delta_composition", "dHex Hex HexNAc"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_, "spec_1_site", "N"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_, "spec_2_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_, "spec_2_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_, "spec_2_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_, "spec_2_site", "S"}, {UNIMOD_HexNAc_2_dHex_1_, "approved", "1"}, {UNIMOD_HexNAc_2_dHex_1_, "delta_composition", "dHex HexNAc(2)"}, {UNIMOD_HexNAc_2_dHex_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_HexNAc_2_dHex_1_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_2_dHex_1_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_2_dHex_1_, "spec_1_site", "N"}, {UNIMOD_Hex_1_HexNAc_2_, "approved", "1"}, {UNIMOD_Hex_1_HexNAc_2_, "delta_composition", "Hex HexNAc(2)"}, {UNIMOD_Hex_1_HexNAc_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_, "spec_1_site", "N"}, {UNIMOD_Hex_1_HexNAc_2_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_, "spec_2_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_, "spec_2_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_, "spec_2_site", "T"}, {UNIMOD_Hex_1_HexNAc_2_, "spec_2_site", "S"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_, "approved", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_, "delta_composition", "Hex HexNAc NeuAc"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_, "spec_1_site", "N"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_, "spec_2_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_, "spec_2_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_, "spec_2_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_, "spec_2_site", "S"}, {UNIMOD_HexNAc_2_dHex_2_, "approved", "1"}, {UNIMOD_HexNAc_2_dHex_2_, "delta_composition", "dHex(2) HexNAc(2)"}, {UNIMOD_HexNAc_2_dHex_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_HexNAc_2_dHex_2_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_2_dHex_2_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_2_dHex_2_, "spec_1_site", "N"}, {UNIMOD_Hex_1_HexNAc_2_Pent_1_, "approved", "1"}, {UNIMOD_Hex_1_HexNAc_2_Pent_1_, "delta_composition", "Pent Hex HexNAc(2)"}, {UNIMOD_Hex_1_HexNAc_2_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_Pent_1_, "spec_1_site", "N"}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_, "approved", "1"}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_, "delta_composition", "dHex Hex HexNAc(2)"}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_, "spec_1_site", "N"}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_, "spec_2_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_, "spec_2_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_, "spec_2_site", "T"}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_, "spec_2_site", "S"}, {UNIMOD_Hex_2_HexNAc_2_, "approved", "1"}, {UNIMOD_Hex_2_HexNAc_2_, "delta_composition", "Hex(2) HexNAc(2)"}, {UNIMOD_Hex_2_HexNAc_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_2_, "spec_1_site", "N"}, {UNIMOD_Hex_2_HexNAc_2_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_2_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_2_, "spec_2_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_2_, "spec_2_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_2_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_2_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_2_, "spec_2_site", "T"}, {UNIMOD_Hex_2_HexNAc_2_, "spec_2_site", "S"}, {UNIMOD_Hex_3_HexNAc_1_Pent_1_, "approved", "1"}, {UNIMOD_Hex_3_HexNAc_1_Pent_1_, "delta_composition", "Pent Hex(3) HexNAc"}, {UNIMOD_Hex_3_HexNAc_1_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_1_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_1_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_1_Pent_1_, "spec_1_site", "N"}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_Pent_1_, "approved", "1"}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_Pent_1_, "delta_composition", "Pent dHex Hex HexNAc(2)"}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_dHex_1_Pent_1_, "spec_1_site", "N"}, {UNIMOD_Hex_1_HexNAc_2_dHex_2_, "approved", "1"}, {UNIMOD_Hex_1_HexNAc_2_dHex_2_, "delta_composition", "dHex(2) Hex HexNAc(2)"}, {UNIMOD_Hex_1_HexNAc_2_dHex_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_dHex_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_dHex_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_dHex_2_, "spec_1_site", "N"}, {UNIMOD_Hex_1_HexNAc_2_dHex_2_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_dHex_2_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_dHex_2_, "spec_2_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_dHex_2_, "spec_2_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_dHex_2_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_dHex_2_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_dHex_2_, "spec_2_site", "T"}, {UNIMOD_Hex_1_HexNAc_2_dHex_2_, "spec_2_site", "S"}, {UNIMOD_Hex_2_HexNAc_2_Pent_1_, "approved", "1"}, {UNIMOD_Hex_2_HexNAc_2_Pent_1_, "delta_composition", "Pent Hex(2) HexNAc(2)"}, {UNIMOD_Hex_2_HexNAc_2_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_2_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_2_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_2_Pent_1_, "spec_1_site", "N"}, {UNIMOD_Hex_2_HexNAc_2_dHex_1_, "approved", "1"}, {UNIMOD_Hex_2_HexNAc_2_dHex_1_, "delta_composition", "dHex Hex(2) HexNAc(2)"}, {UNIMOD_Hex_2_HexNAc_2_dHex_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_2_dHex_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_2_dHex_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_2_dHex_1_, "spec_1_site", "N"}, {UNIMOD_Hex_2_HexNAc_2_dHex_1_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_2_dHex_1_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_2_dHex_1_, "spec_2_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_2_dHex_1_, "spec_2_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_2_dHex_1_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_2_dHex_1_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_2_dHex_1_, "spec_2_site", "T"}, {UNIMOD_Hex_2_HexNAc_2_dHex_1_, "spec_2_site", "S"}, {UNIMOD_Hex_3_HexNAc_2_, "approved", "1"}, {UNIMOD_Hex_3_HexNAc_2_, "delta_composition", "Hex(3) HexNAc(2)"}, {UNIMOD_Hex_3_HexNAc_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_2_, "spec_1_site", "N"}, {UNIMOD_Hex_3_HexNAc_2_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_2_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_2_, "spec_2_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_2_, "spec_2_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_2_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_2_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_2_, "spec_2_site", "T"}, {UNIMOD_Hex_3_HexNAc_2_, "spec_2_site", "S"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_, "approved", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_, "delta_composition", "Hex HexNAc NeuAc(2)"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_, "spec_1_site", "N"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_, "spec_2_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_, "spec_2_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_, "spec_2_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_, "spec_2_site", "S"}, {UNIMOD_Hex_3_HexNAc_2_Phos_1_, "approved", "1"}, {UNIMOD_Hex_3_HexNAc_2_Phos_1_, "delta_composition", "H O(3) P Hex(3) HexNAc(2)"}, {UNIMOD_Hex_3_HexNAc_2_Phos_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_2_Phos_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_2_Phos_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_2_Phos_1_, "spec_1_site", "N"}, {UNIMOD_Delta_S__1_Se_1_, "approved", "1"}, {UNIMOD_Delta_S__1_Se_1_, "delta_composition", "S(-1) Se"}, {UNIMOD_Delta_S__1_Se_1_, "spec_1_classification", "Non-standard residue"}, {UNIMOD_Delta_S__1_Se_1_, "spec_1_hidden", "1"}, {UNIMOD_Delta_S__1_Se_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Delta_S__1_Se_1_, "spec_1_site", "M"}, {UNIMOD_Delta_S__1_Se_1_, "spec_2_classification", "Non-standard residue"}, {UNIMOD_Delta_S__1_Se_1_, "spec_2_hidden", "1"}, {UNIMOD_Delta_S__1_Se_1_, "spec_2_position", "Anywhere"}, {UNIMOD_Delta_S__1_Se_1_, "spec_2_site", "C"}, {UNIMOD_Delta_H_1_N__1_18O_1_, "approved", "1"}, {UNIMOD_Delta_H_1_N__1_18O_1_, "delta_composition", "H(-1) N(-1) 18O"}, {UNIMOD_Delta_H_1_N__1_18O_1_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Delta_H_1_N__1_18O_1_, "spec_1_hidden", "1"}, {UNIMOD_Delta_H_1_N__1_18O_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Delta_H_1_N__1_18O_1_, "spec_1_site", "N"}, {UNIMOD_NBS_13C_6_, "approved", "0"}, {UNIMOD_NBS_13C_6_, "delta_composition", "H(3) 13C(6) N O(2) S"}, {UNIMOD_NBS_13C_6_, "spec_1_classification", "Chemical derivative"}, {UNIMOD_NBS_13C_6_, "spec_1_hidden", "1"}, {UNIMOD_NBS_13C_6_, "spec_1_position", "Anywhere"}, {UNIMOD_NBS_13C_6_, "spec_1_site", "W"}, {UNIMOD_NBS, "approved", "0"}, {UNIMOD_NBS, "delta_composition", "H(3) C(6) N O(2) S"}, {UNIMOD_NBS, "spec_1_classification", "Chemical derivative"}, {UNIMOD_NBS, "spec_1_hidden", "1"}, {UNIMOD_NBS, "spec_1_position", "Anywhere"}, {UNIMOD_NBS, "spec_1_site", "W"}, {UNIMOD_BHT, "approved", "1"}, {UNIMOD_BHT, "delta_composition", "H(22) C(15) O"}, {UNIMOD_BHT, "spec_1_classification", "Other"}, {UNIMOD_BHT, "spec_1_hidden", "1"}, {UNIMOD_BHT, "spec_1_position", "Anywhere"}, {UNIMOD_BHT, "spec_1_site", "K"}, {UNIMOD_BHT, "spec_2_classification", "Other"}, {UNIMOD_BHT, "spec_2_hidden", "1"}, {UNIMOD_BHT, "spec_2_position", "Anywhere"}, {UNIMOD_BHT, "spec_2_site", "H"}, {UNIMOD_BHT, "spec_3_classification", "Other"}, {UNIMOD_BHT, "spec_3_hidden", "1"}, {UNIMOD_BHT, "spec_3_position", "Anywhere"}, {UNIMOD_BHT, "spec_3_site", "C"}, {UNIMOD_DAET, "approved", "1"}, {UNIMOD_DAET, "delta_composition", "H(9) C(4) N O(-1) S"}, {UNIMOD_DAET, "spec_1_classification", "Chemical derivative"}, {UNIMOD_DAET, "spec_1_hidden", "1"}, {UNIMOD_DAET, "spec_1_position", "Anywhere"}, {UNIMOD_DAET, "spec_1_site", "S"}, {UNIMOD_DAET, "spec_2_classification", "Chemical derivative"}, {UNIMOD_DAET, "spec_2_hidden", "1"}, {UNIMOD_DAET, "spec_2_position", "Anywhere"}, {UNIMOD_DAET, "spec_2_site", "T"}, {UNIMOD_Label_13C_9_, "approved", "1"}, {UNIMOD_Label_13C_9_, "delta_composition", "C(-9) 13C(9)"}, {UNIMOD_Label_13C_9_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_9_, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_9_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_9_, "spec_1_site", "Y"}, {UNIMOD_Label_13C_9_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Label_13C_9_, "spec_2_hidden", "1"}, {UNIMOD_Label_13C_9_, "spec_2_position", "Anywhere"}, {UNIMOD_Label_13C_9_, "spec_2_site", "F"}, {UNIMOD_Label_13C_9__Phospho, "approved", "1"}, {UNIMOD_Label_13C_9__Phospho, "delta_composition", "H C(-9) 13C(9) O(3) P"}, {UNIMOD_Label_13C_9__Phospho, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_9__Phospho, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_9__Phospho, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_9__Phospho, "spec_1_site", "Y"}, {UNIMOD_HPG, "approved", "1"}, {UNIMOD_HPG, "delta_composition", "H(4) C(8) O(2)"}, {UNIMOD_HPG, "spec_1_classification", "Chemical derivative"}, {UNIMOD_HPG, "spec_1_hidden", "1"}, {UNIMOD_HPG, "spec_1_position", "Anywhere"}, {UNIMOD_HPG, "spec_1_site", "R"}, {UNIMOD_2HPG, "approved", "1"}, {UNIMOD_2HPG, "delta_composition", "H(10) C(16) O(5)"}, {UNIMOD_2HPG, "spec_1_classification", "Chemical derivative"}, {UNIMOD_2HPG, "spec_1_hidden", "1"}, {UNIMOD_2HPG, "spec_1_position", "Anywhere"}, {UNIMOD_2HPG, "spec_1_site", "R"}, {UNIMOD_Label_13C_6_, "approved", "1"}, {UNIMOD_Label_13C_6_, "delta_composition", "C(-6) 13C(6)"}, {UNIMOD_Label_13C_6_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_6_, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_6_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_6_, "spec_1_site", "R"}, {UNIMOD_Label_13C_6_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Label_13C_6_, "spec_2_hidden", "1"}, {UNIMOD_Label_13C_6_, "spec_2_position", "Anywhere"}, {UNIMOD_Label_13C_6_, "spec_2_site", "K"}, {UNIMOD_Label_13C_6_, "spec_3_classification", "Isotopic label"}, {UNIMOD_Label_13C_6_, "spec_3_hidden", "1"}, {UNIMOD_Label_13C_6_, "spec_3_position", "Anywhere"}, {UNIMOD_Label_13C_6_, "spec_3_site", "L"}, {UNIMOD_Label_13C_6_, "spec_5_classification", "Isotopic label"}, {UNIMOD_Label_13C_6_, "spec_5_hidden", "1"}, {UNIMOD_Label_13C_6_, "spec_5_position", "Anywhere"}, {UNIMOD_Label_13C_6_, "spec_5_site", "I"}, {UNIMOD_Label_18O_2_, "approved", "1"}, {UNIMOD_Label_18O_2_, "delta_composition", "O(-2) 18O(2)"}, {UNIMOD_Label_18O_2_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_18O_2_, "spec_1_hidden", "0"}, {UNIMOD_Label_18O_2_, "spec_1_position", "Any C-term"}, {UNIMOD_Label_18O_2_, "spec_1_site", "C-term"}, {UNIMOD_AccQTag, "approved", "1"}, {UNIMOD_AccQTag, "delta_composition", "H(6) C(10) N(2) O"}, {UNIMOD_AccQTag, "spec_1_classification", "Chemical derivative"}, {UNIMOD_AccQTag, "spec_1_hidden", "1"}, {UNIMOD_AccQTag, "spec_1_position", "Anywhere"}, {UNIMOD_AccQTag, "spec_1_site", "K"}, {UNIMOD_AccQTag, "spec_2_classification", "Chemical derivative"}, {UNIMOD_AccQTag, "spec_2_hidden", "1"}, {UNIMOD_AccQTag, "spec_2_position", "Any N-term"}, {UNIMOD_AccQTag, "spec_2_site", "N-term"}, {UNIMOD_QAT, "approved", "1"}, {UNIMOD_QAT, "delta_composition", "H(19) C(9) N(2) O"}, {UNIMOD_QAT, "spec_1_classification", "Chemical derivative"}, {UNIMOD_QAT, "spec_1_hidden", "1"}, {UNIMOD_QAT, "spec_1_position", "Anywhere"}, {UNIMOD_QAT, "spec_1_site", "C"}, {UNIMOD_QAT_2H_3_, "approved", "1"}, {UNIMOD_QAT_2H_3_, "delta_composition", "H(16) 2H(3) C(9) N(2) O"}, {UNIMOD_QAT_2H_3_, "spec_1_classification", "Isotopic label"}, {UNIMOD_QAT_2H_3_, "spec_1_hidden", "1"}, {UNIMOD_QAT_2H_3_, "spec_1_position", "Anywhere"}, {UNIMOD_QAT_2H_3_, "spec_1_site", "C"}, {UNIMOD_EQAT, "approved", "1"}, {UNIMOD_EQAT, "delta_composition", "H(20) C(10) N(2) O"}, {UNIMOD_EQAT, "spec_1_classification", "Chemical derivative"}, {UNIMOD_EQAT, "spec_1_hidden", "1"}, {UNIMOD_EQAT, "spec_1_position", "Anywhere"}, {UNIMOD_EQAT, "spec_1_site", "C"}, {UNIMOD_EQAT_2H_5_, "approved", "1"}, {UNIMOD_EQAT_2H_5_, "delta_composition", "H(15) 2H(5) C(10) N(2) O"}, {UNIMOD_EQAT_2H_5_, "spec_1_classification", "Isotopic label"}, {UNIMOD_EQAT_2H_5_, "spec_1_hidden", "1"}, {UNIMOD_EQAT_2H_5_, "spec_1_position", "Anywhere"}, {UNIMOD_EQAT_2H_5_, "spec_1_site", "C"}, {UNIMOD_Dimethyl_2H_4_, "approved", "1"}, {UNIMOD_Dimethyl_2H_4_, "delta_composition", "2H(4) C(2)"}, {UNIMOD_Dimethyl_2H_4_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Dimethyl_2H_4_, "spec_1_hidden", "1"}, {UNIMOD_Dimethyl_2H_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Dimethyl_2H_4_, "spec_1_site", "K"}, {UNIMOD_Dimethyl_2H_4_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Dimethyl_2H_4_, "spec_2_hidden", "1"}, {UNIMOD_Dimethyl_2H_4_, "spec_2_position", "Any N-term"}, {UNIMOD_Dimethyl_2H_4_, "spec_2_site", "N-term"}, {UNIMOD_Dimethyl_2H_4_, "spec_3_classification", "Isotopic label"}, {UNIMOD_Dimethyl_2H_4_, "spec_3_hidden", "1"}, {UNIMOD_Dimethyl_2H_4_, "spec_3_position", "Protein N-term"}, {UNIMOD_Dimethyl_2H_4_, "spec_3_site", "N-term"}, {UNIMOD_Dimethyl_2H_4_, "spec_4_classification", "Isotopic label"}, {UNIMOD_Dimethyl_2H_4_, "spec_4_hidden", "1"}, {UNIMOD_Dimethyl_2H_4_, "spec_4_position", "Anywhere"}, {UNIMOD_Dimethyl_2H_4_, "spec_4_site", "R"}, {UNIMOD_Ethanedithiol, "approved", "1"}, {UNIMOD_Ethanedithiol, "delta_composition", "H(4) C(2) O(-1) S(2)"}, {UNIMOD_Ethanedithiol, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Ethanedithiol, "spec_1_hidden", "1"}, {UNIMOD_Ethanedithiol, "spec_1_position", "Anywhere"}, {UNIMOD_Ethanedithiol, "spec_1_site", "S"}, {UNIMOD_Ethanedithiol, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Ethanedithiol, "spec_2_hidden", "1"}, {UNIMOD_Ethanedithiol, "spec_2_position", "Anywhere"}, {UNIMOD_Ethanedithiol, "spec_2_site", "T"}, {UNIMOD_Delta_H_6_C_6_O_1_, "approved", "1"}, {UNIMOD_Delta_H_6_C_6_O_1_, "delta_composition", "H(6) C(6) O"}, {UNIMOD_Delta_H_6_C_6_O_1_, "spec_1_classification", "Other"}, {UNIMOD_Delta_H_6_C_6_O_1_, "spec_1_hidden", "1"}, {UNIMOD_Delta_H_6_C_6_O_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Delta_H_6_C_6_O_1_, "spec_1_site", "K"}, {UNIMOD_Delta_H_4_C_3_O_1_, "approved", "1"}, {UNIMOD_Delta_H_4_C_3_O_1_, "delta_composition", "H(4) C(3) O"}, {UNIMOD_Delta_H_4_C_3_O_1_, "spec_1_classification", "Other"}, {UNIMOD_Delta_H_4_C_3_O_1_, "spec_1_hidden", "1"}, {UNIMOD_Delta_H_4_C_3_O_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Delta_H_4_C_3_O_1_, "spec_1_site", "C"}, {UNIMOD_Delta_H_4_C_3_O_1_, "spec_2_classification", "Other"}, {UNIMOD_Delta_H_4_C_3_O_1_, "spec_2_hidden", "1"}, {UNIMOD_Delta_H_4_C_3_O_1_, "spec_2_position", "Anywhere"}, {UNIMOD_Delta_H_4_C_3_O_1_, "spec_2_site", "H"}, {UNIMOD_Delta_H_4_C_3_O_1_, "spec_3_classification", "Other"}, {UNIMOD_Delta_H_4_C_3_O_1_, "spec_3_hidden", "1"}, {UNIMOD_Delta_H_4_C_3_O_1_, "spec_3_position", "Anywhere"}, {UNIMOD_Delta_H_4_C_3_O_1_, "spec_3_site", "K"}, {UNIMOD_Delta_H_2_C_3_, "approved", "1"}, {UNIMOD_Delta_H_2_C_3_, "delta_composition", "H(2) C(3)"}, {UNIMOD_Delta_H_2_C_3_, "spec_1_classification", "Other"}, {UNIMOD_Delta_H_2_C_3_, "spec_1_hidden", "1"}, {UNIMOD_Delta_H_2_C_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Delta_H_2_C_3_, "spec_1_site", "K"}, {UNIMOD_Delta_H_4_C_6_, "approved", "1"}, {UNIMOD_Delta_H_4_C_6_, "delta_composition", "H(4) C(6)"}, {UNIMOD_Delta_H_4_C_6_, "spec_1_classification", "Other"}, {UNIMOD_Delta_H_4_C_6_, "spec_1_hidden", "1"}, {UNIMOD_Delta_H_4_C_6_, "spec_1_position", "Anywhere"}, {UNIMOD_Delta_H_4_C_6_, "spec_1_site", "K"}, {UNIMOD_Delta_H_8_C_6_O_2_, "approved", "1"}, {UNIMOD_Delta_H_8_C_6_O_2_, "delta_composition", "H(8) C(6) O(2)"}, {UNIMOD_Delta_H_8_C_6_O_2_, "spec_1_classification", "Other"}, {UNIMOD_Delta_H_8_C_6_O_2_, "spec_1_hidden", "1"}, {UNIMOD_Delta_H_8_C_6_O_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Delta_H_8_C_6_O_2_, "spec_1_site", "K"}, {UNIMOD_NEIAA, "approved", "1"}, {UNIMOD_NEIAA, "delta_composition", "H(7) C(4) N O"}, {UNIMOD_NEIAA, "spec_1_classification", "Isotopic label"}, {UNIMOD_NEIAA, "spec_1_hidden", "1"}, {UNIMOD_NEIAA, "spec_1_position", "Anywhere"}, {UNIMOD_NEIAA, "spec_1_site", "C"}, {UNIMOD_NEIAA, "spec_2_classification", "Isotopic label"}, {UNIMOD_NEIAA, "spec_2_hidden", "1"}, {UNIMOD_NEIAA, "spec_2_position", "Anywhere"}, {UNIMOD_NEIAA, "spec_2_site", "Y"}, {UNIMOD_NEIAA_2H_5_, "approved", "1"}, {UNIMOD_NEIAA_2H_5_, "delta_composition", "H(2) 2H(5) C(4) N O"}, {UNIMOD_NEIAA_2H_5_, "spec_1_classification", "Isotopic label"}, {UNIMOD_NEIAA_2H_5_, "spec_1_hidden", "1"}, {UNIMOD_NEIAA_2H_5_, "spec_1_position", "Anywhere"}, {UNIMOD_NEIAA_2H_5_, "spec_1_site", "C"}, {UNIMOD_NEIAA_2H_5_, "spec_2_classification", "Isotopic label"}, {UNIMOD_NEIAA_2H_5_, "spec_2_hidden", "1"}, {UNIMOD_NEIAA_2H_5_, "spec_2_position", "Anywhere"}, {UNIMOD_NEIAA_2H_5_, "spec_2_site", "Y"}, {UNIMOD_ADP_Ribosyl, "approved", "1"}, {UNIMOD_ADP_Ribosyl, "delta_composition", "H(13) C(10) N(5) O(9) P(2) Pent"}, {UNIMOD_ADP_Ribosyl, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_ADP_Ribosyl, "spec_1_hidden", "1"}, {UNIMOD_ADP_Ribosyl, "spec_1_position", "Anywhere"}, {UNIMOD_ADP_Ribosyl, "spec_1_site", "R"}, {UNIMOD_ADP_Ribosyl, "spec_2_classification", "Other glycosylation"}, {UNIMOD_ADP_Ribosyl, "spec_2_hidden", "1"}, {UNIMOD_ADP_Ribosyl, "spec_2_position", "Anywhere"}, {UNIMOD_ADP_Ribosyl, "spec_2_site", "C"}, {UNIMOD_ADP_Ribosyl, "spec_3_classification", "N-linked glycosylation"}, {UNIMOD_ADP_Ribosyl, "spec_3_hidden", "1"}, {UNIMOD_ADP_Ribosyl, "spec_3_position", "Anywhere"}, {UNIMOD_ADP_Ribosyl, "spec_3_site", "N"}, {UNIMOD_ADP_Ribosyl, "spec_4_classification", "O-linked glycosylation"}, {UNIMOD_ADP_Ribosyl, "spec_4_classification", "O-linked glycosylation"}, {UNIMOD_ADP_Ribosyl, "spec_4_hidden", "1"}, {UNIMOD_ADP_Ribosyl, "spec_4_hidden", "1"}, {UNIMOD_ADP_Ribosyl, "spec_4_position", "Anywhere"}, {UNIMOD_ADP_Ribosyl, "spec_4_position", "Anywhere"}, {UNIMOD_ADP_Ribosyl, "spec_4_site", "T"}, {UNIMOD_ADP_Ribosyl, "spec_4_site", "S"}, {UNIMOD_ADP_Ribosyl, "spec_5_classification", "Other glycosylation"}, {UNIMOD_ADP_Ribosyl, "spec_5_hidden", "1"}, {UNIMOD_ADP_Ribosyl, "spec_5_position", "Anywhere"}, {UNIMOD_ADP_Ribosyl, "spec_5_site", "E"}, {UNIMOD_ADP_Ribosyl, "spec_6_classification", "Other glycosylation"}, {UNIMOD_ADP_Ribosyl, "spec_6_hidden", "1"}, {UNIMOD_ADP_Ribosyl, "spec_6_position", "Anywhere"}, {UNIMOD_ADP_Ribosyl, "spec_6_site", "K"}, {UNIMOD_ADP_Ribosyl, "spec_7_classification", "Other glycosylation"}, {UNIMOD_ADP_Ribosyl, "spec_7_hidden", "1"}, {UNIMOD_ADP_Ribosyl, "spec_7_position", "Anywhere"}, {UNIMOD_ADP_Ribosyl, "spec_7_site", "D"}, {UNIMOD_iTRAQ4plex, "approved", "0"}, {UNIMOD_iTRAQ4plex, "delta_composition", "H(12) C(4) 13C(3) N 15N O"}, {UNIMOD_iTRAQ4plex, "spec_1_classification", "Isotopic label"}, {UNIMOD_iTRAQ4plex, "spec_1_hidden", "0"}, {UNIMOD_iTRAQ4plex, "spec_1_position", "Anywhere"}, {UNIMOD_iTRAQ4plex, "spec_1_site", "K"}, {UNIMOD_iTRAQ4plex, "spec_2_classification", "Isotopic label"}, {UNIMOD_iTRAQ4plex, "spec_2_hidden", "0"}, {UNIMOD_iTRAQ4plex, "spec_2_position", "Any N-term"}, {UNIMOD_iTRAQ4plex, "spec_2_site", "N-term"}, {UNIMOD_iTRAQ4plex, "spec_3_classification", "Isotopic label"}, {UNIMOD_iTRAQ4plex, "spec_3_hidden", "0"}, {UNIMOD_iTRAQ4plex, "spec_3_position", "Anywhere"}, {UNIMOD_iTRAQ4plex, "spec_3_site", "Y"}, {UNIMOD_iTRAQ4plex, "spec_4_classification", "Isotopic label"}, {UNIMOD_iTRAQ4plex, "spec_4_hidden", "1"}, {UNIMOD_iTRAQ4plex, "spec_4_position", "Anywhere"}, {UNIMOD_iTRAQ4plex, "spec_4_site", "H"}, {UNIMOD_iTRAQ4plex, "spec_5_classification", "Isotopic label"}, {UNIMOD_iTRAQ4plex, "spec_5_hidden", "1"}, {UNIMOD_iTRAQ4plex, "spec_5_position", "Anywhere"}, {UNIMOD_iTRAQ4plex, "spec_5_site", "S"}, {UNIMOD_iTRAQ4plex, "spec_6_classification", "Isotopic label"}, {UNIMOD_iTRAQ4plex, "spec_6_hidden", "1"}, {UNIMOD_iTRAQ4plex, "spec_6_position", "Anywhere"}, {UNIMOD_iTRAQ4plex, "spec_6_site", "T"}, {UNIMOD_iTRAQ4plex, "spec_7_classification", "Isotopic label"}, {UNIMOD_iTRAQ4plex, "spec_7_hidden", "1"}, {UNIMOD_iTRAQ4plex, "spec_7_position", "Protein N-term"}, {UNIMOD_iTRAQ4plex, "spec_7_site", "N-term"}, {UNIMOD_IGBP, "approved", "1"}, {UNIMOD_IGBP, "delta_composition", "H(13) C(12) N(2) O(2) Br"}, {UNIMOD_IGBP, "spec_1_classification", "Isotopic label"}, {UNIMOD_IGBP, "spec_1_hidden", "1"}, {UNIMOD_IGBP, "spec_1_position", "Anywhere"}, {UNIMOD_IGBP, "spec_1_site", "C"}, {UNIMOD_Crotonaldehyde, "approved", "1"}, {UNIMOD_Crotonaldehyde, "delta_composition", "H(6) C(4) O"}, {UNIMOD_Crotonaldehyde, "spec_1_classification", "Other"}, {UNIMOD_Crotonaldehyde, "spec_1_hidden", "1"}, {UNIMOD_Crotonaldehyde, "spec_1_position", "Anywhere"}, {UNIMOD_Crotonaldehyde, "spec_1_site", "C"}, {UNIMOD_Crotonaldehyde, "spec_2_classification", "Other"}, {UNIMOD_Crotonaldehyde, "spec_2_hidden", "1"}, {UNIMOD_Crotonaldehyde, "spec_2_position", "Anywhere"}, {UNIMOD_Crotonaldehyde, "spec_2_site", "H"}, {UNIMOD_Crotonaldehyde, "spec_3_classification", "Other"}, {UNIMOD_Crotonaldehyde, "spec_3_hidden", "1"}, {UNIMOD_Crotonaldehyde, "spec_3_position", "Anywhere"}, {UNIMOD_Crotonaldehyde, "spec_3_site", "K"}, {UNIMOD_Delta_H_2_C_2_, "approved", "1"}, {UNIMOD_Delta_H_2_C_2_, "delta_composition", "H(2) C(2)"}, {UNIMOD_Delta_H_2_C_2_, "spec_1_classification", "Other"}, {UNIMOD_Delta_H_2_C_2_, "spec_1_hidden", "1"}, {UNIMOD_Delta_H_2_C_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Delta_H_2_C_2_, "spec_1_site", "H"}, {UNIMOD_Delta_H_2_C_2_, "spec_2_classification", "Other"}, {UNIMOD_Delta_H_2_C_2_, "spec_2_hidden", "1"}, {UNIMOD_Delta_H_2_C_2_, "spec_2_position", "Anywhere"}, {UNIMOD_Delta_H_2_C_2_, "spec_2_site", "K"}, {UNIMOD_Delta_H_2_C_2_, "spec_3_classification", "Other"}, {UNIMOD_Delta_H_2_C_2_, "spec_3_hidden", "1"}, {UNIMOD_Delta_H_2_C_2_, "spec_3_position", "Protein N-term"}, {UNIMOD_Delta_H_2_C_2_, "spec_3_site", "N-term"}, {UNIMOD_Delta_H_2_C_2_, "spec_4_classification", "Other"}, {UNIMOD_Delta_H_2_C_2_, "spec_4_hidden", "1"}, {UNIMOD_Delta_H_2_C_2_, "spec_4_position", "Any N-term"}, {UNIMOD_Delta_H_2_C_2_, "spec_4_site", "N-term"}, {UNIMOD_Delta_H_4_C_2_, "approved", "1"}, {UNIMOD_Delta_H_4_C_2_, "delta_composition", "H(4) C(2)"}, {UNIMOD_Delta_H_4_C_2_, "spec_1_classification", "Other"}, {UNIMOD_Delta_H_4_C_2_, "spec_1_hidden", "1"}, {UNIMOD_Delta_H_4_C_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Delta_H_4_C_2_, "spec_1_site", "H"}, {UNIMOD_Delta_H_4_C_2_, "spec_2_classification", "Other"}, {UNIMOD_Delta_H_4_C_2_, "spec_2_hidden", "1"}, {UNIMOD_Delta_H_4_C_2_, "spec_2_position", "Anywhere"}, {UNIMOD_Delta_H_4_C_2_, "spec_2_site", "K"}, {UNIMOD_Delta_H_4_C_2_, "spec_3_classification", "Other"}, {UNIMOD_Delta_H_4_C_2_, "spec_3_hidden", "1"}, {UNIMOD_Delta_H_4_C_2_, "spec_3_position", "Any N-term"}, {UNIMOD_Delta_H_4_C_2_, "spec_3_site", "N-term"}, {UNIMOD_Delta_H_4_C_3_, "approved", "1"}, {UNIMOD_Delta_H_4_C_3_, "delta_composition", "H(4) C(3)"}, {UNIMOD_Delta_H_4_C_3_, "spec_1_classification", "Other"}, {UNIMOD_Delta_H_4_C_3_, "spec_1_hidden", "1"}, {UNIMOD_Delta_H_4_C_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Delta_H_4_C_3_, "spec_1_site", "H"}, {UNIMOD_Delta_H_4_C_3_, "spec_2_classification", "Other"}, {UNIMOD_Delta_H_4_C_3_, "spec_2_hidden", "1"}, {UNIMOD_Delta_H_4_C_3_, "spec_2_position", "Anywhere"}, {UNIMOD_Delta_H_4_C_3_, "spec_2_site", "K"}, {UNIMOD_Delta_H_4_C_3_, "spec_3_classification", "Other"}, {UNIMOD_Delta_H_4_C_3_, "spec_3_hidden", "1"}, {UNIMOD_Delta_H_4_C_3_, "spec_3_position", "Protein N-term"}, {UNIMOD_Delta_H_4_C_3_, "spec_3_site", "N-term"}, {UNIMOD_Label_18O_1_, "approved", "1"}, {UNIMOD_Label_18O_1_, "delta_composition", "O(-1) 18O"}, {UNIMOD_Label_18O_1_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_18O_1_, "spec_1_hidden", "1"}, {UNIMOD_Label_18O_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_18O_1_, "spec_1_site", "S"}, {UNIMOD_Label_18O_1_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Label_18O_1_, "spec_2_hidden", "1"}, {UNIMOD_Label_18O_1_, "spec_2_position", "Anywhere"}, {UNIMOD_Label_18O_1_, "spec_2_site", "T"}, {UNIMOD_Label_18O_1_, "spec_3_classification", "Isotopic label"}, {UNIMOD_Label_18O_1_, "spec_3_hidden", "1"}, {UNIMOD_Label_18O_1_, "spec_3_position", "Anywhere"}, {UNIMOD_Label_18O_1_, "spec_3_site", "Y"}, {UNIMOD_Label_18O_1_, "spec_4_classification", "Isotopic label"}, {UNIMOD_Label_18O_1_, "spec_4_hidden", "0"}, {UNIMOD_Label_18O_1_, "spec_4_position", "Any C-term"}, {UNIMOD_Label_18O_1_, "spec_4_site", "C-term"}, {UNIMOD_Label_13C_6_15N_2_, "approved", "1"}, {UNIMOD_Label_13C_6_15N_2_, "delta_composition", "C(-6) 13C(6) N(-2) 15N(2)"}, {UNIMOD_Label_13C_6_15N_2_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_6_15N_2_, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_6_15N_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_6_15N_2_, "spec_1_site", "K"}, {UNIMOD_Thiophospho, "approved", "1"}, {UNIMOD_Thiophospho, "delta_composition", "H O(2) P S"}, {UNIMOD_Thiophospho, "spec_1_classification", "Other"}, {UNIMOD_Thiophospho, "spec_1_hidden", "1"}, {UNIMOD_Thiophospho, "spec_1_position", "Anywhere"}, {UNIMOD_Thiophospho, "spec_1_site", "S"}, {UNIMOD_Thiophospho, "spec_2_classification", "Other"}, {UNIMOD_Thiophospho, "spec_2_hidden", "1"}, {UNIMOD_Thiophospho, "spec_2_position", "Anywhere"}, {UNIMOD_Thiophospho, "spec_2_site", "T"}, {UNIMOD_Thiophospho, "spec_3_classification", "Other"}, {UNIMOD_Thiophospho, "spec_3_hidden", "1"}, {UNIMOD_Thiophospho, "spec_3_position", "Anywhere"}, {UNIMOD_Thiophospho, "spec_3_site", "Y"}, {UNIMOD_SPITC, "approved", "1"}, {UNIMOD_SPITC, "delta_composition", "H(5) C(7) N O(3) S(2)"}, {UNIMOD_SPITC, "spec_1_classification", "Chemical derivative"}, {UNIMOD_SPITC, "spec_1_hidden", "1"}, {UNIMOD_SPITC, "spec_1_position", "Anywhere"}, {UNIMOD_SPITC, "spec_1_site", "K"}, {UNIMOD_SPITC, "spec_2_classification", "Chemical derivative"}, {UNIMOD_SPITC, "spec_2_hidden", "1"}, {UNIMOD_SPITC, "spec_2_position", "Any N-term"}, {UNIMOD_SPITC, "spec_2_site", "N-term"}, {UNIMOD_Label_2H_3_, "approved", "1"}, {UNIMOD_Label_2H_3_, "delta_composition", "H(-3) 2H(3)"}, {UNIMOD_Label_2H_3_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_2H_3_, "spec_1_hidden", "1"}, {UNIMOD_Label_2H_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_2H_3_, "spec_1_site", "L"}, {UNIMOD_Label_2H_3_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Label_2H_3_, "spec_2_hidden", "1"}, {UNIMOD_Label_2H_3_, "spec_2_position", "Anywhere"}, {UNIMOD_Label_2H_3_, "spec_2_site", "M"}, {UNIMOD_PET, "approved", "1"}, {UNIMOD_PET, "delta_composition", "H(7) C(7) N O(-1) S"}, {UNIMOD_PET, "spec_1_classification", "Chemical derivative"}, {UNIMOD_PET, "spec_1_hidden", "1"}, {UNIMOD_PET, "spec_1_position", "Anywhere"}, {UNIMOD_PET, "spec_1_site", "S"}, {UNIMOD_PET, "spec_2_classification", "Chemical derivative"}, {UNIMOD_PET, "spec_2_hidden", "1"}, {UNIMOD_PET, "spec_2_position", "Anywhere"}, {UNIMOD_PET, "spec_2_site", "T"}, {UNIMOD_Label_13C_6_15N_4_, "approved", "1"}, {UNIMOD_Label_13C_6_15N_4_, "delta_composition", "C(-6) 13C(6) N(-4) 15N(4)"}, {UNIMOD_Label_13C_6_15N_4_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_6_15N_4_, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_6_15N_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_6_15N_4_, "spec_1_site", "R"}, {UNIMOD_Label_13C_5_15N_1_, "approved", "1"}, {UNIMOD_Label_13C_5_15N_1_, "delta_composition", "C(-5) 13C(5) N(-1) 15N"}, {UNIMOD_Label_13C_5_15N_1_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_5_15N_1_, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_5_15N_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_5_15N_1_, "spec_1_site", "V"}, {UNIMOD_Label_13C_5_15N_1_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Label_13C_5_15N_1_, "spec_2_hidden", "1"}, {UNIMOD_Label_13C_5_15N_1_, "spec_2_position", "Anywhere"}, {UNIMOD_Label_13C_5_15N_1_, "spec_2_site", "P"}, {UNIMOD_Label_13C_5_15N_1_, "spec_3_classification", "Isotopic label"}, {UNIMOD_Label_13C_5_15N_1_, "spec_3_hidden", "1"}, {UNIMOD_Label_13C_5_15N_1_, "spec_3_position", "Anywhere"}, {UNIMOD_Label_13C_5_15N_1_, "spec_3_site", "M"}, {UNIMOD_Label_13C_5_15N_1_, "spec_4_classification", "Isotopic label"}, {UNIMOD_Label_13C_5_15N_1_, "spec_4_hidden", "1"}, {UNIMOD_Label_13C_5_15N_1_, "spec_4_position", "Anywhere"}, {UNIMOD_Label_13C_5_15N_1_, "spec_4_site", "E"}, {UNIMOD_Label_13C_9_15N_1_, "approved", "1"}, {UNIMOD_Label_13C_9_15N_1_, "delta_composition", "C(-9) 13C(9) N(-1) 15N"}, {UNIMOD_Label_13C_9_15N_1_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_9_15N_1_, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_9_15N_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_9_15N_1_, "spec_1_site", "F"}, {UNIMOD_Cytopiloyne, "approved", "1"}, {UNIMOD_Cytopiloyne, "delta_composition", "H(22) C(19) O(7)"}, {UNIMOD_Cytopiloyne, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Cytopiloyne, "spec_1_hidden", "1"}, {UNIMOD_Cytopiloyne, "spec_1_position", "Anywhere"}, {UNIMOD_Cytopiloyne, "spec_1_site", "C"}, {UNIMOD_Cytopiloyne, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Cytopiloyne, "spec_2_hidden", "1"}, {UNIMOD_Cytopiloyne, "spec_2_position", "Anywhere"}, {UNIMOD_Cytopiloyne, "spec_2_site", "K"}, {UNIMOD_Cytopiloyne, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Cytopiloyne, "spec_3_hidden", "1"}, {UNIMOD_Cytopiloyne, "spec_3_position", "Any N-term"}, {UNIMOD_Cytopiloyne, "spec_3_site", "N-term"}, {UNIMOD_Cytopiloyne, "spec_4_classification", "Chemical derivative"}, {UNIMOD_Cytopiloyne, "spec_4_hidden", "1"}, {UNIMOD_Cytopiloyne, "spec_4_position", "Anywhere"}, {UNIMOD_Cytopiloyne, "spec_4_site", "P"}, {UNIMOD_Cytopiloyne, "spec_5_classification", "Chemical derivative"}, {UNIMOD_Cytopiloyne, "spec_5_hidden", "1"}, {UNIMOD_Cytopiloyne, "spec_5_position", "Anywhere"}, {UNIMOD_Cytopiloyne, "spec_5_site", "R"}, {UNIMOD_Cytopiloyne, "spec_6_classification", "Chemical derivative"}, {UNIMOD_Cytopiloyne, "spec_6_hidden", "1"}, {UNIMOD_Cytopiloyne, "spec_6_position", "Anywhere"}, {UNIMOD_Cytopiloyne, "spec_6_site", "S"}, {UNIMOD_Cytopiloyne, "spec_7_classification", "Chemical derivative"}, {UNIMOD_Cytopiloyne, "spec_7_hidden", "1"}, {UNIMOD_Cytopiloyne, "spec_7_position", "Anywhere"}, {UNIMOD_Cytopiloyne, "spec_7_site", "Y"}, {UNIMOD_Cytopiloyne_water, "approved", "1"}, {UNIMOD_Cytopiloyne_water, "delta_composition", "H(24) C(19) O(8)"}, {UNIMOD_Cytopiloyne_water, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Cytopiloyne_water, "spec_1_hidden", "1"}, {UNIMOD_Cytopiloyne_water, "spec_1_position", "Anywhere"}, {UNIMOD_Cytopiloyne_water, "spec_1_site", "C"}, {UNIMOD_Cytopiloyne_water, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Cytopiloyne_water, "spec_2_hidden", "1"}, {UNIMOD_Cytopiloyne_water, "spec_2_position", "Anywhere"}, {UNIMOD_Cytopiloyne_water, "spec_2_site", "K"}, {UNIMOD_Cytopiloyne_water, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Cytopiloyne_water, "spec_3_hidden", "1"}, {UNIMOD_Cytopiloyne_water, "spec_3_position", "Any N-term"}, {UNIMOD_Cytopiloyne_water, "spec_3_site", "N-term"}, {UNIMOD_Cytopiloyne_water, "spec_4_classification", "Chemical derivative"}, {UNIMOD_Cytopiloyne_water, "spec_4_hidden", "1"}, {UNIMOD_Cytopiloyne_water, "spec_4_position", "Anywhere"}, {UNIMOD_Cytopiloyne_water, "spec_4_site", "R"}, {UNIMOD_Cytopiloyne_water, "spec_5_classification", "Chemical derivative"}, {UNIMOD_Cytopiloyne_water, "spec_5_hidden", "1"}, {UNIMOD_Cytopiloyne_water, "spec_5_position", "Anywhere"}, {UNIMOD_Cytopiloyne_water, "spec_5_site", "S"}, {UNIMOD_Cytopiloyne_water, "spec_6_classification", "Chemical derivative"}, {UNIMOD_Cytopiloyne_water, "spec_6_hidden", "1"}, {UNIMOD_Cytopiloyne_water, "spec_6_position", "Anywhere"}, {UNIMOD_Cytopiloyne_water, "spec_6_site", "T"}, {UNIMOD_Cytopiloyne_water, "spec_7_classification", "Chemical derivative"}, {UNIMOD_Cytopiloyne_water, "spec_7_hidden", "1"}, {UNIMOD_Cytopiloyne_water, "spec_7_position", "Anywhere"}, {UNIMOD_Cytopiloyne_water, "spec_7_site", "Y"}, {UNIMOD_CAF, "approved", "1"}, {UNIMOD_CAF, "delta_composition", "H(4) C(3) O(4) S"}, {UNIMOD_CAF, "spec_1_classification", "Chemical derivative"}, {UNIMOD_CAF, "spec_1_hidden", "1"}, {UNIMOD_CAF, "spec_1_position", "Any N-term"}, {UNIMOD_CAF, "spec_1_site", "N-term"}, {UNIMOD_Xlink_SSD, "approved", "1"}, {UNIMOD_Xlink_SSD, "delta_composition", "H(15) C(12) N O(5)"}, {UNIMOD_Xlink_SSD, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Xlink_SSD, "spec_1_hidden", "1"}, {UNIMOD_Xlink_SSD, "spec_1_position", "Anywhere"}, {UNIMOD_Xlink_SSD, "spec_1_site", "K"}, {UNIMOD_Nitrosyl, "approved", "1"}, {UNIMOD_Nitrosyl, "delta_composition", "H(-1) N O"}, {UNIMOD_Nitrosyl, "spec_1_classification", "Post-translational"}, {UNIMOD_Nitrosyl, "spec_1_hidden", "1"}, {UNIMOD_Nitrosyl, "spec_1_position", "Anywhere"}, {UNIMOD_Nitrosyl, "spec_1_site", "C"}, {UNIMOD_AEBS, "approved", "1"}, {UNIMOD_AEBS, "delta_composition", "H(9) C(8) N O(2) S"}, {UNIMOD_AEBS, "spec_1_classification", "Artefact"}, {UNIMOD_AEBS, "spec_1_hidden", "1"}, {UNIMOD_AEBS, "spec_1_position", "Anywhere"}, {UNIMOD_AEBS, "spec_1_site", "H"}, {UNIMOD_AEBS, "spec_2_classification", "Artefact"}, {UNIMOD_AEBS, "spec_2_hidden", "1"}, {UNIMOD_AEBS, "spec_2_position", "Anywhere"}, {UNIMOD_AEBS, "spec_2_site", "K"}, {UNIMOD_AEBS, "spec_3_classification", "Artefact"}, {UNIMOD_AEBS, "spec_3_hidden", "1"}, {UNIMOD_AEBS, "spec_3_position", "Protein N-term"}, {UNIMOD_AEBS, "spec_3_site", "N-term"}, {UNIMOD_AEBS, "spec_4_classification", "Artefact"}, {UNIMOD_AEBS, "spec_4_hidden", "1"}, {UNIMOD_AEBS, "spec_4_position", "Anywhere"}, {UNIMOD_AEBS, "spec_4_site", "S"}, {UNIMOD_AEBS, "spec_5_classification", "Artefact"}, {UNIMOD_AEBS, "spec_5_hidden", "1"}, {UNIMOD_AEBS, "spec_5_position", "Anywhere"}, {UNIMOD_AEBS, "spec_5_site", "Y"}, {UNIMOD_Ethanolyl, "approved", "1"}, {UNIMOD_Ethanolyl, "delta_composition", "H(4) C(2) O"}, {UNIMOD_Ethanolyl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Ethanolyl, "spec_1_hidden", "0"}, {UNIMOD_Ethanolyl, "spec_1_position", "Anywhere"}, {UNIMOD_Ethanolyl, "spec_1_site", "C"}, {UNIMOD_Ethanolyl, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Ethanolyl, "spec_2_hidden", "1"}, {UNIMOD_Ethanolyl, "spec_2_position", "Anywhere"}, {UNIMOD_Ethanolyl, "spec_2_site", "K"}, {UNIMOD_Ethanolyl, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Ethanolyl, "spec_3_hidden", "1"}, {UNIMOD_Ethanolyl, "spec_3_position", "Anywhere"}, {UNIMOD_Ethanolyl, "spec_3_site", "R"}, {UNIMOD_Ethyl, "approved", "1"}, {UNIMOD_Ethyl, "delta_composition", "H(4) C(2)"}, {UNIMOD_Ethyl, "spec_1_classification", "Multiple"}, {UNIMOD_Ethyl, "spec_1_hidden", "1"}, {UNIMOD_Ethyl, "spec_1_position", "Anywhere"}, {UNIMOD_Ethyl, "spec_1_site", "K"}, {UNIMOD_Ethyl, "spec_2_classification", "Multiple"}, {UNIMOD_Ethyl, "spec_2_hidden", "1"}, {UNIMOD_Ethyl, "spec_2_position", "Any N-term"}, {UNIMOD_Ethyl, "spec_2_site", "N-term"}, {UNIMOD_Ethyl, "spec_3_classification", "Artefact"}, {UNIMOD_Ethyl, "spec_3_hidden", "1"}, {UNIMOD_Ethyl, "spec_3_position", "Anywhere"}, {UNIMOD_Ethyl, "spec_3_site", "E"}, {UNIMOD_Ethyl, "spec_4_classification", "Chemical derivative"}, {UNIMOD_Ethyl, "spec_4_hidden", "1"}, {UNIMOD_Ethyl, "spec_4_position", "Protein N-term"}, {UNIMOD_Ethyl, "spec_4_site", "N-term"}, {UNIMOD_Ethyl, "spec_5_classification", "Chemical derivative"}, {UNIMOD_Ethyl, "spec_5_hidden", "1"}, {UNIMOD_Ethyl, "spec_5_position", "Any C-term"}, {UNIMOD_Ethyl, "spec_5_site", "C-term"}, {UNIMOD_Ethyl, "spec_6_classification", "Chemical derivative"}, {UNIMOD_Ethyl, "spec_6_hidden", "1"}, {UNIMOD_Ethyl, "spec_6_position", "Anywhere"}, {UNIMOD_Ethyl, "spec_6_site", "D"}, {UNIMOD_CoenzymeA, "approved", "1"}, {UNIMOD_CoenzymeA, "delta_composition", "H(34) C(21) N(7) O(16) P(3) S"}, {UNIMOD_CoenzymeA, "spec_1_classification", "Post-translational"}, {UNIMOD_CoenzymeA, "spec_1_hidden", "1"}, {UNIMOD_CoenzymeA, "spec_1_position", "Anywhere"}, {UNIMOD_CoenzymeA, "spec_1_site", "C"}, {UNIMOD_Methyl_2H_2_, "approved", "1"}, {UNIMOD_Methyl_2H_2_, "delta_composition", "2H(2) C"}, {UNIMOD_Methyl_2H_2_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Methyl_2H_2_, "spec_1_hidden", "1"}, {UNIMOD_Methyl_2H_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Methyl_2H_2_, "spec_1_site", "K"}, {UNIMOD_SulfanilicAcid, "approved", "1"}, {UNIMOD_SulfanilicAcid, "delta_composition", "H(5) C(6) N O(2) S"}, {UNIMOD_SulfanilicAcid, "spec_1_classification", "Isotopic label"}, {UNIMOD_SulfanilicAcid, "spec_1_hidden", "1"}, {UNIMOD_SulfanilicAcid, "spec_1_position", "Any C-term"}, {UNIMOD_SulfanilicAcid, "spec_1_site", "C-term"}, {UNIMOD_SulfanilicAcid, "spec_2_classification", "Isotopic label"}, {UNIMOD_SulfanilicAcid, "spec_2_hidden", "1"}, {UNIMOD_SulfanilicAcid, "spec_2_position", "Anywhere"}, {UNIMOD_SulfanilicAcid, "spec_2_site", "D"}, {UNIMOD_SulfanilicAcid, "spec_3_classification", "Isotopic label"}, {UNIMOD_SulfanilicAcid, "spec_3_hidden", "1"}, {UNIMOD_SulfanilicAcid, "spec_3_position", "Anywhere"}, {UNIMOD_SulfanilicAcid, "spec_3_site", "E"}, {UNIMOD_SulfanilicAcid_13C_6_, "approved", "1"}, {UNIMOD_SulfanilicAcid_13C_6_, "delta_composition", "H(5) 13C(6) N O(2) S"}, {UNIMOD_SulfanilicAcid_13C_6_, "spec_1_classification", "Chemical derivative"}, {UNIMOD_SulfanilicAcid_13C_6_, "spec_1_hidden", "1"}, {UNIMOD_SulfanilicAcid_13C_6_, "spec_1_position", "Any C-term"}, {UNIMOD_SulfanilicAcid_13C_6_, "spec_1_site", "C-term"}, {UNIMOD_SulfanilicAcid_13C_6_, "spec_2_classification", "Chemical derivative"}, {UNIMOD_SulfanilicAcid_13C_6_, "spec_2_hidden", "1"}, {UNIMOD_SulfanilicAcid_13C_6_, "spec_2_position", "Anywhere"}, {UNIMOD_SulfanilicAcid_13C_6_, "spec_2_site", "D"}, {UNIMOD_SulfanilicAcid_13C_6_, "spec_3_classification", "Chemical derivative"}, {UNIMOD_SulfanilicAcid_13C_6_, "spec_3_hidden", "1"}, {UNIMOD_SulfanilicAcid_13C_6_, "spec_3_position", "Anywhere"}, {UNIMOD_SulfanilicAcid_13C_6_, "spec_3_site", "E"}, {UNIMOD_Trp__Oxolactone, "approved", "1"}, {UNIMOD_Trp__Oxolactone, "delta_composition", "H(-2) O"}, {UNIMOD_Trp__Oxolactone, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Trp__Oxolactone, "spec_1_hidden", "1"}, {UNIMOD_Trp__Oxolactone, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__Oxolactone, "spec_1_site", "W"}, {UNIMOD_Biotin_PEO_Amine, "approved", "0"}, {UNIMOD_Biotin_PEO_Amine, "delta_composition", "H(28) C(16) N(4) O(3) S"}, {UNIMOD_Biotin_PEO_Amine, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Biotin_PEO_Amine, "spec_1_hidden", "1"}, {UNIMOD_Biotin_PEO_Amine, "spec_1_position", "Protein C-term"}, {UNIMOD_Biotin_PEO_Amine, "spec_1_site", "C-term"}, {UNIMOD_Biotin_PEO_Amine, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Biotin_PEO_Amine, "spec_2_hidden", "1"}, {UNIMOD_Biotin_PEO_Amine, "spec_2_position", "Anywhere"}, {UNIMOD_Biotin_PEO_Amine, "spec_2_site", "D"}, {UNIMOD_Biotin_PEO_Amine, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Biotin_PEO_Amine, "spec_3_hidden", "1"}, {UNIMOD_Biotin_PEO_Amine, "spec_3_position", "Anywhere"}, {UNIMOD_Biotin_PEO_Amine, "spec_3_site", "E"}, {UNIMOD_Biotin_HPDP, "approved", "0"}, {UNIMOD_Biotin_HPDP, "delta_composition", "H(32) C(19) N(4) O(3) S(2)"}, {UNIMOD_Biotin_HPDP, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Biotin_HPDP, "spec_1_hidden", "1"}, {UNIMOD_Biotin_HPDP, "spec_1_position", "Anywhere"}, {UNIMOD_Biotin_HPDP, "spec_1_site", "C"}, {UNIMOD_Delta_Hg_1_, "approved", "1"}, {UNIMOD_Delta_Hg_1_, "delta_composition", "Hg"}, {UNIMOD_Delta_Hg_1_, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Delta_Hg_1_, "spec_1_hidden", "1"}, {UNIMOD_Delta_Hg_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Delta_Hg_1_, "spec_1_site", "C"}, {UNIMOD_IodoU_AMP, "approved", "1"}, {UNIMOD_IodoU_AMP, "delta_composition", "H(11) C(9) N(2) O(9) P"}, {UNIMOD_IodoU_AMP, "spec_1_classification", "Chemical derivative"}, {UNIMOD_IodoU_AMP, "spec_1_hidden", "1"}, {UNIMOD_IodoU_AMP, "spec_1_position", "Anywhere"}, {UNIMOD_IodoU_AMP, "spec_1_site", "F"}, {UNIMOD_IodoU_AMP, "spec_2_classification", "Chemical derivative"}, {UNIMOD_IodoU_AMP, "spec_2_hidden", "1"}, {UNIMOD_IodoU_AMP, "spec_2_position", "Anywhere"}, {UNIMOD_IodoU_AMP, "spec_2_site", "W"}, {UNIMOD_IodoU_AMP, "spec_3_classification", "Chemical derivative"}, {UNIMOD_IodoU_AMP, "spec_3_hidden", "1"}, {UNIMOD_IodoU_AMP, "spec_3_position", "Anywhere"}, {UNIMOD_IodoU_AMP, "spec_3_site", "Y"}, {UNIMOD_CAMthiopropanoyl, "approved", "1"}, {UNIMOD_CAMthiopropanoyl, "delta_composition", "H(7) C(5) N O(2) S"}, {UNIMOD_CAMthiopropanoyl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_CAMthiopropanoyl, "spec_1_hidden", "1"}, {UNIMOD_CAMthiopropanoyl, "spec_1_position", "Anywhere"}, {UNIMOD_CAMthiopropanoyl, "spec_1_site", "K"}, {UNIMOD_CAMthiopropanoyl, "spec_2_classification", "Chemical derivative"}, {UNIMOD_CAMthiopropanoyl, "spec_2_hidden", "1"}, {UNIMOD_CAMthiopropanoyl, "spec_2_position", "Protein N-term"}, {UNIMOD_CAMthiopropanoyl, "spec_2_site", "N-term"}, {UNIMOD_IED_Biotin, "approved", "1"}, {UNIMOD_IED_Biotin, "delta_composition", "H(22) C(14) N(4) O(3) S"}, {UNIMOD_IED_Biotin, "spec_1_classification", "Chemical derivative"}, {UNIMOD_IED_Biotin, "spec_1_hidden", "1"}, {UNIMOD_IED_Biotin, "spec_1_position", "Anywhere"}, {UNIMOD_IED_Biotin, "spec_1_site", "C"}, {UNIMOD_dHex, "approved", "1"}, {UNIMOD_dHex, "delta_composition", "dHex"}, {UNIMOD_dHex, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex, "spec_1_hidden", "1"}, {UNIMOD_dHex, "spec_1_hidden", "1"}, {UNIMOD_dHex, "spec_1_position", "Anywhere"}, {UNIMOD_dHex, "spec_1_position", "Anywhere"}, {UNIMOD_dHex, "spec_1_site", "T"}, {UNIMOD_dHex, "spec_1_site", "S"}, {UNIMOD_dHex, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_dHex, "spec_2_hidden", "1"}, {UNIMOD_dHex, "spec_2_position", "Anywhere"}, {UNIMOD_dHex, "spec_2_site", "N"}, {UNIMOD_Methyl_2H_3_, "approved", "1"}, {UNIMOD_Methyl_2H_3_, "delta_composition", "H(-1) 2H(3) C"}, {UNIMOD_Methyl_2H_3_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Methyl_2H_3_, "spec_1_hidden", "1"}, {UNIMOD_Methyl_2H_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Methyl_2H_3_, "spec_1_site", "C-term"}, {UNIMOD_Methyl_2H_3_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Methyl_2H_3_, "spec_2_hidden", "1"}, {UNIMOD_Methyl_2H_3_, "spec_2_position", "Anywhere"}, {UNIMOD_Methyl_2H_3_, "spec_2_site", "D"}, {UNIMOD_Methyl_2H_3_, "spec_3_classification", "Isotopic label"}, {UNIMOD_Methyl_2H_3_, "spec_3_hidden", "1"}, {UNIMOD_Methyl_2H_3_, "spec_3_position", "Anywhere"}, {UNIMOD_Methyl_2H_3_, "spec_3_site", "E"}, {UNIMOD_Methyl_2H_3_, "spec_4_classification", "Isotopic label"}, {UNIMOD_Methyl_2H_3_, "spec_4_hidden", "1"}, {UNIMOD_Methyl_2H_3_, "spec_4_position", "Anywhere"}, {UNIMOD_Methyl_2H_3_, "spec_4_site", "K"}, {UNIMOD_Methyl_2H_3_, "spec_5_classification", "Isotopic label"}, {UNIMOD_Methyl_2H_3_, "spec_5_hidden", "1"}, {UNIMOD_Methyl_2H_3_, "spec_5_position", "Anywhere"}, {UNIMOD_Methyl_2H_3_, "spec_5_site", "R"}, {UNIMOD_Carboxy, "approved", "0"}, {UNIMOD_Carboxy, "delta_composition", "C O(2)"}, {UNIMOD_Carboxy, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Carboxy, "spec_1_hidden", "1"}, {UNIMOD_Carboxy, "spec_1_position", "Anywhere"}, {UNIMOD_Carboxy, "spec_1_site", "W"}, {UNIMOD_Carboxy, "spec_2_classification", "Post-translational"}, {UNIMOD_Carboxy, "spec_2_hidden", "1"}, {UNIMOD_Carboxy, "spec_2_position", "Anywhere"}, {UNIMOD_Carboxy, "spec_2_site", "K"}, {UNIMOD_Carboxy, "spec_3_classification", "Post-translational"}, {UNIMOD_Carboxy, "spec_3_hidden", "1"}, {UNIMOD_Carboxy, "spec_3_position", "Anywhere"}, {UNIMOD_Carboxy, "spec_3_site", "D"}, {UNIMOD_Carboxy, "spec_4_classification", "Post-translational"}, {UNIMOD_Carboxy, "spec_4_hidden", "1"}, {UNIMOD_Carboxy, "spec_4_position", "Anywhere"}, {UNIMOD_Carboxy, "spec_4_site", "E"}, {UNIMOD_Carboxy, "spec_5_classification", "Post-translational"}, {UNIMOD_Carboxy, "spec_5_hidden", "1"}, {UNIMOD_Carboxy, "spec_5_position", "Protein N-term"}, {UNIMOD_Carboxy, "spec_5_site", "M"}, {UNIMOD_Bromobimane, "approved", "1"}, {UNIMOD_Bromobimane, "delta_composition", "H(10) C(10) N(2) O(2)"}, {UNIMOD_Bromobimane, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Bromobimane, "spec_1_hidden", "1"}, {UNIMOD_Bromobimane, "spec_1_position", "Anywhere"}, {UNIMOD_Bromobimane, "spec_1_site", "C"}, {UNIMOD_Menadione, "approved", "0"}, {UNIMOD_Menadione, "delta_composition", "H(6) C(11) O(2)"}, {UNIMOD_Menadione, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Menadione, "spec_1_hidden", "1"}, {UNIMOD_Menadione, "spec_1_position", "Anywhere"}, {UNIMOD_Menadione, "spec_1_site", "C"}, {UNIMOD_Menadione, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Menadione, "spec_2_hidden", "1"}, {UNIMOD_Menadione, "spec_2_position", "Anywhere"}, {UNIMOD_Menadione, "spec_2_site", "K"}, {UNIMOD_DeStreak, "approved", "1"}, {UNIMOD_DeStreak, "delta_composition", "H(4) C(2) O S"}, {UNIMOD_DeStreak, "spec_1_classification", "Chemical derivative"}, {UNIMOD_DeStreak, "spec_1_hidden", "1"}, {UNIMOD_DeStreak, "spec_1_position", "Anywhere"}, {UNIMOD_DeStreak, "spec_1_site", "C"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_, "approved", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_, "delta_composition", "dHex Hex(3) HexNAc(4)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_, "spec_2_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_, "spec_2_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_, "spec_2_site", "T"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_, "spec_2_site", "S"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_, "approved", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_, "delta_composition", "dHex Hex(4) HexNAc(4)"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_, "spec_2_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_, "spec_2_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_, "spec_2_site", "T"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_, "spec_2_site", "S"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_, "approved", "1"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_, "delta_composition", "dHex Hex(5) HexNAc(4)"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_, "spec_1_site", "N"}, {UNIMOD_Hex_3_HexNAc_4_, "approved", "1"}, {UNIMOD_Hex_3_HexNAc_4_, "delta_composition", "Hex(3) HexNAc(4)"}, {UNIMOD_Hex_3_HexNAc_4_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_4_, "spec_1_site", "N"}, {UNIMOD_Hex_3_HexNAc_4_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_4_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_4_, "spec_2_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_4_, "spec_2_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_4_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_4_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_4_, "spec_2_site", "T"}, {UNIMOD_Hex_3_HexNAc_4_, "spec_2_site", "S"}, {UNIMOD_Hex_4_HexNAc_4_, "approved", "1"}, {UNIMOD_Hex_4_HexNAc_4_, "delta_composition", "Hex(4) HexNAc(4)"}, {UNIMOD_Hex_4_HexNAc_4_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_4_, "spec_1_site", "N"}, {UNIMOD_Hex_4_HexNAc_4_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_4_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_4_, "spec_2_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_4_, "spec_2_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_4_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_4_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_4_, "spec_2_site", "T"}, {UNIMOD_Hex_4_HexNAc_4_, "spec_2_site", "S"}, {UNIMOD_Hex_5_HexNAc_4_, "approved", "1"}, {UNIMOD_Hex_5_HexNAc_4_, "delta_composition", "Hex(5) HexNAc(4)"}, {UNIMOD_Hex_5_HexNAc_4_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_5_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_HexNAc_4_, "spec_1_site", "N"}, {UNIMOD_Hex_5_HexNAc_4_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_5_HexNAc_4_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_5_HexNAc_4_, "spec_2_hidden", "1"}, {UNIMOD_Hex_5_HexNAc_4_, "spec_2_hidden", "1"}, {UNIMOD_Hex_5_HexNAc_4_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_5_HexNAc_4_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_5_HexNAc_4_, "spec_2_site", "T"}, {UNIMOD_Hex_5_HexNAc_4_, "spec_2_site", "S"}, {UNIMOD_Cysteinyl, "approved", "1"}, {UNIMOD_Cysteinyl, "delta_composition", "H(5) C(3) N O(2) S"}, {UNIMOD_Cysteinyl, "spec_1_classification", "Multiple"}, {UNIMOD_Cysteinyl, "spec_1_hidden", "1"}, {UNIMOD_Cysteinyl, "spec_1_position", "Anywhere"}, {UNIMOD_Cysteinyl, "spec_1_site", "C"}, {UNIMOD_Lys_loss, "approved", "1"}, {UNIMOD_Lys_loss, "delta_composition", "H(-12) C(-6) N(-2) O(-1)"}, {UNIMOD_Lys_loss, "spec_1_classification", "Post-translational"}, {UNIMOD_Lys_loss, "spec_1_hidden", "1"}, {UNIMOD_Lys_loss, "spec_1_position", "Protein C-term"}, {UNIMOD_Lys_loss, "spec_1_site", "K"}, {UNIMOD_Nmethylmaleimide, "approved", "1"}, {UNIMOD_Nmethylmaleimide, "delta_composition", "H(5) C(5) N O(2)"}, {UNIMOD_Nmethylmaleimide, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Nmethylmaleimide, "spec_1_hidden", "1"}, {UNIMOD_Nmethylmaleimide, "spec_1_position", "Anywhere"}, {UNIMOD_Nmethylmaleimide, "spec_1_site", "C"}, {UNIMOD_Nmethylmaleimide, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Nmethylmaleimide, "spec_2_hidden", "1"}, {UNIMOD_Nmethylmaleimide, "spec_2_position", "Anywhere"}, {UNIMOD_Nmethylmaleimide, "spec_2_site", "K"}, {UNIMOD_DimethylpyrroleAdduct, "approved", "1"}, {UNIMOD_DimethylpyrroleAdduct, "delta_composition", "H(6) C(6)"}, {UNIMOD_DimethylpyrroleAdduct, "spec_1_classification", "Chemical derivative"}, {UNIMOD_DimethylpyrroleAdduct, "spec_1_hidden", "1"}, {UNIMOD_DimethylpyrroleAdduct, "spec_1_position", "Anywhere"}, {UNIMOD_DimethylpyrroleAdduct, "spec_1_site", "K"}, {UNIMOD_Delta_H_2_C_5_, "approved", "1"}, {UNIMOD_Delta_H_2_C_5_, "delta_composition", "H(2) C(5)"}, {UNIMOD_Delta_H_2_C_5_, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Delta_H_2_C_5_, "spec_1_hidden", "1"}, {UNIMOD_Delta_H_2_C_5_, "spec_1_position", "Anywhere"}, {UNIMOD_Delta_H_2_C_5_, "spec_1_site", "K"}, {UNIMOD_Delta_H_2_C_3_O_1_, "approved", "1"}, {UNIMOD_Delta_H_2_C_3_O_1_, "delta_composition", "H(2) C(3) O"}, {UNIMOD_Delta_H_2_C_3_O_1_, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Delta_H_2_C_3_O_1_, "spec_1_hidden", "1"}, {UNIMOD_Delta_H_2_C_3_O_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Delta_H_2_C_3_O_1_, "spec_1_site", "K"}, {UNIMOD_Delta_H_2_C_3_O_1_, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Delta_H_2_C_3_O_1_, "spec_2_hidden", "1"}, {UNIMOD_Delta_H_2_C_3_O_1_, "spec_2_position", "Anywhere"}, {UNIMOD_Delta_H_2_C_3_O_1_, "spec_2_site", "R"}, {UNIMOD_Nethylmaleimide_water, "approved", "1"}, {UNIMOD_Nethylmaleimide_water, "delta_composition", "H(9) C(6) N O(3)"}, {UNIMOD_Nethylmaleimide_water, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Nethylmaleimide_water, "spec_1_hidden", "1"}, {UNIMOD_Nethylmaleimide_water, "spec_1_position", "Anywhere"}, {UNIMOD_Nethylmaleimide_water, "spec_1_site", "C"}, {UNIMOD_Nethylmaleimide_water, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Nethylmaleimide_water, "spec_2_hidden", "1"}, {UNIMOD_Nethylmaleimide_water, "spec_2_position", "Anywhere"}, {UNIMOD_Nethylmaleimide_water, "spec_2_site", "K"}, {UNIMOD_Xlink_B10621, "approved", "1"}, {UNIMOD_Xlink_B10621, "delta_composition", "H(30) C(31) N(4) O(6) S I"}, {UNIMOD_Xlink_B10621, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Xlink_B10621, "spec_1_hidden", "1"}, {UNIMOD_Xlink_B10621, "spec_1_position", "Anywhere"}, {UNIMOD_Xlink_B10621, "spec_1_site", "C"}, {UNIMOD_DTBP, "approved", "0"}, {UNIMOD_DTBP, "delta_composition", "H(5) C(3) N S"}, {UNIMOD_DTBP, "spec_1_classification", "Chemical derivative"}, {UNIMOD_DTBP, "spec_1_hidden", "1"}, {UNIMOD_DTBP, "spec_1_position", "Anywhere"}, {UNIMOD_DTBP, "spec_1_site", "N"}, {UNIMOD_DTBP, "spec_2_classification", "Chemical derivative"}, {UNIMOD_DTBP, "spec_2_hidden", "1"}, {UNIMOD_DTBP, "spec_2_position", "Anywhere"}, {UNIMOD_DTBP, "spec_2_site", "Q"}, {UNIMOD_DTBP, "spec_3_classification", "Chemical derivative"}, {UNIMOD_DTBP, "spec_3_hidden", "1"}, {UNIMOD_DTBP, "spec_3_position", "Anywhere"}, {UNIMOD_DTBP, "spec_3_site", "R"}, {UNIMOD_DTBP, "spec_4_classification", "Chemical derivative"}, {UNIMOD_DTBP, "spec_4_hidden", "1"}, {UNIMOD_DTBP, "spec_4_position", "Anywhere"}, {UNIMOD_DTBP, "spec_4_site", "K"}, {UNIMOD_DTBP, "spec_5_classification", "Chemical derivative"}, {UNIMOD_DTBP, "spec_5_hidden", "1"}, {UNIMOD_DTBP, "spec_5_position", "Protein N-term"}, {UNIMOD_DTBP, "spec_5_site", "N-term"}, {UNIMOD_FP_Biotin, "approved", "0"}, {UNIMOD_FP_Biotin, "delta_composition", "H(49) C(27) N(4) O(5) P S"}, {UNIMOD_FP_Biotin, "spec_1_classification", "Chemical derivative"}, {UNIMOD_FP_Biotin, "spec_1_hidden", "1"}, {UNIMOD_FP_Biotin, "spec_1_position", "Anywhere"}, {UNIMOD_FP_Biotin, "spec_1_site", "S"}, {UNIMOD_FP_Biotin, "spec_2_classification", "Chemical derivative"}, {UNIMOD_FP_Biotin, "spec_2_hidden", "1"}, {UNIMOD_FP_Biotin, "spec_2_position", "Anywhere"}, {UNIMOD_FP_Biotin, "spec_2_site", "Y"}, {UNIMOD_FP_Biotin, "spec_3_classification", "Chemical derivative"}, {UNIMOD_FP_Biotin, "spec_3_hidden", "1"}, {UNIMOD_FP_Biotin, "spec_3_position", "Anywhere"}, {UNIMOD_FP_Biotin, "spec_3_site", "T"}, {UNIMOD_FP_Biotin, "spec_4_classification", "Chemical derivative"}, {UNIMOD_FP_Biotin, "spec_4_hidden", "1"}, {UNIMOD_FP_Biotin, "spec_4_position", "Anywhere"}, {UNIMOD_FP_Biotin, "spec_4_site", "K"}, {UNIMOD_Delta_H_4_C_2_O__1_S_1_, "approved", "1"}, {UNIMOD_Delta_H_4_C_2_O__1_S_1_, "delta_composition", "H(4) C(2) O(-1) S"}, {UNIMOD_Delta_H_4_C_2_O__1_S_1_, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Delta_H_4_C_2_O__1_S_1_, "spec_1_hidden", "1"}, {UNIMOD_Delta_H_4_C_2_O__1_S_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Delta_H_4_C_2_O__1_S_1_, "spec_1_site", "S"}, {UNIMOD_Methyl_2H_3_13C_1_, "approved", "1"}, {UNIMOD_Methyl_2H_3_13C_1_, "delta_composition", "H(-1) 2H(3) 13C"}, {UNIMOD_Methyl_2H_3_13C_1_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Methyl_2H_3_13C_1_, "spec_1_hidden", "1"}, {UNIMOD_Methyl_2H_3_13C_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Methyl_2H_3_13C_1_, "spec_1_site", "R"}, {UNIMOD_Methyl_2H_3_13C_1_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Methyl_2H_3_13C_1_, "spec_2_hidden", "1"}, {UNIMOD_Methyl_2H_3_13C_1_, "spec_2_position", "Anywhere"}, {UNIMOD_Methyl_2H_3_13C_1_, "spec_2_site", "K"}, {UNIMOD_Dimethyl_2H_6_13C_2_, "approved", "1"}, {UNIMOD_Dimethyl_2H_6_13C_2_, "delta_composition", "H(-2) 2H(6) 13C(2)"}, {UNIMOD_Dimethyl_2H_6_13C_2_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Dimethyl_2H_6_13C_2_, "spec_1_hidden", "1"}, {UNIMOD_Dimethyl_2H_6_13C_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Dimethyl_2H_6_13C_2_, "spec_1_site", "R"}, {UNIMOD_Dimethyl_2H_6_13C_2_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Dimethyl_2H_6_13C_2_, "spec_2_hidden", "1"}, {UNIMOD_Dimethyl_2H_6_13C_2_, "spec_2_position", "Anywhere"}, {UNIMOD_Dimethyl_2H_6_13C_2_, "spec_2_site", "K"}, {UNIMOD_Dimethyl_2H_6_13C_2_, "spec_3_classification", "Isotopic label"}, {UNIMOD_Dimethyl_2H_6_13C_2_, "spec_3_hidden", "1"}, {UNIMOD_Dimethyl_2H_6_13C_2_, "spec_3_position", "Any N-term"}, {UNIMOD_Dimethyl_2H_6_13C_2_, "spec_3_site", "N-term"}, {UNIMOD_Dimethyl_2H_6_13C_2_, "spec_4_classification", "Isotopic label"}, {UNIMOD_Dimethyl_2H_6_13C_2_, "spec_4_hidden", "1"}, {UNIMOD_Dimethyl_2H_6_13C_2_, "spec_4_position", "Protein N-term"}, {UNIMOD_Dimethyl_2H_6_13C_2_, "spec_4_site", "N-term"}, {UNIMOD_Thiophos_S_S_biotin, "approved", "1"}, {UNIMOD_Thiophos_S_S_biotin, "delta_composition", "H(34) C(19) N(4) O(5) P S(3)"}, {UNIMOD_Thiophos_S_S_biotin, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Thiophos_S_S_biotin, "spec_1_hidden", "1"}, {UNIMOD_Thiophos_S_S_biotin, "spec_1_position", "Anywhere"}, {UNIMOD_Thiophos_S_S_biotin, "spec_1_site", "S"}, {UNIMOD_Thiophos_S_S_biotin, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Thiophos_S_S_biotin, "spec_2_hidden", "1"}, {UNIMOD_Thiophos_S_S_biotin, "spec_2_position", "Anywhere"}, {UNIMOD_Thiophos_S_S_biotin, "spec_2_site", "T"}, {UNIMOD_Thiophos_S_S_biotin, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Thiophos_S_S_biotin, "spec_3_hidden", "1"}, {UNIMOD_Thiophos_S_S_biotin, "spec_3_position", "Anywhere"}, {UNIMOD_Thiophos_S_S_biotin, "spec_3_site", "Y"}, {UNIMOD_Can_FP_biotin, "approved", "0"}, {UNIMOD_Can_FP_biotin, "delta_composition", "H(34) C(19) N(3) O(5) P S"}, {UNIMOD_Can_FP_biotin, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Can_FP_biotin, "spec_1_hidden", "1"}, {UNIMOD_Can_FP_biotin, "spec_1_position", "Anywhere"}, {UNIMOD_Can_FP_biotin, "spec_1_site", "S"}, {UNIMOD_Can_FP_biotin, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Can_FP_biotin, "spec_2_hidden", "1"}, {UNIMOD_Can_FP_biotin, "spec_2_position", "Anywhere"}, {UNIMOD_Can_FP_biotin, "spec_2_site", "Y"}, {UNIMOD_Can_FP_biotin, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Can_FP_biotin, "spec_3_hidden", "1"}, {UNIMOD_Can_FP_biotin, "spec_3_position", "Anywhere"}, {UNIMOD_Can_FP_biotin, "spec_3_site", "T"}, {UNIMOD_HNE_Delta_H_2_, "approved", "1"}, {UNIMOD_HNE_Delta_H_2_, "delta_composition", "H(18) C(9) O(2)"}, {UNIMOD_HNE_Delta_H_2_, "spec_1_classification", "Chemical derivative"}, {UNIMOD_HNE_Delta_H_2_, "spec_1_hidden", "1"}, {UNIMOD_HNE_Delta_H_2_, "spec_1_position", "Anywhere"}, {UNIMOD_HNE_Delta_H_2_, "spec_1_site", "C"}, {UNIMOD_HNE_Delta_H_2_, "spec_2_classification", "Chemical derivative"}, {UNIMOD_HNE_Delta_H_2_, "spec_2_hidden", "1"}, {UNIMOD_HNE_Delta_H_2_, "spec_2_position", "Anywhere"}, {UNIMOD_HNE_Delta_H_2_, "spec_2_site", "H"}, {UNIMOD_HNE_Delta_H_2_, "spec_3_classification", "Chemical derivative"}, {UNIMOD_HNE_Delta_H_2_, "spec_3_hidden", "1"}, {UNIMOD_HNE_Delta_H_2_, "spec_3_position", "Anywhere"}, {UNIMOD_HNE_Delta_H_2_, "spec_3_site", "K"}, {UNIMOD_Methylamine, "approved", "1"}, {UNIMOD_Methylamine, "delta_composition", "H(3) C N O(-1)"}, {UNIMOD_Methylamine, "spec_1_classification", "Artefact"}, {UNIMOD_Methylamine, "spec_1_hidden", "1"}, {UNIMOD_Methylamine, "spec_1_position", "Anywhere"}, {UNIMOD_Methylamine, "spec_1_site", "S"}, {UNIMOD_Methylamine, "spec_2_classification", "Artefact"}, {UNIMOD_Methylamine, "spec_2_hidden", "1"}, {UNIMOD_Methylamine, "spec_2_position", "Anywhere"}, {UNIMOD_Methylamine, "spec_2_site", "T"}, {UNIMOD_Bromo, "approved", "1"}, {UNIMOD_Bromo, "delta_composition", "H(-1) Br"}, {UNIMOD_Bromo, "spec_1_classification", "Post-translational"}, {UNIMOD_Bromo, "spec_1_hidden", "1"}, {UNIMOD_Bromo, "spec_1_position", "Anywhere"}, {UNIMOD_Bromo, "spec_1_site", "W"}, {UNIMOD_Bromo, "spec_2_classification", "Post-translational"}, {UNIMOD_Bromo, "spec_2_hidden", "1"}, {UNIMOD_Bromo, "spec_2_position", "Anywhere"}, {UNIMOD_Bromo, "spec_2_site", "H"}, {UNIMOD_Bromo, "spec_3_classification", "Post-translational"}, {UNIMOD_Bromo, "spec_3_hidden", "1"}, {UNIMOD_Bromo, "spec_3_position", "Anywhere"}, {UNIMOD_Bromo, "spec_3_site", "F"}, {UNIMOD_Bromo, "spec_4_classification", "Artefact"}, {UNIMOD_Bromo, "spec_4_hidden", "1"}, {UNIMOD_Bromo, "spec_4_position", "Anywhere"}, {UNIMOD_Bromo, "spec_4_site", "Y"}, {UNIMOD_Amino, "approved", "1"}, {UNIMOD_Amino, "delta_composition", "H N"}, {UNIMOD_Amino, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Amino, "spec_1_hidden", "1"}, {UNIMOD_Amino, "spec_1_position", "Anywhere"}, {UNIMOD_Amino, "spec_1_site", "Y"}, {UNIMOD_Argbiotinhydrazide, "approved", "0"}, {UNIMOD_Argbiotinhydrazide, "delta_composition", "H(13) C(9) N O(2) S"}, {UNIMOD_Argbiotinhydrazide, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Argbiotinhydrazide, "spec_1_hidden", "1"}, {UNIMOD_Argbiotinhydrazide, "spec_1_position", "Anywhere"}, {UNIMOD_Argbiotinhydrazide, "spec_1_site", "R"}, {UNIMOD_Arg__GluSA, "approved", "1"}, {UNIMOD_Arg__GluSA, "delta_composition", "H(-5) C(-1) N(-3) O"}, {UNIMOD_Arg__GluSA, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Arg__GluSA, "spec_1_hidden", "1"}, {UNIMOD_Arg__GluSA, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__GluSA, "spec_1_site", "R"}, {UNIMOD_Trioxidation, "approved", "1"}, {UNIMOD_Trioxidation, "delta_composition", "O(3)"}, {UNIMOD_Trioxidation, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Trioxidation, "spec_1_hidden", "1"}, {UNIMOD_Trioxidation, "spec_1_position", "Anywhere"}, {UNIMOD_Trioxidation, "spec_1_site", "C"}, {UNIMOD_Trioxidation, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Trioxidation, "spec_2_hidden", "1"}, {UNIMOD_Trioxidation, "spec_2_position", "Anywhere"}, {UNIMOD_Trioxidation, "spec_2_site", "W"}, {UNIMOD_Trioxidation, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Trioxidation, "spec_3_hidden", "1"}, {UNIMOD_Trioxidation, "spec_3_position", "Anywhere"}, {UNIMOD_Trioxidation, "spec_3_site", "Y"}, {UNIMOD_His__Asn, "approved", "1"}, {UNIMOD_His__Asn, "delta_composition", "H(-1) C(-2) N(-1) O"}, {UNIMOD_His__Asn, "spec_1_classification", "AA substitution"}, {UNIMOD_His__Asn, "spec_1_hidden", "1"}, {UNIMOD_His__Asn, "spec_1_position", "Anywhere"}, {UNIMOD_His__Asn, "spec_1_site", "H"}, {UNIMOD_His__Asp, "approved", "1"}, {UNIMOD_His__Asp, "delta_composition", "H(-2) C(-2) N(-2) O(2)"}, {UNIMOD_His__Asp, "spec_1_classification", "AA substitution"}, {UNIMOD_His__Asp, "spec_1_hidden", "1"}, {UNIMOD_His__Asp, "spec_1_position", "Anywhere"}, {UNIMOD_His__Asp, "spec_1_site", "H"}, {UNIMOD_Trp__Hydroxykynurenin, "approved", "1"}, {UNIMOD_Trp__Hydroxykynurenin, "delta_composition", "C(-1) O(2)"}, {UNIMOD_Trp__Hydroxykynurenin, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Trp__Hydroxykynurenin, "spec_1_hidden", "1"}, {UNIMOD_Trp__Hydroxykynurenin, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__Hydroxykynurenin, "spec_1_site", "W"}, {UNIMOD_Trp__Kynurenin, "approved", "1"}, {UNIMOD_Trp__Kynurenin, "delta_composition", "C(-1) O"}, {UNIMOD_Trp__Kynurenin, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Trp__Kynurenin, "spec_1_hidden", "1"}, {UNIMOD_Trp__Kynurenin, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__Kynurenin, "spec_1_site", "W"}, {UNIMOD_Lys__Allysine, "approved", "1"}, {UNIMOD_Lys__Allysine, "delta_composition", "H(-3) N(-1) O"}, {UNIMOD_Lys__Allysine, "spec_1_classification", "Post-translational"}, {UNIMOD_Lys__Allysine, "spec_1_hidden", "1"}, {UNIMOD_Lys__Allysine, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__Allysine, "spec_1_site", "K"}, {UNIMOD_Lysbiotinhydrazide, "approved", "0"}, {UNIMOD_Lysbiotinhydrazide, "delta_composition", "H(15) C(10) N(3) O(2) S"}, {UNIMOD_Lysbiotinhydrazide, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Lysbiotinhydrazide, "spec_1_hidden", "1"}, {UNIMOD_Lysbiotinhydrazide, "spec_1_position", "Anywhere"}, {UNIMOD_Lysbiotinhydrazide, "spec_1_site", "K"}, {UNIMOD_Nitro, "approved", "1"}, {UNIMOD_Nitro, "delta_composition", "H(-1) N O(2)"}, {UNIMOD_Nitro, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Nitro, "spec_1_hidden", "1"}, {UNIMOD_Nitro, "spec_1_position", "Anywhere"}, {UNIMOD_Nitro, "spec_1_site", "W"}, {UNIMOD_Nitro, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Nitro, "spec_2_hidden", "1"}, {UNIMOD_Nitro, "spec_2_position", "Anywhere"}, {UNIMOD_Nitro, "spec_2_site", "Y"}, {UNIMOD_probiotinhydrazide, "approved", "0"}, {UNIMOD_probiotinhydrazide, "delta_composition", "H(18) C(10) N(4) O(2) S"}, {UNIMOD_probiotinhydrazide, "spec_1_classification", "Chemical derivative"}, {UNIMOD_probiotinhydrazide, "spec_1_hidden", "1"}, {UNIMOD_probiotinhydrazide, "spec_1_position", "Anywhere"}, {UNIMOD_probiotinhydrazide, "spec_1_site", "P"}, {UNIMOD_Pro__pyro_Glu, "approved", "1"}, {UNIMOD_Pro__pyro_Glu, "delta_composition", "H(-2) O"}, {UNIMOD_Pro__pyro_Glu, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Pro__pyro_Glu, "spec_1_hidden", "1"}, {UNIMOD_Pro__pyro_Glu, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__pyro_Glu, "spec_1_site", "P"}, {UNIMOD_Pro__Pyrrolidinone, "approved", "1"}, {UNIMOD_Pro__Pyrrolidinone, "delta_composition", "H(-2) C(-1) O(-1)"}, {UNIMOD_Pro__Pyrrolidinone, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Pro__Pyrrolidinone, "spec_1_hidden", "1"}, {UNIMOD_Pro__Pyrrolidinone, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__Pyrrolidinone, "spec_1_site", "P"}, {UNIMOD_Thrbiotinhydrazide, "approved", "0"}, {UNIMOD_Thrbiotinhydrazide, "delta_composition", "H(16) C(10) N(4) O S"}, {UNIMOD_Thrbiotinhydrazide, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Thrbiotinhydrazide, "spec_1_hidden", "1"}, {UNIMOD_Thrbiotinhydrazide, "spec_1_position", "Anywhere"}, {UNIMOD_Thrbiotinhydrazide, "spec_1_site", "T"}, {UNIMOD_Diisopropylphosphate, "approved", "0"}, {UNIMOD_Diisopropylphosphate, "delta_composition", "H(13) C(6) O(3) P"}, {UNIMOD_Diisopropylphosphate, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Diisopropylphosphate, "spec_1_hidden", "1"}, {UNIMOD_Diisopropylphosphate, "spec_1_position", "Anywhere"}, {UNIMOD_Diisopropylphosphate, "spec_1_site", "S"}, {UNIMOD_Diisopropylphosphate, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Diisopropylphosphate, "spec_2_hidden", "1"}, {UNIMOD_Diisopropylphosphate, "spec_2_position", "Anywhere"}, {UNIMOD_Diisopropylphosphate, "spec_2_site", "T"}, {UNIMOD_Diisopropylphosphate, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Diisopropylphosphate, "spec_3_hidden", "1"}, {UNIMOD_Diisopropylphosphate, "spec_3_position", "Anywhere"}, {UNIMOD_Diisopropylphosphate, "spec_3_site", "Y"}, {UNIMOD_Diisopropylphosphate, "spec_4_classification", "Chemical derivative"}, {UNIMOD_Diisopropylphosphate, "spec_4_hidden", "1"}, {UNIMOD_Diisopropylphosphate, "spec_4_position", "Anywhere"}, {UNIMOD_Diisopropylphosphate, "spec_4_site", "K"}, {UNIMOD_Diisopropylphosphate, "spec_5_classification", "Chemical derivative"}, {UNIMOD_Diisopropylphosphate, "spec_5_hidden", "1"}, {UNIMOD_Diisopropylphosphate, "spec_5_position", "Any N-term"}, {UNIMOD_Diisopropylphosphate, "spec_5_site", "N-term"}, {UNIMOD_Isopropylphospho, "approved", "0"}, {UNIMOD_Isopropylphospho, "delta_composition", "H(7) C(3) O(3) P"}, {UNIMOD_Isopropylphospho, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Isopropylphospho, "spec_1_hidden", "1"}, {UNIMOD_Isopropylphospho, "spec_1_position", "Anywhere"}, {UNIMOD_Isopropylphospho, "spec_1_site", "S"}, {UNIMOD_Isopropylphospho, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Isopropylphospho, "spec_2_hidden", "1"}, {UNIMOD_Isopropylphospho, "spec_2_position", "Anywhere"}, {UNIMOD_Isopropylphospho, "spec_2_site", "T"}, {UNIMOD_Isopropylphospho, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Isopropylphospho, "spec_3_hidden", "1"}, {UNIMOD_Isopropylphospho, "spec_3_position", "Anywhere"}, {UNIMOD_Isopropylphospho, "spec_3_site", "Y"}, {UNIMOD_ICPL_13C_6_, "approved", "0"}, {UNIMOD_ICPL_13C_6_, "delta_composition", "H(3) 13C(6) N O"}, {UNIMOD_ICPL_13C_6_, "spec_1_classification", "Isotopic label"}, {UNIMOD_ICPL_13C_6_, "spec_1_hidden", "0"}, {UNIMOD_ICPL_13C_6_, "spec_1_position", "Anywhere"}, {UNIMOD_ICPL_13C_6_, "spec_1_site", "K"}, {UNIMOD_ICPL_13C_6_, "spec_2_classification", "Isotopic label"}, {UNIMOD_ICPL_13C_6_, "spec_2_hidden", "0"}, {UNIMOD_ICPL_13C_6_, "spec_2_position", "Protein N-term"}, {UNIMOD_ICPL_13C_6_, "spec_2_site", "N-term"}, {UNIMOD_ICPL_13C_6_, "spec_3_classification", "Isotopic label"}, {UNIMOD_ICPL_13C_6_, "spec_3_hidden", "1"}, {UNIMOD_ICPL_13C_6_, "spec_3_position", "Any N-term"}, {UNIMOD_ICPL_13C_6_, "spec_3_site", "N-term"}, {UNIMOD_ICPL, "approved", "0"}, {UNIMOD_ICPL, "delta_composition", "H(3) C(6) N O"}, {UNIMOD_ICPL, "spec_1_classification", "Isotopic label"}, {UNIMOD_ICPL, "spec_1_hidden", "0"}, {UNIMOD_ICPL, "spec_1_position", "Anywhere"}, {UNIMOD_ICPL, "spec_1_site", "K"}, {UNIMOD_ICPL, "spec_2_classification", "Isotopic label"}, {UNIMOD_ICPL, "spec_2_hidden", "0"}, {UNIMOD_ICPL, "spec_2_position", "Protein N-term"}, {UNIMOD_ICPL, "spec_2_site", "N-term"}, {UNIMOD_ICPL, "spec_3_classification", "Isotopic label"}, {UNIMOD_ICPL, "spec_3_hidden", "1"}, {UNIMOD_ICPL, "spec_3_position", "Any N-term"}, {UNIMOD_ICPL, "spec_3_site", "N-term"}, {UNIMOD_Deamidated_18O_1_, "approved", "1"}, {UNIMOD_Deamidated_18O_1_, "delta_composition", "H(-1) N(-1) 18O"}, {UNIMOD_Deamidated_18O_1_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Deamidated_18O_1_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Deamidated_18O_1_, "spec_1_hidden", "1"}, {UNIMOD_Deamidated_18O_1_, "spec_1_hidden", "1"}, {UNIMOD_Deamidated_18O_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Deamidated_18O_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Deamidated_18O_1_, "spec_1_site", "Q"}, {UNIMOD_Deamidated_18O_1_, "spec_1_site", "N"}, {UNIMOD_Cys__Dha, "approved", "1"}, {UNIMOD_Cys__Dha, "delta_composition", "H(-2) S(-1)"}, {UNIMOD_Cys__Dha, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Cys__Dha, "spec_1_hidden", "1"}, {UNIMOD_Cys__Dha, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__Dha, "spec_1_site", "C"}, {UNIMOD_Pro__Pyrrolidone, "approved", "0"}, {UNIMOD_Pro__Pyrrolidone, "delta_composition", "C(-1) O(-1)"}, {UNIMOD_Pro__Pyrrolidone, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Pro__Pyrrolidone, "spec_1_hidden", "1"}, {UNIMOD_Pro__Pyrrolidone, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__Pyrrolidone, "spec_1_site", "P"}, {UNIMOD_HMVK, "approved", "1"}, {UNIMOD_HMVK, "delta_composition", "H(6) C(4) O(2)"}, {UNIMOD_HMVK, "spec_1_classification", "Chemical derivative"}, {UNIMOD_HMVK, "spec_1_hidden", "1"}, {UNIMOD_HMVK, "spec_1_position", "Anywhere"}, {UNIMOD_HMVK, "spec_1_site", "C"}, {UNIMOD_Arg__Orn, "approved", "1"}, {UNIMOD_Arg__Orn, "delta_composition", "H(-2) C(-1) N(-2)"}, {UNIMOD_Arg__Orn, "spec_1_classification", "Artefact"}, {UNIMOD_Arg__Orn, "spec_1_hidden", "1"}, {UNIMOD_Arg__Orn, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__Orn, "spec_1_site", "R"}, {UNIMOD_Dehydro, "approved", "1"}, {UNIMOD_Dehydro, "delta_composition", "H(-1)"}, {UNIMOD_Dehydro, "spec_1_classification", "Multiple"}, {UNIMOD_Dehydro, "spec_1_hidden", "0"}, {UNIMOD_Dehydro, "spec_1_position", "Anywhere"}, {UNIMOD_Dehydro, "spec_1_site", "C"}, {UNIMOD_Diphthamide, "approved", "1"}, {UNIMOD_Diphthamide, "delta_composition", "H(15) C(7) N(2) O"}, {UNIMOD_Diphthamide, "spec_1_classification", "Post-translational"}, {UNIMOD_Diphthamide, "spec_1_hidden", "1"}, {UNIMOD_Diphthamide, "spec_1_position", "Anywhere"}, {UNIMOD_Diphthamide, "spec_1_site", "H"}, {UNIMOD_Hydroxyfarnesyl, "approved", "1"}, {UNIMOD_Hydroxyfarnesyl, "delta_composition", "H(24) C(15) O"}, {UNIMOD_Hydroxyfarnesyl, "spec_1_classification", "Post-translational"}, {UNIMOD_Hydroxyfarnesyl, "spec_1_hidden", "1"}, {UNIMOD_Hydroxyfarnesyl, "spec_1_position", "Anywhere"}, {UNIMOD_Hydroxyfarnesyl, "spec_1_site", "C"}, {UNIMOD_Diacylglycerol, "approved", "1"}, {UNIMOD_Diacylglycerol, "delta_composition", "H(68) C(37) O(4)"}, {UNIMOD_Diacylglycerol, "spec_1_classification", "Post-translational"}, {UNIMOD_Diacylglycerol, "spec_1_hidden", "1"}, {UNIMOD_Diacylglycerol, "spec_1_position", "Anywhere"}, {UNIMOD_Diacylglycerol, "spec_1_site", "C"}, {UNIMOD_Carboxyethyl, "approved", "1"}, {UNIMOD_Carboxyethyl, "delta_composition", "H(4) C(3) O(2)"}, {UNIMOD_Carboxyethyl, "spec_1_classification", "Post-translational"}, {UNIMOD_Carboxyethyl, "spec_1_hidden", "1"}, {UNIMOD_Carboxyethyl, "spec_1_position", "Anywhere"}, {UNIMOD_Carboxyethyl, "spec_1_site", "K"}, {UNIMOD_Carboxyethyl, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Carboxyethyl, "spec_2_hidden", "1"}, {UNIMOD_Carboxyethyl, "spec_2_position", "Anywhere"}, {UNIMOD_Carboxyethyl, "spec_2_site", "H"}, {UNIMOD_Hypusine, "approved", "1"}, {UNIMOD_Hypusine, "delta_composition", "H(9) C(4) N O"}, {UNIMOD_Hypusine, "spec_1_classification", "Post-translational"}, {UNIMOD_Hypusine, "spec_1_hidden", "1"}, {UNIMOD_Hypusine, "spec_1_position", "Anywhere"}, {UNIMOD_Hypusine, "spec_1_site", "K"}, {UNIMOD_Retinylidene, "approved", "1"}, {UNIMOD_Retinylidene, "delta_composition", "H(26) C(20)"}, {UNIMOD_Retinylidene, "spec_1_classification", "Post-translational"}, {UNIMOD_Retinylidene, "spec_1_hidden", "1"}, {UNIMOD_Retinylidene, "spec_1_position", "Anywhere"}, {UNIMOD_Retinylidene, "spec_1_site", "K"}, {UNIMOD_Lys__AminoadipicAcid, "approved", "1"}, {UNIMOD_Lys__AminoadipicAcid, "delta_composition", "H(-3) N(-1) O(2)"}, {UNIMOD_Lys__AminoadipicAcid, "spec_1_classification", "Post-translational"}, {UNIMOD_Lys__AminoadipicAcid, "spec_1_hidden", "1"}, {UNIMOD_Lys__AminoadipicAcid, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__AminoadipicAcid, "spec_1_site", "K"}, {UNIMOD_Cys__PyruvicAcid, "approved", "1"}, {UNIMOD_Cys__PyruvicAcid, "delta_composition", "H(-3) N(-1) O S(-1)"}, {UNIMOD_Cys__PyruvicAcid, "spec_1_classification", "Post-translational"}, {UNIMOD_Cys__PyruvicAcid, "spec_1_hidden", "1"}, {UNIMOD_Cys__PyruvicAcid, "spec_1_position", "Protein N-term"}, {UNIMOD_Cys__PyruvicAcid, "spec_1_site", "C"}, {UNIMOD_Ammonia_loss, "approved", "0"}, {UNIMOD_Ammonia_loss, "delta_composition", "H(-3) N(-1)"}, {UNIMOD_Ammonia_loss, "spec_1_classification", "Post-translational"}, {UNIMOD_Ammonia_loss, "spec_1_hidden", "1"}, {UNIMOD_Ammonia_loss, "spec_1_position", "Protein N-term"}, {UNIMOD_Ammonia_loss, "spec_1_site", "T"}, {UNIMOD_Ammonia_loss, "spec_2_classification", "Post-translational"}, {UNIMOD_Ammonia_loss, "spec_2_hidden", "1"}, {UNIMOD_Ammonia_loss, "spec_2_position", "Protein N-term"}, {UNIMOD_Ammonia_loss, "spec_2_site", "S"}, {UNIMOD_Ammonia_loss, "spec_3_classification", "Artefact"}, {UNIMOD_Ammonia_loss, "spec_3_hidden", "0"}, {UNIMOD_Ammonia_loss, "spec_3_position", "Any N-term"}, {UNIMOD_Ammonia_loss, "spec_3_site", "C"}, {UNIMOD_Ammonia_loss, "spec_4_classification", "Chemical derivative"}, {UNIMOD_Ammonia_loss, "spec_4_hidden", "1"}, {UNIMOD_Ammonia_loss, "spec_4_position", "Anywhere"}, {UNIMOD_Ammonia_loss, "spec_4_site", "N"}, {UNIMOD_Phycocyanobilin, "approved", "1"}, {UNIMOD_Phycocyanobilin, "delta_composition", "H(38) C(33) N(4) O(6)"}, {UNIMOD_Phycocyanobilin, "spec_1_classification", "Post-translational"}, {UNIMOD_Phycocyanobilin, "spec_1_hidden", "1"}, {UNIMOD_Phycocyanobilin, "spec_1_position", "Anywhere"}, {UNIMOD_Phycocyanobilin, "spec_1_site", "C"}, {UNIMOD_Phycoerythrobilin, "approved", "1"}, {UNIMOD_Phycoerythrobilin, "delta_composition", "H(40) C(33) N(4) O(6)"}, {UNIMOD_Phycoerythrobilin, "spec_1_classification", "Post-translational"}, {UNIMOD_Phycoerythrobilin, "spec_1_hidden", "1"}, {UNIMOD_Phycoerythrobilin, "spec_1_position", "Anywhere"}, {UNIMOD_Phycoerythrobilin, "spec_1_site", "C"}, {UNIMOD_Phytochromobilin, "approved", "1"}, {UNIMOD_Phytochromobilin, "delta_composition", "H(36) C(33) N(4) O(6)"}, {UNIMOD_Phytochromobilin, "spec_1_classification", "Post-translational"}, {UNIMOD_Phytochromobilin, "spec_1_hidden", "1"}, {UNIMOD_Phytochromobilin, "spec_1_position", "Anywhere"}, {UNIMOD_Phytochromobilin, "spec_1_site", "C"}, {UNIMOD_Heme, "approved", "1"}, {UNIMOD_Heme, "delta_composition", "H(32) C(34) N(4) O(4) Fe"}, {UNIMOD_Heme, "spec_1_classification", "Post-translational"}, {UNIMOD_Heme, "spec_1_hidden", "1"}, {UNIMOD_Heme, "spec_1_position", "Anywhere"}, {UNIMOD_Heme, "spec_1_site", "C"}, {UNIMOD_Heme, "spec_2_classification", "Post-translational"}, {UNIMOD_Heme, "spec_2_hidden", "1"}, {UNIMOD_Heme, "spec_2_position", "Anywhere"}, {UNIMOD_Heme, "spec_2_site", "H"}, {UNIMOD_Molybdopterin, "approved", "1"}, {UNIMOD_Molybdopterin, "delta_composition", "H(11) C(10) N(5) O(8) P S(2) Mo"}, {UNIMOD_Molybdopterin, "spec_1_classification", "Post-translational"}, {UNIMOD_Molybdopterin, "spec_1_hidden", "1"}, {UNIMOD_Molybdopterin, "spec_1_position", "Anywhere"}, {UNIMOD_Molybdopterin, "spec_1_site", "C"}, {UNIMOD_Quinone, "approved", "1"}, {UNIMOD_Quinone, "delta_composition", "H(-2) O(2)"}, {UNIMOD_Quinone, "spec_1_classification", "Post-translational"}, {UNIMOD_Quinone, "spec_1_hidden", "1"}, {UNIMOD_Quinone, "spec_1_position", "Anywhere"}, {UNIMOD_Quinone, "spec_1_site", "Y"}, {UNIMOD_Quinone, "spec_2_classification", "Post-translational"}, {UNIMOD_Quinone, "spec_2_hidden", "1"}, {UNIMOD_Quinone, "spec_2_position", "Anywhere"}, {UNIMOD_Quinone, "spec_2_site", "W"}, {UNIMOD_Glucosylgalactosyl, "approved", "1"}, {UNIMOD_Glucosylgalactosyl, "delta_composition", "O Hex(2)"}, {UNIMOD_Glucosylgalactosyl, "spec_1_classification", "Other glycosylation"}, {UNIMOD_Glucosylgalactosyl, "spec_1_hidden", "1"}, {UNIMOD_Glucosylgalactosyl, "spec_1_position", "Anywhere"}, {UNIMOD_Glucosylgalactosyl, "spec_1_site", "K"}, {UNIMOD_GPIanchor, "approved", "0"}, {UNIMOD_GPIanchor, "delta_composition", "H(6) C(2) N O(3) P"}, {UNIMOD_GPIanchor, "spec_1_classification", "Post-translational"}, {UNIMOD_GPIanchor, "spec_1_hidden", "1"}, {UNIMOD_GPIanchor, "spec_1_position", "Protein C-term"}, {UNIMOD_GPIanchor, "spec_1_site", "C-term"}, {UNIMOD_PhosphoribosyldephosphoCoA, "approved", "1"}, {UNIMOD_PhosphoribosyldephosphoCoA, "delta_composition", "H(42) C(26) N(7) O(19) P(3) S"}, {UNIMOD_PhosphoribosyldephosphoCoA, "spec_1_classification", "Post-translational"}, {UNIMOD_PhosphoribosyldephosphoCoA, "spec_1_hidden", "1"}, {UNIMOD_PhosphoribosyldephosphoCoA, "spec_1_position", "Anywhere"}, {UNIMOD_PhosphoribosyldephosphoCoA, "spec_1_site", "S"}, {UNIMOD_GlycerylPE, "approved", "1"}, {UNIMOD_GlycerylPE, "delta_composition", "H(12) C(5) N O(5) P"}, {UNIMOD_GlycerylPE, "spec_1_classification", "Post-translational"}, {UNIMOD_GlycerylPE, "spec_1_hidden", "1"}, {UNIMOD_GlycerylPE, "spec_1_position", "Anywhere"}, {UNIMOD_GlycerylPE, "spec_1_site", "E"}, {UNIMOD_Triiodothyronine, "approved", "1"}, {UNIMOD_Triiodothyronine, "delta_composition", "H C(6) O I(3)"}, {UNIMOD_Triiodothyronine, "spec_1_classification", "Post-translational"}, {UNIMOD_Triiodothyronine, "spec_1_hidden", "1"}, {UNIMOD_Triiodothyronine, "spec_1_position", "Anywhere"}, {UNIMOD_Triiodothyronine, "spec_1_site", "Y"}, {UNIMOD_Thyroxine, "approved", "1"}, {UNIMOD_Thyroxine, "delta_composition", "C(6) O I(4)"}, {UNIMOD_Thyroxine, "spec_1_classification", "Post-translational"}, {UNIMOD_Thyroxine, "spec_1_hidden", "1"}, {UNIMOD_Thyroxine, "spec_1_position", "Anywhere"}, {UNIMOD_Thyroxine, "spec_1_site", "Y"}, {UNIMOD_Tyr__Dha, "approved", "1"}, {UNIMOD_Tyr__Dha, "delta_composition", "H(-6) C(-6) O(-1)"}, {UNIMOD_Tyr__Dha, "spec_1_classification", "Post-translational"}, {UNIMOD_Tyr__Dha, "spec_1_hidden", "1"}, {UNIMOD_Tyr__Dha, "spec_1_position", "Anywhere"}, {UNIMOD_Tyr__Dha, "spec_1_site", "Y"}, {UNIMOD_Didehydro, "approved", "1"}, {UNIMOD_Didehydro, "delta_composition", "H(-2)"}, {UNIMOD_Didehydro, "spec_1_classification", "Post-translational"}, {UNIMOD_Didehydro, "spec_1_hidden", "1"}, {UNIMOD_Didehydro, "spec_1_position", "Anywhere"}, {UNIMOD_Didehydro, "spec_1_site", "Y"}, {UNIMOD_Didehydro, "spec_2_classification", "Post-translational"}, {UNIMOD_Didehydro, "spec_2_hidden", "1"}, {UNIMOD_Didehydro, "spec_2_position", "Anywhere"}, {UNIMOD_Didehydro, "spec_2_site", "S"}, {UNIMOD_Didehydro, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Didehydro, "spec_3_hidden", "1"}, {UNIMOD_Didehydro, "spec_3_position", "Anywhere"}, {UNIMOD_Didehydro, "spec_3_site", "T"}, {UNIMOD_Didehydro, "spec_4_classification", "Artefact"}, {UNIMOD_Didehydro, "spec_4_hidden", "1"}, {UNIMOD_Didehydro, "spec_4_position", "Any C-term"}, {UNIMOD_Didehydro, "spec_4_site", "K"}, {UNIMOD_Cys__Oxoalanine, "approved", "1"}, {UNIMOD_Cys__Oxoalanine, "delta_composition", "H(-2) O S(-1)"}, {UNIMOD_Cys__Oxoalanine, "spec_1_classification", "Post-translational"}, {UNIMOD_Cys__Oxoalanine, "spec_1_hidden", "1"}, {UNIMOD_Cys__Oxoalanine, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__Oxoalanine, "spec_1_site", "C"}, {UNIMOD_Ser__LacticAcid, "approved", "1"}, {UNIMOD_Ser__LacticAcid, "delta_composition", "H(-1) N(-1)"}, {UNIMOD_Ser__LacticAcid, "spec_1_classification", "Post-translational"}, {UNIMOD_Ser__LacticAcid, "spec_1_hidden", "1"}, {UNIMOD_Ser__LacticAcid, "spec_1_position", "Protein N-term"}, {UNIMOD_Ser__LacticAcid, "spec_1_site", "S"}, {UNIMOD_Phosphoadenosine, "approved", "1"}, {UNIMOD_Phosphoadenosine, "delta_composition", "H(12) C(10) N(5) O(6) P"}, {UNIMOD_Phosphoadenosine, "spec_1_classification", "Post-translational"}, {UNIMOD_Phosphoadenosine, "spec_1_hidden", "1"}, {UNIMOD_Phosphoadenosine, "spec_1_position", "Anywhere"}, {UNIMOD_Phosphoadenosine, "spec_1_site", "Y"}, {UNIMOD_Phosphoadenosine, "spec_2_classification", "Post-translational"}, {UNIMOD_Phosphoadenosine, "spec_2_hidden", "1"}, {UNIMOD_Phosphoadenosine, "spec_2_position", "Anywhere"}, {UNIMOD_Phosphoadenosine, "spec_2_site", "K"}, {UNIMOD_Phosphoadenosine, "spec_3_classification", "Post-translational"}, {UNIMOD_Phosphoadenosine, "spec_3_hidden", "1"}, {UNIMOD_Phosphoadenosine, "spec_3_position", "Anywhere"}, {UNIMOD_Phosphoadenosine, "spec_3_site", "T"}, {UNIMOD_Phosphoadenosine, "spec_4_classification", "Post-translational"}, {UNIMOD_Phosphoadenosine, "spec_4_hidden", "1"}, {UNIMOD_Phosphoadenosine, "spec_4_position", "Anywhere"}, {UNIMOD_Phosphoadenosine, "spec_4_site", "H"}, {UNIMOD_Hydroxycinnamyl, "approved", "1"}, {UNIMOD_Hydroxycinnamyl, "delta_composition", "H(6) C(9) O(2)"}, {UNIMOD_Hydroxycinnamyl, "spec_1_classification", "Post-translational"}, {UNIMOD_Hydroxycinnamyl, "spec_1_hidden", "1"}, {UNIMOD_Hydroxycinnamyl, "spec_1_position", "Anywhere"}, {UNIMOD_Hydroxycinnamyl, "spec_1_site", "C"}, {UNIMOD_Glycosyl, "approved", "1"}, {UNIMOD_Glycosyl, "delta_composition", "H(-2) C(-1) Hex"}, {UNIMOD_Glycosyl, "spec_1_classification", "Other glycosylation"}, {UNIMOD_Glycosyl, "spec_1_hidden", "1"}, {UNIMOD_Glycosyl, "spec_1_position", "Anywhere"}, {UNIMOD_Glycosyl, "spec_1_site", "P"}, {UNIMOD_FMNH, "approved", "1"}, {UNIMOD_FMNH, "delta_composition", "H(19) C(17) N(4) O(9) P"}, {UNIMOD_FMNH, "spec_1_classification", "Post-translational"}, {UNIMOD_FMNH, "spec_1_hidden", "1"}, {UNIMOD_FMNH, "spec_1_position", "Anywhere"}, {UNIMOD_FMNH, "spec_1_site", "C"}, {UNIMOD_FMNH, "spec_2_classification", "Post-translational"}, {UNIMOD_FMNH, "spec_2_hidden", "1"}, {UNIMOD_FMNH, "spec_2_position", "Anywhere"}, {UNIMOD_FMNH, "spec_2_site", "H"}, {UNIMOD_Archaeol, "approved", "1"}, {UNIMOD_Archaeol, "delta_composition", "H(86) C(43) O(2)"}, {UNIMOD_Archaeol, "spec_1_classification", "Post-translational"}, {UNIMOD_Archaeol, "spec_1_hidden", "1"}, {UNIMOD_Archaeol, "spec_1_position", "Anywhere"}, {UNIMOD_Archaeol, "spec_1_site", "C"}, {UNIMOD_Phenylisocyanate, "approved", "1"}, {UNIMOD_Phenylisocyanate, "delta_composition", "H(5) C(7) N O"}, {UNIMOD_Phenylisocyanate, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Phenylisocyanate, "spec_1_hidden", "1"}, {UNIMOD_Phenylisocyanate, "spec_1_position", "Any N-term"}, {UNIMOD_Phenylisocyanate, "spec_1_site", "N-term"}, {UNIMOD_Phenylisocyanate_2H_5_, "approved", "1"}, {UNIMOD_Phenylisocyanate_2H_5_, "delta_composition", "2H(5) C(7) N O"}, {UNIMOD_Phenylisocyanate_2H_5_, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Phenylisocyanate_2H_5_, "spec_1_hidden", "1"}, {UNIMOD_Phenylisocyanate_2H_5_, "spec_1_position", "Any N-term"}, {UNIMOD_Phenylisocyanate_2H_5_, "spec_1_site", "N-term"}, {UNIMOD_Phosphoguanosine, "approved", "1"}, {UNIMOD_Phosphoguanosine, "delta_composition", "H(12) C(10) N(5) O(7) P"}, {UNIMOD_Phosphoguanosine, "spec_1_classification", "Post-translational"}, {UNIMOD_Phosphoguanosine, "spec_1_hidden", "1"}, {UNIMOD_Phosphoguanosine, "spec_1_position", "Anywhere"}, {UNIMOD_Phosphoguanosine, "spec_1_site", "K"}, {UNIMOD_Phosphoguanosine, "spec_2_classification", "Post-translational"}, {UNIMOD_Phosphoguanosine, "spec_2_hidden", "1"}, {UNIMOD_Phosphoguanosine, "spec_2_position", "Anywhere"}, {UNIMOD_Phosphoguanosine, "spec_2_site", "H"}, {UNIMOD_Hydroxymethyl, "approved", "1"}, {UNIMOD_Hydroxymethyl, "delta_composition", "H(2) C O"}, {UNIMOD_Hydroxymethyl, "spec_1_classification", "Post-translational"}, {UNIMOD_Hydroxymethyl, "spec_1_hidden", "1"}, {UNIMOD_Hydroxymethyl, "spec_1_position", "Anywhere"}, {UNIMOD_Hydroxymethyl, "spec_1_site", "N"}, {UNIMOD_MolybdopterinGD_Delta_S__1_Se_1_, "approved", "1"}, {UNIMOD_MolybdopterinGD_Delta_S__1_Se_1_, "delta_composition", "H(47) C(40) N(20) O(26) P(4) S(3) Se Mo"}, {UNIMOD_MolybdopterinGD_Delta_S__1_Se_1_, "spec_1_classification", "Post-translational"}, {UNIMOD_MolybdopterinGD_Delta_S__1_Se_1_, "spec_1_hidden", "1"}, {UNIMOD_MolybdopterinGD_Delta_S__1_Se_1_, "spec_1_position", "Anywhere"}, {UNIMOD_MolybdopterinGD_Delta_S__1_Se_1_, "spec_1_site", "C"}, {UNIMOD_Dipyrrolylmethanemethyl, "approved", "1"}, {UNIMOD_Dipyrrolylmethanemethyl, "delta_composition", "H(22) C(20) N(2) O(8)"}, {UNIMOD_Dipyrrolylmethanemethyl, "spec_1_classification", "Post-translational"}, {UNIMOD_Dipyrrolylmethanemethyl, "spec_1_hidden", "1"}, {UNIMOD_Dipyrrolylmethanemethyl, "spec_1_position", "Anywhere"}, {UNIMOD_Dipyrrolylmethanemethyl, "spec_1_site", "C"}, {UNIMOD_PhosphoUridine, "approved", "1"}, {UNIMOD_PhosphoUridine, "delta_composition", "H(11) C(9) N(2) O(8) P"}, {UNIMOD_PhosphoUridine, "spec_1_classification", "Post-translational"}, {UNIMOD_PhosphoUridine, "spec_1_hidden", "1"}, {UNIMOD_PhosphoUridine, "spec_1_position", "Anywhere"}, {UNIMOD_PhosphoUridine, "spec_1_site", "Y"}, {UNIMOD_PhosphoUridine, "spec_2_classification", "Post-translational"}, {UNIMOD_PhosphoUridine, "spec_2_hidden", "1"}, {UNIMOD_PhosphoUridine, "spec_2_position", "Anywhere"}, {UNIMOD_PhosphoUridine, "spec_2_site", "H"}, {UNIMOD_Glycerophospho, "approved", "1"}, {UNIMOD_Glycerophospho, "delta_composition", "H(7) C(3) O(5) P"}, {UNIMOD_Glycerophospho, "spec_1_classification", "Post-translational"}, {UNIMOD_Glycerophospho, "spec_1_hidden", "1"}, {UNIMOD_Glycerophospho, "spec_1_position", "Anywhere"}, {UNIMOD_Glycerophospho, "spec_1_site", "S"}, {UNIMOD_Carboxy__Thiocarboxy, "approved", "1"}, {UNIMOD_Carboxy__Thiocarboxy, "delta_composition", "O(-1) S"}, {UNIMOD_Carboxy__Thiocarboxy, "spec_1_classification", "Post-translational"}, {UNIMOD_Carboxy__Thiocarboxy, "spec_1_hidden", "1"}, {UNIMOD_Carboxy__Thiocarboxy, "spec_1_position", "Protein C-term"}, {UNIMOD_Carboxy__Thiocarboxy, "spec_1_site", "G"}, {UNIMOD_Sulfide, "approved", "1"}, {UNIMOD_Sulfide, "delta_composition", "S"}, {UNIMOD_Sulfide, "spec_1_classification", "Post-translational"}, {UNIMOD_Sulfide, "spec_1_hidden", "1"}, {UNIMOD_Sulfide, "spec_1_position", "Anywhere"}, {UNIMOD_Sulfide, "spec_1_site", "C"}, {UNIMOD_Sulfide, "spec_2_classification", "Post-translational"}, {UNIMOD_Sulfide, "spec_2_hidden", "1"}, {UNIMOD_Sulfide, "spec_2_position", "Anywhere"}, {UNIMOD_Sulfide, "spec_2_site", "D"}, {UNIMOD_Sulfide, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Sulfide, "spec_3_hidden", "1"}, {UNIMOD_Sulfide, "spec_3_position", "Anywhere"}, {UNIMOD_Sulfide, "spec_3_site", "W"}, {UNIMOD_PyruvicAcidIminyl, "approved", "1"}, {UNIMOD_PyruvicAcidIminyl, "delta_composition", "H(2) C(3) O(2)"}, {UNIMOD_PyruvicAcidIminyl, "spec_1_classification", "Post-translational"}, {UNIMOD_PyruvicAcidIminyl, "spec_1_hidden", "1"}, {UNIMOD_PyruvicAcidIminyl, "spec_1_position", "Protein N-term"}, {UNIMOD_PyruvicAcidIminyl, "spec_1_site", "C"}, {UNIMOD_PyruvicAcidIminyl, "spec_2_classification", "Post-translational"}, {UNIMOD_PyruvicAcidIminyl, "spec_2_hidden", "1"}, {UNIMOD_PyruvicAcidIminyl, "spec_2_position", "Protein N-term"}, {UNIMOD_PyruvicAcidIminyl, "spec_2_site", "V"}, {UNIMOD_PyruvicAcidIminyl, "spec_3_classification", "Post-translational"}, {UNIMOD_PyruvicAcidIminyl, "spec_3_hidden", "1"}, {UNIMOD_PyruvicAcidIminyl, "spec_3_position", "Anywhere"}, {UNIMOD_PyruvicAcidIminyl, "spec_3_site", "K"}, {UNIMOD_Delta_Se_1_, "approved", "1"}, {UNIMOD_Delta_Se_1_, "delta_composition", "Se"}, {UNIMOD_Delta_Se_1_, "spec_1_classification", "Post-translational"}, {UNIMOD_Delta_Se_1_, "spec_1_hidden", "1"}, {UNIMOD_Delta_Se_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Delta_Se_1_, "spec_1_site", "C"}, {UNIMOD_MolybdopterinGD, "approved", "1"}, {UNIMOD_MolybdopterinGD, "delta_composition", "H(47) C(40) N(20) O(26) P(4) S(4) Mo"}, {UNIMOD_MolybdopterinGD, "spec_1_classification", "Post-translational"}, {UNIMOD_MolybdopterinGD, "spec_1_hidden", "1"}, {UNIMOD_MolybdopterinGD, "spec_1_position", "Anywhere"}, {UNIMOD_MolybdopterinGD, "spec_1_site", "C"}, {UNIMOD_MolybdopterinGD, "spec_2_classification", "Post-translational"}, {UNIMOD_MolybdopterinGD, "spec_2_hidden", "1"}, {UNIMOD_MolybdopterinGD, "spec_2_position", "Anywhere"}, {UNIMOD_MolybdopterinGD, "spec_2_site", "D"}, {UNIMOD_Dioxidation, "approved", "1"}, {UNIMOD_Dioxidation, "delta_composition", "O(2)"}, {UNIMOD_Dioxidation, "spec_1_classification", "Post-translational"}, {UNIMOD_Dioxidation, "spec_1_hidden", "1"}, {UNIMOD_Dioxidation, "spec_1_position", "Anywhere"}, {UNIMOD_Dioxidation, "spec_1_site", "P"}, {UNIMOD_Dioxidation, "spec_2_classification", "Post-translational"}, {UNIMOD_Dioxidation, "spec_2_hidden", "1"}, {UNIMOD_Dioxidation, "spec_2_position", "Anywhere"}, {UNIMOD_Dioxidation, "spec_2_site", "R"}, {UNIMOD_Dioxidation, "spec_3_classification", "Post-translational"}, {UNIMOD_Dioxidation, "spec_3_hidden", "1"}, {UNIMOD_Dioxidation, "spec_3_position", "Anywhere"}, {UNIMOD_Dioxidation, "spec_3_site", "K"}, {UNIMOD_Dioxidation, "spec_4_classification", "Post-translational"}, {UNIMOD_Dioxidation, "spec_4_hidden", "0"}, {UNIMOD_Dioxidation, "spec_4_position", "Anywhere"}, {UNIMOD_Dioxidation, "spec_4_site", "M"}, {UNIMOD_Dioxidation, "spec_5_classification", "Chemical derivative"}, {UNIMOD_Dioxidation, "spec_5_hidden", "1"}, {UNIMOD_Dioxidation, "spec_5_position", "Anywhere"}, {UNIMOD_Dioxidation, "spec_5_site", "F"}, {UNIMOD_Dioxidation, "spec_6_classification", "Chemical derivative"}, {UNIMOD_Dioxidation, "spec_6_hidden", "1"}, {UNIMOD_Dioxidation, "spec_6_position", "Anywhere"}, {UNIMOD_Dioxidation, "spec_6_site", "W"}, {UNIMOD_Dioxidation, "spec_7_classification", "Post-translational"}, {UNIMOD_Dioxidation, "spec_7_hidden", "1"}, {UNIMOD_Dioxidation, "spec_7_position", "Anywhere"}, {UNIMOD_Dioxidation, "spec_7_site", "Y"}, {UNIMOD_Dioxidation, "spec_8_classification", "Post-translational"}, {UNIMOD_Dioxidation, "spec_8_hidden", "1"}, {UNIMOD_Dioxidation, "spec_8_position", "Anywhere"}, {UNIMOD_Dioxidation, "spec_8_site", "C"}, {UNIMOD_Octanoyl, "approved", "1"}, {UNIMOD_Octanoyl, "delta_composition", "H(14) C(8) O"}, {UNIMOD_Octanoyl, "spec_1_classification", "Post-translational"}, {UNIMOD_Octanoyl, "spec_1_hidden", "1"}, {UNIMOD_Octanoyl, "spec_1_position", "Anywhere"}, {UNIMOD_Octanoyl, "spec_1_site", "S"}, {UNIMOD_Octanoyl, "spec_2_classification", "Post-translational"}, {UNIMOD_Octanoyl, "spec_2_hidden", "1"}, {UNIMOD_Octanoyl, "spec_2_position", "Anywhere"}, {UNIMOD_Octanoyl, "spec_2_site", "T"}, {UNIMOD_Octanoyl, "spec_3_classification", "Post-translational"}, {UNIMOD_Octanoyl, "spec_3_hidden", "1"}, {UNIMOD_Octanoyl, "spec_3_position", "Anywhere"}, {UNIMOD_Octanoyl, "spec_3_site", "C"}, {UNIMOD_PhosphoHexNAc, "approved", "1"}, {UNIMOD_PhosphoHexNAc, "delta_composition", "H O(3) P HexNAc"}, {UNIMOD_PhosphoHexNAc, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_PhosphoHexNAc, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_PhosphoHexNAc, "spec_1_hidden", "1"}, {UNIMOD_PhosphoHexNAc, "spec_1_hidden", "1"}, {UNIMOD_PhosphoHexNAc, "spec_1_position", "Anywhere"}, {UNIMOD_PhosphoHexNAc, "spec_1_position", "Anywhere"}, {UNIMOD_PhosphoHexNAc, "spec_1_site", "T"}, {UNIMOD_PhosphoHexNAc, "spec_1_site", "S"}, {UNIMOD_PhosphoHex, "approved", "1"}, {UNIMOD_PhosphoHex, "delta_composition", "H O(3) P Hex"}, {UNIMOD_PhosphoHex, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_PhosphoHex, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_PhosphoHex, "spec_1_hidden", "1"}, {UNIMOD_PhosphoHex, "spec_1_hidden", "1"}, {UNIMOD_PhosphoHex, "spec_1_position", "Anywhere"}, {UNIMOD_PhosphoHex, "spec_1_position", "Anywhere"}, {UNIMOD_PhosphoHex, "spec_1_site", "T"}, {UNIMOD_PhosphoHex, "spec_1_site", "S"}, {UNIMOD_Palmitoleyl, "approved", "1"}, {UNIMOD_Palmitoleyl, "delta_composition", "H(28) C(16) O"}, {UNIMOD_Palmitoleyl, "spec_1_classification", "Post-translational"}, {UNIMOD_Palmitoleyl, "spec_1_hidden", "1"}, {UNIMOD_Palmitoleyl, "spec_1_position", "Anywhere"}, {UNIMOD_Palmitoleyl, "spec_1_site", "C"}, {UNIMOD_Palmitoleyl, "spec_2_classification", "Post-translational"}, {UNIMOD_Palmitoleyl, "spec_2_hidden", "1"}, {UNIMOD_Palmitoleyl, "spec_2_position", "Anywhere"}, {UNIMOD_Palmitoleyl, "spec_2_site", "S"}, {UNIMOD_Palmitoleyl, "spec_3_classification", "Pre-translational"}, {UNIMOD_Palmitoleyl, "spec_3_hidden", "1"}, {UNIMOD_Palmitoleyl, "spec_3_position", "Anywhere"}, {UNIMOD_Palmitoleyl, "spec_3_site", "T"}, {UNIMOD_Cholesterol, "approved", "1"}, {UNIMOD_Cholesterol, "delta_composition", "H(44) C(27)"}, {UNIMOD_Cholesterol, "spec_1_classification", "Post-translational"}, {UNIMOD_Cholesterol, "spec_1_hidden", "1"}, {UNIMOD_Cholesterol, "spec_1_position", "Protein C-term"}, {UNIMOD_Cholesterol, "spec_1_site", "C-term"}, {UNIMOD_Didehydroretinylidene, "approved", "1"}, {UNIMOD_Didehydroretinylidene, "delta_composition", "H(24) C(20)"}, {UNIMOD_Didehydroretinylidene, "spec_1_classification", "Post-translational"}, {UNIMOD_Didehydroretinylidene, "spec_1_hidden", "1"}, {UNIMOD_Didehydroretinylidene, "spec_1_position", "Anywhere"}, {UNIMOD_Didehydroretinylidene, "spec_1_site", "K"}, {UNIMOD_CHDH, "approved", "1"}, {UNIMOD_CHDH, "delta_composition", "H(26) C(17) O(4)"}, {UNIMOD_CHDH, "spec_1_classification", "Post-translational"}, {UNIMOD_CHDH, "spec_1_hidden", "1"}, {UNIMOD_CHDH, "spec_1_position", "Anywhere"}, {UNIMOD_CHDH, "spec_1_site", "D"}, {UNIMOD_Methylpyrroline, "approved", "1"}, {UNIMOD_Methylpyrroline, "delta_composition", "H(7) C(6) N O"}, {UNIMOD_Methylpyrroline, "spec_1_classification", "Post-translational"}, {UNIMOD_Methylpyrroline, "spec_1_hidden", "1"}, {UNIMOD_Methylpyrroline, "spec_1_position", "Anywhere"}, {UNIMOD_Methylpyrroline, "spec_1_site", "K"}, {UNIMOD_Hydroxyheme, "approved", "1"}, {UNIMOD_Hydroxyheme, "delta_composition", "H(30) C(34) N(4) O(4) Fe"}, {UNIMOD_Hydroxyheme, "spec_1_classification", "Post-translational"}, {UNIMOD_Hydroxyheme, "spec_1_hidden", "1"}, {UNIMOD_Hydroxyheme, "spec_1_position", "Anywhere"}, {UNIMOD_Hydroxyheme, "spec_1_site", "E"}, {UNIMOD_MicrocinC7, "approved", "1"}, {UNIMOD_MicrocinC7, "delta_composition", "H(19) C(13) N(6) O(6) P"}, {UNIMOD_MicrocinC7, "spec_1_classification", "Post-translational"}, {UNIMOD_MicrocinC7, "spec_1_hidden", "1"}, {UNIMOD_MicrocinC7, "spec_1_position", "Protein C-term"}, {UNIMOD_MicrocinC7, "spec_1_site", "C-term"}, {UNIMOD_Cyano, "approved", "1"}, {UNIMOD_Cyano, "delta_composition", "H(-1) C N"}, {UNIMOD_Cyano, "spec_1_classification", "Post-translational"}, {UNIMOD_Cyano, "spec_1_hidden", "1"}, {UNIMOD_Cyano, "spec_1_position", "Anywhere"}, {UNIMOD_Cyano, "spec_1_site", "C"}, {UNIMOD_Diironsubcluster, "approved", "1"}, {UNIMOD_Diironsubcluster, "delta_composition", "H(-1) C(5) N(2) O(5) S(2) Fe(2)"}, {UNIMOD_Diironsubcluster, "spec_1_classification", "Post-translational"}, {UNIMOD_Diironsubcluster, "spec_1_hidden", "1"}, {UNIMOD_Diironsubcluster, "spec_1_position", "Anywhere"}, {UNIMOD_Diironsubcluster, "spec_1_site", "C"}, {UNIMOD_Amidino, "approved", "1"}, {UNIMOD_Amidino, "delta_composition", "H(2) C N(2)"}, {UNIMOD_Amidino, "spec_1_classification", "Post-translational"}, {UNIMOD_Amidino, "spec_1_hidden", "1"}, {UNIMOD_Amidino, "spec_1_position", "Anywhere"}, {UNIMOD_Amidino, "spec_1_site", "C"}, {UNIMOD_FMN, "approved", "1"}, {UNIMOD_FMN, "delta_composition", "H(19) C(17) N(4) O(8) P"}, {UNIMOD_FMN, "spec_1_classification", "Post-translational"}, {UNIMOD_FMN, "spec_1_hidden", "1"}, {UNIMOD_FMN, "spec_1_position", "Anywhere"}, {UNIMOD_FMN, "spec_1_site", "T"}, {UNIMOD_FMN, "spec_2_classification", "Post-translational"}, {UNIMOD_FMN, "spec_2_hidden", "1"}, {UNIMOD_FMN, "spec_2_position", "Anywhere"}, {UNIMOD_FMN, "spec_2_site", "S"}, {UNIMOD_FMNC, "approved", "1"}, {UNIMOD_FMNC, "delta_composition", "H(21) C(17) N(4) O(9) P"}, {UNIMOD_FMNC, "spec_1_classification", "Post-translational"}, {UNIMOD_FMNC, "spec_1_hidden", "1"}, {UNIMOD_FMNC, "spec_1_position", "Anywhere"}, {UNIMOD_FMNC, "spec_1_site", "C"}, {UNIMOD_CuSMo, "approved", "1"}, {UNIMOD_CuSMo, "delta_composition", "H(24) C(19) N(8) O(15) P(2) S(3) Cu Mo"}, {UNIMOD_CuSMo, "spec_1_classification", "Post-translational"}, {UNIMOD_CuSMo, "spec_1_hidden", "1"}, {UNIMOD_CuSMo, "spec_1_position", "Anywhere"}, {UNIMOD_CuSMo, "spec_1_site", "C"}, {UNIMOD_Hydroxytrimethyl, "approved", "1"}, {UNIMOD_Hydroxytrimethyl, "delta_composition", "H(7) C(3) O"}, {UNIMOD_Hydroxytrimethyl, "spec_1_classification", "Post-translational"}, {UNIMOD_Hydroxytrimethyl, "spec_1_hidden", "1"}, {UNIMOD_Hydroxytrimethyl, "spec_1_position", "Anywhere"}, {UNIMOD_Hydroxytrimethyl, "spec_1_site", "K"}, {UNIMOD_Deoxy, "approved", "1"}, {UNIMOD_Deoxy, "delta_composition", "O(-1)"}, {UNIMOD_Deoxy, "spec_1_classification", "Post-translational"}, {UNIMOD_Deoxy, "spec_1_hidden", "1"}, {UNIMOD_Deoxy, "spec_1_position", "Anywhere"}, {UNIMOD_Deoxy, "spec_1_site", "D"}, {UNIMOD_Deoxy, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Deoxy, "spec_2_hidden", "1"}, {UNIMOD_Deoxy, "spec_2_position", "Anywhere"}, {UNIMOD_Deoxy, "spec_2_site", "S"}, {UNIMOD_Deoxy, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Deoxy, "spec_3_hidden", "1"}, {UNIMOD_Deoxy, "spec_3_position", "Anywhere"}, {UNIMOD_Deoxy, "spec_3_site", "T"}, {UNIMOD_Microcin, "approved", "1"}, {UNIMOD_Microcin, "delta_composition", "H(37) C(36) N(3) O(20)"}, {UNIMOD_Microcin, "spec_1_classification", "Post-translational"}, {UNIMOD_Microcin, "spec_1_hidden", "1"}, {UNIMOD_Microcin, "spec_1_position", "Protein C-term"}, {UNIMOD_Microcin, "spec_1_site", "C-term"}, {UNIMOD_Decanoyl, "approved", "1"}, {UNIMOD_Decanoyl, "delta_composition", "H(18) C(10) O"}, {UNIMOD_Decanoyl, "spec_1_classification", "Post-translational"}, {UNIMOD_Decanoyl, "spec_1_hidden", "1"}, {UNIMOD_Decanoyl, "spec_1_position", "Anywhere"}, {UNIMOD_Decanoyl, "spec_1_site", "S"}, {UNIMOD_Decanoyl, "spec_2_classification", "Post-translational"}, {UNIMOD_Decanoyl, "spec_2_hidden", "1"}, {UNIMOD_Decanoyl, "spec_2_position", "Anywhere"}, {UNIMOD_Decanoyl, "spec_2_site", "T"}, {UNIMOD_Glu, "approved", "0"}, {UNIMOD_Glu, "delta_composition", "H(7) C(5) N O(3)"}, {UNIMOD_Glu, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Glu, "spec_1_hidden", "1"}, {UNIMOD_Glu, "spec_1_position", "Protein C-term"}, {UNIMOD_Glu, "spec_1_site", "C-term"}, {UNIMOD_Glu, "spec_2_classification", "Post-translational"}, {UNIMOD_Glu, "spec_2_hidden", "1"}, {UNIMOD_Glu, "spec_2_position", "Anywhere"}, {UNIMOD_Glu, "spec_2_site", "E"}, {UNIMOD_GluGlu, "approved", "0"}, {UNIMOD_GluGlu, "delta_composition", "H(14) C(10) N(2) O(6)"}, {UNIMOD_GluGlu, "spec_1_classification", "Post-translational"}, {UNIMOD_GluGlu, "spec_1_hidden", "1"}, {UNIMOD_GluGlu, "spec_1_position", "Protein C-term"}, {UNIMOD_GluGlu, "spec_1_site", "C-term"}, {UNIMOD_GluGlu, "spec_2_classification", "Post-translational"}, {UNIMOD_GluGlu, "spec_2_hidden", "1"}, {UNIMOD_GluGlu, "spec_2_position", "Anywhere"}, {UNIMOD_GluGlu, "spec_2_site", "E"}, {UNIMOD_GluGluGlu, "approved", "0"}, {UNIMOD_GluGluGlu, "delta_composition", "H(21) C(15) N(3) O(9)"}, {UNIMOD_GluGluGlu, "spec_1_classification", "Post-translational"}, {UNIMOD_GluGluGlu, "spec_1_hidden", "1"}, {UNIMOD_GluGluGlu, "spec_1_position", "Protein C-term"}, {UNIMOD_GluGluGlu, "spec_1_site", "C-term"}, {UNIMOD_GluGluGlu, "spec_2_classification", "Post-translational"}, {UNIMOD_GluGluGlu, "spec_2_hidden", "1"}, {UNIMOD_GluGluGlu, "spec_2_position", "Anywhere"}, {UNIMOD_GluGluGlu, "spec_2_site", "E"}, {UNIMOD_GluGluGluGlu, "approved", "0"}, {UNIMOD_GluGluGluGlu, "delta_composition", "H(28) C(20) N(4) O(12)"}, {UNIMOD_GluGluGluGlu, "spec_1_classification", "Post-translational"}, {UNIMOD_GluGluGluGlu, "spec_1_hidden", "1"}, {UNIMOD_GluGluGluGlu, "spec_1_position", "Protein C-term"}, {UNIMOD_GluGluGluGlu, "spec_1_site", "C-term"}, {UNIMOD_GluGluGluGlu, "spec_2_classification", "Post-translational"}, {UNIMOD_GluGluGluGlu, "spec_2_hidden", "1"}, {UNIMOD_GluGluGluGlu, "spec_2_position", "Anywhere"}, {UNIMOD_GluGluGluGlu, "spec_2_site", "E"}, {UNIMOD_HexN, "approved", "1"}, {UNIMOD_HexN, "delta_composition", "HexN"}, {UNIMOD_HexN, "spec_1_classification", "Synth. pep. protect. gp."}, {UNIMOD_HexN, "spec_1_hidden", "1"}, {UNIMOD_HexN, "spec_1_position", "Anywhere"}, {UNIMOD_HexN, "spec_1_site", "K"}, {UNIMOD_HexN, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_HexN, "spec_2_hidden", "1"}, {UNIMOD_HexN, "spec_2_position", "Anywhere"}, {UNIMOD_HexN, "spec_2_site", "N"}, {UNIMOD_HexN, "spec_3_classification", "O-linked glycosylation"}, {UNIMOD_HexN, "spec_3_classification", "O-linked glycosylation"}, {UNIMOD_HexN, "spec_3_hidden", "1"}, {UNIMOD_HexN, "spec_3_hidden", "1"}, {UNIMOD_HexN, "spec_3_position", "Anywhere"}, {UNIMOD_HexN, "spec_3_position", "Anywhere"}, {UNIMOD_HexN, "spec_3_site", "T"}, {UNIMOD_HexN, "spec_3_site", "S"}, {UNIMOD_HexN, "spec_4_classification", "Other glycosylation"}, {UNIMOD_HexN, "spec_4_hidden", "1"}, {UNIMOD_HexN, "spec_4_position", "Anywhere"}, {UNIMOD_HexN, "spec_4_site", "W"}, {UNIMOD_Xlink_DMP_s, "approved", "0"}, {UNIMOD_Xlink_DMP_s, "delta_composition", "H(14) C(8) N(2) O"}, {UNIMOD_Xlink_DMP_s, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Xlink_DMP_s, "spec_1_hidden", "1"}, {UNIMOD_Xlink_DMP_s, "spec_1_position", "Anywhere"}, {UNIMOD_Xlink_DMP_s, "spec_1_site", "K"}, {UNIMOD_Xlink_DMP_s, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Xlink_DMP_s, "spec_2_hidden", "1"}, {UNIMOD_Xlink_DMP_s, "spec_2_position", "Protein N-term"}, {UNIMOD_Xlink_DMP_s, "spec_2_site", "N-term"}, {UNIMOD_Xlink_DMP, "approved", "0"}, {UNIMOD_Xlink_DMP, "delta_composition", "H(10) C(7) N(2)"}, {UNIMOD_Xlink_DMP, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Xlink_DMP, "spec_1_hidden", "1"}, {UNIMOD_Xlink_DMP, "spec_1_position", "Anywhere"}, {UNIMOD_Xlink_DMP, "spec_1_site", "K"}, {UNIMOD_Xlink_DMP, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Xlink_DMP, "spec_2_hidden", "1"}, {UNIMOD_Xlink_DMP, "spec_2_position", "Protein N-term"}, {UNIMOD_Xlink_DMP, "spec_2_site", "N-term"}, {UNIMOD_NDA, "approved", "0"}, {UNIMOD_NDA, "delta_composition", "H(5) C(13) N"}, {UNIMOD_NDA, "spec_1_classification", "Chemical derivative"}, {UNIMOD_NDA, "spec_1_hidden", "1"}, {UNIMOD_NDA, "spec_1_position", "Anywhere"}, {UNIMOD_NDA, "spec_1_site", "K"}, {UNIMOD_NDA, "spec_2_classification", "Chemical derivative"}, {UNIMOD_NDA, "spec_2_hidden", "1"}, {UNIMOD_NDA, "spec_2_position", "Any N-term"}, {UNIMOD_NDA, "spec_2_site", "N-term"}, {UNIMOD_SPITC_13C_6_, "approved", "1"}, {UNIMOD_SPITC_13C_6_, "delta_composition", "H(5) C 13C(6) N O(3) S(2)"}, {UNIMOD_SPITC_13C_6_, "spec_1_classification", "Chemical derivative"}, {UNIMOD_SPITC_13C_6_, "spec_1_hidden", "1"}, {UNIMOD_SPITC_13C_6_, "spec_1_position", "Anywhere"}, {UNIMOD_SPITC_13C_6_, "spec_1_site", "K"}, {UNIMOD_SPITC_13C_6_, "spec_2_classification", "Chemical derivative"}, {UNIMOD_SPITC_13C_6_, "spec_2_hidden", "1"}, {UNIMOD_SPITC_13C_6_, "spec_2_position", "Any N-term"}, {UNIMOD_SPITC_13C_6_, "spec_2_site", "N-term"}, {UNIMOD_AEC_MAEC, "approved", "0"}, {UNIMOD_AEC_MAEC, "delta_composition", "H(5) C(2) N O(-1) S"}, {UNIMOD_AEC_MAEC, "spec_1_classification", "Chemical derivative"}, {UNIMOD_AEC_MAEC, "spec_1_hidden", "1"}, {UNIMOD_AEC_MAEC, "spec_1_position", "Anywhere"}, {UNIMOD_AEC_MAEC, "spec_1_site", "S"}, {UNIMOD_AEC_MAEC, "spec_2_classification", "Chemical derivative"}, {UNIMOD_AEC_MAEC, "spec_2_hidden", "1"}, {UNIMOD_AEC_MAEC, "spec_2_position", "Anywhere"}, {UNIMOD_AEC_MAEC, "spec_2_site", "T"}, {UNIMOD_TMAB, "approved", "0"}, {UNIMOD_TMAB, "delta_composition", "H(14) C(7) N O"}, {UNIMOD_TMAB, "spec_1_classification", "Isotopic label"}, {UNIMOD_TMAB, "spec_1_hidden", "1"}, {UNIMOD_TMAB, "spec_1_position", "Anywhere"}, {UNIMOD_TMAB, "spec_1_site", "K"}, {UNIMOD_TMAB, "spec_2_classification", "Isotopic label"}, {UNIMOD_TMAB, "spec_2_hidden", "1"}, {UNIMOD_TMAB, "spec_2_position", "Any N-term"}, {UNIMOD_TMAB, "spec_2_site", "N-term"}, {UNIMOD_TMAB_2H_9_, "approved", "0"}, {UNIMOD_TMAB_2H_9_, "delta_composition", "H(5) 2H(9) C(7) N O"}, {UNIMOD_TMAB_2H_9_, "spec_1_classification", "Isotopic label"}, {UNIMOD_TMAB_2H_9_, "spec_1_hidden", "1"}, {UNIMOD_TMAB_2H_9_, "spec_1_position", "Anywhere"}, {UNIMOD_TMAB_2H_9_, "spec_1_site", "K"}, {UNIMOD_TMAB_2H_9_, "spec_2_classification", "Isotopic label"}, {UNIMOD_TMAB_2H_9_, "spec_2_hidden", "1"}, {UNIMOD_TMAB_2H_9_, "spec_2_position", "Any N-term"}, {UNIMOD_TMAB_2H_9_, "spec_2_site", "N-term"}, {UNIMOD_FTC, "approved", "1"}, {UNIMOD_FTC, "delta_composition", "H(15) C(21) N(3) O(5) S"}, {UNIMOD_FTC, "spec_1_classification", "Chemical derivative"}, {UNIMOD_FTC, "spec_1_hidden", "1"}, {UNIMOD_FTC, "spec_1_position", "Anywhere"}, {UNIMOD_FTC, "spec_1_site", "C"}, {UNIMOD_FTC, "spec_2_classification", "Chemical derivative"}, {UNIMOD_FTC, "spec_2_hidden", "1"}, {UNIMOD_FTC, "spec_2_position", "Anywhere"}, {UNIMOD_FTC, "spec_2_site", "K"}, {UNIMOD_FTC, "spec_3_classification", "Chemical derivative"}, {UNIMOD_FTC, "spec_3_hidden", "1"}, {UNIMOD_FTC, "spec_3_position", "Anywhere"}, {UNIMOD_FTC, "spec_3_site", "P"}, {UNIMOD_FTC, "spec_4_classification", "Chemical derivative"}, {UNIMOD_FTC, "spec_4_hidden", "1"}, {UNIMOD_FTC, "spec_4_position", "Anywhere"}, {UNIMOD_FTC, "spec_4_site", "R"}, {UNIMOD_FTC, "spec_5_classification", "Chemical derivative"}, {UNIMOD_FTC, "spec_5_hidden", "1"}, {UNIMOD_FTC, "spec_5_position", "Anywhere"}, {UNIMOD_FTC, "spec_5_site", "S"}, {UNIMOD_Label_2H_4_, "approved", "0"}, {UNIMOD_Label_2H_4_, "delta_composition", "H(-4) 2H(4)"}, {UNIMOD_Label_2H_4_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_2H_4_, "spec_1_hidden", "1"}, {UNIMOD_Label_2H_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_2H_4_, "spec_1_site", "K"}, {UNIMOD_Label_2H_4_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Label_2H_4_, "spec_2_hidden", "1"}, {UNIMOD_Label_2H_4_, "spec_2_position", "Anywhere"}, {UNIMOD_Label_2H_4_, "spec_2_site", "F"}, {UNIMOD_Label_2H_4_, "spec_3_classification", "Isotopic label"}, {UNIMOD_Label_2H_4_, "spec_3_hidden", "1"}, {UNIMOD_Label_2H_4_, "spec_3_position", "Anywhere"}, {UNIMOD_Label_2H_4_, "spec_3_site", "Y"}, {UNIMOD_DHP, "approved", "0"}, {UNIMOD_DHP, "delta_composition", "H(8) C(8) N"}, {UNIMOD_DHP, "spec_1_classification", "Chemical derivative"}, {UNIMOD_DHP, "spec_1_hidden", "1"}, {UNIMOD_DHP, "spec_1_position", "Anywhere"}, {UNIMOD_DHP, "spec_1_site", "C"}, {UNIMOD_Hep, "approved", "1"}, {UNIMOD_Hep, "delta_composition", "Hep"}, {UNIMOD_Hep, "spec_1_classification", "Other glycosylation"}, {UNIMOD_Hep, "spec_1_hidden", "1"}, {UNIMOD_Hep, "spec_1_position", "Anywhere"}, {UNIMOD_Hep, "spec_1_site", "K"}, {UNIMOD_Hep, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_Hep, "spec_2_hidden", "1"}, {UNIMOD_Hep, "spec_2_position", "Anywhere"}, {UNIMOD_Hep, "spec_2_site", "N"}, {UNIMOD_Hep, "spec_3_classification", "Other glycosylation"}, {UNIMOD_Hep, "spec_3_hidden", "1"}, {UNIMOD_Hep, "spec_3_position", "Anywhere"}, {UNIMOD_Hep, "spec_3_site", "Q"}, {UNIMOD_Hep, "spec_4_classification", "N-linked glycosylation"}, {UNIMOD_Hep, "spec_4_hidden", "1"}, {UNIMOD_Hep, "spec_4_position", "Anywhere"}, {UNIMOD_Hep, "spec_4_site", "R"}, {UNIMOD_Hep, "spec_5_classification", "O-linked glycosylation"}, {UNIMOD_Hep, "spec_5_classification", "O-linked glycosylation"}, {UNIMOD_Hep, "spec_5_hidden", "1"}, {UNIMOD_Hep, "spec_5_hidden", "1"}, {UNIMOD_Hep, "spec_5_position", "Anywhere"}, {UNIMOD_Hep, "spec_5_position", "Anywhere"}, {UNIMOD_Hep, "spec_5_site", "T"}, {UNIMOD_Hep, "spec_5_site", "S"}, {UNIMOD_BADGE, "approved", "0"}, {UNIMOD_BADGE, "delta_composition", "H(24) C(21) O(4)"}, {UNIMOD_BADGE, "spec_1_classification", "Non-standard residue"}, {UNIMOD_BADGE, "spec_1_hidden", "1"}, {UNIMOD_BADGE, "spec_1_position", "Anywhere"}, {UNIMOD_BADGE, "spec_1_site", "C"}, {UNIMOD_CyDye_Cy3, "approved", "0"}, {UNIMOD_CyDye_Cy3, "delta_composition", "H(44) C(37) N(4) O(6) S"}, {UNIMOD_CyDye_Cy3, "spec_1_classification", "Chemical derivative"}, {UNIMOD_CyDye_Cy3, "spec_1_hidden", "1"}, {UNIMOD_CyDye_Cy3, "spec_1_position", "Anywhere"}, {UNIMOD_CyDye_Cy3, "spec_1_site", "C"}, {UNIMOD_CyDye_Cy5, "approved", "0"}, {UNIMOD_CyDye_Cy5, "delta_composition", "H(44) C(38) N(4) O(6) S"}, {UNIMOD_CyDye_Cy5, "spec_1_classification", "Chemical derivative"}, {UNIMOD_CyDye_Cy5, "spec_1_hidden", "1"}, {UNIMOD_CyDye_Cy5, "spec_1_position", "Anywhere"}, {UNIMOD_CyDye_Cy5, "spec_1_site", "C"}, {UNIMOD_BHTOH, "approved", "0"}, {UNIMOD_BHTOH, "delta_composition", "H(22) C(15) O(2)"}, {UNIMOD_BHTOH, "spec_1_classification", "Other"}, {UNIMOD_BHTOH, "spec_1_hidden", "1"}, {UNIMOD_BHTOH, "spec_1_position", "Anywhere"}, {UNIMOD_BHTOH, "spec_1_site", "C"}, {UNIMOD_BHTOH, "spec_2_classification", "Other"}, {UNIMOD_BHTOH, "spec_2_hidden", "1"}, {UNIMOD_BHTOH, "spec_2_position", "Anywhere"}, {UNIMOD_BHTOH, "spec_2_site", "H"}, {UNIMOD_BHTOH, "spec_3_classification", "Other"}, {UNIMOD_BHTOH, "spec_3_hidden", "1"}, {UNIMOD_BHTOH, "spec_3_position", "Anywhere"}, {UNIMOD_BHTOH, "spec_3_site", "K"}, {UNIMOD_IGBP_13C_2_, "approved", "1"}, {UNIMOD_IGBP_13C_2_, "delta_composition", "H(13) C(10) 13C(2) N(2) O(2) Br"}, {UNIMOD_IGBP_13C_2_, "spec_1_classification", "Isotopic label"}, {UNIMOD_IGBP_13C_2_, "spec_1_hidden", "1"}, {UNIMOD_IGBP_13C_2_, "spec_1_position", "Anywhere"}, {UNIMOD_IGBP_13C_2_, "spec_1_site", "C"}, {UNIMOD_Nmethylmaleimide_water, "approved", "0"}, {UNIMOD_Nmethylmaleimide_water, "delta_composition", "H(7) C(5) N O(3)"}, {UNIMOD_Nmethylmaleimide_water, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Nmethylmaleimide_water, "spec_1_hidden", "1"}, {UNIMOD_Nmethylmaleimide_water, "spec_1_position", "Anywhere"}, {UNIMOD_Nmethylmaleimide_water, "spec_1_site", "C"}, {UNIMOD_PyMIC, "approved", "0"}, {UNIMOD_PyMIC, "delta_composition", "H(6) C(7) N(2) O"}, {UNIMOD_PyMIC, "spec_1_classification", "Chemical derivative"}, {UNIMOD_PyMIC, "spec_1_hidden", "1"}, {UNIMOD_PyMIC, "spec_1_position", "Any N-term"}, {UNIMOD_PyMIC, "spec_1_site", "N-term"}, {UNIMOD_LG_lactam_K, "approved", "0"}, {UNIMOD_LG_lactam_K, "delta_composition", "H(28) C(20) O(4)"}, {UNIMOD_LG_lactam_K, "spec_1_classification", "Post-translational"}, {UNIMOD_LG_lactam_K, "spec_1_hidden", "1"}, {UNIMOD_LG_lactam_K, "spec_1_position", "Anywhere"}, {UNIMOD_LG_lactam_K, "spec_1_site", "K"}, {UNIMOD_LG_lactam_K, "spec_2_classification", "Post-translational"}, {UNIMOD_LG_lactam_K, "spec_2_hidden", "1"}, {UNIMOD_LG_lactam_K, "spec_2_position", "Protein N-term"}, {UNIMOD_LG_lactam_K, "spec_2_site", "N-term"}, {UNIMOD_LG_Hlactam_K, "approved", "0"}, {UNIMOD_LG_Hlactam_K, "delta_composition", "H(28) C(20) O(5)"}, {UNIMOD_LG_Hlactam_K, "spec_1_classification", "Post-translational"}, {UNIMOD_LG_Hlactam_K, "spec_1_hidden", "1"}, {UNIMOD_LG_Hlactam_K, "spec_1_position", "Anywhere"}, {UNIMOD_LG_Hlactam_K, "spec_1_site", "K"}, {UNIMOD_LG_Hlactam_K, "spec_2_classification", "Post-translational"}, {UNIMOD_LG_Hlactam_K, "spec_2_hidden", "1"}, {UNIMOD_LG_Hlactam_K, "spec_2_position", "Protein N-term"}, {UNIMOD_LG_Hlactam_K, "spec_2_site", "N-term"}, {UNIMOD_LG_lactam_R, "approved", "0"}, {UNIMOD_LG_lactam_R, "delta_composition", "H(26) C(19) N(-2) O(4)"}, {UNIMOD_LG_lactam_R, "spec_1_classification", "Post-translational"}, {UNIMOD_LG_lactam_R, "spec_1_hidden", "1"}, {UNIMOD_LG_lactam_R, "spec_1_position", "Anywhere"}, {UNIMOD_LG_lactam_R, "spec_1_site", "R"}, {UNIMOD_LG_Hlactam_R, "approved", "0"}, {UNIMOD_LG_Hlactam_R, "delta_composition", "H(26) C(19) N(-2) O(5)"}, {UNIMOD_LG_Hlactam_R, "spec_1_classification", "Post-translational"}, {UNIMOD_LG_Hlactam_R, "spec_1_hidden", "1"}, {UNIMOD_LG_Hlactam_R, "spec_1_position", "Anywhere"}, {UNIMOD_LG_Hlactam_R, "spec_1_site", "R"}, {UNIMOD_Dimethyl_2H_4_13C_2_, "approved", "1"}, {UNIMOD_Dimethyl_2H_4_13C_2_, "delta_composition", "2H(4) 13C(2)"}, {UNIMOD_Dimethyl_2H_4_13C_2_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Dimethyl_2H_4_13C_2_, "spec_1_hidden", "1"}, {UNIMOD_Dimethyl_2H_4_13C_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Dimethyl_2H_4_13C_2_, "spec_1_site", "K"}, {UNIMOD_Dimethyl_2H_4_13C_2_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Dimethyl_2H_4_13C_2_, "spec_2_hidden", "1"}, {UNIMOD_Dimethyl_2H_4_13C_2_, "spec_2_position", "Any N-term"}, {UNIMOD_Dimethyl_2H_4_13C_2_, "spec_2_site", "N-term"}, {UNIMOD_Dimethyl_2H_4_13C_2_, "spec_3_classification", "Isotopic label"}, {UNIMOD_Dimethyl_2H_4_13C_2_, "spec_3_hidden", "1"}, {UNIMOD_Dimethyl_2H_4_13C_2_, "spec_3_position", "Anywhere"}, {UNIMOD_Dimethyl_2H_4_13C_2_, "spec_3_site", "R"}, {UNIMOD_Dimethyl_2H_4_13C_2_, "spec_4_classification", "Isotopic label"}, {UNIMOD_Dimethyl_2H_4_13C_2_, "spec_4_hidden", "1"}, {UNIMOD_Dimethyl_2H_4_13C_2_, "spec_4_position", "Protein N-term"}, {UNIMOD_Dimethyl_2H_4_13C_2_, "spec_4_site", "N-term"}, {UNIMOD_Hex_2_, "approved", "0"}, {UNIMOD_Hex_2_, "delta_composition", "Hex(2)"}, {UNIMOD_Hex_2_, "spec_1_classification", "Other glycosylation"}, {UNIMOD_Hex_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_, "spec_1_site", "K"}, {UNIMOD_Hex_2_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_Hex_2_, "spec_2_hidden", "1"}, {UNIMOD_Hex_2_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_2_, "spec_2_site", "R"}, {UNIMOD_C8_QAT, "approved", "0"}, {UNIMOD_C8_QAT, "delta_composition", "H(29) C(14) N O"}, {UNIMOD_C8_QAT, "spec_1_classification", "Chemical derivative"}, {UNIMOD_C8_QAT, "spec_1_hidden", "1"}, {UNIMOD_C8_QAT, "spec_1_position", "Anywhere"}, {UNIMOD_C8_QAT, "spec_1_site", "K"}, {UNIMOD_C8_QAT, "spec_2_classification", "Chemical derivative"}, {UNIMOD_C8_QAT, "spec_2_hidden", "1"}, {UNIMOD_C8_QAT, "spec_2_position", "Any N-term"}, {UNIMOD_C8_QAT, "spec_2_site", "N-term"}, {UNIMOD_PropylNAGthiazoline, "approved", "0"}, {UNIMOD_PropylNAGthiazoline, "delta_composition", "H(14) C(9) N O(4) S"}, {UNIMOD_PropylNAGthiazoline, "spec_1_classification", "Chemical derivative"}, {UNIMOD_PropylNAGthiazoline, "spec_1_hidden", "1"}, {UNIMOD_PropylNAGthiazoline, "spec_1_position", "Anywhere"}, {UNIMOD_PropylNAGthiazoline, "spec_1_site", "C"}, {UNIMOD_FNEM, "approved", "0"}, {UNIMOD_FNEM, "delta_composition", "H(13) C(24) N O(7)"}, {UNIMOD_FNEM, "spec_1_classification", "Chemical derivative"}, {UNIMOD_FNEM, "spec_1_hidden", "1"}, {UNIMOD_FNEM, "spec_1_position", "Anywhere"}, {UNIMOD_FNEM, "spec_1_site", "C"}, {UNIMOD_Diethyl, "approved", "0"}, {UNIMOD_Diethyl, "delta_composition", "H(8) C(4)"}, {UNIMOD_Diethyl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Diethyl, "spec_1_hidden", "1"}, {UNIMOD_Diethyl, "spec_1_position", "Anywhere"}, {UNIMOD_Diethyl, "spec_1_site", "K"}, {UNIMOD_Diethyl, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Diethyl, "spec_2_hidden", "1"}, {UNIMOD_Diethyl, "spec_2_position", "Any N-term"}, {UNIMOD_Diethyl, "spec_2_site", "N-term"}, {UNIMOD_BisANS, "approved", "0"}, {UNIMOD_BisANS, "delta_composition", "H(22) C(32) N(2) O(6) S(2)"}, {UNIMOD_BisANS, "spec_1_classification", "Chemical derivative"}, {UNIMOD_BisANS, "spec_1_hidden", "1"}, {UNIMOD_BisANS, "spec_1_position", "Anywhere"}, {UNIMOD_BisANS, "spec_1_site", "K"}, {UNIMOD_Piperidine, "approved", "0"}, {UNIMOD_Piperidine, "delta_composition", "H(8) C(5)"}, {UNIMOD_Piperidine, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Piperidine, "spec_1_hidden", "1"}, {UNIMOD_Piperidine, "spec_1_position", "Anywhere"}, {UNIMOD_Piperidine, "spec_1_site", "K"}, {UNIMOD_Piperidine, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Piperidine, "spec_2_hidden", "1"}, {UNIMOD_Piperidine, "spec_2_position", "Any N-term"}, {UNIMOD_Piperidine, "spec_2_site", "N-term"}, {UNIMOD_Maleimide_PEO2_Biotin, "approved", "0"}, {UNIMOD_Maleimide_PEO2_Biotin, "delta_composition", "H(35) C(23) N(5) O(7) S"}, {UNIMOD_Maleimide_PEO2_Biotin, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Maleimide_PEO2_Biotin, "spec_1_hidden", "1"}, {UNIMOD_Maleimide_PEO2_Biotin, "spec_1_position", "Anywhere"}, {UNIMOD_Maleimide_PEO2_Biotin, "spec_1_site", "C"}, {UNIMOD_Sulfo_NHS_LC_LC_Biotin, "approved", "0"}, {UNIMOD_Sulfo_NHS_LC_LC_Biotin, "delta_composition", "H(36) C(22) N(4) O(4) S"}, {UNIMOD_Sulfo_NHS_LC_LC_Biotin, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Sulfo_NHS_LC_LC_Biotin, "spec_1_hidden", "1"}, {UNIMOD_Sulfo_NHS_LC_LC_Biotin, "spec_1_position", "Anywhere"}, {UNIMOD_Sulfo_NHS_LC_LC_Biotin, "spec_1_site", "K"}, {UNIMOD_Sulfo_NHS_LC_LC_Biotin, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Sulfo_NHS_LC_LC_Biotin, "spec_2_hidden", "1"}, {UNIMOD_Sulfo_NHS_LC_LC_Biotin, "spec_2_position", "Any N-term"}, {UNIMOD_Sulfo_NHS_LC_LC_Biotin, "spec_2_site", "N-term"}, {UNIMOD_CLIP_TRAQ_2, "approved", "0"}, {UNIMOD_CLIP_TRAQ_2, "delta_composition", "H(12) C(6) 13C N(2) O"}, {UNIMOD_CLIP_TRAQ_2, "spec_1_classification", "Isotopic label"}, {UNIMOD_CLIP_TRAQ_2, "spec_1_hidden", "1"}, {UNIMOD_CLIP_TRAQ_2, "spec_1_position", "Anywhere"}, {UNIMOD_CLIP_TRAQ_2, "spec_1_site", "K"}, {UNIMOD_CLIP_TRAQ_2, "spec_2_classification", "Isotopic label"}, {UNIMOD_CLIP_TRAQ_2, "spec_2_hidden", "1"}, {UNIMOD_CLIP_TRAQ_2, "spec_2_position", "Any N-term"}, {UNIMOD_CLIP_TRAQ_2, "spec_2_site", "N-term"}, {UNIMOD_CLIP_TRAQ_2, "spec_3_classification", "Isotopic label"}, {UNIMOD_CLIP_TRAQ_2, "spec_3_hidden", "1"}, {UNIMOD_CLIP_TRAQ_2, "spec_3_position", "Anywhere"}, {UNIMOD_CLIP_TRAQ_2, "spec_3_site", "Y"}, {UNIMOD_Dethiomethyl, "approved", "1"}, {UNIMOD_Dethiomethyl, "delta_composition", "H(-4) C(-1) S(-1)"}, {UNIMOD_Dethiomethyl, "spec_1_classification", "Artefact"}, {UNIMOD_Dethiomethyl, "spec_1_hidden", "1"}, {UNIMOD_Dethiomethyl, "spec_1_position", "Anywhere"}, {UNIMOD_Dethiomethyl, "spec_1_site", "M"}, {UNIMOD_Methyl_Deamidated, "approved", "1"}, {UNIMOD_Methyl_Deamidated, "delta_composition", "H C N(-1) O"}, {UNIMOD_Methyl_Deamidated, "spec_1_classification", "Post-translational"}, {UNIMOD_Methyl_Deamidated, "spec_1_hidden", "1"}, {UNIMOD_Methyl_Deamidated, "spec_1_position", "Anywhere"}, {UNIMOD_Methyl_Deamidated, "spec_1_site", "Q"}, {UNIMOD_Methyl_Deamidated, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Methyl_Deamidated, "spec_2_hidden", "1"}, {UNIMOD_Methyl_Deamidated, "spec_2_position", "Anywhere"}, {UNIMOD_Methyl_Deamidated, "spec_2_site", "N"}, {UNIMOD_Delta_H_5_C_2_, "approved", "1"}, {UNIMOD_Delta_H_5_C_2_, "delta_composition", "H(5) C(2)"}, {UNIMOD_Delta_H_5_C_2_, "spec_1_classification", "Post-translational"}, {UNIMOD_Delta_H_5_C_2_, "spec_1_hidden", "1"}, {UNIMOD_Delta_H_5_C_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Delta_H_5_C_2_, "spec_1_site", "P"}, {UNIMOD_Cation_K, "approved", "1"}, {UNIMOD_Cation_K, "delta_composition", "H(-1) K"}, {UNIMOD_Cation_K, "spec_1_classification", "Artefact"}, {UNIMOD_Cation_K, "spec_1_classification", "Artefact"}, {UNIMOD_Cation_K, "spec_1_hidden", "1"}, {UNIMOD_Cation_K, "spec_1_hidden", "1"}, {UNIMOD_Cation_K, "spec_1_position", "Anywhere"}, {UNIMOD_Cation_K, "spec_1_position", "Anywhere"}, {UNIMOD_Cation_K, "spec_1_site", "E"}, {UNIMOD_Cation_K, "spec_1_site", "D"}, {UNIMOD_Cation_K, "spec_2_classification", "Artefact"}, {UNIMOD_Cation_K, "spec_2_hidden", "1"}, {UNIMOD_Cation_K, "spec_2_position", "Any C-term"}, {UNIMOD_Cation_K, "spec_2_site", "C-term"}, {UNIMOD_Cation_Cu_I_, "approved", "1"}, {UNIMOD_Cation_Cu_I_, "delta_composition", "H(-1) Cu"}, {UNIMOD_Cation_Cu_I_, "spec_1_classification", "Artefact"}, {UNIMOD_Cation_Cu_I_, "spec_1_classification", "Artefact"}, {UNIMOD_Cation_Cu_I_, "spec_1_hidden", "1"}, {UNIMOD_Cation_Cu_I_, "spec_1_hidden", "1"}, {UNIMOD_Cation_Cu_I_, "spec_1_position", "Anywhere"}, {UNIMOD_Cation_Cu_I_, "spec_1_position", "Anywhere"}, {UNIMOD_Cation_Cu_I_, "spec_1_site", "E"}, {UNIMOD_Cation_Cu_I_, "spec_1_site", "D"}, {UNIMOD_Cation_Cu_I_, "spec_2_classification", "Artefact"}, {UNIMOD_Cation_Cu_I_, "spec_2_hidden", "1"}, {UNIMOD_Cation_Cu_I_, "spec_2_position", "Any C-term"}, {UNIMOD_Cation_Cu_I_, "spec_2_site", "C-term"}, {UNIMOD_Cation_Cu_I_, "spec_3_classification", "Artefact"}, {UNIMOD_Cation_Cu_I_, "spec_3_hidden", "1"}, {UNIMOD_Cation_Cu_I_, "spec_3_position", "Anywhere"}, {UNIMOD_Cation_Cu_I_, "spec_3_site", "H"}, {UNIMOD_iTRAQ4plex114, "approved", "0"}, {UNIMOD_iTRAQ4plex114, "delta_composition", "H(12) C(5) 13C(2) N(2) 18O"}, {UNIMOD_iTRAQ4plex114, "spec_1_classification", "Isotopic label"}, {UNIMOD_iTRAQ4plex114, "spec_1_hidden", "1"}, {UNIMOD_iTRAQ4plex114, "spec_1_position", "Anywhere"}, {UNIMOD_iTRAQ4plex114, "spec_1_site", "K"}, {UNIMOD_iTRAQ4plex114, "spec_2_classification", "Isotopic label"}, {UNIMOD_iTRAQ4plex114, "spec_2_hidden", "1"}, {UNIMOD_iTRAQ4plex114, "spec_2_position", "Any N-term"}, {UNIMOD_iTRAQ4plex114, "spec_2_site", "N-term"}, {UNIMOD_iTRAQ4plex114, "spec_3_classification", "Isotopic label"}, {UNIMOD_iTRAQ4plex114, "spec_3_hidden", "1"}, {UNIMOD_iTRAQ4plex114, "spec_3_position", "Anywhere"}, {UNIMOD_iTRAQ4plex114, "spec_3_site", "Y"}, {UNIMOD_iTRAQ4plex115, "approved", "0"}, {UNIMOD_iTRAQ4plex115, "delta_composition", "H(12) C(6) 13C N 15N 18O"}, {UNIMOD_iTRAQ4plex115, "spec_1_classification", "Isotopic label"}, {UNIMOD_iTRAQ4plex115, "spec_1_hidden", "1"}, {UNIMOD_iTRAQ4plex115, "spec_1_position", "Anywhere"}, {UNIMOD_iTRAQ4plex115, "spec_1_site", "K"}, {UNIMOD_iTRAQ4plex115, "spec_2_classification", "Isotopic label"}, {UNIMOD_iTRAQ4plex115, "spec_2_hidden", "1"}, {UNIMOD_iTRAQ4plex115, "spec_2_position", "Any N-term"}, {UNIMOD_iTRAQ4plex115, "spec_2_site", "N-term"}, {UNIMOD_iTRAQ4plex115, "spec_3_classification", "Isotopic label"}, {UNIMOD_iTRAQ4plex115, "spec_3_hidden", "1"}, {UNIMOD_iTRAQ4plex115, "spec_3_position", "Anywhere"}, {UNIMOD_iTRAQ4plex115, "spec_3_site", "Y"}, {UNIMOD_Dibromo, "approved", "1"}, {UNIMOD_Dibromo, "delta_composition", "H(-2) Br(2)"}, {UNIMOD_Dibromo, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Dibromo, "spec_1_hidden", "1"}, {UNIMOD_Dibromo, "spec_1_position", "Anywhere"}, {UNIMOD_Dibromo, "spec_1_site", "Y"}, {UNIMOD_LRGG, "approved", "1"}, {UNIMOD_LRGG, "delta_composition", "H(29) C(16) N(7) O(4)"}, {UNIMOD_LRGG, "spec_1_classification", "Chemical derivative"}, {UNIMOD_LRGG, "spec_1_hidden", "1"}, {UNIMOD_LRGG, "spec_1_position", "Anywhere"}, {UNIMOD_LRGG, "spec_1_site", "K"}, {UNIMOD_CLIP_TRAQ_3, "approved", "0"}, {UNIMOD_CLIP_TRAQ_3, "delta_composition", "H(20) C(11) 13C N(3) O(4)"}, {UNIMOD_CLIP_TRAQ_3, "spec_1_classification", "Isotopic label"}, {UNIMOD_CLIP_TRAQ_3, "spec_1_hidden", "1"}, {UNIMOD_CLIP_TRAQ_3, "spec_1_position", "Anywhere"}, {UNIMOD_CLIP_TRAQ_3, "spec_1_site", "K"}, {UNIMOD_CLIP_TRAQ_3, "spec_2_classification", "Isotopic label"}, {UNIMOD_CLIP_TRAQ_3, "spec_2_hidden", "1"}, {UNIMOD_CLIP_TRAQ_3, "spec_2_position", "Any N-term"}, {UNIMOD_CLIP_TRAQ_3, "spec_2_site", "N-term"}, {UNIMOD_CLIP_TRAQ_3, "spec_3_classification", "Isotopic label"}, {UNIMOD_CLIP_TRAQ_3, "spec_3_hidden", "1"}, {UNIMOD_CLIP_TRAQ_3, "spec_3_position", "Anywhere"}, {UNIMOD_CLIP_TRAQ_3, "spec_3_site", "Y"}, {UNIMOD_CLIP_TRAQ_4, "approved", "0"}, {UNIMOD_CLIP_TRAQ_4, "delta_composition", "H(15) C(9) 13C N(2) O(5)"}, {UNIMOD_CLIP_TRAQ_4, "spec_1_classification", "Isotopic label"}, {UNIMOD_CLIP_TRAQ_4, "spec_1_hidden", "1"}, {UNIMOD_CLIP_TRAQ_4, "spec_1_position", "Anywhere"}, {UNIMOD_CLIP_TRAQ_4, "spec_1_site", "K"}, {UNIMOD_CLIP_TRAQ_4, "spec_2_classification", "Isotopic label"}, {UNIMOD_CLIP_TRAQ_4, "spec_2_hidden", "1"}, {UNIMOD_CLIP_TRAQ_4, "spec_2_position", "Any N-term"}, {UNIMOD_CLIP_TRAQ_4, "spec_2_site", "N-term"}, {UNIMOD_CLIP_TRAQ_4, "spec_3_classification", "Isotopic label"}, {UNIMOD_CLIP_TRAQ_4, "spec_3_hidden", "1"}, {UNIMOD_CLIP_TRAQ_4, "spec_3_position", "Anywhere"}, {UNIMOD_CLIP_TRAQ_4, "spec_3_site", "Y"}, {UNIMOD_Biotin_Cayman_10141, "approved", "0"}, {UNIMOD_Biotin_Cayman_10141, "delta_composition", "H(54) C(35) N(4) O(4) S"}, {UNIMOD_Biotin_Cayman_10141, "spec_1_classification", "Other"}, {UNIMOD_Biotin_Cayman_10141, "spec_1_hidden", "1"}, {UNIMOD_Biotin_Cayman_10141, "spec_1_position", "Anywhere"}, {UNIMOD_Biotin_Cayman_10141, "spec_1_site", "C"}, {UNIMOD_Biotin_Cayman_10013, "approved", "0"}, {UNIMOD_Biotin_Cayman_10013, "delta_composition", "H(60) C(36) N(4) O(5) S"}, {UNIMOD_Biotin_Cayman_10013, "spec_1_classification", "Other"}, {UNIMOD_Biotin_Cayman_10013, "spec_1_hidden", "1"}, {UNIMOD_Biotin_Cayman_10013, "spec_1_position", "Anywhere"}, {UNIMOD_Biotin_Cayman_10013, "spec_1_site", "C"}, {UNIMOD_Ala__Ser, "approved", "0"}, {UNIMOD_Ala__Ser, "delta_composition", "O"}, {UNIMOD_Ala__Ser, "spec_1_classification", "AA substitution"}, {UNIMOD_Ala__Ser, "spec_1_hidden", "1"}, {UNIMOD_Ala__Ser, "spec_1_position", "Anywhere"}, {UNIMOD_Ala__Ser, "spec_1_site", "A"}, {UNIMOD_Ala__Thr, "approved", "0"}, {UNIMOD_Ala__Thr, "delta_composition", "H(2) C O"}, {UNIMOD_Ala__Thr, "spec_1_classification", "AA substitution"}, {UNIMOD_Ala__Thr, "spec_1_hidden", "1"}, {UNIMOD_Ala__Thr, "spec_1_position", "Anywhere"}, {UNIMOD_Ala__Thr, "spec_1_site", "A"}, {UNIMOD_Ala__Asp, "approved", "0"}, {UNIMOD_Ala__Asp, "delta_composition", "C O(2)"}, {UNIMOD_Ala__Asp, "spec_1_classification", "AA substitution"}, {UNIMOD_Ala__Asp, "spec_1_hidden", "1"}, {UNIMOD_Ala__Asp, "spec_1_position", "Anywhere"}, {UNIMOD_Ala__Asp, "spec_1_site", "A"}, {UNIMOD_Ala__Pro, "approved", "0"}, {UNIMOD_Ala__Pro, "delta_composition", "H(2) C(2)"}, {UNIMOD_Ala__Pro, "spec_1_classification", "AA substitution"}, {UNIMOD_Ala__Pro, "spec_1_hidden", "1"}, {UNIMOD_Ala__Pro, "spec_1_position", "Anywhere"}, {UNIMOD_Ala__Pro, "spec_1_site", "A"}, {UNIMOD_Ala__Gly, "approved", "0"}, {UNIMOD_Ala__Gly, "delta_composition", "H(-2) C(-1)"}, {UNIMOD_Ala__Gly, "spec_1_classification", "AA substitution"}, {UNIMOD_Ala__Gly, "spec_1_hidden", "1"}, {UNIMOD_Ala__Gly, "spec_1_position", "Anywhere"}, {UNIMOD_Ala__Gly, "spec_1_site", "A"}, {UNIMOD_Ala__Glu, "approved", "0"}, {UNIMOD_Ala__Glu, "delta_composition", "H(2) C(2) O(2)"}, {UNIMOD_Ala__Glu, "spec_1_classification", "AA substitution"}, {UNIMOD_Ala__Glu, "spec_1_hidden", "1"}, {UNIMOD_Ala__Glu, "spec_1_position", "Anywhere"}, {UNIMOD_Ala__Glu, "spec_1_site", "A"}, {UNIMOD_Ala__Val, "approved", "0"}, {UNIMOD_Ala__Val, "delta_composition", "H(4) C(2)"}, {UNIMOD_Ala__Val, "spec_1_classification", "AA substitution"}, {UNIMOD_Ala__Val, "spec_1_hidden", "1"}, {UNIMOD_Ala__Val, "spec_1_position", "Anywhere"}, {UNIMOD_Ala__Val, "spec_1_site", "A"}, {UNIMOD_Cys__Phe, "approved", "0"}, {UNIMOD_Cys__Phe, "delta_composition", "H(4) C(6) S(-1)"}, {UNIMOD_Cys__Phe, "spec_1_classification", "AA substitution"}, {UNIMOD_Cys__Phe, "spec_1_hidden", "1"}, {UNIMOD_Cys__Phe, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__Phe, "spec_1_site", "C"}, {UNIMOD_Cys__Ser, "approved", "0"}, {UNIMOD_Cys__Ser, "delta_composition", "O S(-1)"}, {UNIMOD_Cys__Ser, "spec_1_classification", "AA substitution"}, {UNIMOD_Cys__Ser, "spec_1_hidden", "1"}, {UNIMOD_Cys__Ser, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__Ser, "spec_1_site", "C"}, {UNIMOD_Cys__Trp, "approved", "0"}, {UNIMOD_Cys__Trp, "delta_composition", "H(5) C(8) N S(-1)"}, {UNIMOD_Cys__Trp, "spec_1_classification", "AA substitution"}, {UNIMOD_Cys__Trp, "spec_1_hidden", "1"}, {UNIMOD_Cys__Trp, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__Trp, "spec_1_site", "C"}, {UNIMOD_Cys__Tyr, "approved", "0"}, {UNIMOD_Cys__Tyr, "delta_composition", "H(4) C(6) O S(-1)"}, {UNIMOD_Cys__Tyr, "spec_1_classification", "AA substitution"}, {UNIMOD_Cys__Tyr, "spec_1_hidden", "1"}, {UNIMOD_Cys__Tyr, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__Tyr, "spec_1_site", "C"}, {UNIMOD_Cys__Arg, "approved", "0"}, {UNIMOD_Cys__Arg, "delta_composition", "H(7) C(3) N(3) S(-1)"}, {UNIMOD_Cys__Arg, "spec_1_classification", "AA substitution"}, {UNIMOD_Cys__Arg, "spec_1_hidden", "1"}, {UNIMOD_Cys__Arg, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__Arg, "spec_1_site", "C"}, {UNIMOD_Cys__Gly, "approved", "0"}, {UNIMOD_Cys__Gly, "delta_composition", "H(-2) C(-1) S(-1)"}, {UNIMOD_Cys__Gly, "spec_1_classification", "AA substitution"}, {UNIMOD_Cys__Gly, "spec_1_hidden", "1"}, {UNIMOD_Cys__Gly, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__Gly, "spec_1_site", "C"}, {UNIMOD_Asp__Ala, "approved", "0"}, {UNIMOD_Asp__Ala, "delta_composition", "C(-1) O(-2)"}, {UNIMOD_Asp__Ala, "spec_1_classification", "AA substitution"}, {UNIMOD_Asp__Ala, "spec_1_hidden", "1"}, {UNIMOD_Asp__Ala, "spec_1_position", "Anywhere"}, {UNIMOD_Asp__Ala, "spec_1_site", "D"}, {UNIMOD_Asp__His, "approved", "0"}, {UNIMOD_Asp__His, "delta_composition", "H(2) C(2) N(2) O(-2)"}, {UNIMOD_Asp__His, "spec_1_classification", "AA substitution"}, {UNIMOD_Asp__His, "spec_1_hidden", "1"}, {UNIMOD_Asp__His, "spec_1_position", "Anywhere"}, {UNIMOD_Asp__His, "spec_1_site", "D"}, {UNIMOD_Asp__Asn, "approved", "0"}, {UNIMOD_Asp__Asn, "delta_composition", "H N O(-1)"}, {UNIMOD_Asp__Asn, "spec_1_classification", "AA substitution"}, {UNIMOD_Asp__Asn, "spec_1_hidden", "1"}, {UNIMOD_Asp__Asn, "spec_1_position", "Anywhere"}, {UNIMOD_Asp__Asn, "spec_1_site", "D"}, {UNIMOD_Asp__Gly, "approved", "0"}, {UNIMOD_Asp__Gly, "delta_composition", "H(-2) C(-2) O(-2)"}, {UNIMOD_Asp__Gly, "spec_1_classification", "AA substitution"}, {UNIMOD_Asp__Gly, "spec_1_hidden", "1"}, {UNIMOD_Asp__Gly, "spec_1_position", "Anywhere"}, {UNIMOD_Asp__Gly, "spec_1_site", "D"}, {UNIMOD_Asp__Tyr, "approved", "0"}, {UNIMOD_Asp__Tyr, "delta_composition", "H(4) C(5) O(-1)"}, {UNIMOD_Asp__Tyr, "spec_1_classification", "AA substitution"}, {UNIMOD_Asp__Tyr, "spec_1_hidden", "1"}, {UNIMOD_Asp__Tyr, "spec_1_position", "Anywhere"}, {UNIMOD_Asp__Tyr, "spec_1_site", "D"}, {UNIMOD_Asp__Glu, "approved", "0"}, {UNIMOD_Asp__Glu, "delta_composition", "H(2) C"}, {UNIMOD_Asp__Glu, "spec_1_classification", "AA substitution"}, {UNIMOD_Asp__Glu, "spec_1_hidden", "1"}, {UNIMOD_Asp__Glu, "spec_1_position", "Anywhere"}, {UNIMOD_Asp__Glu, "spec_1_site", "D"}, {UNIMOD_Asp__Val, "approved", "0"}, {UNIMOD_Asp__Val, "delta_composition", "H(4) C O(-2)"}, {UNIMOD_Asp__Val, "spec_1_classification", "AA substitution"}, {UNIMOD_Asp__Val, "spec_1_hidden", "1"}, {UNIMOD_Asp__Val, "spec_1_position", "Anywhere"}, {UNIMOD_Asp__Val, "spec_1_site", "D"}, {UNIMOD_Glu__Ala, "approved", "0"}, {UNIMOD_Glu__Ala, "delta_composition", "H(-2) C(-2) O(-2)"}, {UNIMOD_Glu__Ala, "spec_1_classification", "AA substitution"}, {UNIMOD_Glu__Ala, "spec_1_hidden", "1"}, {UNIMOD_Glu__Ala, "spec_1_position", "Anywhere"}, {UNIMOD_Glu__Ala, "spec_1_site", "E"}, {UNIMOD_Glu__Gln, "approved", "0"}, {UNIMOD_Glu__Gln, "delta_composition", "H N O(-1)"}, {UNIMOD_Glu__Gln, "spec_1_classification", "AA substitution"}, {UNIMOD_Glu__Gln, "spec_1_hidden", "1"}, {UNIMOD_Glu__Gln, "spec_1_position", "Anywhere"}, {UNIMOD_Glu__Gln, "spec_1_site", "E"}, {UNIMOD_Glu__Asp, "approved", "0"}, {UNIMOD_Glu__Asp, "delta_composition", "H(-2) C(-1)"}, {UNIMOD_Glu__Asp, "spec_1_classification", "AA substitution"}, {UNIMOD_Glu__Asp, "spec_1_hidden", "1"}, {UNIMOD_Glu__Asp, "spec_1_position", "Anywhere"}, {UNIMOD_Glu__Asp, "spec_1_site", "E"}, {UNIMOD_Glu__Lys, "approved", "0"}, {UNIMOD_Glu__Lys, "delta_composition", "H(5) C N O(-2)"}, {UNIMOD_Glu__Lys, "spec_1_classification", "AA substitution"}, {UNIMOD_Glu__Lys, "spec_1_hidden", "1"}, {UNIMOD_Glu__Lys, "spec_1_position", "Anywhere"}, {UNIMOD_Glu__Lys, "spec_1_site", "E"}, {UNIMOD_Glu__Gly, "approved", "0"}, {UNIMOD_Glu__Gly, "delta_composition", "H(-4) C(-3) O(-2)"}, {UNIMOD_Glu__Gly, "spec_1_classification", "AA substitution"}, {UNIMOD_Glu__Gly, "spec_1_hidden", "1"}, {UNIMOD_Glu__Gly, "spec_1_position", "Anywhere"}, {UNIMOD_Glu__Gly, "spec_1_site", "E"}, {UNIMOD_Glu__Val, "approved", "0"}, {UNIMOD_Glu__Val, "delta_composition", "H(2) O(-2)"}, {UNIMOD_Glu__Val, "spec_1_classification", "AA substitution"}, {UNIMOD_Glu__Val, "spec_1_hidden", "1"}, {UNIMOD_Glu__Val, "spec_1_position", "Anywhere"}, {UNIMOD_Glu__Val, "spec_1_site", "E"}, {UNIMOD_Phe__Ser, "approved", "0"}, {UNIMOD_Phe__Ser, "delta_composition", "H(-4) C(-6) O"}, {UNIMOD_Phe__Ser, "spec_1_classification", "AA substitution"}, {UNIMOD_Phe__Ser, "spec_1_hidden", "1"}, {UNIMOD_Phe__Ser, "spec_1_position", "Anywhere"}, {UNIMOD_Phe__Ser, "spec_1_site", "F"}, {UNIMOD_Phe__Cys, "approved", "0"}, {UNIMOD_Phe__Cys, "delta_composition", "H(-4) C(-6) S"}, {UNIMOD_Phe__Cys, "spec_1_classification", "AA substitution"}, {UNIMOD_Phe__Cys, "spec_1_hidden", "1"}, {UNIMOD_Phe__Cys, "spec_1_position", "Anywhere"}, {UNIMOD_Phe__Cys, "spec_1_site", "F"}, {UNIMOD_Phe__Xle, "approved", "0"}, {UNIMOD_Phe__Xle, "delta_composition", "H(2) C(-3)"}, {UNIMOD_Phe__Xle, "spec_1_classification", "AA substitution"}, {UNIMOD_Phe__Xle, "spec_1_hidden", "1"}, {UNIMOD_Phe__Xle, "spec_1_position", "Anywhere"}, {UNIMOD_Phe__Xle, "spec_1_site", "F"}, {UNIMOD_Phe__Tyr, "approved", "0"}, {UNIMOD_Phe__Tyr, "delta_composition", "O"}, {UNIMOD_Phe__Tyr, "spec_1_classification", "AA substitution"}, {UNIMOD_Phe__Tyr, "spec_1_hidden", "1"}, {UNIMOD_Phe__Tyr, "spec_1_position", "Anywhere"}, {UNIMOD_Phe__Tyr, "spec_1_site", "F"}, {UNIMOD_Phe__Val, "approved", "0"}, {UNIMOD_Phe__Val, "delta_composition", "C(-4)"}, {UNIMOD_Phe__Val, "spec_1_classification", "AA substitution"}, {UNIMOD_Phe__Val, "spec_1_hidden", "1"}, {UNIMOD_Phe__Val, "spec_1_position", "Anywhere"}, {UNIMOD_Phe__Val, "spec_1_site", "F"}, {UNIMOD_Gly__Ala, "approved", "0"}, {UNIMOD_Gly__Ala, "delta_composition", "H(2) C"}, {UNIMOD_Gly__Ala, "spec_1_classification", "AA substitution"}, {UNIMOD_Gly__Ala, "spec_1_hidden", "1"}, {UNIMOD_Gly__Ala, "spec_1_position", "Anywhere"}, {UNIMOD_Gly__Ala, "spec_1_site", "G"}, {UNIMOD_Gly__Ser, "approved", "0"}, {UNIMOD_Gly__Ser, "delta_composition", "H(2) C O"}, {UNIMOD_Gly__Ser, "spec_1_classification", "AA substitution"}, {UNIMOD_Gly__Ser, "spec_1_hidden", "1"}, {UNIMOD_Gly__Ser, "spec_1_position", "Anywhere"}, {UNIMOD_Gly__Ser, "spec_1_site", "G"}, {UNIMOD_Gly__Trp, "approved", "0"}, {UNIMOD_Gly__Trp, "delta_composition", "H(7) C(9) N"}, {UNIMOD_Gly__Trp, "spec_1_classification", "AA substitution"}, {UNIMOD_Gly__Trp, "spec_1_hidden", "1"}, {UNIMOD_Gly__Trp, "spec_1_position", "Anywhere"}, {UNIMOD_Gly__Trp, "spec_1_site", "G"}, {UNIMOD_Gly__Glu, "approved", "0"}, {UNIMOD_Gly__Glu, "delta_composition", "H(4) C(3) O(2)"}, {UNIMOD_Gly__Glu, "spec_1_classification", "AA substitution"}, {UNIMOD_Gly__Glu, "spec_1_hidden", "1"}, {UNIMOD_Gly__Glu, "spec_1_position", "Anywhere"}, {UNIMOD_Gly__Glu, "spec_1_site", "G"}, {UNIMOD_Gly__Val, "approved", "0"}, {UNIMOD_Gly__Val, "delta_composition", "H(6) C(3)"}, {UNIMOD_Gly__Val, "spec_1_classification", "AA substitution"}, {UNIMOD_Gly__Val, "spec_1_hidden", "1"}, {UNIMOD_Gly__Val, "spec_1_position", "Anywhere"}, {UNIMOD_Gly__Val, "spec_1_site", "G"}, {UNIMOD_Gly__Asp, "approved", "0"}, {UNIMOD_Gly__Asp, "delta_composition", "H(2) C(2) O(2)"}, {UNIMOD_Gly__Asp, "spec_1_classification", "AA substitution"}, {UNIMOD_Gly__Asp, "spec_1_hidden", "1"}, {UNIMOD_Gly__Asp, "spec_1_position", "Anywhere"}, {UNIMOD_Gly__Asp, "spec_1_site", "G"}, {UNIMOD_Gly__Cys, "approved", "0"}, {UNIMOD_Gly__Cys, "delta_composition", "H(2) C S"}, {UNIMOD_Gly__Cys, "spec_1_classification", "AA substitution"}, {UNIMOD_Gly__Cys, "spec_1_hidden", "1"}, {UNIMOD_Gly__Cys, "spec_1_position", "Anywhere"}, {UNIMOD_Gly__Cys, "spec_1_site", "G"}, {UNIMOD_Gly__Arg, "approved", "0"}, {UNIMOD_Gly__Arg, "delta_composition", "H(9) C(4) N(3)"}, {UNIMOD_Gly__Arg, "spec_1_classification", "AA substitution"}, {UNIMOD_Gly__Arg, "spec_1_hidden", "1"}, {UNIMOD_Gly__Arg, "spec_1_position", "Anywhere"}, {UNIMOD_Gly__Arg, "spec_1_site", "G"}, {UNIMOD_His__Pro, "approved", "0"}, {UNIMOD_His__Pro, "delta_composition", "C(-1) N(-2)"}, {UNIMOD_His__Pro, "spec_1_classification", "AA substitution"}, {UNIMOD_His__Pro, "spec_1_hidden", "1"}, {UNIMOD_His__Pro, "spec_1_position", "Anywhere"}, {UNIMOD_His__Pro, "spec_1_site", "H"}, {UNIMOD_His__Tyr, "approved", "0"}, {UNIMOD_His__Tyr, "delta_composition", "H(2) C(3) N(-2) O"}, {UNIMOD_His__Tyr, "spec_1_classification", "AA substitution"}, {UNIMOD_His__Tyr, "spec_1_hidden", "1"}, {UNIMOD_His__Tyr, "spec_1_position", "Anywhere"}, {UNIMOD_His__Tyr, "spec_1_site", "H"}, {UNIMOD_His__Gln, "approved", "0"}, {UNIMOD_His__Gln, "delta_composition", "H C(-1) N(-1) O"}, {UNIMOD_His__Gln, "spec_1_classification", "AA substitution"}, {UNIMOD_His__Gln, "spec_1_hidden", "1"}, {UNIMOD_His__Gln, "spec_1_position", "Anywhere"}, {UNIMOD_His__Gln, "spec_1_site", "H"}, {UNIMOD_His__Arg, "approved", "0"}, {UNIMOD_His__Arg, "delta_composition", "H(5) N"}, {UNIMOD_His__Arg, "spec_1_classification", "AA substitution"}, {UNIMOD_His__Arg, "spec_1_hidden", "1"}, {UNIMOD_His__Arg, "spec_1_position", "Anywhere"}, {UNIMOD_His__Arg, "spec_1_site", "H"}, {UNIMOD_His__Xle, "approved", "0"}, {UNIMOD_His__Xle, "delta_composition", "H(4) N(-2)"}, {UNIMOD_His__Xle, "spec_1_classification", "AA substitution"}, {UNIMOD_His__Xle, "spec_1_hidden", "1"}, {UNIMOD_His__Xle, "spec_1_position", "Anywhere"}, {UNIMOD_His__Xle, "spec_1_site", "H"}, {UNIMOD_Xle__Thr, "approved", "0"}, {UNIMOD_Xle__Thr, "delta_composition", "H(-4) C(-2) O"}, {UNIMOD_Xle__Thr, "spec_1_classification", "AA substitution"}, {UNIMOD_Xle__Thr, "spec_1_hidden", "1"}, {UNIMOD_Xle__Thr, "spec_1_position", "Anywhere"}, {UNIMOD_Xle__Thr, "spec_1_site", "I"}, {UNIMOD_Xle__Thr, "spec_2_classification", "AA substitution"}, {UNIMOD_Xle__Thr, "spec_2_hidden", "1"}, {UNIMOD_Xle__Thr, "spec_2_position", "Anywhere"}, {UNIMOD_Xle__Thr, "spec_2_site", "L"}, {UNIMOD_Xle__Asn, "approved", "0"}, {UNIMOD_Xle__Asn, "delta_composition", "H(-5) C(-2) N O"}, {UNIMOD_Xle__Asn, "spec_1_classification", "AA substitution"}, {UNIMOD_Xle__Asn, "spec_1_hidden", "1"}, {UNIMOD_Xle__Asn, "spec_1_position", "Anywhere"}, {UNIMOD_Xle__Asn, "spec_1_site", "I"}, {UNIMOD_Xle__Asn, "spec_2_classification", "AA substitution"}, {UNIMOD_Xle__Asn, "spec_2_hidden", "1"}, {UNIMOD_Xle__Asn, "spec_2_position", "Anywhere"}, {UNIMOD_Xle__Asn, "spec_2_site", "L"}, {UNIMOD_Xle__Lys, "approved", "0"}, {UNIMOD_Xle__Lys, "delta_composition", "H N"}, {UNIMOD_Xle__Lys, "spec_1_classification", "AA substitution"}, {UNIMOD_Xle__Lys, "spec_1_hidden", "1"}, {UNIMOD_Xle__Lys, "spec_1_position", "Anywhere"}, {UNIMOD_Xle__Lys, "spec_1_site", "I"}, {UNIMOD_Xle__Lys, "spec_2_classification", "AA substitution"}, {UNIMOD_Xle__Lys, "spec_2_hidden", "1"}, {UNIMOD_Xle__Lys, "spec_2_position", "Anywhere"}, {UNIMOD_Xle__Lys, "spec_2_site", "L"}, {UNIMOD_Lys__Thr, "approved", "0"}, {UNIMOD_Lys__Thr, "delta_composition", "H(-5) C(-2) N(-1) O"}, {UNIMOD_Lys__Thr, "spec_1_classification", "AA substitution"}, {UNIMOD_Lys__Thr, "spec_1_hidden", "1"}, {UNIMOD_Lys__Thr, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__Thr, "spec_1_site", "K"}, {UNIMOD_Lys__Asn, "approved", "0"}, {UNIMOD_Lys__Asn, "delta_composition", "H(-6) C(-2) O"}, {UNIMOD_Lys__Asn, "spec_1_classification", "AA substitution"}, {UNIMOD_Lys__Asn, "spec_1_hidden", "1"}, {UNIMOD_Lys__Asn, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__Asn, "spec_1_site", "K"}, {UNIMOD_Lys__Glu, "approved", "0"}, {UNIMOD_Lys__Glu, "delta_composition", "H(-5) C(-1) N(-1) O(2)"}, {UNIMOD_Lys__Glu, "spec_1_classification", "AA substitution"}, {UNIMOD_Lys__Glu, "spec_1_hidden", "1"}, {UNIMOD_Lys__Glu, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__Glu, "spec_1_site", "K"}, {UNIMOD_Lys__Gln, "approved", "0"}, {UNIMOD_Lys__Gln, "delta_composition", "H(-4) C(-1) O"}, {UNIMOD_Lys__Gln, "spec_1_classification", "AA substitution"}, {UNIMOD_Lys__Gln, "spec_1_hidden", "1"}, {UNIMOD_Lys__Gln, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__Gln, "spec_1_site", "K"}, {UNIMOD_Lys__Met, "approved", "0"}, {UNIMOD_Lys__Met, "delta_composition", "H(-3) C(-1) N(-1) S"}, {UNIMOD_Lys__Met, "spec_1_classification", "AA substitution"}, {UNIMOD_Lys__Met, "spec_1_hidden", "1"}, {UNIMOD_Lys__Met, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__Met, "spec_1_site", "K"}, {UNIMOD_Lys__Arg, "approved", "0"}, {UNIMOD_Lys__Arg, "delta_composition", "N(2)"}, {UNIMOD_Lys__Arg, "spec_1_classification", "AA substitution"}, {UNIMOD_Lys__Arg, "spec_1_hidden", "1"}, {UNIMOD_Lys__Arg, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__Arg, "spec_1_site", "K"}, {UNIMOD_Lys__Xle, "approved", "0"}, {UNIMOD_Lys__Xle, "delta_composition", "H(-1) N(-1)"}, {UNIMOD_Lys__Xle, "spec_1_classification", "AA substitution"}, {UNIMOD_Lys__Xle, "spec_1_hidden", "1"}, {UNIMOD_Lys__Xle, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__Xle, "spec_1_site", "K"}, {UNIMOD_Xle__Ser, "approved", "0"}, {UNIMOD_Xle__Ser, "delta_composition", "H(-6) C(-3) O"}, {UNIMOD_Xle__Ser, "spec_1_classification", "AA substitution"}, {UNIMOD_Xle__Ser, "spec_1_hidden", "1"}, {UNIMOD_Xle__Ser, "spec_1_position", "Anywhere"}, {UNIMOD_Xle__Ser, "spec_1_site", "L"}, {UNIMOD_Xle__Ser, "spec_2_classification", "AA substitution"}, {UNIMOD_Xle__Ser, "spec_2_hidden", "1"}, {UNIMOD_Xle__Ser, "spec_2_position", "Anywhere"}, {UNIMOD_Xle__Ser, "spec_2_site", "I"}, {UNIMOD_Xle__Phe, "approved", "0"}, {UNIMOD_Xle__Phe, "delta_composition", "H(-2) C(3)"}, {UNIMOD_Xle__Phe, "spec_1_classification", "AA substitution"}, {UNIMOD_Xle__Phe, "spec_1_hidden", "1"}, {UNIMOD_Xle__Phe, "spec_1_position", "Anywhere"}, {UNIMOD_Xle__Phe, "spec_1_site", "L"}, {UNIMOD_Xle__Phe, "spec_2_classification", "AA substitution"}, {UNIMOD_Xle__Phe, "spec_2_hidden", "1"}, {UNIMOD_Xle__Phe, "spec_2_position", "Anywhere"}, {UNIMOD_Xle__Phe, "spec_2_site", "I"}, {UNIMOD_Xle__Trp, "approved", "0"}, {UNIMOD_Xle__Trp, "delta_composition", "H(-1) C(5) N"}, {UNIMOD_Xle__Trp, "spec_1_classification", "AA substitution"}, {UNIMOD_Xle__Trp, "spec_1_hidden", "1"}, {UNIMOD_Xle__Trp, "spec_1_position", "Anywhere"}, {UNIMOD_Xle__Trp, "spec_1_site", "L"}, {UNIMOD_Xle__Trp, "spec_2_classification", "AA substitution"}, {UNIMOD_Xle__Trp, "spec_2_hidden", "1"}, {UNIMOD_Xle__Trp, "spec_2_position", "Anywhere"}, {UNIMOD_Xle__Trp, "spec_2_site", "I"}, {UNIMOD_Xle__Pro, "approved", "0"}, {UNIMOD_Xle__Pro, "delta_composition", "H(-4) C(-1)"}, {UNIMOD_Xle__Pro, "spec_1_classification", "AA substitution"}, {UNIMOD_Xle__Pro, "spec_1_hidden", "1"}, {UNIMOD_Xle__Pro, "spec_1_position", "Anywhere"}, {UNIMOD_Xle__Pro, "spec_1_site", "L"}, {UNIMOD_Xle__Pro, "spec_2_classification", "AA substitution"}, {UNIMOD_Xle__Pro, "spec_2_hidden", "1"}, {UNIMOD_Xle__Pro, "spec_2_position", "Anywhere"}, {UNIMOD_Xle__Pro, "spec_2_site", "I"}, {UNIMOD_Xle__Val, "approved", "0"}, {UNIMOD_Xle__Val, "delta_composition", "H(-2) C(-1)"}, {UNIMOD_Xle__Val, "spec_1_classification", "AA substitution"}, {UNIMOD_Xle__Val, "spec_1_hidden", "1"}, {UNIMOD_Xle__Val, "spec_1_position", "Anywhere"}, {UNIMOD_Xle__Val, "spec_1_site", "L"}, {UNIMOD_Xle__Val, "spec_2_classification", "AA substitution"}, {UNIMOD_Xle__Val, "spec_2_hidden", "1"}, {UNIMOD_Xle__Val, "spec_2_position", "Anywhere"}, {UNIMOD_Xle__Val, "spec_2_site", "I"}, {UNIMOD_Xle__His, "approved", "0"}, {UNIMOD_Xle__His, "delta_composition", "H(-4) N(2)"}, {UNIMOD_Xle__His, "spec_1_classification", "AA substitution"}, {UNIMOD_Xle__His, "spec_1_hidden", "1"}, {UNIMOD_Xle__His, "spec_1_position", "Anywhere"}, {UNIMOD_Xle__His, "spec_1_site", "L"}, {UNIMOD_Xle__His, "spec_2_classification", "AA substitution"}, {UNIMOD_Xle__His, "spec_2_hidden", "1"}, {UNIMOD_Xle__His, "spec_2_position", "Anywhere"}, {UNIMOD_Xle__His, "spec_2_site", "I"}, {UNIMOD_Xle__Gln, "approved", "0"}, {UNIMOD_Xle__Gln, "delta_composition", "H(-3) C(-1) N O"}, {UNIMOD_Xle__Gln, "spec_1_classification", "AA substitution"}, {UNIMOD_Xle__Gln, "spec_1_hidden", "1"}, {UNIMOD_Xle__Gln, "spec_1_position", "Anywhere"}, {UNIMOD_Xle__Gln, "spec_1_site", "L"}, {UNIMOD_Xle__Gln, "spec_2_classification", "AA substitution"}, {UNIMOD_Xle__Gln, "spec_2_hidden", "1"}, {UNIMOD_Xle__Gln, "spec_2_position", "Anywhere"}, {UNIMOD_Xle__Gln, "spec_2_site", "I"}, {UNIMOD_Xle__Met, "approved", "0"}, {UNIMOD_Xle__Met, "delta_composition", "H(-2) C(-1) S"}, {UNIMOD_Xle__Met, "spec_1_classification", "AA substitution"}, {UNIMOD_Xle__Met, "spec_1_hidden", "1"}, {UNIMOD_Xle__Met, "spec_1_position", "Anywhere"}, {UNIMOD_Xle__Met, "spec_1_site", "L"}, {UNIMOD_Xle__Met, "spec_2_classification", "AA substitution"}, {UNIMOD_Xle__Met, "spec_2_hidden", "1"}, {UNIMOD_Xle__Met, "spec_2_position", "Anywhere"}, {UNIMOD_Xle__Met, "spec_2_site", "I"}, {UNIMOD_Xle__Arg, "approved", "0"}, {UNIMOD_Xle__Arg, "delta_composition", "H N(3)"}, {UNIMOD_Xle__Arg, "spec_1_classification", "AA substitution"}, {UNIMOD_Xle__Arg, "spec_1_hidden", "1"}, {UNIMOD_Xle__Arg, "spec_1_position", "Anywhere"}, {UNIMOD_Xle__Arg, "spec_1_site", "L"}, {UNIMOD_Xle__Arg, "spec_2_classification", "AA substitution"}, {UNIMOD_Xle__Arg, "spec_2_hidden", "1"}, {UNIMOD_Xle__Arg, "spec_2_position", "Anywhere"}, {UNIMOD_Xle__Arg, "spec_2_site", "I"}, {UNIMOD_Met__Thr, "approved", "0"}, {UNIMOD_Met__Thr, "delta_composition", "H(-2) C(-1) O S(-1)"}, {UNIMOD_Met__Thr, "spec_1_classification", "AA substitution"}, {UNIMOD_Met__Thr, "spec_1_hidden", "1"}, {UNIMOD_Met__Thr, "spec_1_position", "Anywhere"}, {UNIMOD_Met__Thr, "spec_1_site", "M"}, {UNIMOD_Met__Arg, "approved", "0"}, {UNIMOD_Met__Arg, "delta_composition", "H(3) C N(3) S(-1)"}, {UNIMOD_Met__Arg, "spec_1_classification", "AA substitution"}, {UNIMOD_Met__Arg, "spec_1_hidden", "1"}, {UNIMOD_Met__Arg, "spec_1_position", "Anywhere"}, {UNIMOD_Met__Arg, "spec_1_site", "M"}, {UNIMOD_Met__Lys, "approved", "0"}, {UNIMOD_Met__Lys, "delta_composition", "H(3) C N S(-1)"}, {UNIMOD_Met__Lys, "spec_1_classification", "AA substitution"}, {UNIMOD_Met__Lys, "spec_1_hidden", "1"}, {UNIMOD_Met__Lys, "spec_1_position", "Anywhere"}, {UNIMOD_Met__Lys, "spec_1_site", "M"}, {UNIMOD_Met__Xle, "approved", "0"}, {UNIMOD_Met__Xle, "delta_composition", "H(2) C S(-1)"}, {UNIMOD_Met__Xle, "spec_1_classification", "AA substitution"}, {UNIMOD_Met__Xle, "spec_1_hidden", "1"}, {UNIMOD_Met__Xle, "spec_1_position", "Anywhere"}, {UNIMOD_Met__Xle, "spec_1_site", "M"}, {UNIMOD_Met__Val, "approved", "0"}, {UNIMOD_Met__Val, "delta_composition", "S(-1)"}, {UNIMOD_Met__Val, "spec_1_classification", "AA substitution"}, {UNIMOD_Met__Val, "spec_1_hidden", "1"}, {UNIMOD_Met__Val, "spec_1_position", "Anywhere"}, {UNIMOD_Met__Val, "spec_1_site", "M"}, {UNIMOD_Asn__Ser, "approved", "0"}, {UNIMOD_Asn__Ser, "delta_composition", "H(-1) C(-1) N(-1)"}, {UNIMOD_Asn__Ser, "spec_1_classification", "AA substitution"}, {UNIMOD_Asn__Ser, "spec_1_hidden", "1"}, {UNIMOD_Asn__Ser, "spec_1_position", "Anywhere"}, {UNIMOD_Asn__Ser, "spec_1_site", "N"}, {UNIMOD_Asn__Thr, "approved", "0"}, {UNIMOD_Asn__Thr, "delta_composition", "H N(-1)"}, {UNIMOD_Asn__Thr, "spec_1_classification", "AA substitution"}, {UNIMOD_Asn__Thr, "spec_1_hidden", "1"}, {UNIMOD_Asn__Thr, "spec_1_position", "Anywhere"}, {UNIMOD_Asn__Thr, "spec_1_site", "N"}, {UNIMOD_Asn__Lys, "approved", "0"}, {UNIMOD_Asn__Lys, "delta_composition", "H(6) C(2) O(-1)"}, {UNIMOD_Asn__Lys, "spec_1_classification", "AA substitution"}, {UNIMOD_Asn__Lys, "spec_1_hidden", "1"}, {UNIMOD_Asn__Lys, "spec_1_position", "Anywhere"}, {UNIMOD_Asn__Lys, "spec_1_site", "N"}, {UNIMOD_Asn__Tyr, "approved", "0"}, {UNIMOD_Asn__Tyr, "delta_composition", "H(3) C(5) N(-1)"}, {UNIMOD_Asn__Tyr, "spec_1_classification", "AA substitution"}, {UNIMOD_Asn__Tyr, "spec_1_hidden", "1"}, {UNIMOD_Asn__Tyr, "spec_1_position", "Anywhere"}, {UNIMOD_Asn__Tyr, "spec_1_site", "N"}, {UNIMOD_Asn__His, "approved", "0"}, {UNIMOD_Asn__His, "delta_composition", "H C(2) N O(-1)"}, {UNIMOD_Asn__His, "spec_1_classification", "AA substitution"}, {UNIMOD_Asn__His, "spec_1_hidden", "1"}, {UNIMOD_Asn__His, "spec_1_position", "Anywhere"}, {UNIMOD_Asn__His, "spec_1_site", "N"}, {UNIMOD_Asn__Asp, "approved", "0"}, {UNIMOD_Asn__Asp, "delta_composition", "H(-1) N(-1) O"}, {UNIMOD_Asn__Asp, "spec_1_classification", "AA substitution"}, {UNIMOD_Asn__Asp, "spec_1_hidden", "1"}, {UNIMOD_Asn__Asp, "spec_1_position", "Anywhere"}, {UNIMOD_Asn__Asp, "spec_1_site", "N"}, {UNIMOD_Asn__Xle, "approved", "0"}, {UNIMOD_Asn__Xle, "delta_composition", "H(5) C(2) N(-1) O(-1)"}, {UNIMOD_Asn__Xle, "spec_1_classification", "AA substitution"}, {UNIMOD_Asn__Xle, "spec_1_hidden", "1"}, {UNIMOD_Asn__Xle, "spec_1_position", "Anywhere"}, {UNIMOD_Asn__Xle, "spec_1_site", "N"}, {UNIMOD_Pro__Ser, "approved", "0"}, {UNIMOD_Pro__Ser, "delta_composition", "H(-2) C(-2) O"}, {UNIMOD_Pro__Ser, "spec_1_classification", "AA substitution"}, {UNIMOD_Pro__Ser, "spec_1_hidden", "1"}, {UNIMOD_Pro__Ser, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__Ser, "spec_1_site", "P"}, {UNIMOD_Pro__Ala, "approved", "0"}, {UNIMOD_Pro__Ala, "delta_composition", "H(-2) C(-2)"}, {UNIMOD_Pro__Ala, "spec_1_classification", "AA substitution"}, {UNIMOD_Pro__Ala, "spec_1_hidden", "1"}, {UNIMOD_Pro__Ala, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__Ala, "spec_1_site", "P"}, {UNIMOD_Pro__His, "approved", "0"}, {UNIMOD_Pro__His, "delta_composition", "C N(2)"}, {UNIMOD_Pro__His, "spec_1_classification", "AA substitution"}, {UNIMOD_Pro__His, "spec_1_hidden", "1"}, {UNIMOD_Pro__His, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__His, "spec_1_site", "P"}, {UNIMOD_Pro__Gln, "approved", "0"}, {UNIMOD_Pro__Gln, "delta_composition", "H N O"}, {UNIMOD_Pro__Gln, "spec_1_classification", "AA substitution"}, {UNIMOD_Pro__Gln, "spec_1_hidden", "1"}, {UNIMOD_Pro__Gln, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__Gln, "spec_1_site", "P"}, {UNIMOD_Pro__Thr, "approved", "0"}, {UNIMOD_Pro__Thr, "delta_composition", "C(-1) O"}, {UNIMOD_Pro__Thr, "spec_1_classification", "AA substitution"}, {UNIMOD_Pro__Thr, "spec_1_hidden", "1"}, {UNIMOD_Pro__Thr, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__Thr, "spec_1_site", "P"}, {UNIMOD_Pro__Arg, "approved", "0"}, {UNIMOD_Pro__Arg, "delta_composition", "H(5) C N(3)"}, {UNIMOD_Pro__Arg, "spec_1_classification", "AA substitution"}, {UNIMOD_Pro__Arg, "spec_1_hidden", "1"}, {UNIMOD_Pro__Arg, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__Arg, "spec_1_site", "P"}, {UNIMOD_Pro__Xle, "approved", "0"}, {UNIMOD_Pro__Xle, "delta_composition", "H(4) C"}, {UNIMOD_Pro__Xle, "spec_1_classification", "AA substitution"}, {UNIMOD_Pro__Xle, "spec_1_hidden", "1"}, {UNIMOD_Pro__Xle, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__Xle, "spec_1_site", "P"}, {UNIMOD_Gln__Pro, "approved", "0"}, {UNIMOD_Gln__Pro, "delta_composition", "H(-1) N(-1) O(-1)"}, {UNIMOD_Gln__Pro, "spec_1_classification", "AA substitution"}, {UNIMOD_Gln__Pro, "spec_1_hidden", "1"}, {UNIMOD_Gln__Pro, "spec_1_position", "Anywhere"}, {UNIMOD_Gln__Pro, "spec_1_site", "Q"}, {UNIMOD_Gln__Lys, "approved", "0"}, {UNIMOD_Gln__Lys, "delta_composition", "H(4) C O(-1)"}, {UNIMOD_Gln__Lys, "spec_1_classification", "AA substitution"}, {UNIMOD_Gln__Lys, "spec_1_hidden", "1"}, {UNIMOD_Gln__Lys, "spec_1_position", "Anywhere"}, {UNIMOD_Gln__Lys, "spec_1_site", "Q"}, {UNIMOD_Gln__Glu, "approved", "0"}, {UNIMOD_Gln__Glu, "delta_composition", "H(-1) N(-1) O"}, {UNIMOD_Gln__Glu, "spec_1_classification", "AA substitution"}, {UNIMOD_Gln__Glu, "spec_1_hidden", "1"}, {UNIMOD_Gln__Glu, "spec_1_position", "Anywhere"}, {UNIMOD_Gln__Glu, "spec_1_site", "Q"}, {UNIMOD_Gln__His, "approved", "0"}, {UNIMOD_Gln__His, "delta_composition", "H(-1) C N O(-1)"}, {UNIMOD_Gln__His, "spec_1_classification", "AA substitution"}, {UNIMOD_Gln__His, "spec_1_hidden", "1"}, {UNIMOD_Gln__His, "spec_1_position", "Anywhere"}, {UNIMOD_Gln__His, "spec_1_site", "Q"}, {UNIMOD_Gln__Arg, "approved", "0"}, {UNIMOD_Gln__Arg, "delta_composition", "H(4) C N(2) O(-1)"}, {UNIMOD_Gln__Arg, "spec_1_classification", "AA substitution"}, {UNIMOD_Gln__Arg, "spec_1_hidden", "1"}, {UNIMOD_Gln__Arg, "spec_1_position", "Anywhere"}, {UNIMOD_Gln__Arg, "spec_1_site", "Q"}, {UNIMOD_Gln__Xle, "approved", "0"}, {UNIMOD_Gln__Xle, "delta_composition", "H(3) C N(-1) O(-1)"}, {UNIMOD_Gln__Xle, "spec_1_classification", "AA substitution"}, {UNIMOD_Gln__Xle, "spec_1_hidden", "1"}, {UNIMOD_Gln__Xle, "spec_1_position", "Anywhere"}, {UNIMOD_Gln__Xle, "spec_1_site", "Q"}, {UNIMOD_Arg__Ser, "approved", "0"}, {UNIMOD_Arg__Ser, "delta_composition", "H(-7) C(-3) N(-3) O"}, {UNIMOD_Arg__Ser, "spec_1_classification", "AA substitution"}, {UNIMOD_Arg__Ser, "spec_1_hidden", "1"}, {UNIMOD_Arg__Ser, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__Ser, "spec_1_site", "R"}, {UNIMOD_Arg__Trp, "approved", "0"}, {UNIMOD_Arg__Trp, "delta_composition", "H(-2) C(5) N(-2)"}, {UNIMOD_Arg__Trp, "spec_1_classification", "AA substitution"}, {UNIMOD_Arg__Trp, "spec_1_hidden", "1"}, {UNIMOD_Arg__Trp, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__Trp, "spec_1_site", "R"}, {UNIMOD_Arg__Thr, "approved", "0"}, {UNIMOD_Arg__Thr, "delta_composition", "H(-5) C(-2) N(-3) O"}, {UNIMOD_Arg__Thr, "spec_1_classification", "AA substitution"}, {UNIMOD_Arg__Thr, "spec_1_hidden", "1"}, {UNIMOD_Arg__Thr, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__Thr, "spec_1_site", "R"}, {UNIMOD_Arg__Pro, "approved", "0"}, {UNIMOD_Arg__Pro, "delta_composition", "H(-5) C(-1) N(-3)"}, {UNIMOD_Arg__Pro, "spec_1_classification", "AA substitution"}, {UNIMOD_Arg__Pro, "spec_1_hidden", "1"}, {UNIMOD_Arg__Pro, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__Pro, "spec_1_site", "R"}, {UNIMOD_Arg__Lys, "approved", "0"}, {UNIMOD_Arg__Lys, "delta_composition", "N(-2)"}, {UNIMOD_Arg__Lys, "spec_1_classification", "AA substitution"}, {UNIMOD_Arg__Lys, "spec_1_hidden", "1"}, {UNIMOD_Arg__Lys, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__Lys, "spec_1_site", "R"}, {UNIMOD_Arg__His, "approved", "0"}, {UNIMOD_Arg__His, "delta_composition", "H(-5) N(-1)"}, {UNIMOD_Arg__His, "spec_1_classification", "AA substitution"}, {UNIMOD_Arg__His, "spec_1_hidden", "1"}, {UNIMOD_Arg__His, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__His, "spec_1_site", "R"}, {UNIMOD_Arg__Gln, "approved", "0"}, {UNIMOD_Arg__Gln, "delta_composition", "H(-4) C(-1) N(-2) O"}, {UNIMOD_Arg__Gln, "spec_1_classification", "AA substitution"}, {UNIMOD_Arg__Gln, "spec_1_hidden", "1"}, {UNIMOD_Arg__Gln, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__Gln, "spec_1_site", "R"}, {UNIMOD_Arg__Met, "approved", "0"}, {UNIMOD_Arg__Met, "delta_composition", "H(-3) C(-1) N(-3) S"}, {UNIMOD_Arg__Met, "spec_1_classification", "AA substitution"}, {UNIMOD_Arg__Met, "spec_1_hidden", "1"}, {UNIMOD_Arg__Met, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__Met, "spec_1_site", "R"}, {UNIMOD_Arg__Cys, "approved", "0"}, {UNIMOD_Arg__Cys, "delta_composition", "H(-7) C(-3) N(-3) S"}, {UNIMOD_Arg__Cys, "spec_1_classification", "AA substitution"}, {UNIMOD_Arg__Cys, "spec_1_hidden", "1"}, {UNIMOD_Arg__Cys, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__Cys, "spec_1_site", "R"}, {UNIMOD_Arg__Xle, "approved", "0"}, {UNIMOD_Arg__Xle, "delta_composition", "H(-1) N(-3)"}, {UNIMOD_Arg__Xle, "spec_1_classification", "AA substitution"}, {UNIMOD_Arg__Xle, "spec_1_hidden", "1"}, {UNIMOD_Arg__Xle, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__Xle, "spec_1_site", "R"}, {UNIMOD_Arg__Gly, "approved", "0"}, {UNIMOD_Arg__Gly, "delta_composition", "H(-9) C(-4) N(-3)"}, {UNIMOD_Arg__Gly, "spec_1_classification", "AA substitution"}, {UNIMOD_Arg__Gly, "spec_1_hidden", "1"}, {UNIMOD_Arg__Gly, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__Gly, "spec_1_site", "R"}, {UNIMOD_Ser__Phe, "approved", "0"}, {UNIMOD_Ser__Phe, "delta_composition", "H(4) C(6) O(-1)"}, {UNIMOD_Ser__Phe, "spec_1_classification", "AA substitution"}, {UNIMOD_Ser__Phe, "spec_1_hidden", "1"}, {UNIMOD_Ser__Phe, "spec_1_position", "Anywhere"}, {UNIMOD_Ser__Phe, "spec_1_site", "S"}, {UNIMOD_Ser__Ala, "approved", "0"}, {UNIMOD_Ser__Ala, "delta_composition", "O(-1)"}, {UNIMOD_Ser__Ala, "spec_1_classification", "AA substitution"}, {UNIMOD_Ser__Ala, "spec_1_hidden", "1"}, {UNIMOD_Ser__Ala, "spec_1_position", "Anywhere"}, {UNIMOD_Ser__Ala, "spec_1_site", "S"}, {UNIMOD_Ser__Trp, "approved", "0"}, {UNIMOD_Ser__Trp, "delta_composition", "H(5) C(8) N O(-1)"}, {UNIMOD_Ser__Trp, "spec_1_classification", "AA substitution"}, {UNIMOD_Ser__Trp, "spec_1_hidden", "1"}, {UNIMOD_Ser__Trp, "spec_1_position", "Anywhere"}, {UNIMOD_Ser__Trp, "spec_1_site", "S"}, {UNIMOD_Ser__Thr, "approved", "0"}, {UNIMOD_Ser__Thr, "delta_composition", "H(2) C"}, {UNIMOD_Ser__Thr, "spec_1_classification", "AA substitution"}, {UNIMOD_Ser__Thr, "spec_1_hidden", "1"}, {UNIMOD_Ser__Thr, "spec_1_position", "Anywhere"}, {UNIMOD_Ser__Thr, "spec_1_site", "S"}, {UNIMOD_Ser__Asn, "approved", "0"}, {UNIMOD_Ser__Asn, "delta_composition", "H C N"}, {UNIMOD_Ser__Asn, "spec_1_classification", "AA substitution"}, {UNIMOD_Ser__Asn, "spec_1_hidden", "1"}, {UNIMOD_Ser__Asn, "spec_1_position", "Anywhere"}, {UNIMOD_Ser__Asn, "spec_1_site", "S"}, {UNIMOD_Ser__Pro, "approved", "0"}, {UNIMOD_Ser__Pro, "delta_composition", "H(2) C(2) O(-1)"}, {UNIMOD_Ser__Pro, "spec_1_classification", "AA substitution"}, {UNIMOD_Ser__Pro, "spec_1_hidden", "1"}, {UNIMOD_Ser__Pro, "spec_1_position", "Anywhere"}, {UNIMOD_Ser__Pro, "spec_1_site", "S"}, {UNIMOD_Ser__Tyr, "approved", "0"}, {UNIMOD_Ser__Tyr, "delta_composition", "H(4) C(6)"}, {UNIMOD_Ser__Tyr, "spec_1_classification", "AA substitution"}, {UNIMOD_Ser__Tyr, "spec_1_hidden", "1"}, {UNIMOD_Ser__Tyr, "spec_1_position", "Anywhere"}, {UNIMOD_Ser__Tyr, "spec_1_site", "S"}, {UNIMOD_Ser__Cys, "approved", "0"}, {UNIMOD_Ser__Cys, "delta_composition", "O(-1) S"}, {UNIMOD_Ser__Cys, "spec_1_classification", "AA substitution"}, {UNIMOD_Ser__Cys, "spec_1_hidden", "1"}, {UNIMOD_Ser__Cys, "spec_1_position", "Anywhere"}, {UNIMOD_Ser__Cys, "spec_1_site", "S"}, {UNIMOD_Ser__Arg, "approved", "0"}, {UNIMOD_Ser__Arg, "delta_composition", "H(7) C(3) N(3) O(-1)"}, {UNIMOD_Ser__Arg, "spec_1_classification", "AA substitution"}, {UNIMOD_Ser__Arg, "spec_1_hidden", "1"}, {UNIMOD_Ser__Arg, "spec_1_position", "Anywhere"}, {UNIMOD_Ser__Arg, "spec_1_site", "S"}, {UNIMOD_Ser__Xle, "approved", "0"}, {UNIMOD_Ser__Xle, "delta_composition", "H(6) C(3) O(-1)"}, {UNIMOD_Ser__Xle, "spec_1_classification", "AA substitution"}, {UNIMOD_Ser__Xle, "spec_1_hidden", "1"}, {UNIMOD_Ser__Xle, "spec_1_position", "Anywhere"}, {UNIMOD_Ser__Xle, "spec_1_site", "S"}, {UNIMOD_Ser__Gly, "approved", "0"}, {UNIMOD_Ser__Gly, "delta_composition", "H(-2) C(-1) O(-1)"}, {UNIMOD_Ser__Gly, "spec_1_classification", "AA substitution"}, {UNIMOD_Ser__Gly, "spec_1_hidden", "1"}, {UNIMOD_Ser__Gly, "spec_1_position", "Anywhere"}, {UNIMOD_Ser__Gly, "spec_1_site", "S"}, {UNIMOD_Thr__Ser, "approved", "0"}, {UNIMOD_Thr__Ser, "delta_composition", "H(-2) C(-1)"}, {UNIMOD_Thr__Ser, "spec_1_classification", "AA substitution"}, {UNIMOD_Thr__Ser, "spec_1_hidden", "1"}, {UNIMOD_Thr__Ser, "spec_1_position", "Anywhere"}, {UNIMOD_Thr__Ser, "spec_1_site", "T"}, {UNIMOD_Thr__Ala, "approved", "0"}, {UNIMOD_Thr__Ala, "delta_composition", "H(-2) C(-1) O(-1)"}, {UNIMOD_Thr__Ala, "spec_1_classification", "AA substitution"}, {UNIMOD_Thr__Ala, "spec_1_hidden", "1"}, {UNIMOD_Thr__Ala, "spec_1_position", "Anywhere"}, {UNIMOD_Thr__Ala, "spec_1_site", "T"}, {UNIMOD_Thr__Asn, "approved", "0"}, {UNIMOD_Thr__Asn, "delta_composition", "H(-1) N"}, {UNIMOD_Thr__Asn, "spec_1_classification", "AA substitution"}, {UNIMOD_Thr__Asn, "spec_1_hidden", "1"}, {UNIMOD_Thr__Asn, "spec_1_position", "Anywhere"}, {UNIMOD_Thr__Asn, "spec_1_site", "T"}, {UNIMOD_Thr__Lys, "approved", "0"}, {UNIMOD_Thr__Lys, "delta_composition", "H(5) C(2) N O(-1)"}, {UNIMOD_Thr__Lys, "spec_1_classification", "AA substitution"}, {UNIMOD_Thr__Lys, "spec_1_hidden", "1"}, {UNIMOD_Thr__Lys, "spec_1_position", "Anywhere"}, {UNIMOD_Thr__Lys, "spec_1_site", "T"}, {UNIMOD_Thr__Pro, "approved", "0"}, {UNIMOD_Thr__Pro, "delta_composition", "C O(-1)"}, {UNIMOD_Thr__Pro, "spec_1_classification", "AA substitution"}, {UNIMOD_Thr__Pro, "spec_1_hidden", "1"}, {UNIMOD_Thr__Pro, "spec_1_position", "Anywhere"}, {UNIMOD_Thr__Pro, "spec_1_site", "T"}, {UNIMOD_Thr__Met, "approved", "0"}, {UNIMOD_Thr__Met, "delta_composition", "H(2) C O(-1) S"}, {UNIMOD_Thr__Met, "spec_1_classification", "AA substitution"}, {UNIMOD_Thr__Met, "spec_1_hidden", "1"}, {UNIMOD_Thr__Met, "spec_1_position", "Anywhere"}, {UNIMOD_Thr__Met, "spec_1_site", "T"}, {UNIMOD_Thr__Xle, "approved", "0"}, {UNIMOD_Thr__Xle, "delta_composition", "H(4) C(2) O(-1)"}, {UNIMOD_Thr__Xle, "spec_1_classification", "AA substitution"}, {UNIMOD_Thr__Xle, "spec_1_hidden", "1"}, {UNIMOD_Thr__Xle, "spec_1_position", "Anywhere"}, {UNIMOD_Thr__Xle, "spec_1_site", "T"}, {UNIMOD_Thr__Arg, "approved", "0"}, {UNIMOD_Thr__Arg, "delta_composition", "H(5) C(2) N(3) O(-1)"}, {UNIMOD_Thr__Arg, "spec_1_classification", "AA substitution"}, {UNIMOD_Thr__Arg, "spec_1_hidden", "1"}, {UNIMOD_Thr__Arg, "spec_1_position", "Anywhere"}, {UNIMOD_Thr__Arg, "spec_1_site", "T"}, {UNIMOD_Val__Phe, "approved", "0"}, {UNIMOD_Val__Phe, "delta_composition", "C(4)"}, {UNIMOD_Val__Phe, "spec_1_classification", "AA substitution"}, {UNIMOD_Val__Phe, "spec_1_hidden", "1"}, {UNIMOD_Val__Phe, "spec_1_position", "Anywhere"}, {UNIMOD_Val__Phe, "spec_1_site", "V"}, {UNIMOD_Val__Ala, "approved", "0"}, {UNIMOD_Val__Ala, "delta_composition", "H(-4) C(-2)"}, {UNIMOD_Val__Ala, "spec_1_classification", "AA substitution"}, {UNIMOD_Val__Ala, "spec_1_hidden", "1"}, {UNIMOD_Val__Ala, "spec_1_position", "Anywhere"}, {UNIMOD_Val__Ala, "spec_1_site", "V"}, {UNIMOD_Val__Glu, "approved", "0"}, {UNIMOD_Val__Glu, "delta_composition", "H(-2) O(2)"}, {UNIMOD_Val__Glu, "spec_1_classification", "AA substitution"}, {UNIMOD_Val__Glu, "spec_1_hidden", "1"}, {UNIMOD_Val__Glu, "spec_1_position", "Anywhere"}, {UNIMOD_Val__Glu, "spec_1_site", "V"}, {UNIMOD_Val__Met, "approved", "0"}, {UNIMOD_Val__Met, "delta_composition", "S"}, {UNIMOD_Val__Met, "spec_1_classification", "AA substitution"}, {UNIMOD_Val__Met, "spec_1_hidden", "1"}, {UNIMOD_Val__Met, "spec_1_position", "Anywhere"}, {UNIMOD_Val__Met, "spec_1_site", "V"}, {UNIMOD_Val__Asp, "approved", "0"}, {UNIMOD_Val__Asp, "delta_composition", "H(-4) C(-1) O(2)"}, {UNIMOD_Val__Asp, "spec_1_classification", "AA substitution"}, {UNIMOD_Val__Asp, "spec_1_hidden", "1"}, {UNIMOD_Val__Asp, "spec_1_position", "Anywhere"}, {UNIMOD_Val__Asp, "spec_1_site", "V"}, {UNIMOD_Val__Xle, "approved", "0"}, {UNIMOD_Val__Xle, "delta_composition", "H(2) C"}, {UNIMOD_Val__Xle, "spec_1_classification", "AA substitution"}, {UNIMOD_Val__Xle, "spec_1_hidden", "1"}, {UNIMOD_Val__Xle, "spec_1_position", "Anywhere"}, {UNIMOD_Val__Xle, "spec_1_site", "V"}, {UNIMOD_Val__Gly, "approved", "0"}, {UNIMOD_Val__Gly, "delta_composition", "H(-6) C(-3)"}, {UNIMOD_Val__Gly, "spec_1_classification", "AA substitution"}, {UNIMOD_Val__Gly, "spec_1_hidden", "1"}, {UNIMOD_Val__Gly, "spec_1_position", "Anywhere"}, {UNIMOD_Val__Gly, "spec_1_site", "V"}, {UNIMOD_Trp__Ser, "approved", "0"}, {UNIMOD_Trp__Ser, "delta_composition", "H(-5) C(-8) N(-1) O"}, {UNIMOD_Trp__Ser, "spec_1_classification", "AA substitution"}, {UNIMOD_Trp__Ser, "spec_1_hidden", "1"}, {UNIMOD_Trp__Ser, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__Ser, "spec_1_site", "W"}, {UNIMOD_Trp__Cys, "approved", "0"}, {UNIMOD_Trp__Cys, "delta_composition", "H(-5) C(-8) N(-1) S"}, {UNIMOD_Trp__Cys, "spec_1_classification", "AA substitution"}, {UNIMOD_Trp__Cys, "spec_1_hidden", "1"}, {UNIMOD_Trp__Cys, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__Cys, "spec_1_site", "W"}, {UNIMOD_Trp__Arg, "approved", "0"}, {UNIMOD_Trp__Arg, "delta_composition", "H(2) C(-5) N(2)"}, {UNIMOD_Trp__Arg, "spec_1_classification", "AA substitution"}, {UNIMOD_Trp__Arg, "spec_1_hidden", "1"}, {UNIMOD_Trp__Arg, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__Arg, "spec_1_site", "W"}, {UNIMOD_Trp__Gly, "approved", "0"}, {UNIMOD_Trp__Gly, "delta_composition", "H(-7) C(-9) N(-1)"}, {UNIMOD_Trp__Gly, "spec_1_classification", "AA substitution"}, {UNIMOD_Trp__Gly, "spec_1_hidden", "1"}, {UNIMOD_Trp__Gly, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__Gly, "spec_1_site", "W"}, {UNIMOD_Trp__Xle, "approved", "0"}, {UNIMOD_Trp__Xle, "delta_composition", "H C(-5) N(-1)"}, {UNIMOD_Trp__Xle, "spec_1_classification", "AA substitution"}, {UNIMOD_Trp__Xle, "spec_1_hidden", "1"}, {UNIMOD_Trp__Xle, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__Xle, "spec_1_site", "W"}, {UNIMOD_Tyr__Phe, "approved", "0"}, {UNIMOD_Tyr__Phe, "delta_composition", "O(-1)"}, {UNIMOD_Tyr__Phe, "spec_1_classification", "AA substitution"}, {UNIMOD_Tyr__Phe, "spec_1_hidden", "1"}, {UNIMOD_Tyr__Phe, "spec_1_position", "Anywhere"}, {UNIMOD_Tyr__Phe, "spec_1_site", "Y"}, {UNIMOD_Tyr__Ser, "approved", "0"}, {UNIMOD_Tyr__Ser, "delta_composition", "H(-4) C(-6)"}, {UNIMOD_Tyr__Ser, "spec_1_classification", "AA substitution"}, {UNIMOD_Tyr__Ser, "spec_1_hidden", "1"}, {UNIMOD_Tyr__Ser, "spec_1_position", "Anywhere"}, {UNIMOD_Tyr__Ser, "spec_1_site", "Y"}, {UNIMOD_Tyr__Asn, "approved", "0"}, {UNIMOD_Tyr__Asn, "delta_composition", "H(-3) C(-5) N"}, {UNIMOD_Tyr__Asn, "spec_1_classification", "AA substitution"}, {UNIMOD_Tyr__Asn, "spec_1_hidden", "1"}, {UNIMOD_Tyr__Asn, "spec_1_position", "Anywhere"}, {UNIMOD_Tyr__Asn, "spec_1_site", "Y"}, {UNIMOD_Tyr__His, "approved", "0"}, {UNIMOD_Tyr__His, "delta_composition", "H(-2) C(-3) N(2) O(-1)"}, {UNIMOD_Tyr__His, "spec_1_classification", "AA substitution"}, {UNIMOD_Tyr__His, "spec_1_hidden", "1"}, {UNIMOD_Tyr__His, "spec_1_position", "Anywhere"}, {UNIMOD_Tyr__His, "spec_1_site", "Y"}, {UNIMOD_Tyr__Asp, "approved", "0"}, {UNIMOD_Tyr__Asp, "delta_composition", "H(-4) C(-5) O"}, {UNIMOD_Tyr__Asp, "spec_1_classification", "AA substitution"}, {UNIMOD_Tyr__Asp, "spec_1_hidden", "1"}, {UNIMOD_Tyr__Asp, "spec_1_position", "Anywhere"}, {UNIMOD_Tyr__Asp, "spec_1_site", "Y"}, {UNIMOD_Tyr__Cys, "approved", "0"}, {UNIMOD_Tyr__Cys, "delta_composition", "H(-4) C(-6) O(-1) S"}, {UNIMOD_Tyr__Cys, "spec_1_classification", "AA substitution"}, {UNIMOD_Tyr__Cys, "spec_1_hidden", "1"}, {UNIMOD_Tyr__Cys, "spec_1_position", "Anywhere"}, {UNIMOD_Tyr__Cys, "spec_1_site", "Y"}, {UNIMOD_BDMAPP, "approved", "0"}, {UNIMOD_BDMAPP, "delta_composition", "H(12) C(11) N O Br"}, {UNIMOD_BDMAPP, "spec_1_classification", "Artefact"}, {UNIMOD_BDMAPP, "spec_1_hidden", "1"}, {UNIMOD_BDMAPP, "spec_1_position", "Anywhere"}, {UNIMOD_BDMAPP, "spec_1_site", "H"}, {UNIMOD_BDMAPP, "spec_2_classification", "Chemical derivative"}, {UNIMOD_BDMAPP, "spec_2_hidden", "1"}, {UNIMOD_BDMAPP, "spec_2_position", "Anywhere"}, {UNIMOD_BDMAPP, "spec_2_site", "K"}, {UNIMOD_BDMAPP, "spec_3_classification", "Chemical derivative"}, {UNIMOD_BDMAPP, "spec_3_hidden", "1"}, {UNIMOD_BDMAPP, "spec_3_position", "Protein N-term"}, {UNIMOD_BDMAPP, "spec_3_site", "N-term"}, {UNIMOD_BDMAPP, "spec_4_classification", "Artefact"}, {UNIMOD_BDMAPP, "spec_4_hidden", "1"}, {UNIMOD_BDMAPP, "spec_4_position", "Anywhere"}, {UNIMOD_BDMAPP, "spec_4_site", "Y"}, {UNIMOD_BDMAPP, "spec_5_classification", "Artefact"}, {UNIMOD_BDMAPP, "spec_5_hidden", "1"}, {UNIMOD_BDMAPP, "spec_5_position", "Anywhere"}, {UNIMOD_BDMAPP, "spec_5_site", "W"}, {UNIMOD_NA_LNO2, "approved", "0"}, {UNIMOD_NA_LNO2, "delta_composition", "H(31) C(18) N O(4)"}, {UNIMOD_NA_LNO2, "spec_1_classification", "Post-translational"}, {UNIMOD_NA_LNO2, "spec_1_hidden", "1"}, {UNIMOD_NA_LNO2, "spec_1_position", "Anywhere"}, {UNIMOD_NA_LNO2, "spec_1_site", "C"}, {UNIMOD_NA_LNO2, "spec_2_classification", "Post-translational"}, {UNIMOD_NA_LNO2, "spec_2_hidden", "1"}, {UNIMOD_NA_LNO2, "spec_2_position", "Anywhere"}, {UNIMOD_NA_LNO2, "spec_2_site", "H"}, {UNIMOD_NA_OA_NO2, "approved", "0"}, {UNIMOD_NA_OA_NO2, "delta_composition", "H(33) C(18) N O(4)"}, {UNIMOD_NA_OA_NO2, "spec_1_classification", "Post-translational"}, {UNIMOD_NA_OA_NO2, "spec_1_hidden", "1"}, {UNIMOD_NA_OA_NO2, "spec_1_position", "Anywhere"}, {UNIMOD_NA_OA_NO2, "spec_1_site", "C"}, {UNIMOD_NA_OA_NO2, "spec_2_classification", "Post-translational"}, {UNIMOD_NA_OA_NO2, "spec_2_hidden", "1"}, {UNIMOD_NA_OA_NO2, "spec_2_position", "Anywhere"}, {UNIMOD_NA_OA_NO2, "spec_2_site", "H"}, {UNIMOD_ICPL_2H_4_, "approved", "0"}, {UNIMOD_ICPL_2H_4_, "delta_composition", "H(-1) 2H(4) C(6) N O"}, {UNIMOD_ICPL_2H_4_, "spec_1_classification", "Isotopic label"}, {UNIMOD_ICPL_2H_4_, "spec_1_hidden", "0"}, {UNIMOD_ICPL_2H_4_, "spec_1_position", "Anywhere"}, {UNIMOD_ICPL_2H_4_, "spec_1_site", "K"}, {UNIMOD_ICPL_2H_4_, "spec_2_classification", "Isotopic label"}, {UNIMOD_ICPL_2H_4_, "spec_2_hidden", "0"}, {UNIMOD_ICPL_2H_4_, "spec_2_position", "Protein N-term"}, {UNIMOD_ICPL_2H_4_, "spec_2_site", "N-term"}, {UNIMOD_ICPL_2H_4_, "spec_3_classification", "Isotopic label"}, {UNIMOD_ICPL_2H_4_, "spec_3_hidden", "1"}, {UNIMOD_ICPL_2H_4_, "spec_3_position", "Any N-term"}, {UNIMOD_ICPL_2H_4_, "spec_3_site", "N-term"}, {UNIMOD_Label_13C_6_15N_1_, "approved", "1"}, {UNIMOD_Label_13C_6_15N_1_, "delta_composition", "C(-6) 13C(6) N(-1) 15N"}, {UNIMOD_Label_13C_6_15N_1_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_6_15N_1_, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_6_15N_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_6_15N_1_, "spec_1_site", "L"}, {UNIMOD_Label_13C_6_15N_1_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Label_13C_6_15N_1_, "spec_2_hidden", "1"}, {UNIMOD_Label_13C_6_15N_1_, "spec_2_position", "Anywhere"}, {UNIMOD_Label_13C_6_15N_1_, "spec_2_site", "I"}, {UNIMOD_Label_2H_9_13C_6_15N_2_, "approved", "0"}, {UNIMOD_Label_2H_9_13C_6_15N_2_, "delta_composition", "H(-9) 2H(9) C(-6) 13C(6) N(-2) 15N(2)"}, {UNIMOD_Label_2H_9_13C_6_15N_2_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_2H_9_13C_6_15N_2_, "spec_1_hidden", "1"}, {UNIMOD_Label_2H_9_13C_6_15N_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_2H_9_13C_6_15N_2_, "spec_1_site", "K"}, {UNIMOD_NIC, "approved", "0"}, {UNIMOD_NIC, "delta_composition", "H(3) C(6) N O"}, {UNIMOD_NIC, "spec_1_classification", "Isotopic label"}, {UNIMOD_NIC, "spec_1_hidden", "1"}, {UNIMOD_NIC, "spec_1_position", "Any N-term"}, {UNIMOD_NIC, "spec_1_site", "N-term"}, {UNIMOD_NIC, "spec_2_classification", "Isotopic label"}, {UNIMOD_NIC, "spec_2_hidden", "1"}, {UNIMOD_NIC, "spec_2_position", "Anywhere"}, {UNIMOD_NIC, "spec_2_site", "K"}, {UNIMOD_dNIC, "approved", "0"}, {UNIMOD_dNIC, "delta_composition", "H 2H(3) C(6) N O"}, {UNIMOD_dNIC, "spec_1_classification", "Isotopic label"}, {UNIMOD_dNIC, "spec_1_hidden", "1"}, {UNIMOD_dNIC, "spec_1_position", "Any N-term"}, {UNIMOD_dNIC, "spec_1_site", "N-term"}, {UNIMOD_dNIC, "spec_2_classification", "Isotopic label"}, {UNIMOD_dNIC, "spec_2_hidden", "1"}, {UNIMOD_dNIC, "spec_2_position", "Anywhere"}, {UNIMOD_dNIC, "spec_2_site", "K"}, {UNIMOD_HNE_Delta_H_2_O, "approved", "0"}, {UNIMOD_HNE_Delta_H_2_O, "delta_composition", "H(14) C(9) O"}, {UNIMOD_HNE_Delta_H_2_O, "spec_1_classification", "Chemical derivative"}, {UNIMOD_HNE_Delta_H_2_O, "spec_1_hidden", "1"}, {UNIMOD_HNE_Delta_H_2_O, "spec_1_position", "Anywhere"}, {UNIMOD_HNE_Delta_H_2_O, "spec_1_site", "C"}, {UNIMOD_HNE_Delta_H_2_O, "spec_2_classification", "Chemical derivative"}, {UNIMOD_HNE_Delta_H_2_O, "spec_2_hidden", "1"}, {UNIMOD_HNE_Delta_H_2_O, "spec_2_position", "Anywhere"}, {UNIMOD_HNE_Delta_H_2_O, "spec_2_site", "H"}, {UNIMOD_HNE_Delta_H_2_O, "spec_3_classification", "Chemical derivative"}, {UNIMOD_HNE_Delta_H_2_O, "spec_3_hidden", "1"}, {UNIMOD_HNE_Delta_H_2_O, "spec_3_position", "Anywhere"}, {UNIMOD_HNE_Delta_H_2_O, "spec_3_site", "K"}, {UNIMOD_4_ONE, "approved", "0"}, {UNIMOD_4_ONE, "delta_composition", "H(14) C(9) O(2)"}, {UNIMOD_4_ONE, "spec_1_classification", "Chemical derivative"}, {UNIMOD_4_ONE, "spec_1_hidden", "1"}, {UNIMOD_4_ONE, "spec_1_position", "Anywhere"}, {UNIMOD_4_ONE, "spec_1_site", "C"}, {UNIMOD_4_ONE, "spec_2_classification", "Chemical derivative"}, {UNIMOD_4_ONE, "spec_2_hidden", "1"}, {UNIMOD_4_ONE, "spec_2_position", "Anywhere"}, {UNIMOD_4_ONE, "spec_2_site", "H"}, {UNIMOD_4_ONE, "spec_3_classification", "Chemical derivative"}, {UNIMOD_4_ONE, "spec_3_hidden", "1"}, {UNIMOD_4_ONE, "spec_3_position", "Anywhere"}, {UNIMOD_4_ONE, "spec_3_site", "K"}, {UNIMOD_O_Dimethylphosphate, "approved", "0"}, {UNIMOD_O_Dimethylphosphate, "delta_composition", "H(5) C(2) O(3) P"}, {UNIMOD_O_Dimethylphosphate, "spec_1_classification", "Chemical derivative"}, {UNIMOD_O_Dimethylphosphate, "spec_1_hidden", "1"}, {UNIMOD_O_Dimethylphosphate, "spec_1_position", "Anywhere"}, {UNIMOD_O_Dimethylphosphate, "spec_1_site", "S"}, {UNIMOD_O_Dimethylphosphate, "spec_2_classification", "Chemical derivative"}, {UNIMOD_O_Dimethylphosphate, "spec_2_hidden", "1"}, {UNIMOD_O_Dimethylphosphate, "spec_2_position", "Anywhere"}, {UNIMOD_O_Dimethylphosphate, "spec_2_site", "T"}, {UNIMOD_O_Dimethylphosphate, "spec_3_classification", "Chemical derivative"}, {UNIMOD_O_Dimethylphosphate, "spec_3_hidden", "1"}, {UNIMOD_O_Dimethylphosphate, "spec_3_position", "Anywhere"}, {UNIMOD_O_Dimethylphosphate, "spec_3_site", "Y"}, {UNIMOD_O_Methylphosphate, "approved", "0"}, {UNIMOD_O_Methylphosphate, "delta_composition", "H(3) C O(3) P"}, {UNIMOD_O_Methylphosphate, "spec_1_classification", "Chemical derivative"}, {UNIMOD_O_Methylphosphate, "spec_1_hidden", "1"}, {UNIMOD_O_Methylphosphate, "spec_1_position", "Anywhere"}, {UNIMOD_O_Methylphosphate, "spec_1_site", "S"}, {UNIMOD_O_Methylphosphate, "spec_2_classification", "Chemical derivative"}, {UNIMOD_O_Methylphosphate, "spec_2_hidden", "1"}, {UNIMOD_O_Methylphosphate, "spec_2_position", "Anywhere"}, {UNIMOD_O_Methylphosphate, "spec_2_site", "T"}, {UNIMOD_O_Methylphosphate, "spec_3_classification", "Chemical derivative"}, {UNIMOD_O_Methylphosphate, "spec_3_hidden", "1"}, {UNIMOD_O_Methylphosphate, "spec_3_position", "Anywhere"}, {UNIMOD_O_Methylphosphate, "spec_3_site", "Y"}, {UNIMOD_Diethylphosphate, "approved", "0"}, {UNIMOD_Diethylphosphate, "delta_composition", "H(9) C(4) O(3) P"}, {UNIMOD_Diethylphosphate, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Diethylphosphate, "spec_1_hidden", "1"}, {UNIMOD_Diethylphosphate, "spec_1_position", "Anywhere"}, {UNIMOD_Diethylphosphate, "spec_1_site", "S"}, {UNIMOD_Diethylphosphate, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Diethylphosphate, "spec_2_hidden", "1"}, {UNIMOD_Diethylphosphate, "spec_2_position", "Anywhere"}, {UNIMOD_Diethylphosphate, "spec_2_site", "T"}, {UNIMOD_Diethylphosphate, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Diethylphosphate, "spec_3_hidden", "1"}, {UNIMOD_Diethylphosphate, "spec_3_position", "Anywhere"}, {UNIMOD_Diethylphosphate, "spec_3_site", "Y"}, {UNIMOD_Diethylphosphate, "spec_4_classification", "Chemical derivative"}, {UNIMOD_Diethylphosphate, "spec_4_hidden", "1"}, {UNIMOD_Diethylphosphate, "spec_4_position", "Anywhere"}, {UNIMOD_Diethylphosphate, "spec_4_site", "K"}, {UNIMOD_Diethylphosphate, "spec_5_classification", "Chemical derivative"}, {UNIMOD_Diethylphosphate, "spec_5_hidden", "1"}, {UNIMOD_Diethylphosphate, "spec_5_position", "Anywhere"}, {UNIMOD_Diethylphosphate, "spec_5_site", "C"}, {UNIMOD_Diethylphosphate, "spec_6_classification", "Chemical derivative"}, {UNIMOD_Diethylphosphate, "spec_6_hidden", "1"}, {UNIMOD_Diethylphosphate, "spec_6_position", "Anywhere"}, {UNIMOD_Diethylphosphate, "spec_6_site", "H"}, {UNIMOD_Diethylphosphate, "spec_7_classification", "Chemical derivative"}, {UNIMOD_Diethylphosphate, "spec_7_hidden", "1"}, {UNIMOD_Diethylphosphate, "spec_7_position", "Any N-term"}, {UNIMOD_Diethylphosphate, "spec_7_site", "N-term"}, {UNIMOD_Ethylphosphate, "approved", "0"}, {UNIMOD_Ethylphosphate, "delta_composition", "H(5) C(2) O(3) P"}, {UNIMOD_Ethylphosphate, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Ethylphosphate, "spec_1_hidden", "1"}, {UNIMOD_Ethylphosphate, "spec_1_position", "Anywhere"}, {UNIMOD_Ethylphosphate, "spec_1_site", "S"}, {UNIMOD_Ethylphosphate, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Ethylphosphate, "spec_2_hidden", "1"}, {UNIMOD_Ethylphosphate, "spec_2_position", "Anywhere"}, {UNIMOD_Ethylphosphate, "spec_2_site", "T"}, {UNIMOD_Ethylphosphate, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Ethylphosphate, "spec_3_hidden", "1"}, {UNIMOD_Ethylphosphate, "spec_3_position", "Anywhere"}, {UNIMOD_Ethylphosphate, "spec_3_site", "Y"}, {UNIMOD_Ethylphosphate, "spec_4_classification", "Chemical derivative"}, {UNIMOD_Ethylphosphate, "spec_4_hidden", "1"}, {UNIMOD_Ethylphosphate, "spec_4_position", "Anywhere"}, {UNIMOD_Ethylphosphate, "spec_4_site", "K"}, {UNIMOD_Ethylphosphate, "spec_5_classification", "Chemical derivative"}, {UNIMOD_Ethylphosphate, "spec_5_hidden", "1"}, {UNIMOD_Ethylphosphate, "spec_5_position", "Any N-term"}, {UNIMOD_Ethylphosphate, "spec_5_site", "N-term"}, {UNIMOD_O_pinacolylmethylphosphonate, "approved", "0"}, {UNIMOD_O_pinacolylmethylphosphonate, "delta_composition", "H(15) C(7) O(2) P"}, {UNIMOD_O_pinacolylmethylphosphonate, "spec_1_classification", "Chemical derivative"}, {UNIMOD_O_pinacolylmethylphosphonate, "spec_1_hidden", "1"}, {UNIMOD_O_pinacolylmethylphosphonate, "spec_1_position", "Anywhere"}, {UNIMOD_O_pinacolylmethylphosphonate, "spec_1_site", "S"}, {UNIMOD_O_pinacolylmethylphosphonate, "spec_2_classification", "Chemical derivative"}, {UNIMOD_O_pinacolylmethylphosphonate, "spec_2_hidden", "1"}, {UNIMOD_O_pinacolylmethylphosphonate, "spec_2_position", "Anywhere"}, {UNIMOD_O_pinacolylmethylphosphonate, "spec_2_site", "T"}, {UNIMOD_O_pinacolylmethylphosphonate, "spec_3_classification", "Chemical derivative"}, {UNIMOD_O_pinacolylmethylphosphonate, "spec_3_hidden", "1"}, {UNIMOD_O_pinacolylmethylphosphonate, "spec_3_position", "Anywhere"}, {UNIMOD_O_pinacolylmethylphosphonate, "spec_3_site", "Y"}, {UNIMOD_O_pinacolylmethylphosphonate, "spec_4_classification", "Chemical derivative"}, {UNIMOD_O_pinacolylmethylphosphonate, "spec_4_hidden", "1"}, {UNIMOD_O_pinacolylmethylphosphonate, "spec_4_position", "Anywhere"}, {UNIMOD_O_pinacolylmethylphosphonate, "spec_4_site", "H"}, {UNIMOD_O_pinacolylmethylphosphonate, "spec_5_classification", "Chemical derivative"}, {UNIMOD_O_pinacolylmethylphosphonate, "spec_5_hidden", "1"}, {UNIMOD_O_pinacolylmethylphosphonate, "spec_5_position", "Anywhere"}, {UNIMOD_O_pinacolylmethylphosphonate, "spec_5_site", "K"}, {UNIMOD_Methylphosphonate, "approved", "0"}, {UNIMOD_Methylphosphonate, "delta_composition", "H(3) C O(2) P"}, {UNIMOD_Methylphosphonate, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Methylphosphonate, "spec_1_hidden", "1"}, {UNIMOD_Methylphosphonate, "spec_1_position", "Anywhere"}, {UNIMOD_Methylphosphonate, "spec_1_site", "S"}, {UNIMOD_Methylphosphonate, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Methylphosphonate, "spec_2_hidden", "1"}, {UNIMOD_Methylphosphonate, "spec_2_position", "Anywhere"}, {UNIMOD_Methylphosphonate, "spec_2_site", "T"}, {UNIMOD_Methylphosphonate, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Methylphosphonate, "spec_3_hidden", "1"}, {UNIMOD_Methylphosphonate, "spec_3_position", "Anywhere"}, {UNIMOD_Methylphosphonate, "spec_3_site", "Y"}, {UNIMOD_O_Isopropylmethylphosphonate, "approved", "0"}, {UNIMOD_O_Isopropylmethylphosphonate, "delta_composition", "H(9) C(4) O(2) P"}, {UNIMOD_O_Isopropylmethylphosphonate, "spec_1_classification", "Chemical derivative"}, {UNIMOD_O_Isopropylmethylphosphonate, "spec_1_hidden", "1"}, {UNIMOD_O_Isopropylmethylphosphonate, "spec_1_position", "Anywhere"}, {UNIMOD_O_Isopropylmethylphosphonate, "spec_1_site", "S"}, {UNIMOD_O_Isopropylmethylphosphonate, "spec_2_classification", "Chemical derivative"}, {UNIMOD_O_Isopropylmethylphosphonate, "spec_2_hidden", "1"}, {UNIMOD_O_Isopropylmethylphosphonate, "spec_2_position", "Anywhere"}, {UNIMOD_O_Isopropylmethylphosphonate, "spec_2_site", "T"}, {UNIMOD_O_Isopropylmethylphosphonate, "spec_3_classification", "Chemical derivative"}, {UNIMOD_O_Isopropylmethylphosphonate, "spec_3_hidden", "1"}, {UNIMOD_O_Isopropylmethylphosphonate, "spec_3_position", "Anywhere"}, {UNIMOD_O_Isopropylmethylphosphonate, "spec_3_site", "Y"}, {UNIMOD_iTRAQ8plex, "approved", "0"}, {UNIMOD_iTRAQ8plex, "delta_composition", "H(24) C(7) 13C(7) N(3) 15N O(3)"}, {UNIMOD_iTRAQ8plex, "spec_1_classification", "Isotopic label"}, {UNIMOD_iTRAQ8plex, "spec_1_hidden", "0"}, {UNIMOD_iTRAQ8plex, "spec_1_position", "Anywhere"}, {UNIMOD_iTRAQ8plex, "spec_1_site", "K"}, {UNIMOD_iTRAQ8plex, "spec_2_classification", "Isotopic label"}, {UNIMOD_iTRAQ8plex, "spec_2_hidden", "0"}, {UNIMOD_iTRAQ8plex, "spec_2_position", "Any N-term"}, {UNIMOD_iTRAQ8plex, "spec_2_site", "N-term"}, {UNIMOD_iTRAQ8plex, "spec_3_classification", "Isotopic label"}, {UNIMOD_iTRAQ8plex, "spec_3_hidden", "0"}, {UNIMOD_iTRAQ8plex, "spec_3_position", "Anywhere"}, {UNIMOD_iTRAQ8plex, "spec_3_site", "Y"}, {UNIMOD_iTRAQ8plex, "spec_4_classification", "Isotopic label"}, {UNIMOD_iTRAQ8plex, "spec_4_hidden", "1"}, {UNIMOD_iTRAQ8plex, "spec_4_position", "Anywhere"}, {UNIMOD_iTRAQ8plex, "spec_4_site", "H"}, {UNIMOD_iTRAQ8plex, "spec_5_classification", "Isotopic label"}, {UNIMOD_iTRAQ8plex, "spec_5_hidden", "1"}, {UNIMOD_iTRAQ8plex, "spec_5_position", "Anywhere"}, {UNIMOD_iTRAQ8plex, "spec_5_site", "S"}, {UNIMOD_iTRAQ8plex, "spec_6_classification", "Isotopic label"}, {UNIMOD_iTRAQ8plex, "spec_6_hidden", "1"}, {UNIMOD_iTRAQ8plex, "spec_6_position", "Anywhere"}, {UNIMOD_iTRAQ8plex, "spec_6_site", "T"}, {UNIMOD_iTRAQ8plex, "spec_7_classification", "Isotopic label"}, {UNIMOD_iTRAQ8plex, "spec_7_hidden", "1"}, {UNIMOD_iTRAQ8plex, "spec_7_position", "Protein N-term"}, {UNIMOD_iTRAQ8plex, "spec_7_site", "N-term"}, {UNIMOD_iTRAQ8plex_13C_6_15N_2_, "approved", "0"}, {UNIMOD_iTRAQ8plex_13C_6_15N_2_, "delta_composition", "H(24) C(8) 13C(6) N(2) 15N(2) O(3)"}, {UNIMOD_iTRAQ8plex_13C_6_15N_2_, "spec_1_classification", "Isotopic label"}, {UNIMOD_iTRAQ8plex_13C_6_15N_2_, "spec_1_hidden", "1"}, {UNIMOD_iTRAQ8plex_13C_6_15N_2_, "spec_1_position", "Anywhere"}, {UNIMOD_iTRAQ8plex_13C_6_15N_2_, "spec_1_site", "K"}, {UNIMOD_iTRAQ8plex_13C_6_15N_2_, "spec_2_classification", "Isotopic label"}, {UNIMOD_iTRAQ8plex_13C_6_15N_2_, "spec_2_hidden", "1"}, {UNIMOD_iTRAQ8plex_13C_6_15N_2_, "spec_2_position", "Any N-term"}, {UNIMOD_iTRAQ8plex_13C_6_15N_2_, "spec_2_site", "N-term"}, {UNIMOD_iTRAQ8plex_13C_6_15N_2_, "spec_3_classification", "Isotopic label"}, {UNIMOD_iTRAQ8plex_13C_6_15N_2_, "spec_3_hidden", "1"}, {UNIMOD_iTRAQ8plex_13C_6_15N_2_, "spec_3_position", "Anywhere"}, {UNIMOD_iTRAQ8plex_13C_6_15N_2_, "spec_3_site", "Y"}, {UNIMOD_Ethanolamine, "approved", "0"}, {UNIMOD_Ethanolamine, "delta_composition", "H(5) C(2) N"}, {UNIMOD_Ethanolamine, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Ethanolamine, "spec_1_hidden", "1"}, {UNIMOD_Ethanolamine, "spec_1_position", "Any C-term"}, {UNIMOD_Ethanolamine, "spec_1_site", "C-term"}, {UNIMOD_Ethanolamine, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Ethanolamine, "spec_2_hidden", "1"}, {UNIMOD_Ethanolamine, "spec_2_position", "Anywhere"}, {UNIMOD_Ethanolamine, "spec_2_site", "D"}, {UNIMOD_Ethanolamine, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Ethanolamine, "spec_3_hidden", "1"}, {UNIMOD_Ethanolamine, "spec_3_position", "Anywhere"}, {UNIMOD_Ethanolamine, "spec_3_site", "E"}, {UNIMOD_Ethanolamine, "spec_4_classification", "Chemical derivative"}, {UNIMOD_Ethanolamine, "spec_4_hidden", "1"}, {UNIMOD_Ethanolamine, "spec_4_position", "Anywhere"}, {UNIMOD_Ethanolamine, "spec_4_site", "C"}, {UNIMOD_DTT_ST, "approved", "0"}, {UNIMOD_DTT_ST, "delta_composition", "H(8) C(4) O S(2)"}, {UNIMOD_DTT_ST, "spec_1_classification", "Chemical derivative"}, {UNIMOD_DTT_ST, "spec_1_hidden", "1"}, {UNIMOD_DTT_ST, "spec_1_position", "Anywhere"}, {UNIMOD_DTT_ST, "spec_1_site", "S"}, {UNIMOD_DTT_ST, "spec_2_classification", "Chemical derivative"}, {UNIMOD_DTT_ST, "spec_2_hidden", "1"}, {UNIMOD_DTT_ST, "spec_2_position", "Anywhere"}, {UNIMOD_DTT_ST, "spec_2_site", "T"}, {UNIMOD_DTT_C, "approved", "0"}, {UNIMOD_DTT_C, "delta_composition", "H(8) C(4) O(2) S"}, {UNIMOD_DTT_C, "spec_1_classification", "Chemical derivative"}, {UNIMOD_DTT_C, "spec_1_hidden", "1"}, {UNIMOD_DTT_C, "spec_1_position", "Anywhere"}, {UNIMOD_DTT_C, "spec_1_site", "C"}, {UNIMOD_TMT6plex, "approved", "0"}, {UNIMOD_TMT6plex, "delta_composition", "H(20) C(8) 13C(4) N 15N O(2)"}, {UNIMOD_TMT6plex, "spec_1_classification", "Isotopic label"}, {UNIMOD_TMT6plex, "spec_1_hidden", "0"}, {UNIMOD_TMT6plex, "spec_1_position", "Anywhere"}, {UNIMOD_TMT6plex, "spec_1_site", "K"}, {UNIMOD_TMT6plex, "spec_2_classification", "Isotopic label"}, {UNIMOD_TMT6plex, "spec_2_hidden", "0"}, {UNIMOD_TMT6plex, "spec_2_position", "Any N-term"}, {UNIMOD_TMT6plex, "spec_2_site", "N-term"}, {UNIMOD_TMT6plex, "spec_3_classification", "Isotopic label"}, {UNIMOD_TMT6plex, "spec_3_hidden", "1"}, {UNIMOD_TMT6plex, "spec_3_position", "Protein N-term"}, {UNIMOD_TMT6plex, "spec_3_site", "N-term"}, {UNIMOD_TMT6plex, "spec_4_classification", "Isotopic label"}, {UNIMOD_TMT6plex, "spec_4_hidden", "1"}, {UNIMOD_TMT6plex, "spec_4_position", "Anywhere"}, {UNIMOD_TMT6plex, "spec_4_site", "H"}, {UNIMOD_TMT6plex, "spec_5_classification", "Isotopic label"}, {UNIMOD_TMT6plex, "spec_5_hidden", "1"}, {UNIMOD_TMT6plex, "spec_5_position", "Anywhere"}, {UNIMOD_TMT6plex, "spec_5_site", "S"}, {UNIMOD_TMT6plex, "spec_6_classification", "Isotopic label"}, {UNIMOD_TMT6plex, "spec_6_hidden", "1"}, {UNIMOD_TMT6plex, "spec_6_position", "Anywhere"}, {UNIMOD_TMT6plex, "spec_6_site", "T"}, {UNIMOD_TMT2plex, "approved", "0"}, {UNIMOD_TMT2plex, "delta_composition", "H(20) C(11) 13C N(2) O(2)"}, {UNIMOD_TMT2plex, "spec_1_classification", "Isotopic label"}, {UNIMOD_TMT2plex, "spec_1_hidden", "0"}, {UNIMOD_TMT2plex, "spec_1_position", "Anywhere"}, {UNIMOD_TMT2plex, "spec_1_site", "K"}, {UNIMOD_TMT2plex, "spec_2_classification", "Isotopic label"}, {UNIMOD_TMT2plex, "spec_2_hidden", "0"}, {UNIMOD_TMT2plex, "spec_2_position", "Any N-term"}, {UNIMOD_TMT2plex, "spec_2_site", "N-term"}, {UNIMOD_TMT2plex, "spec_3_classification", "Isotopic label"}, {UNIMOD_TMT2plex, "spec_3_hidden", "1"}, {UNIMOD_TMT2plex, "spec_3_position", "Protein N-term"}, {UNIMOD_TMT2plex, "spec_3_site", "N-term"}, {UNIMOD_TMT2plex, "spec_4_classification", "Isotopic label"}, {UNIMOD_TMT2plex, "spec_4_hidden", "1"}, {UNIMOD_TMT2plex, "spec_4_position", "Anywhere"}, {UNIMOD_TMT2plex, "spec_4_site", "H"}, {UNIMOD_TMT2plex, "spec_5_classification", "Isotopic label"}, {UNIMOD_TMT2plex, "spec_5_hidden", "1"}, {UNIMOD_TMT2plex, "spec_5_position", "Anywhere"}, {UNIMOD_TMT2plex, "spec_5_site", "S"}, {UNIMOD_TMT2plex, "spec_6_classification", "Isotopic label"}, {UNIMOD_TMT2plex, "spec_6_hidden", "1"}, {UNIMOD_TMT2plex, "spec_6_position", "Anywhere"}, {UNIMOD_TMT2plex, "spec_6_site", "T"}, {UNIMOD_TMT, "approved", "0"}, {UNIMOD_TMT, "delta_composition", "H(20) C(12) N(2) O(2)"}, {UNIMOD_TMT, "spec_1_classification", "Chemical derivative"}, {UNIMOD_TMT, "spec_1_hidden", "1"}, {UNIMOD_TMT, "spec_1_position", "Anywhere"}, {UNIMOD_TMT, "spec_1_site", "K"}, {UNIMOD_TMT, "spec_2_classification", "Chemical derivative"}, {UNIMOD_TMT, "spec_2_hidden", "1"}, {UNIMOD_TMT, "spec_2_position", "Any N-term"}, {UNIMOD_TMT, "spec_2_site", "N-term"}, {UNIMOD_TMT, "spec_3_classification", "Chemical derivative"}, {UNIMOD_TMT, "spec_3_hidden", "1"}, {UNIMOD_TMT, "spec_3_position", "Protein N-term"}, {UNIMOD_TMT, "spec_3_site", "N-term"}, {UNIMOD_TMT, "spec_4_classification", "Isotopic label"}, {UNIMOD_TMT, "spec_4_hidden", "1"}, {UNIMOD_TMT, "spec_4_position", "Anywhere"}, {UNIMOD_TMT, "spec_4_site", "H"}, {UNIMOD_TMT, "spec_5_classification", "Isotopic label"}, {UNIMOD_TMT, "spec_5_hidden", "1"}, {UNIMOD_TMT, "spec_5_position", "Anywhere"}, {UNIMOD_TMT, "spec_5_site", "S"}, {UNIMOD_TMT, "spec_6_classification", "Isotopic label"}, {UNIMOD_TMT, "spec_6_hidden", "1"}, {UNIMOD_TMT, "spec_6_position", "Anywhere"}, {UNIMOD_TMT, "spec_6_site", "T"}, {UNIMOD_ExacTagThiol, "approved", "0"}, {UNIMOD_ExacTagThiol, "delta_composition", "H(50) C(23) 13C(12) N(8) 15N(6) O(18)"}, {UNIMOD_ExacTagThiol, "spec_1_classification", "Isotopic label"}, {UNIMOD_ExacTagThiol, "spec_1_hidden", "0"}, {UNIMOD_ExacTagThiol, "spec_1_position", "Anywhere"}, {UNIMOD_ExacTagThiol, "spec_1_site", "C"}, {UNIMOD_ExacTagAmine, "approved", "0"}, {UNIMOD_ExacTagAmine, "delta_composition", "H(52) C(25) 13C(12) N(8) 15N(6) O(19) S"}, {UNIMOD_ExacTagAmine, "spec_1_classification", "Isotopic label"}, {UNIMOD_ExacTagAmine, "spec_1_hidden", "0"}, {UNIMOD_ExacTagAmine, "spec_1_position", "Anywhere"}, {UNIMOD_ExacTagAmine, "spec_1_site", "K"}, {UNIMOD_4_ONE_Delta_H__2_O__1_, "approved", "0"}, {UNIMOD_4_ONE_Delta_H__2_O__1_, "delta_composition", "H(12) C(9) O"}, {UNIMOD_4_ONE_Delta_H__2_O__1_, "spec_1_classification", "Chemical derivative"}, {UNIMOD_4_ONE_Delta_H__2_O__1_, "spec_1_hidden", "1"}, {UNIMOD_4_ONE_Delta_H__2_O__1_, "spec_1_position", "Anywhere"}, {UNIMOD_4_ONE_Delta_H__2_O__1_, "spec_1_site", "C"}, {UNIMOD_4_ONE_Delta_H__2_O__1_, "spec_2_classification", "Chemical derivative"}, {UNIMOD_4_ONE_Delta_H__2_O__1_, "spec_2_hidden", "1"}, {UNIMOD_4_ONE_Delta_H__2_O__1_, "spec_2_position", "Anywhere"}, {UNIMOD_4_ONE_Delta_H__2_O__1_, "spec_2_site", "H"}, {UNIMOD_4_ONE_Delta_H__2_O__1_, "spec_3_classification", "Chemical derivative"}, {UNIMOD_4_ONE_Delta_H__2_O__1_, "spec_3_hidden", "1"}, {UNIMOD_4_ONE_Delta_H__2_O__1_, "spec_3_position", "Anywhere"}, {UNIMOD_4_ONE_Delta_H__2_O__1_, "spec_3_site", "K"}, {UNIMOD_NO_SMX_SEMD, "approved", "0"}, {UNIMOD_NO_SMX_SEMD, "delta_composition", "H(10) C(10) N(3) O(3) S"}, {UNIMOD_NO_SMX_SEMD, "spec_1_classification", "Chemical derivative"}, {UNIMOD_NO_SMX_SEMD, "spec_1_hidden", "1"}, {UNIMOD_NO_SMX_SEMD, "spec_1_position", "Anywhere"}, {UNIMOD_NO_SMX_SEMD, "spec_1_site", "C"}, {UNIMOD_NO_SMX_SMCT, "approved", "0"}, {UNIMOD_NO_SMX_SMCT, "delta_composition", "H(10) C(10) N(3) O(4) S"}, {UNIMOD_NO_SMX_SMCT, "spec_1_classification", "Chemical derivative"}, {UNIMOD_NO_SMX_SMCT, "spec_1_hidden", "1"}, {UNIMOD_NO_SMX_SMCT, "spec_1_position", "Anywhere"}, {UNIMOD_NO_SMX_SMCT, "spec_1_site", "C"}, {UNIMOD_NO_SMX_SIMD, "approved", "0"}, {UNIMOD_NO_SMX_SIMD, "delta_composition", "H(9) C(10) N(3) O(4) S"}, {UNIMOD_NO_SMX_SIMD, "spec_1_classification", "Chemical derivative"}, {UNIMOD_NO_SMX_SIMD, "spec_1_hidden", "1"}, {UNIMOD_NO_SMX_SIMD, "spec_1_position", "Anywhere"}, {UNIMOD_NO_SMX_SIMD, "spec_1_site", "C"}, {UNIMOD_Malonyl, "approved", "0"}, {UNIMOD_Malonyl, "delta_composition", "H(2) C(3) O(3)"}, {UNIMOD_Malonyl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Malonyl, "spec_1_hidden", "1"}, {UNIMOD_Malonyl, "spec_1_position", "Anywhere"}, {UNIMOD_Malonyl, "spec_1_site", "C"}, {UNIMOD_Malonyl, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Malonyl, "spec_2_hidden", "1"}, {UNIMOD_Malonyl, "spec_2_position", "Anywhere"}, {UNIMOD_Malonyl, "spec_2_site", "S"}, {UNIMOD_3sulfo, "approved", "0"}, {UNIMOD_3sulfo, "delta_composition", "H(4) C(7) O(4) S"}, {UNIMOD_3sulfo, "spec_1_classification", "Chemical derivative"}, {UNIMOD_3sulfo, "spec_1_hidden", "1"}, {UNIMOD_3sulfo, "spec_1_position", "Any N-term"}, {UNIMOD_3sulfo, "spec_1_site", "N-term"}, {UNIMOD_trifluoro, "approved", "0"}, {UNIMOD_trifluoro, "delta_composition", "H(-3) F(3)"}, {UNIMOD_trifluoro, "spec_1_classification", "Non-standard residue"}, {UNIMOD_trifluoro, "spec_1_hidden", "1"}, {UNIMOD_trifluoro, "spec_1_position", "Anywhere"}, {UNIMOD_trifluoro, "spec_1_site", "L"}, {UNIMOD_TNBS, "approved", "0"}, {UNIMOD_TNBS, "delta_composition", "H C(6) N(3) O(6)"}, {UNIMOD_TNBS, "spec_1_classification", "Chemical derivative"}, {UNIMOD_TNBS, "spec_1_hidden", "1"}, {UNIMOD_TNBS, "spec_1_position", "Anywhere"}, {UNIMOD_TNBS, "spec_1_site", "K"}, {UNIMOD_TNBS, "spec_2_classification", "Chemical derivative"}, {UNIMOD_TNBS, "spec_2_hidden", "1"}, {UNIMOD_TNBS, "spec_2_position", "Any N-term"}, {UNIMOD_TNBS, "spec_2_site", "N-term"}, {UNIMOD_IDEnT, "approved", "0"}, {UNIMOD_IDEnT, "delta_composition", "H(7) C(9) N O Cl(2)"}, {UNIMOD_IDEnT, "spec_1_classification", "Isotopic label"}, {UNIMOD_IDEnT, "spec_1_hidden", "1"}, {UNIMOD_IDEnT, "spec_1_position", "Anywhere"}, {UNIMOD_IDEnT, "spec_1_site", "C"}, {UNIMOD_DTT_ST_2H_6_, "approved", "0"}, {UNIMOD_DTT_ST_2H_6_, "delta_composition", "H(2) 2H(6) C(4) O S(2)"}, {UNIMOD_DTT_ST_2H_6_, "spec_1_classification", "Isotopic label"}, {UNIMOD_DTT_ST_2H_6_, "spec_1_hidden", "1"}, {UNIMOD_DTT_ST_2H_6_, "spec_1_position", "Anywhere"}, {UNIMOD_DTT_ST_2H_6_, "spec_1_site", "S"}, {UNIMOD_DTT_ST_2H_6_, "spec_2_classification", "Isotopic label"}, {UNIMOD_DTT_ST_2H_6_, "spec_2_hidden", "1"}, {UNIMOD_DTT_ST_2H_6_, "spec_2_position", "Anywhere"}, {UNIMOD_DTT_ST_2H_6_, "spec_2_site", "T"}, {UNIMOD_DTT_C_2H_6_, "approved", "0"}, {UNIMOD_DTT_C_2H_6_, "delta_composition", "H(2) 2H(6) C(4) O(2) S"}, {UNIMOD_DTT_C_2H_6_, "spec_1_classification", "Isotopic label"}, {UNIMOD_DTT_C_2H_6_, "spec_1_hidden", "1"}, {UNIMOD_DTT_C_2H_6_, "spec_1_position", "Anywhere"}, {UNIMOD_DTT_C_2H_6_, "spec_1_site", "C"}, {UNIMOD_Met_loss, "approved", "0"}, {UNIMOD_Met_loss, "delta_composition", "H(-9) C(-5) N(-1) O(-1) S(-1)"}, {UNIMOD_Met_loss, "spec_1_classification", "Co-translational"}, {UNIMOD_Met_loss, "spec_1_hidden", "1"}, {UNIMOD_Met_loss, "spec_1_position", "Protein N-term"}, {UNIMOD_Met_loss, "spec_1_site", "M"}, {UNIMOD_Met_loss_Acetyl, "approved", "0"}, {UNIMOD_Met_loss_Acetyl, "delta_composition", "H(-7) C(-3) N(-1) S(-1)"}, {UNIMOD_Met_loss_Acetyl, "spec_1_classification", "Co-translational"}, {UNIMOD_Met_loss_Acetyl, "spec_1_hidden", "1"}, {UNIMOD_Met_loss_Acetyl, "spec_1_position", "Protein N-term"}, {UNIMOD_Met_loss_Acetyl, "spec_1_site", "M"}, {UNIMOD_Menadione_HQ, "approved", "0"}, {UNIMOD_Menadione_HQ, "delta_composition", "H(8) C(11) O(2)"}, {UNIMOD_Menadione_HQ, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Menadione_HQ, "spec_1_hidden", "1"}, {UNIMOD_Menadione_HQ, "spec_1_position", "Anywhere"}, {UNIMOD_Menadione_HQ, "spec_1_site", "C"}, {UNIMOD_Menadione_HQ, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Menadione_HQ, "spec_2_hidden", "1"}, {UNIMOD_Menadione_HQ, "spec_2_position", "Anywhere"}, {UNIMOD_Menadione_HQ, "spec_2_site", "K"}, {UNIMOD_Methyl_Acetyl_2H_3_, "approved", "0"}, {UNIMOD_Methyl_Acetyl_2H_3_, "delta_composition", "H 2H(3) C(3) O"}, {UNIMOD_Methyl_Acetyl_2H_3_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Methyl_Acetyl_2H_3_, "spec_1_hidden", "1"}, {UNIMOD_Methyl_Acetyl_2H_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Methyl_Acetyl_2H_3_, "spec_1_site", "K"}, {UNIMOD_lapachenole, "approved", "0"}, {UNIMOD_lapachenole, "delta_composition", "H(16) C(16) O(2)"}, {UNIMOD_lapachenole, "spec_1_classification", "Chemical derivative"}, {UNIMOD_lapachenole, "spec_1_hidden", "1"}, {UNIMOD_lapachenole, "spec_1_position", "Anywhere"}, {UNIMOD_lapachenole, "spec_1_site", "C"}, {UNIMOD_Label_13C_5_, "approved", "1"}, {UNIMOD_Label_13C_5_, "delta_composition", "C(-5) 13C(5)"}, {UNIMOD_Label_13C_5_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_5_, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_5_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_5_, "spec_1_site", "P"}, {UNIMOD_maleimide, "approved", "0"}, {UNIMOD_maleimide, "delta_composition", "H(3) C(4) N O(2)"}, {UNIMOD_maleimide, "spec_1_classification", "Chemical derivative"}, {UNIMOD_maleimide, "spec_1_hidden", "1"}, {UNIMOD_maleimide, "spec_1_position", "Anywhere"}, {UNIMOD_maleimide, "spec_1_site", "C"}, {UNIMOD_maleimide, "spec_2_classification", "Chemical derivative"}, {UNIMOD_maleimide, "spec_2_hidden", "1"}, {UNIMOD_maleimide, "spec_2_position", "Anywhere"}, {UNIMOD_maleimide, "spec_2_site", "K"}, {UNIMOD_Biotin_phenacyl, "approved", "0"}, {UNIMOD_Biotin_phenacyl, "delta_composition", "H(38) C(29) N(8) O(6) S"}, {UNIMOD_Biotin_phenacyl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Biotin_phenacyl, "spec_1_hidden", "1"}, {UNIMOD_Biotin_phenacyl, "spec_1_position", "Anywhere"}, {UNIMOD_Biotin_phenacyl, "spec_1_site", "C"}, {UNIMOD_Biotin_phenacyl, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Biotin_phenacyl, "spec_2_hidden", "1"}, {UNIMOD_Biotin_phenacyl, "spec_2_position", "Anywhere"}, {UNIMOD_Biotin_phenacyl, "spec_2_site", "H"}, {UNIMOD_Biotin_phenacyl, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Biotin_phenacyl, "spec_3_hidden", "1"}, {UNIMOD_Biotin_phenacyl, "spec_3_position", "Anywhere"}, {UNIMOD_Biotin_phenacyl, "spec_3_site", "S"}, {UNIMOD_Carboxymethyl_13C_2_, "approved", "0"}, {UNIMOD_Carboxymethyl_13C_2_, "delta_composition", "H(2) 13C(2) O(2)"}, {UNIMOD_Carboxymethyl_13C_2_, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Carboxymethyl_13C_2_, "spec_1_hidden", "1"}, {UNIMOD_Carboxymethyl_13C_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Carboxymethyl_13C_2_, "spec_1_site", "C"}, {UNIMOD_NEM_2H_5_, "approved", "0"}, {UNIMOD_NEM_2H_5_, "delta_composition", "H(2) 2H(5) C(6) N O(2)"}, {UNIMOD_NEM_2H_5_, "spec_1_classification", "Chemical derivative"}, {UNIMOD_NEM_2H_5_, "spec_1_hidden", "1"}, {UNIMOD_NEM_2H_5_, "spec_1_position", "Anywhere"}, {UNIMOD_NEM_2H_5_, "spec_1_site", "C"}, {UNIMOD_AEC_MAEC_2H_4_, "approved", "0"}, {UNIMOD_AEC_MAEC_2H_4_, "delta_composition", "H 2H(4) C(2) N O(-1) S"}, {UNIMOD_AEC_MAEC_2H_4_, "spec_1_classification", "Isotopic label"}, {UNIMOD_AEC_MAEC_2H_4_, "spec_1_hidden", "1"}, {UNIMOD_AEC_MAEC_2H_4_, "spec_1_position", "Anywhere"}, {UNIMOD_AEC_MAEC_2H_4_, "spec_1_site", "S"}, {UNIMOD_AEC_MAEC_2H_4_, "spec_2_classification", "Isotopic label"}, {UNIMOD_AEC_MAEC_2H_4_, "spec_2_hidden", "1"}, {UNIMOD_AEC_MAEC_2H_4_, "spec_2_position", "Anywhere"}, {UNIMOD_AEC_MAEC_2H_4_, "spec_2_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_1_, "delta_composition", "Hex HexNAc"}, {UNIMOD_Hex_1_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_1_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_, "spec_2_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_, "spec_2_site", "N"}, {UNIMOD_Label_13C_6__GG, "approved", "0"}, {UNIMOD_Label_13C_6__GG, "delta_composition", "H(6) C(-2) 13C(6) N(2) O(2)"}, {UNIMOD_Label_13C_6__GG, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_6__GG, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_6__GG, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_6__GG, "spec_1_site", "K"}, {UNIMOD_Biotin_Thermo_21345, "approved", "0"}, {UNIMOD_Biotin_Thermo_21345, "delta_composition", "H(25) C(15) N(3) O(2) S"}, {UNIMOD_Biotin_Thermo_21345, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Biotin_Thermo_21345, "spec_1_hidden", "1"}, {UNIMOD_Biotin_Thermo_21345, "spec_1_position", "Anywhere"}, {UNIMOD_Biotin_Thermo_21345, "spec_1_site", "Q"}, {UNIMOD_Pentylamine, "approved", "0"}, {UNIMOD_Pentylamine, "delta_composition", "H(11) C(5) N"}, {UNIMOD_Pentylamine, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Pentylamine, "spec_1_hidden", "1"}, {UNIMOD_Pentylamine, "spec_1_position", "Anywhere"}, {UNIMOD_Pentylamine, "spec_1_site", "Q"}, {UNIMOD_Biotin_Thermo_21360, "approved", "0"}, {UNIMOD_Biotin_Thermo_21360, "delta_composition", "H(37) C(21) N(5) O(6) S"}, {UNIMOD_Biotin_Thermo_21360, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Biotin_Thermo_21360, "spec_1_hidden", "1"}, {UNIMOD_Biotin_Thermo_21360, "spec_1_position", "Anywhere"}, {UNIMOD_Biotin_Thermo_21360, "spec_1_site", "C-term"}, {UNIMOD_Cy3b_maleimide, "approved", "0"}, {UNIMOD_Cy3b_maleimide, "delta_composition", "H(38) C(37) N(4) O(7) S"}, {UNIMOD_Cy3b_maleimide, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Cy3b_maleimide, "spec_1_hidden", "1"}, {UNIMOD_Cy3b_maleimide, "spec_1_position", "Anywhere"}, {UNIMOD_Cy3b_maleimide, "spec_1_site", "C"}, {UNIMOD_Gly_loss_Amide, "approved", "0"}, {UNIMOD_Gly_loss_Amide, "delta_composition", "H(-2) C(-2) O(-2)"}, {UNIMOD_Gly_loss_Amide, "spec_1_classification", "Post-translational"}, {UNIMOD_Gly_loss_Amide, "spec_1_hidden", "1"}, {UNIMOD_Gly_loss_Amide, "spec_1_position", "Any C-term"}, {UNIMOD_Gly_loss_Amide, "spec_1_site", "G"}, {UNIMOD_BMOE, "approved", "0"}, {UNIMOD_BMOE, "delta_composition", "H(8) C(10) N(2) O(4)"}, {UNIMOD_BMOE, "spec_1_classification", "Chemical derivative"}, {UNIMOD_BMOE, "spec_1_hidden", "1"}, {UNIMOD_BMOE, "spec_1_position", "Anywhere"}, {UNIMOD_BMOE, "spec_1_site", "C"}, {UNIMOD_DFDNB, "approved", "0"}, {UNIMOD_DFDNB, "delta_composition", "H(2) C(6) N(2) O(4) F(2)"}, {UNIMOD_DFDNB, "spec_1_classification", "Chemical derivative"}, {UNIMOD_DFDNB, "spec_1_hidden", "1"}, {UNIMOD_DFDNB, "spec_1_position", "Anywhere"}, {UNIMOD_DFDNB, "spec_1_site", "K"}, {UNIMOD_DFDNB, "spec_2_classification", "Chemical derivative"}, {UNIMOD_DFDNB, "spec_2_hidden", "1"}, {UNIMOD_DFDNB, "spec_2_position", "Anywhere"}, {UNIMOD_DFDNB, "spec_2_site", "R"}, {UNIMOD_DFDNB, "spec_3_classification", "Chemical derivative"}, {UNIMOD_DFDNB, "spec_3_hidden", "1"}, {UNIMOD_DFDNB, "spec_3_position", "Anywhere"}, {UNIMOD_DFDNB, "spec_3_site", "Q"}, {UNIMOD_DFDNB, "spec_4_classification", "Chemical derivative"}, {UNIMOD_DFDNB, "spec_4_hidden", "1"}, {UNIMOD_DFDNB, "spec_4_position", "Anywhere"}, {UNIMOD_DFDNB, "spec_4_site", "N"}, {UNIMOD_TMPP_Ac, "approved", "0"}, {UNIMOD_TMPP_Ac, "delta_composition", "H(33) C(29) O(10) P"}, {UNIMOD_TMPP_Ac, "spec_1_classification", "Chemical derivative"}, {UNIMOD_TMPP_Ac, "spec_1_hidden", "1"}, {UNIMOD_TMPP_Ac, "spec_1_position", "Any N-term"}, {UNIMOD_TMPP_Ac, "spec_1_site", "N-term"}, {UNIMOD_Dihydroxyimidazolidine, "approved", "0"}, {UNIMOD_Dihydroxyimidazolidine, "delta_composition", "H(4) C(3) O(2)"}, {UNIMOD_Dihydroxyimidazolidine, "spec_1_classification", "Multiple"}, {UNIMOD_Dihydroxyimidazolidine, "spec_1_hidden", "1"}, {UNIMOD_Dihydroxyimidazolidine, "spec_1_position", "Anywhere"}, {UNIMOD_Dihydroxyimidazolidine, "spec_1_site", "R"}, {UNIMOD_Label_2H_4__Acetyl, "approved", "0"}, {UNIMOD_Label_2H_4__Acetyl, "delta_composition", "H(-2) 2H(4) C(2) O"}, {UNIMOD_Label_2H_4__Acetyl, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_2H_4__Acetyl, "spec_1_hidden", "1"}, {UNIMOD_Label_2H_4__Acetyl, "spec_1_position", "Anywhere"}, {UNIMOD_Label_2H_4__Acetyl, "spec_1_site", "K"}, {UNIMOD_Label_13C_6__Acetyl, "approved", "0"}, {UNIMOD_Label_13C_6__Acetyl, "delta_composition", "H(2) C(-4) 13C(6) O"}, {UNIMOD_Label_13C_6__Acetyl, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_6__Acetyl, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_6__Acetyl, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_6__Acetyl, "spec_1_site", "K"}, {UNIMOD_Label_13C_6_15N_2__Acetyl, "approved", "0"}, {UNIMOD_Label_13C_6_15N_2__Acetyl, "delta_composition", "H(2) C(-4) 13C(6) N(-2) 15N(2) O"}, {UNIMOD_Label_13C_6_15N_2__Acetyl, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_6_15N_2__Acetyl, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_6_15N_2__Acetyl, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_6_15N_2__Acetyl, "spec_1_site", "K"}, {UNIMOD_Arg__Npo, "approved", "0"}, {UNIMOD_Arg__Npo, "delta_composition", "H(-1) C(3) N O(2)"}, {UNIMOD_Arg__Npo, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Arg__Npo, "spec_1_hidden", "1"}, {UNIMOD_Arg__Npo, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__Npo, "spec_1_site", "R"}, {UNIMOD_EQIGG, "approved", "0"}, {UNIMOD_EQIGG, "delta_composition", "H(32) C(20) N(6) O(8)"}, {UNIMOD_EQIGG, "spec_1_classification", "Other"}, {UNIMOD_EQIGG, "spec_1_hidden", "1"}, {UNIMOD_EQIGG, "spec_1_position", "Anywhere"}, {UNIMOD_EQIGG, "spec_1_site", "K"}, {UNIMOD_Arg2PG, "approved", "0"}, {UNIMOD_Arg2PG, "delta_composition", "H(10) C(16) O(4)"}, {UNIMOD_Arg2PG, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Arg2PG, "spec_1_hidden", "1"}, {UNIMOD_Arg2PG, "spec_1_position", "Anywhere"}, {UNIMOD_Arg2PG, "spec_1_site", "R"}, {UNIMOD_cGMP, "approved", "0"}, {UNIMOD_cGMP, "delta_composition", "H(10) C(10) N(5) O(7) P"}, {UNIMOD_cGMP, "spec_1_classification", "Post-translational"}, {UNIMOD_cGMP, "spec_1_hidden", "1"}, {UNIMOD_cGMP, "spec_1_position", "Anywhere"}, {UNIMOD_cGMP, "spec_1_site", "C"}, {UNIMOD_cGMP, "spec_2_classification", "Post-translational"}, {UNIMOD_cGMP, "spec_2_hidden", "1"}, {UNIMOD_cGMP, "spec_2_position", "Anywhere"}, {UNIMOD_cGMP, "spec_2_site", "S"}, {UNIMOD_cGMP_RMP_loss, "approved", "0"}, {UNIMOD_cGMP_RMP_loss, "delta_composition", "H(4) C(5) N(5) O"}, {UNIMOD_cGMP_RMP_loss, "spec_1_classification", "Post-translational"}, {UNIMOD_cGMP_RMP_loss, "spec_1_hidden", "1"}, {UNIMOD_cGMP_RMP_loss, "spec_1_position", "Anywhere"}, {UNIMOD_cGMP_RMP_loss, "spec_1_site", "C"}, {UNIMOD_cGMP_RMP_loss, "spec_2_classification", "Post-translational"}, {UNIMOD_cGMP_RMP_loss, "spec_2_hidden", "1"}, {UNIMOD_cGMP_RMP_loss, "spec_2_position", "Anywhere"}, {UNIMOD_cGMP_RMP_loss, "spec_2_site", "S"}, {UNIMOD_Label_2H_4__GG, "approved", "0"}, {UNIMOD_Label_2H_4__GG, "delta_composition", "H(2) 2H(4) C(4) N(2) O(2)"}, {UNIMOD_Label_2H_4__GG, "spec_1_classification", "Post-translational"}, {UNIMOD_Label_2H_4__GG, "spec_1_hidden", "1"}, {UNIMOD_Label_2H_4__GG, "spec_1_position", "Anywhere"}, {UNIMOD_Label_2H_4__GG, "spec_1_site", "K"}, {UNIMOD_MG_H1, "approved", "0"}, {UNIMOD_MG_H1, "delta_composition", "H(2) C(3) O"}, {UNIMOD_MG_H1, "spec_1_classification", "Other"}, {UNIMOD_MG_H1, "spec_1_hidden", "1"}, {UNIMOD_MG_H1, "spec_1_position", "Anywhere"}, {UNIMOD_MG_H1, "spec_1_site", "R"}, {UNIMOD_G_H1, "approved", "0"}, {UNIMOD_G_H1, "delta_composition", "C(2) O"}, {UNIMOD_G_H1, "spec_1_classification", "Other"}, {UNIMOD_G_H1, "spec_1_hidden", "1"}, {UNIMOD_G_H1, "spec_1_position", "Anywhere"}, {UNIMOD_G_H1, "spec_1_site", "R"}, {UNIMOD_ZGB, "approved", "0"}, {UNIMOD_ZGB, "delta_composition", "H(53) B C(37) N(6) O(6) F(2) S"}, {UNIMOD_ZGB, "spec_1_classification", "Other"}, {UNIMOD_ZGB, "spec_1_hidden", "1"}, {UNIMOD_ZGB, "spec_1_position", "Anywhere"}, {UNIMOD_ZGB, "spec_1_site", "K"}, {UNIMOD_ZGB, "spec_2_classification", "Other"}, {UNIMOD_ZGB, "spec_2_hidden", "1"}, {UNIMOD_ZGB, "spec_2_position", "Any N-term"}, {UNIMOD_ZGB, "spec_2_site", "N-term"}, {UNIMOD_Label_13C_1_2H_3_, "approved", "0"}, {UNIMOD_Label_13C_1_2H_3_, "delta_composition", "H(-3) 2H(3) C(-1) 13C"}, {UNIMOD_Label_13C_1_2H_3_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_1_2H_3_, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_1_2H_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_1_2H_3_, "spec_1_site", "M"}, {UNIMOD_Label_13C_6_15N_2__GG, "approved", "0"}, {UNIMOD_Label_13C_6_15N_2__GG, "delta_composition", "H(6) C(-2) 13C(6) 15N(2) O(2)"}, {UNIMOD_Label_13C_6_15N_2__GG, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_6_15N_2__GG, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_6_15N_2__GG, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_6_15N_2__GG, "spec_1_site", "K"}, {UNIMOD_ICPL_13C_6_2H_4_, "approved", "0"}, {UNIMOD_ICPL_13C_6_2H_4_, "delta_composition", "H(-1) 2H(4) 13C(6) N O"}, {UNIMOD_ICPL_13C_6_2H_4_, "spec_1_classification", "Isotopic label"}, {UNIMOD_ICPL_13C_6_2H_4_, "spec_1_hidden", "0"}, {UNIMOD_ICPL_13C_6_2H_4_, "spec_1_position", "Anywhere"}, {UNIMOD_ICPL_13C_6_2H_4_, "spec_1_site", "K"}, {UNIMOD_ICPL_13C_6_2H_4_, "spec_2_classification", "Isotopic label"}, {UNIMOD_ICPL_13C_6_2H_4_, "spec_2_hidden", "0"}, {UNIMOD_ICPL_13C_6_2H_4_, "spec_2_position", "Protein N-term"}, {UNIMOD_ICPL_13C_6_2H_4_, "spec_2_site", "N-term"}, {UNIMOD_ICPL_13C_6_2H_4_, "spec_3_classification", "Isotopic label"}, {UNIMOD_ICPL_13C_6_2H_4_, "spec_3_hidden", "0"}, {UNIMOD_ICPL_13C_6_2H_4_, "spec_3_position", "Any N-term"}, {UNIMOD_ICPL_13C_6_2H_4_, "spec_3_site", "N-term"}, {UNIMOD_QEQTGG, "approved", "0"}, {UNIMOD_QEQTGG, "delta_composition", "H(36) C(23) N(8) O(11)"}, {UNIMOD_QEQTGG, "spec_1_classification", "Other"}, {UNIMOD_QEQTGG, "spec_1_hidden", "1"}, {UNIMOD_QEQTGG, "spec_1_position", "Anywhere"}, {UNIMOD_QEQTGG, "spec_1_site", "K"}, {UNIMOD_QQQTGG, "approved", "0"}, {UNIMOD_QQQTGG, "delta_composition", "H(37) C(23) N(9) O(10)"}, {UNIMOD_QQQTGG, "spec_1_classification", "Other"}, {UNIMOD_QQQTGG, "spec_1_hidden", "1"}, {UNIMOD_QQQTGG, "spec_1_position", "Anywhere"}, {UNIMOD_QQQTGG, "spec_1_site", "K"}, {UNIMOD_Bodipy, "approved", "0"}, {UNIMOD_Bodipy, "delta_composition", "H(21) B C(20) N(4) O(3) F(2)"}, {UNIMOD_Bodipy, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Bodipy, "spec_1_hidden", "1"}, {UNIMOD_Bodipy, "spec_1_position", "Anywhere"}, {UNIMOD_Bodipy, "spec_1_site", "C"}, {UNIMOD_Biotin_Thermo_21325, "approved", "0"}, {UNIMOD_Biotin_Thermo_21325, "delta_composition", "H(45) C(34) N(7) O(7) S"}, {UNIMOD_Biotin_Thermo_21325, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Biotin_Thermo_21325, "spec_1_hidden", "1"}, {UNIMOD_Biotin_Thermo_21325, "spec_1_position", "Anywhere"}, {UNIMOD_Biotin_Thermo_21325, "spec_1_site", "K"}, {UNIMOD_Label_13C_1_2H_3__Oxidation, "approved", "0"}, {UNIMOD_Label_13C_1_2H_3__Oxidation, "delta_composition", "H(-3) 2H(3) C(-1) 13C O"}, {UNIMOD_Label_13C_1_2H_3__Oxidation, "spec_1_classification", "Multiple"}, {UNIMOD_Label_13C_1_2H_3__Oxidation, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_1_2H_3__Oxidation, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_1_2H_3__Oxidation, "spec_1_site", "M"}, {UNIMOD_HydroxymethylOP, "approved", "0"}, {UNIMOD_HydroxymethylOP, "delta_composition", "H(4) C(6) O(2)"}, {UNIMOD_HydroxymethylOP, "spec_1_classification", "Other"}, {UNIMOD_HydroxymethylOP, "spec_1_hidden", "1"}, {UNIMOD_HydroxymethylOP, "spec_1_position", "Anywhere"}, {UNIMOD_HydroxymethylOP, "spec_1_site", "K"}, {UNIMOD_MDCC, "approved", "0"}, {UNIMOD_MDCC, "delta_composition", "H(21) C(20) N(3) O(5)"}, {UNIMOD_MDCC, "spec_1_classification", "Chemical derivative"}, {UNIMOD_MDCC, "spec_1_hidden", "1"}, {UNIMOD_MDCC, "spec_1_position", "Anywhere"}, {UNIMOD_MDCC, "spec_1_site", "C"}, {UNIMOD_mTRAQ, "approved", "0"}, {UNIMOD_mTRAQ, "delta_composition", "H(12) C(7) N(2) O"}, {UNIMOD_mTRAQ, "spec_1_classification", "Isotopic label"}, {UNIMOD_mTRAQ, "spec_1_hidden", "0"}, {UNIMOD_mTRAQ, "spec_1_position", "Anywhere"}, {UNIMOD_mTRAQ, "spec_1_site", "K"}, {UNIMOD_mTRAQ, "spec_2_classification", "Isotopic label"}, {UNIMOD_mTRAQ, "spec_2_hidden", "0"}, {UNIMOD_mTRAQ, "spec_2_position", "Any N-term"}, {UNIMOD_mTRAQ, "spec_2_site", "N-term"}, {UNIMOD_mTRAQ, "spec_3_classification", "Isotopic label"}, {UNIMOD_mTRAQ, "spec_3_hidden", "0"}, {UNIMOD_mTRAQ, "spec_3_position", "Anywhere"}, {UNIMOD_mTRAQ, "spec_3_site", "Y"}, {UNIMOD_mTRAQ, "spec_4_classification", "Isotopic label"}, {UNIMOD_mTRAQ, "spec_4_hidden", "1"}, {UNIMOD_mTRAQ, "spec_4_position", "Anywhere"}, {UNIMOD_mTRAQ, "spec_4_site", "H"}, {UNIMOD_mTRAQ, "spec_5_classification", "Isotopic label"}, {UNIMOD_mTRAQ, "spec_5_hidden", "1"}, {UNIMOD_mTRAQ, "spec_5_position", "Anywhere"}, {UNIMOD_mTRAQ, "spec_5_site", "S"}, {UNIMOD_mTRAQ, "spec_6_classification", "Isotopic label"}, {UNIMOD_mTRAQ, "spec_6_hidden", "1"}, {UNIMOD_mTRAQ, "spec_6_position", "Anywhere"}, {UNIMOD_mTRAQ, "spec_6_site", "T"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "approved", "0"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "delta_composition", "H(12) C(4) 13C(3) N 15N O"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_1_classification", "Isotopic label"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_1_hidden", "0"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_1_position", "Anywhere"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_1_site", "K"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_2_classification", "Isotopic label"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_2_hidden", "0"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_2_position", "Any N-term"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_2_site", "N-term"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_3_classification", "Isotopic label"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_3_hidden", "0"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_3_position", "Anywhere"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_3_site", "Y"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_4_classification", "Isotopic label"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_4_hidden", "1"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_4_position", "Anywhere"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_4_site", "H"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_5_classification", "Isotopic label"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_5_hidden", "1"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_5_position", "Anywhere"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_5_site", "S"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_6_classification", "Isotopic label"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_6_hidden", "1"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_6_position", "Anywhere"}, {UNIMOD_mTRAQ_13C_3_15N_1_, "spec_6_site", "T"}, {UNIMOD_DyLight_maleimide, "approved", "0"}, {UNIMOD_DyLight_maleimide, "delta_composition", "H(48) C(39) N(4) O(15) S(4)"}, {UNIMOD_DyLight_maleimide, "spec_1_classification", "Chemical derivative"}, {UNIMOD_DyLight_maleimide, "spec_1_hidden", "1"}, {UNIMOD_DyLight_maleimide, "spec_1_position", "Anywhere"}, {UNIMOD_DyLight_maleimide, "spec_1_site", "C"}, {UNIMOD_Methyl_PEO12_Maleimide, "approved", "0"}, {UNIMOD_Methyl_PEO12_Maleimide, "delta_composition", "H(58) C(32) N(2) O(15)"}, {UNIMOD_Methyl_PEO12_Maleimide, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Methyl_PEO12_Maleimide, "spec_1_hidden", "1"}, {UNIMOD_Methyl_PEO12_Maleimide, "spec_1_position", "Anywhere"}, {UNIMOD_Methyl_PEO12_Maleimide, "spec_1_site", "C"}, {UNIMOD_CarbamidomethylDTT, "approved", "0"}, {UNIMOD_CarbamidomethylDTT, "delta_composition", "H(11) C(6) N O(3) S(2)"}, {UNIMOD_CarbamidomethylDTT, "spec_1_classification", "Artefact"}, {UNIMOD_CarbamidomethylDTT, "spec_1_hidden", "1"}, {UNIMOD_CarbamidomethylDTT, "spec_1_position", "Anywhere"}, {UNIMOD_CarbamidomethylDTT, "spec_1_site", "C"}, {UNIMOD_CarboxymethylDTT, "approved", "0"}, {UNIMOD_CarboxymethylDTT, "delta_composition", "H(10) C(6) O(4) S(2)"}, {UNIMOD_CarboxymethylDTT, "spec_1_classification", "Artefact"}, {UNIMOD_CarboxymethylDTT, "spec_1_hidden", "1"}, {UNIMOD_CarboxymethylDTT, "spec_1_position", "Anywhere"}, {UNIMOD_CarboxymethylDTT, "spec_1_site", "C"}, {UNIMOD_Biotin_PEG_PRA, "approved", "0"}, {UNIMOD_Biotin_PEG_PRA, "delta_composition", "H(42) C(26) N(8) O(7)"}, {UNIMOD_Biotin_PEG_PRA, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Biotin_PEG_PRA, "spec_1_hidden", "1"}, {UNIMOD_Biotin_PEG_PRA, "spec_1_position", "Anywhere"}, {UNIMOD_Biotin_PEG_PRA, "spec_1_site", "M"}, {UNIMOD_Met__Aha, "approved", "0"}, {UNIMOD_Met__Aha, "delta_composition", "H(-3) C(-1) N(3) S(-1)"}, {UNIMOD_Met__Aha, "spec_1_classification", "Non-standard residue"}, {UNIMOD_Met__Aha, "spec_1_hidden", "1"}, {UNIMOD_Met__Aha, "spec_1_position", "Anywhere"}, {UNIMOD_Met__Aha, "spec_1_site", "M"}, {UNIMOD_Label_15N_4_, "approved", "0"}, {UNIMOD_Label_15N_4_, "delta_composition", "N(-4) 15N(4)"}, {UNIMOD_Label_15N_4_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_15N_4_, "spec_1_hidden", "1"}, {UNIMOD_Label_15N_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_15N_4_, "spec_1_site", "R"}, {UNIMOD_pyrophospho, "approved", "0"}, {UNIMOD_pyrophospho, "delta_composition", "H(2) O(6) P(2)"}, {UNIMOD_pyrophospho, "spec_1_classification", "Post-translational"}, {UNIMOD_pyrophospho, "spec_1_hidden", "1"}, {UNIMOD_pyrophospho, "spec_1_position", "Anywhere"}, {UNIMOD_pyrophospho, "spec_1_site", "S"}, {UNIMOD_pyrophospho, "spec_2_classification", "Post-translational"}, {UNIMOD_pyrophospho, "spec_2_hidden", "1"}, {UNIMOD_pyrophospho, "spec_2_position", "Anywhere"}, {UNIMOD_pyrophospho, "spec_2_site", "T"}, {UNIMOD_Met__Hpg, "approved", "0"}, {UNIMOD_Met__Hpg, "delta_composition", "H(-2) C S(-1)"}, {UNIMOD_Met__Hpg, "spec_1_classification", "Non-standard residue"}, {UNIMOD_Met__Hpg, "spec_1_hidden", "1"}, {UNIMOD_Met__Hpg, "spec_1_position", "Anywhere"}, {UNIMOD_Met__Hpg, "spec_1_site", "M"}, {UNIMOD_4AcAllylGal, "approved", "0"}, {UNIMOD_4AcAllylGal, "delta_composition", "H(24) C(17) O(9)"}, {UNIMOD_4AcAllylGal, "spec_1_classification", "Chemical derivative"}, {UNIMOD_4AcAllylGal, "spec_1_hidden", "1"}, {UNIMOD_4AcAllylGal, "spec_1_position", "Anywhere"}, {UNIMOD_4AcAllylGal, "spec_1_site", "C"}, {UNIMOD_DimethylArsino, "approved", "0"}, {UNIMOD_DimethylArsino, "delta_composition", "H(5) C(2) As"}, {UNIMOD_DimethylArsino, "spec_1_classification", "Post-translational"}, {UNIMOD_DimethylArsino, "spec_1_hidden", "1"}, {UNIMOD_DimethylArsino, "spec_1_position", "Anywhere"}, {UNIMOD_DimethylArsino, "spec_1_site", "C"}, {UNIMOD_Lys__CamCys, "approved", "0"}, {UNIMOD_Lys__CamCys, "delta_composition", "H(-4) C(-1) O S"}, {UNIMOD_Lys__CamCys, "spec_1_classification", "Pre-translational"}, {UNIMOD_Lys__CamCys, "spec_1_hidden", "1"}, {UNIMOD_Lys__CamCys, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__CamCys, "spec_1_site", "K"}, {UNIMOD_Phe__CamCys, "approved", "0"}, {UNIMOD_Phe__CamCys, "delta_composition", "H(-1) C(-4) N O S"}, {UNIMOD_Phe__CamCys, "spec_1_classification", "Pre-translational"}, {UNIMOD_Phe__CamCys, "spec_1_hidden", "1"}, {UNIMOD_Phe__CamCys, "spec_1_position", "Anywhere"}, {UNIMOD_Phe__CamCys, "spec_1_site", "F"}, {UNIMOD_Leu__MetOx, "approved", "0"}, {UNIMOD_Leu__MetOx, "delta_composition", "H(-2) C(-1) O S"}, {UNIMOD_Leu__MetOx, "spec_1_classification", "Pre-translational"}, {UNIMOD_Leu__MetOx, "spec_1_hidden", "1"}, {UNIMOD_Leu__MetOx, "spec_1_position", "Anywhere"}, {UNIMOD_Leu__MetOx, "spec_1_site", "L"}, {UNIMOD_Lys__MetOx, "approved", "0"}, {UNIMOD_Lys__MetOx, "delta_composition", "H(-3) C(-1) N(-1) O S"}, {UNIMOD_Lys__MetOx, "spec_1_classification", "Pre-translational"}, {UNIMOD_Lys__MetOx, "spec_1_hidden", "1"}, {UNIMOD_Lys__MetOx, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__MetOx, "spec_1_site", "K"}, {UNIMOD_Galactosyl, "approved", "0"}, {UNIMOD_Galactosyl, "delta_composition", "O Hex"}, {UNIMOD_Galactosyl, "spec_1_classification", "Other glycosylation"}, {UNIMOD_Galactosyl, "spec_1_hidden", "1"}, {UNIMOD_Galactosyl, "spec_1_position", "Anywhere"}, {UNIMOD_Galactosyl, "spec_1_site", "K"}, {UNIMOD_SMCC_maleimide, "approved", "0"}, {UNIMOD_SMCC_maleimide, "delta_composition", "H(27) C(17) N(3) O(3)"}, {UNIMOD_SMCC_maleimide, "spec_1_classification", "Chemical derivative"}, {UNIMOD_SMCC_maleimide, "spec_1_hidden", "1"}, {UNIMOD_SMCC_maleimide, "spec_1_position", "Anywhere"}, {UNIMOD_SMCC_maleimide, "spec_1_site", "C"}, {UNIMOD_Bacillosamine, "approved", "0"}, {UNIMOD_Bacillosamine, "delta_composition", "H(6) C(4) N(2) dHex"}, {UNIMOD_Bacillosamine, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Bacillosamine, "spec_1_hidden", "1"}, {UNIMOD_Bacillosamine, "spec_1_position", "Anywhere"}, {UNIMOD_Bacillosamine, "spec_1_site", "N"}, {UNIMOD_MTSL, "approved", "0"}, {UNIMOD_MTSL, "delta_composition", "H(14) C(9) N O S"}, {UNIMOD_MTSL, "spec_1_classification", "Chemical derivative"}, {UNIMOD_MTSL, "spec_1_hidden", "1"}, {UNIMOD_MTSL, "spec_1_position", "Anywhere"}, {UNIMOD_MTSL, "spec_1_site", "C"}, {UNIMOD_HNE_BAHAH, "approved", "0"}, {UNIMOD_HNE_BAHAH, "delta_composition", "H(45) C(25) N(5) O(4) S"}, {UNIMOD_HNE_BAHAH, "spec_1_classification", "Chemical derivative"}, {UNIMOD_HNE_BAHAH, "spec_1_hidden", "1"}, {UNIMOD_HNE_BAHAH, "spec_1_position", "Anywhere"}, {UNIMOD_HNE_BAHAH, "spec_1_site", "C"}, {UNIMOD_HNE_BAHAH, "spec_2_classification", "Chemical derivative"}, {UNIMOD_HNE_BAHAH, "spec_2_hidden", "1"}, {UNIMOD_HNE_BAHAH, "spec_2_position", "Anywhere"}, {UNIMOD_HNE_BAHAH, "spec_2_site", "H"}, {UNIMOD_HNE_BAHAH, "spec_3_classification", "Chemical derivative"}, {UNIMOD_HNE_BAHAH, "spec_3_hidden", "1"}, {UNIMOD_HNE_BAHAH, "spec_3_position", "Anywhere"}, {UNIMOD_HNE_BAHAH, "spec_3_site", "K"}, {UNIMOD_Methylmalonylation, "approved", "0"}, {UNIMOD_Methylmalonylation, "delta_composition", "H(4) C(4) O(3)"}, {UNIMOD_Methylmalonylation, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Methylmalonylation, "spec_1_hidden", "1"}, {UNIMOD_Methylmalonylation, "spec_1_position", "Anywhere"}, {UNIMOD_Methylmalonylation, "spec_1_site", "S"}, {UNIMOD_Ethoxyformyl, "approved", "0"}, {UNIMOD_Ethoxyformyl, "delta_composition", "H(5) C(3) O(2)"}, {UNIMOD_Ethoxyformyl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Ethoxyformyl, "spec_1_hidden", "1"}, {UNIMOD_Ethoxyformyl, "spec_1_position", "Anywhere"}, {UNIMOD_Ethoxyformyl, "spec_1_site", "H"}, {UNIMOD_Label_13C_4_15N_2__GG, "approved", "0"}, {UNIMOD_Label_13C_4_15N_2__GG, "delta_composition", "H(6) 13C(4) 15N(2) O(2)"}, {UNIMOD_Label_13C_4_15N_2__GG, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_4_15N_2__GG, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_4_15N_2__GG, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_4_15N_2__GG, "spec_1_site", "K"}, {UNIMOD_ethylamino, "approved", "0"}, {UNIMOD_ethylamino, "delta_composition", "H(5) C(2) N O(-1)"}, {UNIMOD_ethylamino, "spec_1_classification", "Chemical derivative"}, {UNIMOD_ethylamino, "spec_1_hidden", "1"}, {UNIMOD_ethylamino, "spec_1_position", "Anywhere"}, {UNIMOD_ethylamino, "spec_1_site", "S"}, {UNIMOD_ethylamino, "spec_2_classification", "Chemical derivative"}, {UNIMOD_ethylamino, "spec_2_hidden", "1"}, {UNIMOD_ethylamino, "spec_2_position", "Anywhere"}, {UNIMOD_ethylamino, "spec_2_site", "T"}, {UNIMOD_MercaptoEthanol, "approved", "0"}, {UNIMOD_MercaptoEthanol, "delta_composition", "H(4) C(2) S"}, {UNIMOD_MercaptoEthanol, "spec_1_classification", "Chemical derivative"}, {UNIMOD_MercaptoEthanol, "spec_1_hidden", "1"}, {UNIMOD_MercaptoEthanol, "spec_1_position", "Anywhere"}, {UNIMOD_MercaptoEthanol, "spec_1_site", "S"}, {UNIMOD_MercaptoEthanol, "spec_2_classification", "Chemical derivative"}, {UNIMOD_MercaptoEthanol, "spec_2_hidden", "1"}, {UNIMOD_MercaptoEthanol, "spec_2_position", "Anywhere"}, {UNIMOD_MercaptoEthanol, "spec_2_site", "T"}, {UNIMOD_Ethyl_Deamidated, "approved", "0"}, {UNIMOD_Ethyl_Deamidated, "delta_composition", "H(3) C(2) N(-1) O"}, {UNIMOD_Ethyl_Deamidated, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Ethyl_Deamidated, "spec_1_hidden", "1"}, {UNIMOD_Ethyl_Deamidated, "spec_1_position", "Anywhere"}, {UNIMOD_Ethyl_Deamidated, "spec_1_site", "N"}, {UNIMOD_Ethyl_Deamidated, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Ethyl_Deamidated, "spec_2_hidden", "1"}, {UNIMOD_Ethyl_Deamidated, "spec_2_position", "Anywhere"}, {UNIMOD_Ethyl_Deamidated, "spec_2_site", "Q"}, {UNIMOD_VFQQQTGG, "approved", "0"}, {UNIMOD_VFQQQTGG, "delta_composition", "H(55) C(37) N(11) O(12)"}, {UNIMOD_VFQQQTGG, "spec_1_classification", "Other"}, {UNIMOD_VFQQQTGG, "spec_1_hidden", "1"}, {UNIMOD_VFQQQTGG, "spec_1_position", "Anywhere"}, {UNIMOD_VFQQQTGG, "spec_1_site", "K"}, {UNIMOD_VIEVYQEQTGG, "approved", "0"}, {UNIMOD_VIEVYQEQTGG, "delta_composition", "H(81) C(53) N(13) O(19)"}, {UNIMOD_VIEVYQEQTGG, "spec_1_classification", "Other"}, {UNIMOD_VIEVYQEQTGG, "spec_1_hidden", "1"}, {UNIMOD_VIEVYQEQTGG, "spec_1_position", "Anywhere"}, {UNIMOD_VIEVYQEQTGG, "spec_1_site", "K"}, {UNIMOD_AMTzHexNAc2, "approved", "0"}, {UNIMOD_AMTzHexNAc2, "delta_composition", "H(30) C(19) N(6) O(10)"}, {UNIMOD_AMTzHexNAc2, "spec_1_classification", "Chemical derivative"}, {UNIMOD_AMTzHexNAc2, "spec_1_hidden", "1"}, {UNIMOD_AMTzHexNAc2, "spec_1_position", "Anywhere"}, {UNIMOD_AMTzHexNAc2, "spec_1_site", "N"}, {UNIMOD_AMTzHexNAc2, "spec_2_classification", "Chemical derivative"}, {UNIMOD_AMTzHexNAc2, "spec_2_hidden", "1"}, {UNIMOD_AMTzHexNAc2, "spec_2_position", "Anywhere"}, {UNIMOD_AMTzHexNAc2, "spec_2_site", "S"}, {UNIMOD_AMTzHexNAc2, "spec_3_classification", "Chemical derivative"}, {UNIMOD_AMTzHexNAc2, "spec_3_hidden", "1"}, {UNIMOD_AMTzHexNAc2, "spec_3_position", "Anywhere"}, {UNIMOD_AMTzHexNAc2, "spec_3_site", "T"}, {UNIMOD_Atto495Maleimide, "approved", "0"}, {UNIMOD_Atto495Maleimide, "delta_composition", "H(32) C(27) N(5) O(3)"}, {UNIMOD_Atto495Maleimide, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Atto495Maleimide, "spec_1_hidden", "1"}, {UNIMOD_Atto495Maleimide, "spec_1_position", "Anywhere"}, {UNIMOD_Atto495Maleimide, "spec_1_site", "C"}, {UNIMOD_Chlorination, "approved", "0"}, {UNIMOD_Chlorination, "delta_composition", "H(-1) Cl"}, {UNIMOD_Chlorination, "spec_1_classification", "Artefact"}, {UNIMOD_Chlorination, "spec_1_hidden", "1"}, {UNIMOD_Chlorination, "spec_1_position", "Anywhere"}, {UNIMOD_Chlorination, "spec_1_site", "Y"}, {UNIMOD_dichlorination, "approved", "0"}, {UNIMOD_dichlorination, "delta_composition", "H(-2) Cl(2)"}, {UNIMOD_dichlorination, "spec_1_classification", "Artefact"}, {UNIMOD_dichlorination, "spec_1_hidden", "1"}, {UNIMOD_dichlorination, "spec_1_position", "Anywhere"}, {UNIMOD_dichlorination, "spec_1_site", "Y"}, {UNIMOD_dichlorination, "spec_2_classification", "Chemical derivative"}, {UNIMOD_dichlorination, "spec_2_hidden", "1"}, {UNIMOD_dichlorination, "spec_2_position", "Anywhere"}, {UNIMOD_dichlorination, "spec_2_site", "C"}, {UNIMOD_AROD, "approved", "0"}, {UNIMOD_AROD, "delta_composition", "H(52) C(35) N(10) O(9) S(2)"}, {UNIMOD_AROD, "spec_1_classification", "Chemical derivative"}, {UNIMOD_AROD, "spec_1_hidden", "1"}, {UNIMOD_AROD, "spec_1_position", "Anywhere"}, {UNIMOD_AROD, "spec_1_site", "C"}, {UNIMOD_Cys__methylaminoAla, "approved", "0"}, {UNIMOD_Cys__methylaminoAla, "delta_composition", "H(3) C N S(-1)"}, {UNIMOD_Cys__methylaminoAla, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Cys__methylaminoAla, "spec_1_hidden", "1"}, {UNIMOD_Cys__methylaminoAla, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__methylaminoAla, "spec_1_site", "C"}, {UNIMOD_Cys__ethylaminoAla, "approved", "0"}, {UNIMOD_Cys__ethylaminoAla, "delta_composition", "H(5) C(2) N S(-1)"}, {UNIMOD_Cys__ethylaminoAla, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Cys__ethylaminoAla, "spec_1_hidden", "1"}, {UNIMOD_Cys__ethylaminoAla, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__ethylaminoAla, "spec_1_site", "C"}, {UNIMOD_DNPS, "approved", "0"}, {UNIMOD_DNPS, "delta_composition", "H(3) C(6) N(2) O(4) S"}, {UNIMOD_DNPS, "spec_1_classification", "Chemical derivative"}, {UNIMOD_DNPS, "spec_1_hidden", "1"}, {UNIMOD_DNPS, "spec_1_position", "Anywhere"}, {UNIMOD_DNPS, "spec_1_site", "C"}, {UNIMOD_DNPS, "spec_2_classification", "Chemical derivative"}, {UNIMOD_DNPS, "spec_2_hidden", "1"}, {UNIMOD_DNPS, "spec_2_position", "Anywhere"}, {UNIMOD_DNPS, "spec_2_site", "W"}, {UNIMOD_SulfoGMBS, "approved", "0"}, {UNIMOD_SulfoGMBS, "delta_composition", "H(26) C(22) N(4) O(5) S"}, {UNIMOD_SulfoGMBS, "spec_1_classification", "Other"}, {UNIMOD_SulfoGMBS, "spec_1_hidden", "1"}, {UNIMOD_SulfoGMBS, "spec_1_position", "Anywhere"}, {UNIMOD_SulfoGMBS, "spec_1_site", "C"}, {UNIMOD_DimethylamineGMBS, "approved", "0"}, {UNIMOD_DimethylamineGMBS, "delta_composition", "H(21) C(13) N(3) O(3)"}, {UNIMOD_DimethylamineGMBS, "spec_1_classification", "Chemical derivative"}, {UNIMOD_DimethylamineGMBS, "spec_1_hidden", "1"}, {UNIMOD_DimethylamineGMBS, "spec_1_position", "Anywhere"}, {UNIMOD_DimethylamineGMBS, "spec_1_site", "C"}, {UNIMOD_Label_15N_2_2H_9_, "approved", "0"}, {UNIMOD_Label_15N_2_2H_9_, "delta_composition", "H(-9) 2H(9) N(-2) 15N(2)"}, {UNIMOD_Label_15N_2_2H_9_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_15N_2_2H_9_, "spec_1_hidden", "1"}, {UNIMOD_Label_15N_2_2H_9_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_15N_2_2H_9_, "spec_1_site", "K"}, {UNIMOD_LG_anhydrolactam, "approved", "0"}, {UNIMOD_LG_anhydrolactam, "delta_composition", "H(26) C(20) O(3)"}, {UNIMOD_LG_anhydrolactam, "spec_1_classification", "Post-translational"}, {UNIMOD_LG_anhydrolactam, "spec_1_hidden", "1"}, {UNIMOD_LG_anhydrolactam, "spec_1_position", "Anywhere"}, {UNIMOD_LG_anhydrolactam, "spec_1_site", "K"}, {UNIMOD_LG_anhydrolactam, "spec_2_classification", "Post-translational"}, {UNIMOD_LG_anhydrolactam, "spec_2_hidden", "1"}, {UNIMOD_LG_anhydrolactam, "spec_2_position", "Any N-term"}, {UNIMOD_LG_anhydrolactam, "spec_2_site", "N-term"}, {UNIMOD_LG_pyrrole, "approved", "0"}, {UNIMOD_LG_pyrrole, "delta_composition", "H(28) C(20) O(3)"}, {UNIMOD_LG_pyrrole, "spec_1_classification", "Post-translational"}, {UNIMOD_LG_pyrrole, "spec_1_hidden", "1"}, {UNIMOD_LG_pyrrole, "spec_1_position", "Anywhere"}, {UNIMOD_LG_pyrrole, "spec_1_site", "K"}, {UNIMOD_LG_pyrrole, "spec_2_classification", "Post-translational"}, {UNIMOD_LG_pyrrole, "spec_2_hidden", "1"}, {UNIMOD_LG_pyrrole, "spec_2_position", "Any N-term"}, {UNIMOD_LG_pyrrole, "spec_2_site", "N-term"}, {UNIMOD_LG_anhyropyrrole, "approved", "0"}, {UNIMOD_LG_anhyropyrrole, "delta_composition", "H(26) C(20) O(2)"}, {UNIMOD_LG_anhyropyrrole, "spec_1_classification", "Post-translational"}, {UNIMOD_LG_anhyropyrrole, "spec_1_hidden", "1"}, {UNIMOD_LG_anhyropyrrole, "spec_1_position", "Anywhere"}, {UNIMOD_LG_anhyropyrrole, "spec_1_site", "K"}, {UNIMOD_LG_anhyropyrrole, "spec_2_classification", "Post-translational"}, {UNIMOD_LG_anhyropyrrole, "spec_2_hidden", "1"}, {UNIMOD_LG_anhyropyrrole, "spec_2_position", "Any N-term"}, {UNIMOD_LG_anhyropyrrole, "spec_2_site", "N-term"}, {UNIMOD_3_deoxyglucosone, "approved", "0"}, {UNIMOD_3_deoxyglucosone, "delta_composition", "H(8) C(6) O(4)"}, {UNIMOD_3_deoxyglucosone, "spec_1_classification", "Multiple"}, {UNIMOD_3_deoxyglucosone, "spec_1_hidden", "1"}, {UNIMOD_3_deoxyglucosone, "spec_1_position", "Anywhere"}, {UNIMOD_3_deoxyglucosone, "spec_1_site", "R"}, {UNIMOD_Cation_Li, "approved", "0"}, {UNIMOD_Cation_Li, "delta_composition", "H(-1) Li"}, {UNIMOD_Cation_Li, "spec_1_classification", "Artefact"}, {UNIMOD_Cation_Li, "spec_1_classification", "Artefact"}, {UNIMOD_Cation_Li, "spec_1_hidden", "1"}, {UNIMOD_Cation_Li, "spec_1_hidden", "1"}, {UNIMOD_Cation_Li, "spec_1_position", "Anywhere"}, {UNIMOD_Cation_Li, "spec_1_position", "Anywhere"}, {UNIMOD_Cation_Li, "spec_1_site", "D"}, {UNIMOD_Cation_Li, "spec_1_site", "E"}, {UNIMOD_Cation_Li, "spec_2_classification", "Artefact"}, {UNIMOD_Cation_Li, "spec_2_hidden", "1"}, {UNIMOD_Cation_Li, "spec_2_position", "Any C-term"}, {UNIMOD_Cation_Li, "spec_2_site", "C-term"}, {UNIMOD_Cation_Ca_II_, "approved", "0"}, {UNIMOD_Cation_Ca_II_, "delta_composition", "H(-2) Ca"}, {UNIMOD_Cation_Ca_II_, "spec_1_classification", "Artefact"}, {UNIMOD_Cation_Ca_II_, "spec_1_classification", "Artefact"}, {UNIMOD_Cation_Ca_II_, "spec_1_hidden", "1"}, {UNIMOD_Cation_Ca_II_, "spec_1_hidden", "1"}, {UNIMOD_Cation_Ca_II_, "spec_1_position", "Anywhere"}, {UNIMOD_Cation_Ca_II_, "spec_1_position", "Anywhere"}, {UNIMOD_Cation_Ca_II_, "spec_1_site", "E"}, {UNIMOD_Cation_Ca_II_, "spec_1_site", "D"}, {UNIMOD_Cation_Ca_II_, "spec_2_classification", "Artefact"}, {UNIMOD_Cation_Ca_II_, "spec_2_hidden", "1"}, {UNIMOD_Cation_Ca_II_, "spec_2_position", "Any C-term"}, {UNIMOD_Cation_Ca_II_, "spec_2_site", "C-term"}, {UNIMOD_Cation_Fe_II_, "approved", "0"}, {UNIMOD_Cation_Fe_II_, "delta_composition", "H(-2) Fe"}, {UNIMOD_Cation_Fe_II_, "spec_1_classification", "Artefact"}, {UNIMOD_Cation_Fe_II_, "spec_1_classification", "Artefact"}, {UNIMOD_Cation_Fe_II_, "spec_1_hidden", "1"}, {UNIMOD_Cation_Fe_II_, "spec_1_hidden", "1"}, {UNIMOD_Cation_Fe_II_, "spec_1_position", "Anywhere"}, {UNIMOD_Cation_Fe_II_, "spec_1_position", "Anywhere"}, {UNIMOD_Cation_Fe_II_, "spec_1_site", "D"}, {UNIMOD_Cation_Fe_II_, "spec_1_site", "E"}, {UNIMOD_Cation_Fe_II_, "spec_2_classification", "Artefact"}, {UNIMOD_Cation_Fe_II_, "spec_2_hidden", "1"}, {UNIMOD_Cation_Fe_II_, "spec_2_position", "Any C-term"}, {UNIMOD_Cation_Fe_II_, "spec_2_site", "C-term"}, {UNIMOD_Cation_Ni_II_, "approved", "0"}, {UNIMOD_Cation_Ni_II_, "delta_composition", "H(-2) Ni"}, {UNIMOD_Cation_Ni_II_, "spec_1_classification", "Artefact"}, {UNIMOD_Cation_Ni_II_, "spec_1_classification", "Artefact"}, {UNIMOD_Cation_Ni_II_, "spec_1_hidden", "1"}, {UNIMOD_Cation_Ni_II_, "spec_1_hidden", "1"}, {UNIMOD_Cation_Ni_II_, "spec_1_position", "Anywhere"}, {UNIMOD_Cation_Ni_II_, "spec_1_position", "Anywhere"}, {UNIMOD_Cation_Ni_II_, "spec_1_site", "D"}, {UNIMOD_Cation_Ni_II_, "spec_1_site", "E"}, {UNIMOD_Cation_Ni_II_, "spec_2_classification", "Artefact"}, {UNIMOD_Cation_Ni_II_, "spec_2_hidden", "1"}, {UNIMOD_Cation_Ni_II_, "spec_2_position", "Any C-term"}, {UNIMOD_Cation_Ni_II_, "spec_2_site", "C-term"}, {UNIMOD_Cation_Zn_II_, "approved", "0"}, {UNIMOD_Cation_Zn_II_, "delta_composition", "H(-2) Zn"}, {UNIMOD_Cation_Zn_II_, "spec_1_classification", "Artefact"}, {UNIMOD_Cation_Zn_II_, "spec_1_classification", "Artefact"}, {UNIMOD_Cation_Zn_II_, "spec_1_hidden", "1"}, {UNIMOD_Cation_Zn_II_, "spec_1_hidden", "1"}, {UNIMOD_Cation_Zn_II_, "spec_1_position", "Anywhere"}, {UNIMOD_Cation_Zn_II_, "spec_1_position", "Anywhere"}, {UNIMOD_Cation_Zn_II_, "spec_1_site", "E"}, {UNIMOD_Cation_Zn_II_, "spec_1_site", "D"}, {UNIMOD_Cation_Zn_II_, "spec_2_classification", "Artefact"}, {UNIMOD_Cation_Zn_II_, "spec_2_hidden", "1"}, {UNIMOD_Cation_Zn_II_, "spec_2_position", "Any C-term"}, {UNIMOD_Cation_Zn_II_, "spec_2_site", "C-term"}, {UNIMOD_Cation_Zn_II_, "spec_3_classification", "Artefact"}, {UNIMOD_Cation_Zn_II_, "spec_3_hidden", "1"}, {UNIMOD_Cation_Zn_II_, "spec_3_position", "Anywhere"}, {UNIMOD_Cation_Zn_II_, "spec_3_site", "H"}, {UNIMOD_Cation_Ag, "approved", "0"}, {UNIMOD_Cation_Ag, "delta_composition", "H(-1) Ag"}, {UNIMOD_Cation_Ag, "spec_1_classification", "Artefact"}, {UNIMOD_Cation_Ag, "spec_1_classification", "Artefact"}, {UNIMOD_Cation_Ag, "spec_1_hidden", "1"}, {UNIMOD_Cation_Ag, "spec_1_hidden", "1"}, {UNIMOD_Cation_Ag, "spec_1_position", "Anywhere"}, {UNIMOD_Cation_Ag, "spec_1_position", "Anywhere"}, {UNIMOD_Cation_Ag, "spec_1_site", "D"}, {UNIMOD_Cation_Ag, "spec_1_site", "E"}, {UNIMOD_Cation_Ag, "spec_2_classification", "Artefact"}, {UNIMOD_Cation_Ag, "spec_2_hidden", "1"}, {UNIMOD_Cation_Ag, "spec_2_position", "Any C-term"}, {UNIMOD_Cation_Ag, "spec_2_site", "C-term"}, {UNIMOD_Cation_Mg_II_, "approved", "0"}, {UNIMOD_Cation_Mg_II_, "delta_composition", "H(-2) Mg"}, {UNIMOD_Cation_Mg_II_, "spec_1_classification", "Artefact"}, {UNIMOD_Cation_Mg_II_, "spec_1_classification", "Artefact"}, {UNIMOD_Cation_Mg_II_, "spec_1_hidden", "1"}, {UNIMOD_Cation_Mg_II_, "spec_1_hidden", "1"}, {UNIMOD_Cation_Mg_II_, "spec_1_position", "Anywhere"}, {UNIMOD_Cation_Mg_II_, "spec_1_position", "Anywhere"}, {UNIMOD_Cation_Mg_II_, "spec_1_site", "D"}, {UNIMOD_Cation_Mg_II_, "spec_1_site", "E"}, {UNIMOD_Cation_Mg_II_, "spec_2_classification", "Artefact"}, {UNIMOD_Cation_Mg_II_, "spec_2_hidden", "1"}, {UNIMOD_Cation_Mg_II_, "spec_2_position", "Any C-term"}, {UNIMOD_Cation_Mg_II_, "spec_2_site", "C-term"}, {UNIMOD_2_succinyl, "approved", "0"}, {UNIMOD_2_succinyl, "delta_composition", "H(4) C(4) O(4)"}, {UNIMOD_2_succinyl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_2_succinyl, "spec_1_hidden", "1"}, {UNIMOD_2_succinyl, "spec_1_position", "Anywhere"}, {UNIMOD_2_succinyl, "spec_1_site", "C"}, {UNIMOD_Propargylamine, "approved", "0"}, {UNIMOD_Propargylamine, "delta_composition", "H(3) C(3) N O(-1)"}, {UNIMOD_Propargylamine, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Propargylamine, "spec_1_hidden", "1"}, {UNIMOD_Propargylamine, "spec_1_position", "Any C-term"}, {UNIMOD_Propargylamine, "spec_1_site", "C-term"}, {UNIMOD_Propargylamine, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Propargylamine, "spec_2_hidden", "1"}, {UNIMOD_Propargylamine, "spec_2_position", "Anywhere"}, {UNIMOD_Propargylamine, "spec_2_site", "D"}, {UNIMOD_Propargylamine, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Propargylamine, "spec_3_hidden", "1"}, {UNIMOD_Propargylamine, "spec_3_position", "Anywhere"}, {UNIMOD_Propargylamine, "spec_3_site", "E"}, {UNIMOD_Phosphopropargyl, "approved", "0"}, {UNIMOD_Phosphopropargyl, "delta_composition", "H(4) C(3) N O(2) P"}, {UNIMOD_Phosphopropargyl, "spec_1_classification", "Multiple"}, {UNIMOD_Phosphopropargyl, "spec_1_hidden", "1"}, {UNIMOD_Phosphopropargyl, "spec_1_position", "Anywhere"}, {UNIMOD_Phosphopropargyl, "spec_1_site", "S"}, {UNIMOD_Phosphopropargyl, "spec_2_classification", "Multiple"}, {UNIMOD_Phosphopropargyl, "spec_2_hidden", "1"}, {UNIMOD_Phosphopropargyl, "spec_2_position", "Anywhere"}, {UNIMOD_Phosphopropargyl, "spec_2_site", "T"}, {UNIMOD_Phosphopropargyl, "spec_3_classification", "Multiple"}, {UNIMOD_Phosphopropargyl, "spec_3_hidden", "1"}, {UNIMOD_Phosphopropargyl, "spec_3_position", "Anywhere"}, {UNIMOD_Phosphopropargyl, "spec_3_site", "Y"}, {UNIMOD_SUMO2135, "approved", "0"}, {UNIMOD_SUMO2135, "delta_composition", "H(137) C(90) N(21) O(37) S"}, {UNIMOD_SUMO2135, "spec_1_classification", "Other"}, {UNIMOD_SUMO2135, "spec_1_hidden", "1"}, {UNIMOD_SUMO2135, "spec_1_position", "Anywhere"}, {UNIMOD_SUMO2135, "spec_1_site", "K"}, {UNIMOD_SUMO3549, "approved", "0"}, {UNIMOD_SUMO3549, "delta_composition", "H(224) C(150) N(38) O(60) S"}, {UNIMOD_SUMO3549, "spec_1_classification", "Other"}, {UNIMOD_SUMO3549, "spec_1_hidden", "1"}, {UNIMOD_SUMO3549, "spec_1_position", "Anywhere"}, {UNIMOD_SUMO3549, "spec_1_site", "K"}, {UNIMOD_thioacylPA, "approved", "0"}, {UNIMOD_thioacylPA, "delta_composition", "H(9) C(6) N O(2) S"}, {UNIMOD_thioacylPA, "spec_1_classification", "Chemical derivative"}, {UNIMOD_thioacylPA, "spec_1_hidden", "1"}, {UNIMOD_thioacylPA, "spec_1_position", "Anywhere"}, {UNIMOD_thioacylPA, "spec_1_site", "K"}, {UNIMOD_maleimide3, "approved", "0"}, {UNIMOD_maleimide3, "delta_composition", "H(59) C(37) N(7) O(23)"}, {UNIMOD_maleimide3, "spec_1_classification", "Post-translational"}, {UNIMOD_maleimide3, "spec_1_hidden", "1"}, {UNIMOD_maleimide3, "spec_1_position", "Anywhere"}, {UNIMOD_maleimide3, "spec_1_site", "K"}, {UNIMOD_maleimide3, "spec_2_classification", "Post-translational"}, {UNIMOD_maleimide3, "spec_2_hidden", "1"}, {UNIMOD_maleimide3, "spec_2_position", "Anywhere"}, {UNIMOD_maleimide3, "spec_2_site", "C"}, {UNIMOD_maleimide5, "approved", "0"}, {UNIMOD_maleimide5, "delta_composition", "H(79) C(49) N(7) O(33)"}, {UNIMOD_maleimide5, "spec_1_classification", "Post-translational"}, {UNIMOD_maleimide5, "spec_1_hidden", "1"}, {UNIMOD_maleimide5, "spec_1_position", "Anywhere"}, {UNIMOD_maleimide5, "spec_1_site", "C"}, {UNIMOD_maleimide5, "spec_2_classification", "Post-translational"}, {UNIMOD_maleimide5, "spec_2_hidden", "1"}, {UNIMOD_maleimide5, "spec_2_position", "Anywhere"}, {UNIMOD_maleimide5, "spec_2_site", "K"}, {UNIMOD_Puromycin, "approved", "0"}, {UNIMOD_Puromycin, "delta_composition", "H(27) C(22) N(7) O(4)"}, {UNIMOD_Puromycin, "spec_1_classification", "Co-translational"}, {UNIMOD_Puromycin, "spec_1_hidden", "1"}, {UNIMOD_Puromycin, "spec_1_position", "Any C-term"}, {UNIMOD_Puromycin, "spec_1_site", "C-term"}, {UNIMOD_Chlorpyrifos, "approved", "0"}, {UNIMOD_Chlorpyrifos, "delta_composition", "H(10) C(4) O(2) P S"}, {UNIMOD_Chlorpyrifos, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Chlorpyrifos, "spec_1_hidden", "1"}, {UNIMOD_Chlorpyrifos, "spec_1_position", "Anywhere"}, {UNIMOD_Chlorpyrifos, "spec_1_site", "S"}, {UNIMOD_Chlorpyrifos, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Chlorpyrifos, "spec_2_hidden", "1"}, {UNIMOD_Chlorpyrifos, "spec_2_position", "Anywhere"}, {UNIMOD_Chlorpyrifos, "spec_2_site", "T"}, {UNIMOD_Chlorpyrifos, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Chlorpyrifos, "spec_3_hidden", "1"}, {UNIMOD_Chlorpyrifos, "spec_3_position", "Anywhere"}, {UNIMOD_Chlorpyrifos, "spec_3_site", "Y"}, {UNIMOD_Carbofuran, "approved", "0"}, {UNIMOD_Carbofuran, "delta_composition", "H(4) C(2) N O"}, {UNIMOD_Carbofuran, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Carbofuran, "spec_1_hidden", "1"}, {UNIMOD_Carbofuran, "spec_1_position", "Anywhere"}, {UNIMOD_Carbofuran, "spec_1_site", "S"}, {UNIMOD_BITC, "approved", "0"}, {UNIMOD_BITC, "delta_composition", "H(7) C(8) N S"}, {UNIMOD_BITC, "spec_1_classification", "Chemical derivative"}, {UNIMOD_BITC, "spec_1_hidden", "1"}, {UNIMOD_BITC, "spec_1_position", "Anywhere"}, {UNIMOD_BITC, "spec_1_site", "C"}, {UNIMOD_BITC, "spec_2_classification", "Chemical derivative"}, {UNIMOD_BITC, "spec_2_hidden", "1"}, {UNIMOD_BITC, "spec_2_position", "Anywhere"}, {UNIMOD_BITC, "spec_2_site", "K"}, {UNIMOD_BITC, "spec_3_classification", "Chemical derivative"}, {UNIMOD_BITC, "spec_3_hidden", "1"}, {UNIMOD_BITC, "spec_3_position", "Any N-term"}, {UNIMOD_BITC, "spec_3_site", "N-term"}, {UNIMOD_PEITC, "approved", "0"}, {UNIMOD_PEITC, "delta_composition", "H(9) C(9) N S"}, {UNIMOD_PEITC, "spec_1_classification", "Chemical derivative"}, {UNIMOD_PEITC, "spec_1_hidden", "1"}, {UNIMOD_PEITC, "spec_1_position", "Anywhere"}, {UNIMOD_PEITC, "spec_1_site", "C"}, {UNIMOD_PEITC, "spec_2_classification", "Chemical derivative"}, {UNIMOD_PEITC, "spec_2_hidden", "1"}, {UNIMOD_PEITC, "spec_2_position", "Anywhere"}, {UNIMOD_PEITC, "spec_2_site", "K"}, {UNIMOD_PEITC, "spec_3_classification", "Chemical derivative"}, {UNIMOD_PEITC, "spec_3_hidden", "1"}, {UNIMOD_PEITC, "spec_3_position", "Any N-term"}, {UNIMOD_PEITC, "spec_3_site", "N-term"}, {UNIMOD_glucosone, "approved", "0"}, {UNIMOD_glucosone, "delta_composition", "H(8) C(6) O(5)"}, {UNIMOD_glucosone, "spec_1_classification", "Other"}, {UNIMOD_glucosone, "spec_1_hidden", "1"}, {UNIMOD_glucosone, "spec_1_position", "Anywhere"}, {UNIMOD_glucosone, "spec_1_site", "R"}, {UNIMOD_cysTMT, "approved", "0"}, {UNIMOD_cysTMT, "delta_composition", "H(25) C(14) N(3) O(2) S"}, {UNIMOD_cysTMT, "spec_1_classification", "Chemical derivative"}, {UNIMOD_cysTMT, "spec_1_hidden", "1"}, {UNIMOD_cysTMT, "spec_1_position", "Anywhere"}, {UNIMOD_cysTMT, "spec_1_site", "C"}, {UNIMOD_cysTMT6plex, "approved", "0"}, {UNIMOD_cysTMT6plex, "delta_composition", "H(25) C(10) 13C(4) N(2) 15N O(2) S"}, {UNIMOD_cysTMT6plex, "spec_1_classification", "Isotopic label"}, {UNIMOD_cysTMT6plex, "spec_1_hidden", "0"}, {UNIMOD_cysTMT6plex, "spec_1_position", "Anywhere"}, {UNIMOD_cysTMT6plex, "spec_1_site", "C"}, {UNIMOD_Label_13C_6__Dimethyl, "approved", "0"}, {UNIMOD_Label_13C_6__Dimethyl, "delta_composition", "H(4) C(-4) 13C(6)"}, {UNIMOD_Label_13C_6__Dimethyl, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_6__Dimethyl, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_6__Dimethyl, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_6__Dimethyl, "spec_1_site", "K"}, {UNIMOD_Label_13C_6_15N_2__Dimethyl, "approved", "0"}, {UNIMOD_Label_13C_6_15N_2__Dimethyl, "delta_composition", "H(4) C(-4) 13C(6) N(-2) 15N(2)"}, {UNIMOD_Label_13C_6_15N_2__Dimethyl, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_6_15N_2__Dimethyl, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_6_15N_2__Dimethyl, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_6_15N_2__Dimethyl, "spec_1_site", "K"}, {UNIMOD_Ammonium, "approved", "0"}, {UNIMOD_Ammonium, "delta_composition", "H(3) N"}, {UNIMOD_Ammonium, "spec_1_classification", "Artefact"}, {UNIMOD_Ammonium, "spec_1_hidden", "1"}, {UNIMOD_Ammonium, "spec_1_position", "Any C-term"}, {UNIMOD_Ammonium, "spec_1_site", "C-term"}, {UNIMOD_Ammonium, "spec_2_classification", "Artefact"}, {UNIMOD_Ammonium, "spec_2_classification", "Artefact"}, {UNIMOD_Ammonium, "spec_2_hidden", "1"}, {UNIMOD_Ammonium, "spec_2_hidden", "1"}, {UNIMOD_Ammonium, "spec_2_position", "Anywhere"}, {UNIMOD_Ammonium, "spec_2_position", "Anywhere"}, {UNIMOD_Ammonium, "spec_2_site", "E"}, {UNIMOD_Ammonium, "spec_2_site", "D"}, {UNIMOD_ISD_z_2_ion, "approved", "0"}, {UNIMOD_ISD_z_2_ion, "delta_composition", "H(-1) N(-1)"}, {UNIMOD_ISD_z_2_ion, "spec_1_classification", "Artefact"}, {UNIMOD_ISD_z_2_ion, "spec_1_hidden", "1"}, {UNIMOD_ISD_z_2_ion, "spec_1_position", "Any N-term"}, {UNIMOD_ISD_z_2_ion, "spec_1_site", "N-term"}, {UNIMOD_Biotin_Sigma_B1267, "approved", "0"}, {UNIMOD_Biotin_Sigma_B1267, "delta_composition", "H(27) C(20) N(5) O(5) S"}, {UNIMOD_Biotin_Sigma_B1267, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Biotin_Sigma_B1267, "spec_1_hidden", "1"}, {UNIMOD_Biotin_Sigma_B1267, "spec_1_position", "Anywhere"}, {UNIMOD_Biotin_Sigma_B1267, "spec_1_site", "C"}, {UNIMOD_Label_15N_1_, "approved", "0"}, {UNIMOD_Label_15N_1_, "delta_composition", "N(-1) 15N"}, {UNIMOD_Label_15N_1_, "spec_10_classification", "Isotopic label"}, {UNIMOD_Label_15N_1_, "spec_10_hidden", "1"}, {UNIMOD_Label_15N_1_, "spec_10_position", "Anywhere"}, {UNIMOD_Label_15N_1_, "spec_10_site", "I"}, {UNIMOD_Label_15N_1_, "spec_11_classification", "Isotopic label"}, {UNIMOD_Label_15N_1_, "spec_11_hidden", "1"}, {UNIMOD_Label_15N_1_, "spec_11_position", "Anywhere"}, {UNIMOD_Label_15N_1_, "spec_11_site", "L"}, {UNIMOD_Label_15N_1_, "spec_12_classification", "Isotopic label"}, {UNIMOD_Label_15N_1_, "spec_12_hidden", "1"}, {UNIMOD_Label_15N_1_, "spec_12_position", "Anywhere"}, {UNIMOD_Label_15N_1_, "spec_12_site", "D"}, {UNIMOD_Label_15N_1_, "spec_13_classification", "Isotopic label"}, {UNIMOD_Label_15N_1_, "spec_13_hidden", "1"}, {UNIMOD_Label_15N_1_, "spec_13_position", "Anywhere"}, {UNIMOD_Label_15N_1_, "spec_13_site", "E"}, {UNIMOD_Label_15N_1_, "spec_14_classification", "Isotopic label"}, {UNIMOD_Label_15N_1_, "spec_14_hidden", "1"}, {UNIMOD_Label_15N_1_, "spec_14_position", "Anywhere"}, {UNIMOD_Label_15N_1_, "spec_14_site", "M"}, {UNIMOD_Label_15N_1_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_15N_1_, "spec_1_hidden", "1"}, {UNIMOD_Label_15N_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_15N_1_, "spec_1_site", "F"}, {UNIMOD_Label_15N_1_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Label_15N_1_, "spec_2_hidden", "1"}, {UNIMOD_Label_15N_1_, "spec_2_position", "Anywhere"}, {UNIMOD_Label_15N_1_, "spec_2_site", "Y"}, {UNIMOD_Label_15N_1_, "spec_3_classification", "Isotopic label"}, {UNIMOD_Label_15N_1_, "spec_3_hidden", "1"}, {UNIMOD_Label_15N_1_, "spec_3_position", "Anywhere"}, {UNIMOD_Label_15N_1_, "spec_3_site", "G"}, {UNIMOD_Label_15N_1_, "spec_4_classification", "Isotopic label"}, {UNIMOD_Label_15N_1_, "spec_4_hidden", "1"}, {UNIMOD_Label_15N_1_, "spec_4_position", "Anywhere"}, {UNIMOD_Label_15N_1_, "spec_4_site", "A"}, {UNIMOD_Label_15N_1_, "spec_5_classification", "Isotopic label"}, {UNIMOD_Label_15N_1_, "spec_5_hidden", "1"}, {UNIMOD_Label_15N_1_, "spec_5_position", "Anywhere"}, {UNIMOD_Label_15N_1_, "spec_5_site", "S"}, {UNIMOD_Label_15N_1_, "spec_6_classification", "Isotopic label"}, {UNIMOD_Label_15N_1_, "spec_6_hidden", "1"}, {UNIMOD_Label_15N_1_, "spec_6_position", "Anywhere"}, {UNIMOD_Label_15N_1_, "spec_6_site", "P"}, {UNIMOD_Label_15N_1_, "spec_7_classification", "Isotopic label"}, {UNIMOD_Label_15N_1_, "spec_7_hidden", "1"}, {UNIMOD_Label_15N_1_, "spec_7_position", "Anywhere"}, {UNIMOD_Label_15N_1_, "spec_7_site", "V"}, {UNIMOD_Label_15N_1_, "spec_8_classification", "Isotopic label"}, {UNIMOD_Label_15N_1_, "spec_8_hidden", "1"}, {UNIMOD_Label_15N_1_, "spec_8_position", "Anywhere"}, {UNIMOD_Label_15N_1_, "spec_8_site", "T"}, {UNIMOD_Label_15N_1_, "spec_9_classification", "Isotopic label"}, {UNIMOD_Label_15N_1_, "spec_9_hidden", "1"}, {UNIMOD_Label_15N_1_, "spec_9_position", "Anywhere"}, {UNIMOD_Label_15N_1_, "spec_9_site", "C"}, {UNIMOD_Label_15N_2_, "approved", "0"}, {UNIMOD_Label_15N_2_, "delta_composition", "N(-2) 15N(2)"}, {UNIMOD_Label_15N_2_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_15N_2_, "spec_1_hidden", "1"}, {UNIMOD_Label_15N_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_15N_2_, "spec_1_site", "N"}, {UNIMOD_Label_15N_2_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Label_15N_2_, "spec_2_hidden", "1"}, {UNIMOD_Label_15N_2_, "spec_2_position", "Anywhere"}, {UNIMOD_Label_15N_2_, "spec_2_site", "Q"}, {UNIMOD_Label_15N_2_, "spec_3_classification", "Isotopic label"}, {UNIMOD_Label_15N_2_, "spec_3_hidden", "1"}, {UNIMOD_Label_15N_2_, "spec_3_position", "Anywhere"}, {UNIMOD_Label_15N_2_, "spec_3_site", "K"}, {UNIMOD_Label_15N_2_, "spec_4_classification", "Isotopic label"}, {UNIMOD_Label_15N_2_, "spec_4_hidden", "1"}, {UNIMOD_Label_15N_2_, "spec_4_position", "Anywhere"}, {UNIMOD_Label_15N_2_, "spec_4_site", "W"}, {UNIMOD_Label_15N_3_, "approved", "0"}, {UNIMOD_Label_15N_3_, "delta_composition", "N(-3) 15N(3)"}, {UNIMOD_Label_15N_3_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_15N_3_, "spec_1_hidden", "1"}, {UNIMOD_Label_15N_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_15N_3_, "spec_1_site", "H"}, {UNIMOD_sulfo_amino, "approved", "0"}, {UNIMOD_sulfo_amino, "delta_composition", "H N O(3) S"}, {UNIMOD_sulfo_amino, "spec_1_classification", "Chemical derivative"}, {UNIMOD_sulfo_amino, "spec_1_hidden", "1"}, {UNIMOD_sulfo_amino, "spec_1_position", "Anywhere"}, {UNIMOD_sulfo_amino, "spec_1_site", "Y"}, {UNIMOD_BHAc, "approved", "0"}, {UNIMOD_BHAc, "delta_composition", "H(25) C(16) N(3) O(3) S"}, {UNIMOD_BHAc, "spec_1_classification", "Chemical derivative"}, {UNIMOD_BHAc, "spec_1_hidden", "1"}, {UNIMOD_BHAc, "spec_1_position", "Anywhere"}, {UNIMOD_BHAc, "spec_1_site", "K"}, {UNIMOD_AHA_Alkyne, "approved", "0"}, {UNIMOD_AHA_Alkyne, "delta_composition", "H(5) C(4) N(5) O S(-1)"}, {UNIMOD_AHA_Alkyne, "spec_1_classification", "Chemical derivative"}, {UNIMOD_AHA_Alkyne, "spec_1_hidden", "1"}, {UNIMOD_AHA_Alkyne, "spec_1_position", "Anywhere"}, {UNIMOD_AHA_Alkyne, "spec_1_site", "M"}, {UNIMOD_AHA_Alkyne_KDDDD, "approved", "0"}, {UNIMOD_AHA_Alkyne_KDDDD, "delta_composition", "H(37) C(26) N(11) O(14) S(-1)"}, {UNIMOD_AHA_Alkyne_KDDDD, "spec_1_classification", "Chemical derivative"}, {UNIMOD_AHA_Alkyne_KDDDD, "spec_1_hidden", "1"}, {UNIMOD_AHA_Alkyne_KDDDD, "spec_1_position", "Anywhere"}, {UNIMOD_AHA_Alkyne_KDDDD, "spec_1_site", "M"}, {UNIMOD_EGCG1, "approved", "0"}, {UNIMOD_EGCG1, "delta_composition", "H(16) C(22) O(11)"}, {UNIMOD_EGCG1, "spec_1_classification", "Post-translational"}, {UNIMOD_EGCG1, "spec_1_hidden", "1"}, {UNIMOD_EGCG1, "spec_1_position", "Anywhere"}, {UNIMOD_EGCG1, "spec_1_site", "C"}, {UNIMOD_EGCG2, "approved", "0"}, {UNIMOD_EGCG2, "delta_composition", "H(11) C(15) O(6)"}, {UNIMOD_EGCG2, "spec_1_classification", "Post-translational"}, {UNIMOD_EGCG2, "spec_1_hidden", "1"}, {UNIMOD_EGCG2, "spec_1_position", "Anywhere"}, {UNIMOD_EGCG2, "spec_1_site", "C"}, {UNIMOD_Label_13C_6_15N_4__Methyl, "approved", "0"}, {UNIMOD_Label_13C_6_15N_4__Methyl, "delta_composition", "H(2) C(-5) 13C(6) N(-4) 15N(4)"}, {UNIMOD_Label_13C_6_15N_4__Methyl, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_6_15N_4__Methyl, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_6_15N_4__Methyl, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_6_15N_4__Methyl, "spec_1_site", "R"}, {UNIMOD_Label_13C_6_15N_4__Dimethyl, "approved", "0"}, {UNIMOD_Label_13C_6_15N_4__Dimethyl, "delta_composition", "H(4) C(-4) 13C(6) N(-4) 15N(4)"}, {UNIMOD_Label_13C_6_15N_4__Dimethyl, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_6_15N_4__Dimethyl, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_6_15N_4__Dimethyl, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_6_15N_4__Dimethyl, "spec_1_site", "R"}, {UNIMOD_Label_13C_6_15N_4__Methyl_2H_3_13C_1_, "approved", "0"}, {UNIMOD_Label_13C_6_15N_4__Methyl_2H_3_13C_1_, "delta_composition", "H(-1) 2H(3) C(-6) 13C(7) N(-4) 15N(4)"}, {UNIMOD_Label_13C_6_15N_4__Methyl_2H_3_13C_1_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_6_15N_4__Methyl_2H_3_13C_1_, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_6_15N_4__Methyl_2H_3_13C_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_6_15N_4__Methyl_2H_3_13C_1_, "spec_1_site", "R"}, {UNIMOD_Label_13C_6_15N_4__Dimethyl_2H_6_13C_2_, "approved", "0"}, {UNIMOD_Label_13C_6_15N_4__Dimethyl_2H_6_13C_2_, "delta_composition", "H(-2) 2H(6) C(-6) 13C(8) N(-4) 15N(4)"}, {UNIMOD_Label_13C_6_15N_4__Dimethyl_2H_6_13C_2_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_6_15N_4__Dimethyl_2H_6_13C_2_, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_6_15N_4__Dimethyl_2H_6_13C_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_6_15N_4__Dimethyl_2H_6_13C_2_, "spec_1_site", "R"}, {UNIMOD_SecCarbamidomethyl, "approved", "0"}, {UNIMOD_SecCarbamidomethyl, "delta_composition", "H(3) C(2) N O S(-1) Se"}, {UNIMOD_SecCarbamidomethyl, "spec_1_classification", "Non-standard residue"}, {UNIMOD_SecCarbamidomethyl, "spec_1_hidden", "1"}, {UNIMOD_SecCarbamidomethyl, "spec_1_position", "Anywhere"}, {UNIMOD_SecCarbamidomethyl, "spec_1_site", "C"}, {UNIMOD_Thiazolidine, "approved", "0"}, {UNIMOD_Thiazolidine, "delta_composition", "C"}, {UNIMOD_Thiazolidine, "spec_1_classification", "Synth. pep. protect. gp."}, {UNIMOD_Thiazolidine, "spec_1_hidden", "1"}, {UNIMOD_Thiazolidine, "spec_1_position", "Any N-term"}, {UNIMOD_Thiazolidine, "spec_1_site", "C"}, {UNIMOD_DEDGFLYMVYASQETFG, "approved", "0"}, {UNIMOD_DEDGFLYMVYASQETFG, "delta_composition", "H(122) C(89) N(18) O(31) S"}, {UNIMOD_DEDGFLYMVYASQETFG, "spec_1_classification", "Post-translational"}, {UNIMOD_DEDGFLYMVYASQETFG, "spec_1_hidden", "1"}, {UNIMOD_DEDGFLYMVYASQETFG, "spec_1_position", "Anywhere"}, {UNIMOD_DEDGFLYMVYASQETFG, "spec_1_site", "K"}, {UNIMOD_Biotin_Invitrogen_M1602, "approved", "0"}, {UNIMOD_Biotin_Invitrogen_M1602, "delta_composition", "H(33) C(23) N(5) O(7) S"}, {UNIMOD_Biotin_Invitrogen_M1602, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Biotin_Invitrogen_M1602, "spec_1_hidden", "1"}, {UNIMOD_Biotin_Invitrogen_M1602, "spec_1_position", "Anywhere"}, {UNIMOD_Biotin_Invitrogen_M1602, "spec_1_site", "C"}, {UNIMOD_glycidamide, "approved", "0"}, {UNIMOD_glycidamide, "delta_composition", "H(5) C(3) N O(2)"}, {UNIMOD_glycidamide, "spec_1_classification", "Chemical derivative"}, {UNIMOD_glycidamide, "spec_1_hidden", "1"}, {UNIMOD_glycidamide, "spec_1_position", "Anywhere"}, {UNIMOD_glycidamide, "spec_1_site", "K"}, {UNIMOD_glycidamide, "spec_2_classification", "Chemical derivative"}, {UNIMOD_glycidamide, "spec_2_hidden", "1"}, {UNIMOD_glycidamide, "spec_2_position", "Any N-term"}, {UNIMOD_glycidamide, "spec_2_site", "N-term"}, {UNIMOD_Ahx2_Hsl, "approved", "0"}, {UNIMOD_Ahx2_Hsl, "delta_composition", "H(27) C(16) N(3) O(3)"}, {UNIMOD_Ahx2_Hsl, "spec_1_classification", "Non-standard residue"}, {UNIMOD_Ahx2_Hsl, "spec_1_hidden", "1"}, {UNIMOD_Ahx2_Hsl, "spec_1_position", "Any C-term"}, {UNIMOD_Ahx2_Hsl, "spec_1_site", "C-term"}, {UNIMOD_DMPO, "approved", "0"}, {UNIMOD_DMPO, "delta_composition", "H(9) C(6) N O"}, {UNIMOD_DMPO, "spec_1_classification", "Post-translational"}, {UNIMOD_DMPO, "spec_1_hidden", "1"}, {UNIMOD_DMPO, "spec_1_position", "Anywhere"}, {UNIMOD_DMPO, "spec_1_site", "C"}, {UNIMOD_DMPO, "spec_2_classification", "Post-translational"}, {UNIMOD_DMPO, "spec_2_hidden", "1"}, {UNIMOD_DMPO, "spec_2_position", "Anywhere"}, {UNIMOD_DMPO, "spec_2_site", "H"}, {UNIMOD_DMPO, "spec_3_classification", "Post-translational"}, {UNIMOD_DMPO, "spec_3_hidden", "1"}, {UNIMOD_DMPO, "spec_3_position", "Anywhere"}, {UNIMOD_DMPO, "spec_3_site", "Y"}, {UNIMOD_ICDID, "approved", "0"}, {UNIMOD_ICDID, "delta_composition", "H(10) C(8) O(2)"}, {UNIMOD_ICDID, "spec_1_classification", "Isotopic label"}, {UNIMOD_ICDID, "spec_1_hidden", "1"}, {UNIMOD_ICDID, "spec_1_position", "Anywhere"}, {UNIMOD_ICDID, "spec_1_site", "C"}, {UNIMOD_ICDID_2H_6_, "approved", "0"}, {UNIMOD_ICDID_2H_6_, "delta_composition", "H(4) 2H(6) C(8) O(2)"}, {UNIMOD_ICDID_2H_6_, "spec_1_classification", "Isotopic label"}, {UNIMOD_ICDID_2H_6_, "spec_1_hidden", "1"}, {UNIMOD_ICDID_2H_6_, "spec_1_position", "Anywhere"}, {UNIMOD_ICDID_2H_6_, "spec_1_site", "C"}, {UNIMOD_Xlink_DSS, "approved", "0"}, {UNIMOD_Xlink_DSS, "delta_composition", "H(12) C(8) O(3)"}, {UNIMOD_Xlink_DSS, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Xlink_DSS, "spec_1_hidden", "1"}, {UNIMOD_Xlink_DSS, "spec_1_position", "Anywhere"}, {UNIMOD_Xlink_DSS, "spec_1_site", "K"}, {UNIMOD_Xlink_DSS, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Xlink_DSS, "spec_2_hidden", "1"}, {UNIMOD_Xlink_DSS, "spec_2_position", "Protein N-term"}, {UNIMOD_Xlink_DSS, "spec_2_site", "N-term"}, {UNIMOD_Xlink_EGS, "approved", "0"}, {UNIMOD_Xlink_EGS, "delta_composition", "H(12) C(10) O(7)"}, {UNIMOD_Xlink_EGS, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Xlink_EGS, "spec_1_hidden", "1"}, {UNIMOD_Xlink_EGS, "spec_1_position", "Anywhere"}, {UNIMOD_Xlink_EGS, "spec_1_site", "K"}, {UNIMOD_Xlink_EGS, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Xlink_EGS, "spec_2_hidden", "1"}, {UNIMOD_Xlink_EGS, "spec_2_position", "Protein N-term"}, {UNIMOD_Xlink_EGS, "spec_2_site", "N-term"}, {UNIMOD_Xlink_DST, "approved", "0"}, {UNIMOD_Xlink_DST, "delta_composition", "H(4) C(4) O(5)"}, {UNIMOD_Xlink_DST, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Xlink_DST, "spec_1_hidden", "1"}, {UNIMOD_Xlink_DST, "spec_1_position", "Anywhere"}, {UNIMOD_Xlink_DST, "spec_1_site", "K"}, {UNIMOD_Xlink_DST, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Xlink_DST, "spec_2_hidden", "1"}, {UNIMOD_Xlink_DST, "spec_2_position", "Protein N-term"}, {UNIMOD_Xlink_DST, "spec_2_site", "N-term"}, {UNIMOD_Xlink_DTSSP, "approved", "0"}, {UNIMOD_Xlink_DTSSP, "delta_composition", "H(8) C(6) O(3) S(2)"}, {UNIMOD_Xlink_DTSSP, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Xlink_DTSSP, "spec_1_hidden", "1"}, {UNIMOD_Xlink_DTSSP, "spec_1_position", "Anywhere"}, {UNIMOD_Xlink_DTSSP, "spec_1_site", "K"}, {UNIMOD_Xlink_DTSSP, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Xlink_DTSSP, "spec_2_hidden", "1"}, {UNIMOD_Xlink_DTSSP, "spec_2_position", "Protein N-term"}, {UNIMOD_Xlink_DTSSP, "spec_2_site", "N-term"}, {UNIMOD_Xlink_SMCC, "approved", "0"}, {UNIMOD_Xlink_SMCC, "delta_composition", "H(15) C(12) N O(4)"}, {UNIMOD_Xlink_SMCC, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Xlink_SMCC, "spec_1_hidden", "1"}, {UNIMOD_Xlink_SMCC, "spec_1_position", "Anywhere"}, {UNIMOD_Xlink_SMCC, "spec_1_site", "C"}, {UNIMOD_Xlink_DMP_de, "approved", "0"}, {UNIMOD_Xlink_DMP_de, "delta_composition", "H(12) C(7) N(2) O"}, {UNIMOD_Xlink_DMP_de, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Xlink_DMP_de, "spec_1_hidden", "1"}, {UNIMOD_Xlink_DMP_de, "spec_1_position", "Anywhere"}, {UNIMOD_Xlink_DMP_de, "spec_1_site", "K"}, {UNIMOD_Xlink_DMP_de, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Xlink_DMP_de, "spec_2_hidden", "1"}, {UNIMOD_Xlink_DMP_de, "spec_2_position", "Protein N-term"}, {UNIMOD_Xlink_DMP_de, "spec_2_site", "N-term"}, {UNIMOD_Xlink_EGScleaved, "approved", "0"}, {UNIMOD_Xlink_EGScleaved, "delta_composition", "H(5) C(4) N O(2)"}, {UNIMOD_Xlink_EGScleaved, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Xlink_EGScleaved, "spec_1_hidden", "1"}, {UNIMOD_Xlink_EGScleaved, "spec_1_position", "Anywhere"}, {UNIMOD_Xlink_EGScleaved, "spec_1_site", "K"}, {UNIMOD_Xlink_EGScleaved, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Xlink_EGScleaved, "spec_2_hidden", "1"}, {UNIMOD_Xlink_EGScleaved, "spec_2_position", "Protein N-term"}, {UNIMOD_Xlink_EGScleaved, "spec_2_site", "N-term"}, {UNIMOD_Biotin_Thermo_88310, "approved", "0"}, {UNIMOD_Biotin_Thermo_88310, "delta_composition", "H(16) C(10) N(2) O(2)"}, {UNIMOD_Biotin_Thermo_88310, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Biotin_Thermo_88310, "spec_1_hidden", "1"}, {UNIMOD_Biotin_Thermo_88310, "spec_1_position", "Anywhere"}, {UNIMOD_Biotin_Thermo_88310, "spec_1_site", "K"}, {UNIMOD_2_nitrobenzyl, "approved", "0"}, {UNIMOD_2_nitrobenzyl, "delta_composition", "H(5) C(7) N O(2)"}, {UNIMOD_2_nitrobenzyl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_2_nitrobenzyl, "spec_1_hidden", "1"}, {UNIMOD_2_nitrobenzyl, "spec_1_position", "Anywhere"}, {UNIMOD_2_nitrobenzyl, "spec_1_site", "Y"}, {UNIMOD_SecNEM, "approved", "0"}, {UNIMOD_SecNEM, "delta_composition", "H(7) C(6) N O(2) S(-1) Se"}, {UNIMOD_SecNEM, "spec_1_classification", "Non-standard residue"}, {UNIMOD_SecNEM, "spec_1_hidden", "1"}, {UNIMOD_SecNEM, "spec_1_position", "Anywhere"}, {UNIMOD_SecNEM, "spec_1_site", "C"}, {UNIMOD_SecNEM_2H_5_, "approved", "0"}, {UNIMOD_SecNEM_2H_5_, "delta_composition", "H(2) 2H(5) C(6) N O(2) S(-1) Se"}, {UNIMOD_SecNEM_2H_5_, "spec_1_classification", "Chemical derivative"}, {UNIMOD_SecNEM_2H_5_, "spec_1_hidden", "1"}, {UNIMOD_SecNEM_2H_5_, "spec_1_position", "Anywhere"}, {UNIMOD_SecNEM_2H_5_, "spec_1_site", "C"}, {UNIMOD_Thiadiazole, "approved", "0"}, {UNIMOD_Thiadiazole, "delta_composition", "H(6) C(9) N(2) S"}, {UNIMOD_Thiadiazole, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Thiadiazole, "spec_1_hidden", "1"}, {UNIMOD_Thiadiazole, "spec_1_position", "Anywhere"}, {UNIMOD_Thiadiazole, "spec_1_site", "C"}, {UNIMOD_Withaferin, "approved", "0"}, {UNIMOD_Withaferin, "delta_composition", "H(38) C(28) O(6)"}, {UNIMOD_Withaferin, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Withaferin, "spec_1_hidden", "1"}, {UNIMOD_Withaferin, "spec_1_position", "Anywhere"}, {UNIMOD_Withaferin, "spec_1_site", "C"}, {UNIMOD_Biotin_Thermo_88317, "approved", "0"}, {UNIMOD_Biotin_Thermo_88317, "delta_composition", "H(42) C(22) N(3) O(4) P"}, {UNIMOD_Biotin_Thermo_88317, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Biotin_Thermo_88317, "spec_1_hidden", "1"}, {UNIMOD_Biotin_Thermo_88317, "spec_1_position", "Anywhere"}, {UNIMOD_Biotin_Thermo_88317, "spec_1_site", "Y"}, {UNIMOD_Biotin_Thermo_88317, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Biotin_Thermo_88317, "spec_2_hidden", "1"}, {UNIMOD_Biotin_Thermo_88317, "spec_2_position", "Anywhere"}, {UNIMOD_Biotin_Thermo_88317, "spec_2_site", "S"}, {UNIMOD_TAMRA_FP, "approved", "0"}, {UNIMOD_TAMRA_FP, "delta_composition", "H(46) C(37) N(3) O(6) P"}, {UNIMOD_TAMRA_FP, "spec_1_classification", "Chemical derivative"}, {UNIMOD_TAMRA_FP, "spec_1_hidden", "1"}, {UNIMOD_TAMRA_FP, "spec_1_position", "Anywhere"}, {UNIMOD_TAMRA_FP, "spec_1_site", "S"}, {UNIMOD_TAMRA_FP, "spec_2_classification", "Chemical derivative"}, {UNIMOD_TAMRA_FP, "spec_2_hidden", "1"}, {UNIMOD_TAMRA_FP, "spec_2_position", "Anywhere"}, {UNIMOD_TAMRA_FP, "spec_2_site", "Y"}, {UNIMOD_Biotin_Thermo_21901_H2O, "approved", "0"}, {UNIMOD_Biotin_Thermo_21901_H2O, "delta_composition", "H(37) C(23) N(5) O(8) S"}, {UNIMOD_Biotin_Thermo_21901_H2O, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Biotin_Thermo_21901_H2O, "spec_1_hidden", "1"}, {UNIMOD_Biotin_Thermo_21901_H2O, "spec_1_position", "Anywhere"}, {UNIMOD_Biotin_Thermo_21901_H2O, "spec_1_site", "C"}, {UNIMOD_Deoxyhypusine, "approved", "0"}, {UNIMOD_Deoxyhypusine, "delta_composition", "H(9) C(4) N"}, {UNIMOD_Deoxyhypusine, "spec_1_classification", "Post-translational"}, {UNIMOD_Deoxyhypusine, "spec_1_hidden", "1"}, {UNIMOD_Deoxyhypusine, "spec_1_position", "Anywhere"}, {UNIMOD_Deoxyhypusine, "spec_1_site", "K"}, {UNIMOD_Deoxyhypusine, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Deoxyhypusine, "spec_2_hidden", "1"}, {UNIMOD_Deoxyhypusine, "spec_2_position", "Anywhere"}, {UNIMOD_Deoxyhypusine, "spec_2_site", "Q"}, {UNIMOD_Acetyldeoxyhypusine, "approved", "0"}, {UNIMOD_Acetyldeoxyhypusine, "delta_composition", "H(11) C(6) N"}, {UNIMOD_Acetyldeoxyhypusine, "spec_1_classification", "Post-translational"}, {UNIMOD_Acetyldeoxyhypusine, "spec_1_hidden", "1"}, {UNIMOD_Acetyldeoxyhypusine, "spec_1_position", "Anywhere"}, {UNIMOD_Acetyldeoxyhypusine, "spec_1_site", "K"}, {UNIMOD_Acetylhypusine, "approved", "0"}, {UNIMOD_Acetylhypusine, "delta_composition", "H(11) C(6) N O"}, {UNIMOD_Acetylhypusine, "spec_1_classification", "Post-translational"}, {UNIMOD_Acetylhypusine, "spec_1_hidden", "1"}, {UNIMOD_Acetylhypusine, "spec_1_position", "Anywhere"}, {UNIMOD_Acetylhypusine, "spec_1_site", "K"}, {UNIMOD_Ala__Cys, "approved", "0"}, {UNIMOD_Ala__Cys, "delta_composition", "S"}, {UNIMOD_Ala__Cys, "spec_1_classification", "AA substitution"}, {UNIMOD_Ala__Cys, "spec_1_hidden", "1"}, {UNIMOD_Ala__Cys, "spec_1_position", "Anywhere"}, {UNIMOD_Ala__Cys, "spec_1_site", "A"}, {UNIMOD_Ala__Phe, "approved", "0"}, {UNIMOD_Ala__Phe, "delta_composition", "H(4) C(6)"}, {UNIMOD_Ala__Phe, "spec_1_classification", "AA substitution"}, {UNIMOD_Ala__Phe, "spec_1_hidden", "1"}, {UNIMOD_Ala__Phe, "spec_1_position", "Anywhere"}, {UNIMOD_Ala__Phe, "spec_1_site", "A"}, {UNIMOD_Ala__His, "approved", "0"}, {UNIMOD_Ala__His, "delta_composition", "H(2) C(3) N(2)"}, {UNIMOD_Ala__His, "spec_1_classification", "AA substitution"}, {UNIMOD_Ala__His, "spec_1_hidden", "1"}, {UNIMOD_Ala__His, "spec_1_position", "Anywhere"}, {UNIMOD_Ala__His, "spec_1_site", "A"}, {UNIMOD_Ala__Xle, "approved", "0"}, {UNIMOD_Ala__Xle, "delta_composition", "H(6) C(3)"}, {UNIMOD_Ala__Xle, "spec_1_classification", "AA substitution"}, {UNIMOD_Ala__Xle, "spec_1_hidden", "1"}, {UNIMOD_Ala__Xle, "spec_1_position", "Anywhere"}, {UNIMOD_Ala__Xle, "spec_1_site", "A"}, {UNIMOD_Ala__Lys, "approved", "0"}, {UNIMOD_Ala__Lys, "delta_composition", "H(7) C(3) N"}, {UNIMOD_Ala__Lys, "spec_1_classification", "AA substitution"}, {UNIMOD_Ala__Lys, "spec_1_hidden", "1"}, {UNIMOD_Ala__Lys, "spec_1_position", "Anywhere"}, {UNIMOD_Ala__Lys, "spec_1_site", "A"}, {UNIMOD_Ala__Met, "approved", "0"}, {UNIMOD_Ala__Met, "delta_composition", "H(4) C(2) S"}, {UNIMOD_Ala__Met, "spec_1_classification", "AA substitution"}, {UNIMOD_Ala__Met, "spec_1_hidden", "1"}, {UNIMOD_Ala__Met, "spec_1_position", "Anywhere"}, {UNIMOD_Ala__Met, "spec_1_site", "A"}, {UNIMOD_Ala__Asn, "approved", "0"}, {UNIMOD_Ala__Asn, "delta_composition", "H C N O"}, {UNIMOD_Ala__Asn, "spec_1_classification", "AA substitution"}, {UNIMOD_Ala__Asn, "spec_1_hidden", "1"}, {UNIMOD_Ala__Asn, "spec_1_position", "Anywhere"}, {UNIMOD_Ala__Asn, "spec_1_site", "A"}, {UNIMOD_Ala__Gln, "approved", "0"}, {UNIMOD_Ala__Gln, "delta_composition", "H(3) C(2) N O"}, {UNIMOD_Ala__Gln, "spec_1_classification", "AA substitution"}, {UNIMOD_Ala__Gln, "spec_1_hidden", "1"}, {UNIMOD_Ala__Gln, "spec_1_position", "Anywhere"}, {UNIMOD_Ala__Gln, "spec_1_site", "A"}, {UNIMOD_Ala__Arg, "approved", "0"}, {UNIMOD_Ala__Arg, "delta_composition", "H(7) C(3) N(3)"}, {UNIMOD_Ala__Arg, "spec_1_classification", "AA substitution"}, {UNIMOD_Ala__Arg, "spec_1_hidden", "1"}, {UNIMOD_Ala__Arg, "spec_1_position", "Anywhere"}, {UNIMOD_Ala__Arg, "spec_1_site", "A"}, {UNIMOD_Ala__Trp, "approved", "0"}, {UNIMOD_Ala__Trp, "delta_composition", "H(5) C(8) N"}, {UNIMOD_Ala__Trp, "spec_1_classification", "AA substitution"}, {UNIMOD_Ala__Trp, "spec_1_hidden", "1"}, {UNIMOD_Ala__Trp, "spec_1_position", "Anywhere"}, {UNIMOD_Ala__Trp, "spec_1_site", "A"}, {UNIMOD_Ala__Tyr, "approved", "0"}, {UNIMOD_Ala__Tyr, "delta_composition", "H(4) C(6) O"}, {UNIMOD_Ala__Tyr, "spec_1_classification", "AA substitution"}, {UNIMOD_Ala__Tyr, "spec_1_hidden", "1"}, {UNIMOD_Ala__Tyr, "spec_1_position", "Anywhere"}, {UNIMOD_Ala__Tyr, "spec_1_site", "A"}, {UNIMOD_Cys__Ala, "approved", "0"}, {UNIMOD_Cys__Ala, "delta_composition", "S(-1)"}, {UNIMOD_Cys__Ala, "spec_1_classification", "AA substitution"}, {UNIMOD_Cys__Ala, "spec_1_hidden", "1"}, {UNIMOD_Cys__Ala, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__Ala, "spec_1_site", "C"}, {UNIMOD_Cys__Asp, "approved", "0"}, {UNIMOD_Cys__Asp, "delta_composition", "C O(2) S(-1)"}, {UNIMOD_Cys__Asp, "spec_1_classification", "AA substitution"}, {UNIMOD_Cys__Asp, "spec_1_hidden", "1"}, {UNIMOD_Cys__Asp, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__Asp, "spec_1_site", "C"}, {UNIMOD_Cys__Glu, "approved", "0"}, {UNIMOD_Cys__Glu, "delta_composition", "H(2) C(2) O(2) S(-1)"}, {UNIMOD_Cys__Glu, "spec_1_classification", "AA substitution"}, {UNIMOD_Cys__Glu, "spec_1_hidden", "1"}, {UNIMOD_Cys__Glu, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__Glu, "spec_1_site", "C"}, {UNIMOD_Cys__His, "approved", "0"}, {UNIMOD_Cys__His, "delta_composition", "H(2) C(3) N(2) S(-1)"}, {UNIMOD_Cys__His, "spec_1_classification", "AA substitution"}, {UNIMOD_Cys__His, "spec_1_hidden", "1"}, {UNIMOD_Cys__His, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__His, "spec_1_site", "C"}, {UNIMOD_Cys__Xle, "approved", "0"}, {UNIMOD_Cys__Xle, "delta_composition", "H(6) C(3) S(-1)"}, {UNIMOD_Cys__Xle, "spec_1_classification", "AA substitution"}, {UNIMOD_Cys__Xle, "spec_1_hidden", "1"}, {UNIMOD_Cys__Xle, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__Xle, "spec_1_site", "C"}, {UNIMOD_Cys__Lys, "approved", "0"}, {UNIMOD_Cys__Lys, "delta_composition", "H(7) C(3) N S(-1)"}, {UNIMOD_Cys__Lys, "spec_1_classification", "AA substitution"}, {UNIMOD_Cys__Lys, "spec_1_hidden", "1"}, {UNIMOD_Cys__Lys, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__Lys, "spec_1_site", "C"}, {UNIMOD_Cys__Met, "approved", "0"}, {UNIMOD_Cys__Met, "delta_composition", "H(4) C(2)"}, {UNIMOD_Cys__Met, "spec_1_classification", "AA substitution"}, {UNIMOD_Cys__Met, "spec_1_hidden", "1"}, {UNIMOD_Cys__Met, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__Met, "spec_1_site", "C"}, {UNIMOD_Cys__Asn, "approved", "0"}, {UNIMOD_Cys__Asn, "delta_composition", "H C N O S(-1)"}, {UNIMOD_Cys__Asn, "spec_1_classification", "AA substitution"}, {UNIMOD_Cys__Asn, "spec_1_hidden", "1"}, {UNIMOD_Cys__Asn, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__Asn, "spec_1_site", "C"}, {UNIMOD_Cys__Pro, "approved", "0"}, {UNIMOD_Cys__Pro, "delta_composition", "H(2) C(2) S(-1)"}, {UNIMOD_Cys__Pro, "spec_1_classification", "AA substitution"}, {UNIMOD_Cys__Pro, "spec_1_hidden", "1"}, {UNIMOD_Cys__Pro, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__Pro, "spec_1_site", "C"}, {UNIMOD_Cys__Gln, "approved", "0"}, {UNIMOD_Cys__Gln, "delta_composition", "H(3) C(2) N O S(-1)"}, {UNIMOD_Cys__Gln, "spec_1_classification", "AA substitution"}, {UNIMOD_Cys__Gln, "spec_1_hidden", "1"}, {UNIMOD_Cys__Gln, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__Gln, "spec_1_site", "C"}, {UNIMOD_Cys__Thr, "approved", "0"}, {UNIMOD_Cys__Thr, "delta_composition", "H(2) C O S(-1)"}, {UNIMOD_Cys__Thr, "spec_1_classification", "AA substitution"}, {UNIMOD_Cys__Thr, "spec_1_hidden", "1"}, {UNIMOD_Cys__Thr, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__Thr, "spec_1_site", "C"}, {UNIMOD_Cys__Val, "approved", "0"}, {UNIMOD_Cys__Val, "delta_composition", "H(4) C(2) S(-1)"}, {UNIMOD_Cys__Val, "spec_1_classification", "AA substitution"}, {UNIMOD_Cys__Val, "spec_1_hidden", "1"}, {UNIMOD_Cys__Val, "spec_1_position", "Anywhere"}, {UNIMOD_Cys__Val, "spec_1_site", "C"}, {UNIMOD_Asp__Cys, "approved", "0"}, {UNIMOD_Asp__Cys, "delta_composition", "C(-1) O(-2) S"}, {UNIMOD_Asp__Cys, "spec_1_classification", "AA substitution"}, {UNIMOD_Asp__Cys, "spec_1_hidden", "1"}, {UNIMOD_Asp__Cys, "spec_1_position", "Anywhere"}, {UNIMOD_Asp__Cys, "spec_1_site", "D"}, {UNIMOD_Asp__Phe, "approved", "0"}, {UNIMOD_Asp__Phe, "delta_composition", "H(4) C(5) O(-2)"}, {UNIMOD_Asp__Phe, "spec_1_classification", "AA substitution"}, {UNIMOD_Asp__Phe, "spec_1_hidden", "1"}, {UNIMOD_Asp__Phe, "spec_1_position", "Anywhere"}, {UNIMOD_Asp__Phe, "spec_1_site", "D"}, {UNIMOD_Asp__Xle, "approved", "0"}, {UNIMOD_Asp__Xle, "delta_composition", "H(6) C(2) O(-2)"}, {UNIMOD_Asp__Xle, "spec_1_classification", "AA substitution"}, {UNIMOD_Asp__Xle, "spec_1_hidden", "1"}, {UNIMOD_Asp__Xle, "spec_1_position", "Anywhere"}, {UNIMOD_Asp__Xle, "spec_1_site", "D"}, {UNIMOD_Asp__Lys, "approved", "0"}, {UNIMOD_Asp__Lys, "delta_composition", "H(7) C(2) N O(-2)"}, {UNIMOD_Asp__Lys, "spec_1_classification", "AA substitution"}, {UNIMOD_Asp__Lys, "spec_1_hidden", "1"}, {UNIMOD_Asp__Lys, "spec_1_position", "Anywhere"}, {UNIMOD_Asp__Lys, "spec_1_site", "D"}, {UNIMOD_Asp__Met, "approved", "0"}, {UNIMOD_Asp__Met, "delta_composition", "H(4) C O(-2) S"}, {UNIMOD_Asp__Met, "spec_1_classification", "AA substitution"}, {UNIMOD_Asp__Met, "spec_1_hidden", "1"}, {UNIMOD_Asp__Met, "spec_1_position", "Anywhere"}, {UNIMOD_Asp__Met, "spec_1_site", "D"}, {UNIMOD_Asp__Pro, "approved", "0"}, {UNIMOD_Asp__Pro, "delta_composition", "H(2) C O(-2)"}, {UNIMOD_Asp__Pro, "spec_1_classification", "AA substitution"}, {UNIMOD_Asp__Pro, "spec_1_hidden", "1"}, {UNIMOD_Asp__Pro, "spec_1_position", "Anywhere"}, {UNIMOD_Asp__Pro, "spec_1_site", "D"}, {UNIMOD_Asp__Gln, "approved", "0"}, {UNIMOD_Asp__Gln, "delta_composition", "H(3) C N O(-1)"}, {UNIMOD_Asp__Gln, "spec_1_classification", "AA substitution"}, {UNIMOD_Asp__Gln, "spec_1_hidden", "1"}, {UNIMOD_Asp__Gln, "spec_1_position", "Anywhere"}, {UNIMOD_Asp__Gln, "spec_1_site", "D"}, {UNIMOD_Asp__Arg, "approved", "0"}, {UNIMOD_Asp__Arg, "delta_composition", "H(7) C(2) N(3) O(-2)"}, {UNIMOD_Asp__Arg, "spec_1_classification", "AA substitution"}, {UNIMOD_Asp__Arg, "spec_1_hidden", "1"}, {UNIMOD_Asp__Arg, "spec_1_position", "Anywhere"}, {UNIMOD_Asp__Arg, "spec_1_site", "D"}, {UNIMOD_Asp__Ser, "approved", "0"}, {UNIMOD_Asp__Ser, "delta_composition", "C(-1) O(-1)"}, {UNIMOD_Asp__Ser, "spec_1_classification", "AA substitution"}, {UNIMOD_Asp__Ser, "spec_1_hidden", "1"}, {UNIMOD_Asp__Ser, "spec_1_position", "Anywhere"}, {UNIMOD_Asp__Ser, "spec_1_site", "D"}, {UNIMOD_Asp__Thr, "approved", "0"}, {UNIMOD_Asp__Thr, "delta_composition", "H(2) O(-1)"}, {UNIMOD_Asp__Thr, "spec_1_classification", "AA substitution"}, {UNIMOD_Asp__Thr, "spec_1_hidden", "1"}, {UNIMOD_Asp__Thr, "spec_1_position", "Anywhere"}, {UNIMOD_Asp__Thr, "spec_1_site", "D"}, {UNIMOD_Asp__Trp, "approved", "0"}, {UNIMOD_Asp__Trp, "delta_composition", "H(5) C(7) N O(-2)"}, {UNIMOD_Asp__Trp, "spec_1_classification", "AA substitution"}, {UNIMOD_Asp__Trp, "spec_1_hidden", "1"}, {UNIMOD_Asp__Trp, "spec_1_position", "Anywhere"}, {UNIMOD_Asp__Trp, "spec_1_site", "D"}, {UNIMOD_Glu__Cys, "approved", "0"}, {UNIMOD_Glu__Cys, "delta_composition", "H(-2) C(-2) O(-2) S"}, {UNIMOD_Glu__Cys, "spec_1_classification", "AA substitution"}, {UNIMOD_Glu__Cys, "spec_1_hidden", "1"}, {UNIMOD_Glu__Cys, "spec_1_position", "Anywhere"}, {UNIMOD_Glu__Cys, "spec_1_site", "E"}, {UNIMOD_Glu__Phe, "approved", "0"}, {UNIMOD_Glu__Phe, "delta_composition", "H(2) C(4) O(-2)"}, {UNIMOD_Glu__Phe, "spec_1_classification", "AA substitution"}, {UNIMOD_Glu__Phe, "spec_1_hidden", "1"}, {UNIMOD_Glu__Phe, "spec_1_position", "Anywhere"}, {UNIMOD_Glu__Phe, "spec_1_site", "E"}, {UNIMOD_Glu__His, "approved", "0"}, {UNIMOD_Glu__His, "delta_composition", "C N(2) O(-2)"}, {UNIMOD_Glu__His, "spec_1_classification", "AA substitution"}, {UNIMOD_Glu__His, "spec_1_hidden", "1"}, {UNIMOD_Glu__His, "spec_1_position", "Anywhere"}, {UNIMOD_Glu__His, "spec_1_site", "E"}, {UNIMOD_Glu__Xle, "approved", "0"}, {UNIMOD_Glu__Xle, "delta_composition", "H(4) C O(-2)"}, {UNIMOD_Glu__Xle, "spec_1_classification", "AA substitution"}, {UNIMOD_Glu__Xle, "spec_1_hidden", "1"}, {UNIMOD_Glu__Xle, "spec_1_position", "Anywhere"}, {UNIMOD_Glu__Xle, "spec_1_site", "E"}, {UNIMOD_Glu__Met, "approved", "0"}, {UNIMOD_Glu__Met, "delta_composition", "H(2) O(-2) S"}, {UNIMOD_Glu__Met, "spec_1_classification", "AA substitution"}, {UNIMOD_Glu__Met, "spec_1_hidden", "1"}, {UNIMOD_Glu__Met, "spec_1_position", "Anywhere"}, {UNIMOD_Glu__Met, "spec_1_site", "E"}, {UNIMOD_Glu__Asn, "approved", "0"}, {UNIMOD_Glu__Asn, "delta_composition", "H(-1) C(-1) N O(-1)"}, {UNIMOD_Glu__Asn, "spec_1_classification", "AA substitution"}, {UNIMOD_Glu__Asn, "spec_1_hidden", "1"}, {UNIMOD_Glu__Asn, "spec_1_position", "Anywhere"}, {UNIMOD_Glu__Asn, "spec_1_site", "E"}, {UNIMOD_Glu__Pro, "approved", "0"}, {UNIMOD_Glu__Pro, "delta_composition", "O(-2)"}, {UNIMOD_Glu__Pro, "spec_1_classification", "AA substitution"}, {UNIMOD_Glu__Pro, "spec_1_hidden", "1"}, {UNIMOD_Glu__Pro, "spec_1_position", "Anywhere"}, {UNIMOD_Glu__Pro, "spec_1_site", "E"}, {UNIMOD_Glu__Arg, "approved", "0"}, {UNIMOD_Glu__Arg, "delta_composition", "H(5) C N(3) O(-2)"}, {UNIMOD_Glu__Arg, "spec_1_classification", "AA substitution"}, {UNIMOD_Glu__Arg, "spec_1_hidden", "1"}, {UNIMOD_Glu__Arg, "spec_1_position", "Anywhere"}, {UNIMOD_Glu__Arg, "spec_1_site", "E"}, {UNIMOD_Glu__Ser, "approved", "0"}, {UNIMOD_Glu__Ser, "delta_composition", "H(-2) C(-2) O(-1)"}, {UNIMOD_Glu__Ser, "spec_1_classification", "AA substitution"}, {UNIMOD_Glu__Ser, "spec_1_hidden", "1"}, {UNIMOD_Glu__Ser, "spec_1_position", "Anywhere"}, {UNIMOD_Glu__Ser, "spec_1_site", "E"}, {UNIMOD_Glu__Thr, "approved", "0"}, {UNIMOD_Glu__Thr, "delta_composition", "C(-1) O(-1)"}, {UNIMOD_Glu__Thr, "spec_1_classification", "AA substitution"}, {UNIMOD_Glu__Thr, "spec_1_hidden", "1"}, {UNIMOD_Glu__Thr, "spec_1_position", "Anywhere"}, {UNIMOD_Glu__Thr, "spec_1_site", "E"}, {UNIMOD_Glu__Trp, "approved", "0"}, {UNIMOD_Glu__Trp, "delta_composition", "H(3) C(6) N O(-2)"}, {UNIMOD_Glu__Trp, "spec_1_classification", "AA substitution"}, {UNIMOD_Glu__Trp, "spec_1_hidden", "1"}, {UNIMOD_Glu__Trp, "spec_1_position", "Anywhere"}, {UNIMOD_Glu__Trp, "spec_1_site", "E"}, {UNIMOD_Glu__Tyr, "approved", "0"}, {UNIMOD_Glu__Tyr, "delta_composition", "H(2) C(4) O(-1)"}, {UNIMOD_Glu__Tyr, "spec_1_classification", "AA substitution"}, {UNIMOD_Glu__Tyr, "spec_1_hidden", "1"}, {UNIMOD_Glu__Tyr, "spec_1_position", "Anywhere"}, {UNIMOD_Glu__Tyr, "spec_1_site", "E"}, {UNIMOD_Phe__Ala, "approved", "0"}, {UNIMOD_Phe__Ala, "delta_composition", "H(-4) C(-6)"}, {UNIMOD_Phe__Ala, "spec_1_classification", "AA substitution"}, {UNIMOD_Phe__Ala, "spec_1_hidden", "1"}, {UNIMOD_Phe__Ala, "spec_1_position", "Anywhere"}, {UNIMOD_Phe__Ala, "spec_1_site", "F"}, {UNIMOD_Phe__Asp, "approved", "0"}, {UNIMOD_Phe__Asp, "delta_composition", "H(-4) C(-5) O(2)"}, {UNIMOD_Phe__Asp, "spec_1_classification", "AA substitution"}, {UNIMOD_Phe__Asp, "spec_1_hidden", "1"}, {UNIMOD_Phe__Asp, "spec_1_position", "Anywhere"}, {UNIMOD_Phe__Asp, "spec_1_site", "F"}, {UNIMOD_Phe__Glu, "approved", "0"}, {UNIMOD_Phe__Glu, "delta_composition", "H(-2) C(-4) O(2)"}, {UNIMOD_Phe__Glu, "spec_1_classification", "AA substitution"}, {UNIMOD_Phe__Glu, "spec_1_hidden", "1"}, {UNIMOD_Phe__Glu, "spec_1_position", "Anywhere"}, {UNIMOD_Phe__Glu, "spec_1_site", "F"}, {UNIMOD_Phe__Gly, "approved", "0"}, {UNIMOD_Phe__Gly, "delta_composition", "H(-6) C(-7)"}, {UNIMOD_Phe__Gly, "spec_1_classification", "AA substitution"}, {UNIMOD_Phe__Gly, "spec_1_hidden", "1"}, {UNIMOD_Phe__Gly, "spec_1_position", "Anywhere"}, {UNIMOD_Phe__Gly, "spec_1_site", "F"}, {UNIMOD_Phe__His, "approved", "0"}, {UNIMOD_Phe__His, "delta_composition", "H(-2) C(-3) N(2)"}, {UNIMOD_Phe__His, "spec_1_classification", "AA substitution"}, {UNIMOD_Phe__His, "spec_1_hidden", "1"}, {UNIMOD_Phe__His, "spec_1_position", "Anywhere"}, {UNIMOD_Phe__His, "spec_1_site", "F"}, {UNIMOD_Phe__Lys, "approved", "0"}, {UNIMOD_Phe__Lys, "delta_composition", "H(3) C(-3) N"}, {UNIMOD_Phe__Lys, "spec_1_classification", "AA substitution"}, {UNIMOD_Phe__Lys, "spec_1_hidden", "1"}, {UNIMOD_Phe__Lys, "spec_1_position", "Anywhere"}, {UNIMOD_Phe__Lys, "spec_1_site", "F"}, {UNIMOD_Phe__Met, "approved", "0"}, {UNIMOD_Phe__Met, "delta_composition", "C(-4) S"}, {UNIMOD_Phe__Met, "spec_1_classification", "AA substitution"}, {UNIMOD_Phe__Met, "spec_1_hidden", "1"}, {UNIMOD_Phe__Met, "spec_1_position", "Anywhere"}, {UNIMOD_Phe__Met, "spec_1_site", "F"}, {UNIMOD_Phe__Asn, "approved", "0"}, {UNIMOD_Phe__Asn, "delta_composition", "H(-3) C(-5) N O"}, {UNIMOD_Phe__Asn, "spec_1_classification", "AA substitution"}, {UNIMOD_Phe__Asn, "spec_1_hidden", "1"}, {UNIMOD_Phe__Asn, "spec_1_position", "Anywhere"}, {UNIMOD_Phe__Asn, "spec_1_site", "F"}, {UNIMOD_Phe__Pro, "approved", "0"}, {UNIMOD_Phe__Pro, "delta_composition", "H(-2) C(-4)"}, {UNIMOD_Phe__Pro, "spec_1_classification", "AA substitution"}, {UNIMOD_Phe__Pro, "spec_1_hidden", "1"}, {UNIMOD_Phe__Pro, "spec_1_position", "Anywhere"}, {UNIMOD_Phe__Pro, "spec_1_site", "F"}, {UNIMOD_Phe__Gln, "approved", "0"}, {UNIMOD_Phe__Gln, "delta_composition", "H(-1) C(-4) N O"}, {UNIMOD_Phe__Gln, "spec_1_classification", "AA substitution"}, {UNIMOD_Phe__Gln, "spec_1_hidden", "1"}, {UNIMOD_Phe__Gln, "spec_1_position", "Anywhere"}, {UNIMOD_Phe__Gln, "spec_1_site", "F"}, {UNIMOD_Phe__Arg, "approved", "0"}, {UNIMOD_Phe__Arg, "delta_composition", "H(3) C(-3) N(3)"}, {UNIMOD_Phe__Arg, "spec_1_classification", "AA substitution"}, {UNIMOD_Phe__Arg, "spec_1_hidden", "1"}, {UNIMOD_Phe__Arg, "spec_1_position", "Anywhere"}, {UNIMOD_Phe__Arg, "spec_1_site", "F"}, {UNIMOD_Phe__Thr, "approved", "0"}, {UNIMOD_Phe__Thr, "delta_composition", "H(-2) C(-5) O"}, {UNIMOD_Phe__Thr, "spec_1_classification", "AA substitution"}, {UNIMOD_Phe__Thr, "spec_1_hidden", "1"}, {UNIMOD_Phe__Thr, "spec_1_position", "Anywhere"}, {UNIMOD_Phe__Thr, "spec_1_site", "F"}, {UNIMOD_Phe__Trp, "approved", "0"}, {UNIMOD_Phe__Trp, "delta_composition", "H C(2) N"}, {UNIMOD_Phe__Trp, "spec_1_classification", "AA substitution"}, {UNIMOD_Phe__Trp, "spec_1_hidden", "1"}, {UNIMOD_Phe__Trp, "spec_1_position", "Anywhere"}, {UNIMOD_Phe__Trp, "spec_1_site", "F"}, {UNIMOD_Gly__Phe, "approved", "0"}, {UNIMOD_Gly__Phe, "delta_composition", "H(6) C(7)"}, {UNIMOD_Gly__Phe, "spec_1_classification", "AA substitution"}, {UNIMOD_Gly__Phe, "spec_1_hidden", "1"}, {UNIMOD_Gly__Phe, "spec_1_position", "Anywhere"}, {UNIMOD_Gly__Phe, "spec_1_site", "G"}, {UNIMOD_Gly__His, "approved", "0"}, {UNIMOD_Gly__His, "delta_composition", "H(4) C(4) N(2)"}, {UNIMOD_Gly__His, "spec_1_classification", "AA substitution"}, {UNIMOD_Gly__His, "spec_1_hidden", "1"}, {UNIMOD_Gly__His, "spec_1_position", "Anywhere"}, {UNIMOD_Gly__His, "spec_1_site", "G"}, {UNIMOD_Gly__Xle, "approved", "0"}, {UNIMOD_Gly__Xle, "delta_composition", "H(8) C(4)"}, {UNIMOD_Gly__Xle, "spec_1_classification", "AA substitution"}, {UNIMOD_Gly__Xle, "spec_1_hidden", "1"}, {UNIMOD_Gly__Xle, "spec_1_position", "Anywhere"}, {UNIMOD_Gly__Xle, "spec_1_site", "G"}, {UNIMOD_Gly__Lys, "approved", "0"}, {UNIMOD_Gly__Lys, "delta_composition", "H(9) C(4) N"}, {UNIMOD_Gly__Lys, "spec_1_classification", "AA substitution"}, {UNIMOD_Gly__Lys, "spec_1_hidden", "1"}, {UNIMOD_Gly__Lys, "spec_1_position", "Anywhere"}, {UNIMOD_Gly__Lys, "spec_1_site", "G"}, {UNIMOD_Gly__Met, "approved", "0"}, {UNIMOD_Gly__Met, "delta_composition", "H(6) C(3) S"}, {UNIMOD_Gly__Met, "spec_1_classification", "AA substitution"}, {UNIMOD_Gly__Met, "spec_1_hidden", "1"}, {UNIMOD_Gly__Met, "spec_1_position", "Anywhere"}, {UNIMOD_Gly__Met, "spec_1_site", "G"}, {UNIMOD_Gly__Asn, "approved", "0"}, {UNIMOD_Gly__Asn, "delta_composition", "H(3) C(2) N O"}, {UNIMOD_Gly__Asn, "spec_1_classification", "AA substitution"}, {UNIMOD_Gly__Asn, "spec_1_hidden", "1"}, {UNIMOD_Gly__Asn, "spec_1_position", "Anywhere"}, {UNIMOD_Gly__Asn, "spec_1_site", "G"}, {UNIMOD_Gly__Pro, "approved", "0"}, {UNIMOD_Gly__Pro, "delta_composition", "H(4) C(3)"}, {UNIMOD_Gly__Pro, "spec_1_classification", "AA substitution"}, {UNIMOD_Gly__Pro, "spec_1_hidden", "1"}, {UNIMOD_Gly__Pro, "spec_1_position", "Anywhere"}, {UNIMOD_Gly__Pro, "spec_1_site", "G"}, {UNIMOD_Gly__Gln, "approved", "0"}, {UNIMOD_Gly__Gln, "delta_composition", "H(5) C(3) N O"}, {UNIMOD_Gly__Gln, "spec_1_classification", "AA substitution"}, {UNIMOD_Gly__Gln, "spec_1_hidden", "1"}, {UNIMOD_Gly__Gln, "spec_1_position", "Anywhere"}, {UNIMOD_Gly__Gln, "spec_1_site", "G"}, {UNIMOD_Gly__Thr, "approved", "0"}, {UNIMOD_Gly__Thr, "delta_composition", "H(4) C(2) O"}, {UNIMOD_Gly__Thr, "spec_1_classification", "AA substitution"}, {UNIMOD_Gly__Thr, "spec_1_hidden", "1"}, {UNIMOD_Gly__Thr, "spec_1_position", "Anywhere"}, {UNIMOD_Gly__Thr, "spec_1_site", "G"}, {UNIMOD_Gly__Tyr, "approved", "0"}, {UNIMOD_Gly__Tyr, "delta_composition", "H(6) C(7) O"}, {UNIMOD_Gly__Tyr, "spec_1_classification", "AA substitution"}, {UNIMOD_Gly__Tyr, "spec_1_hidden", "1"}, {UNIMOD_Gly__Tyr, "spec_1_position", "Anywhere"}, {UNIMOD_Gly__Tyr, "spec_1_site", "G"}, {UNIMOD_His__Ala, "approved", "0"}, {UNIMOD_His__Ala, "delta_composition", "H(-2) C(-3) N(-2)"}, {UNIMOD_His__Ala, "spec_1_classification", "AA substitution"}, {UNIMOD_His__Ala, "spec_1_hidden", "1"}, {UNIMOD_His__Ala, "spec_1_position", "Anywhere"}, {UNIMOD_His__Ala, "spec_1_site", "H"}, {UNIMOD_His__Cys, "approved", "0"}, {UNIMOD_His__Cys, "delta_composition", "H(-2) C(-3) N(-2) S"}, {UNIMOD_His__Cys, "spec_1_classification", "AA substitution"}, {UNIMOD_His__Cys, "spec_1_hidden", "1"}, {UNIMOD_His__Cys, "spec_1_position", "Anywhere"}, {UNIMOD_His__Cys, "spec_1_site", "H"}, {UNIMOD_His__Glu, "approved", "0"}, {UNIMOD_His__Glu, "delta_composition", "C(-1) N(-2) O(2)"}, {UNIMOD_His__Glu, "spec_1_classification", "AA substitution"}, {UNIMOD_His__Glu, "spec_1_hidden", "1"}, {UNIMOD_His__Glu, "spec_1_position", "Anywhere"}, {UNIMOD_His__Glu, "spec_1_site", "H"}, {UNIMOD_His__Phe, "approved", "0"}, {UNIMOD_His__Phe, "delta_composition", "H(2) C(3) N(-2)"}, {UNIMOD_His__Phe, "spec_1_classification", "AA substitution"}, {UNIMOD_His__Phe, "spec_1_hidden", "1"}, {UNIMOD_His__Phe, "spec_1_position", "Anywhere"}, {UNIMOD_His__Phe, "spec_1_site", "H"}, {UNIMOD_His__Gly, "approved", "0"}, {UNIMOD_His__Gly, "delta_composition", "H(-4) C(-4) N(-2)"}, {UNIMOD_His__Gly, "spec_1_classification", "AA substitution"}, {UNIMOD_His__Gly, "spec_1_hidden", "1"}, {UNIMOD_His__Gly, "spec_1_position", "Anywhere"}, {UNIMOD_His__Gly, "spec_1_site", "H"}, {UNIMOD_His__Lys, "approved", "0"}, {UNIMOD_His__Lys, "delta_composition", "H(5) N(-1)"}, {UNIMOD_His__Lys, "spec_1_classification", "AA substitution"}, {UNIMOD_His__Lys, "spec_1_hidden", "1"}, {UNIMOD_His__Lys, "spec_1_position", "Anywhere"}, {UNIMOD_His__Lys, "spec_1_site", "H"}, {UNIMOD_His__Met, "approved", "0"}, {UNIMOD_His__Met, "delta_composition", "H(2) C(-1) N(-2) S"}, {UNIMOD_His__Met, "spec_1_classification", "AA substitution"}, {UNIMOD_His__Met, "spec_1_hidden", "1"}, {UNIMOD_His__Met, "spec_1_position", "Anywhere"}, {UNIMOD_His__Met, "spec_1_site", "H"}, {UNIMOD_His__Ser, "approved", "0"}, {UNIMOD_His__Ser, "delta_composition", "H(-2) C(-3) N(-2) O"}, {UNIMOD_His__Ser, "spec_1_classification", "AA substitution"}, {UNIMOD_His__Ser, "spec_1_hidden", "1"}, {UNIMOD_His__Ser, "spec_1_position", "Anywhere"}, {UNIMOD_His__Ser, "spec_1_site", "H"}, {UNIMOD_His__Thr, "approved", "0"}, {UNIMOD_His__Thr, "delta_composition", "C(-2) N(-2) O"}, {UNIMOD_His__Thr, "spec_1_classification", "AA substitution"}, {UNIMOD_His__Thr, "spec_1_hidden", "1"}, {UNIMOD_His__Thr, "spec_1_position", "Anywhere"}, {UNIMOD_His__Thr, "spec_1_site", "H"}, {UNIMOD_His__Val, "approved", "0"}, {UNIMOD_His__Val, "delta_composition", "H(2) C(-1) N(-2)"}, {UNIMOD_His__Val, "spec_1_classification", "AA substitution"}, {UNIMOD_His__Val, "spec_1_hidden", "1"}, {UNIMOD_His__Val, "spec_1_position", "Anywhere"}, {UNIMOD_His__Val, "spec_1_site", "H"}, {UNIMOD_His__Trp, "approved", "0"}, {UNIMOD_His__Trp, "delta_composition", "H(3) C(5) N(-1)"}, {UNIMOD_His__Trp, "spec_1_classification", "AA substitution"}, {UNIMOD_His__Trp, "spec_1_hidden", "1"}, {UNIMOD_His__Trp, "spec_1_position", "Anywhere"}, {UNIMOD_His__Trp, "spec_1_site", "H"}, {UNIMOD_Xle__Ala, "approved", "0"}, {UNIMOD_Xle__Ala, "delta_composition", "H(-6) C(-3)"}, {UNIMOD_Xle__Ala, "spec_1_classification", "AA substitution"}, {UNIMOD_Xle__Ala, "spec_1_hidden", "1"}, {UNIMOD_Xle__Ala, "spec_1_position", "Anywhere"}, {UNIMOD_Xle__Ala, "spec_1_site", "L"}, {UNIMOD_Xle__Ala, "spec_2_classification", "AA substitution"}, {UNIMOD_Xle__Ala, "spec_2_hidden", "1"}, {UNIMOD_Xle__Ala, "spec_2_position", "Anywhere"}, {UNIMOD_Xle__Ala, "spec_2_site", "I"}, {UNIMOD_Xle__Cys, "approved", "0"}, {UNIMOD_Xle__Cys, "delta_composition", "H(-6) C(-3) S"}, {UNIMOD_Xle__Cys, "spec_1_classification", "AA substitution"}, {UNIMOD_Xle__Cys, "spec_1_hidden", "1"}, {UNIMOD_Xle__Cys, "spec_1_position", "Anywhere"}, {UNIMOD_Xle__Cys, "spec_1_site", "L"}, {UNIMOD_Xle__Cys, "spec_2_classification", "AA substitution"}, {UNIMOD_Xle__Cys, "spec_2_hidden", "1"}, {UNIMOD_Xle__Cys, "spec_2_position", "Anywhere"}, {UNIMOD_Xle__Cys, "spec_2_site", "I"}, {UNIMOD_Xle__Asp, "approved", "0"}, {UNIMOD_Xle__Asp, "delta_composition", "H(-6) C(-2) O(2)"}, {UNIMOD_Xle__Asp, "spec_1_classification", "AA substitution"}, {UNIMOD_Xle__Asp, "spec_1_hidden", "1"}, {UNIMOD_Xle__Asp, "spec_1_position", "Anywhere"}, {UNIMOD_Xle__Asp, "spec_1_site", "L"}, {UNIMOD_Xle__Asp, "spec_2_classification", "AA substitution"}, {UNIMOD_Xle__Asp, "spec_2_hidden", "1"}, {UNIMOD_Xle__Asp, "spec_2_position", "Anywhere"}, {UNIMOD_Xle__Asp, "spec_2_site", "I"}, {UNIMOD_Xle__Glu, "approved", "0"}, {UNIMOD_Xle__Glu, "delta_composition", "H(-4) C(-1) O(2)"}, {UNIMOD_Xle__Glu, "spec_1_classification", "AA substitution"}, {UNIMOD_Xle__Glu, "spec_1_hidden", "1"}, {UNIMOD_Xle__Glu, "spec_1_position", "Anywhere"}, {UNIMOD_Xle__Glu, "spec_1_site", "L"}, {UNIMOD_Xle__Glu, "spec_2_classification", "AA substitution"}, {UNIMOD_Xle__Glu, "spec_2_hidden", "1"}, {UNIMOD_Xle__Glu, "spec_2_position", "Anywhere"}, {UNIMOD_Xle__Glu, "spec_2_site", "I"}, {UNIMOD_Xle__Gly, "approved", "0"}, {UNIMOD_Xle__Gly, "delta_composition", "H(-8) C(-4)"}, {UNIMOD_Xle__Gly, "spec_1_classification", "AA substitution"}, {UNIMOD_Xle__Gly, "spec_1_hidden", "1"}, {UNIMOD_Xle__Gly, "spec_1_position", "Anywhere"}, {UNIMOD_Xle__Gly, "spec_1_site", "L"}, {UNIMOD_Xle__Gly, "spec_2_classification", "AA substitution"}, {UNIMOD_Xle__Gly, "spec_2_hidden", "1"}, {UNIMOD_Xle__Gly, "spec_2_position", "Anywhere"}, {UNIMOD_Xle__Gly, "spec_2_site", "I"}, {UNIMOD_Xle__Tyr, "approved", "0"}, {UNIMOD_Xle__Tyr, "delta_composition", "H(-2) C(3) O"}, {UNIMOD_Xle__Tyr, "spec_1_classification", "AA substitution"}, {UNIMOD_Xle__Tyr, "spec_1_hidden", "1"}, {UNIMOD_Xle__Tyr, "spec_1_position", "Anywhere"}, {UNIMOD_Xle__Tyr, "spec_1_site", "L"}, {UNIMOD_Xle__Tyr, "spec_2_classification", "AA substitution"}, {UNIMOD_Xle__Tyr, "spec_2_hidden", "1"}, {UNIMOD_Xle__Tyr, "spec_2_position", "Anywhere"}, {UNIMOD_Xle__Tyr, "spec_2_site", "I"}, {UNIMOD_Lys__Ala, "approved", "0"}, {UNIMOD_Lys__Ala, "delta_composition", "H(-7) C(-3) N(-1)"}, {UNIMOD_Lys__Ala, "spec_1_classification", "AA substitution"}, {UNIMOD_Lys__Ala, "spec_1_hidden", "1"}, {UNIMOD_Lys__Ala, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__Ala, "spec_1_site", "K"}, {UNIMOD_Lys__Cys, "approved", "0"}, {UNIMOD_Lys__Cys, "delta_composition", "H(-7) C(-3) N(-1) S"}, {UNIMOD_Lys__Cys, "spec_1_classification", "AA substitution"}, {UNIMOD_Lys__Cys, "spec_1_hidden", "1"}, {UNIMOD_Lys__Cys, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__Cys, "spec_1_site", "K"}, {UNIMOD_Lys__Asp, "approved", "0"}, {UNIMOD_Lys__Asp, "delta_composition", "H(-7) C(-2) N(-1) O(2)"}, {UNIMOD_Lys__Asp, "spec_1_classification", "AA substitution"}, {UNIMOD_Lys__Asp, "spec_1_hidden", "1"}, {UNIMOD_Lys__Asp, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__Asp, "spec_1_site", "K"}, {UNIMOD_Lys__Phe, "approved", "0"}, {UNIMOD_Lys__Phe, "delta_composition", "H(-3) C(3) N(-1)"}, {UNIMOD_Lys__Phe, "spec_1_classification", "AA substitution"}, {UNIMOD_Lys__Phe, "spec_1_hidden", "1"}, {UNIMOD_Lys__Phe, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__Phe, "spec_1_site", "K"}, {UNIMOD_Lys__Gly, "approved", "0"}, {UNIMOD_Lys__Gly, "delta_composition", "H(-9) C(-4) N(-1)"}, {UNIMOD_Lys__Gly, "spec_1_classification", "AA substitution"}, {UNIMOD_Lys__Gly, "spec_1_hidden", "1"}, {UNIMOD_Lys__Gly, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__Gly, "spec_1_site", "K"}, {UNIMOD_Lys__His, "approved", "0"}, {UNIMOD_Lys__His, "delta_composition", "H(-5) N"}, {UNIMOD_Lys__His, "spec_1_classification", "AA substitution"}, {UNIMOD_Lys__His, "spec_1_hidden", "1"}, {UNIMOD_Lys__His, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__His, "spec_1_site", "K"}, {UNIMOD_Lys__Pro, "approved", "0"}, {UNIMOD_Lys__Pro, "delta_composition", "H(-5) C(-1) N(-1)"}, {UNIMOD_Lys__Pro, "spec_1_classification", "AA substitution"}, {UNIMOD_Lys__Pro, "spec_1_hidden", "1"}, {UNIMOD_Lys__Pro, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__Pro, "spec_1_site", "K"}, {UNIMOD_Lys__Ser, "approved", "0"}, {UNIMOD_Lys__Ser, "delta_composition", "H(-7) C(-3) N(-1) O"}, {UNIMOD_Lys__Ser, "spec_1_classification", "AA substitution"}, {UNIMOD_Lys__Ser, "spec_1_hidden", "1"}, {UNIMOD_Lys__Ser, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__Ser, "spec_1_site", "K"}, {UNIMOD_Lys__Val, "approved", "0"}, {UNIMOD_Lys__Val, "delta_composition", "H(-3) C(-1) N(-1)"}, {UNIMOD_Lys__Val, "spec_1_classification", "AA substitution"}, {UNIMOD_Lys__Val, "spec_1_hidden", "1"}, {UNIMOD_Lys__Val, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__Val, "spec_1_site", "K"}, {UNIMOD_Lys__Trp, "approved", "0"}, {UNIMOD_Lys__Trp, "delta_composition", "H(-2) C(5)"}, {UNIMOD_Lys__Trp, "spec_1_classification", "AA substitution"}, {UNIMOD_Lys__Trp, "spec_1_hidden", "1"}, {UNIMOD_Lys__Trp, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__Trp, "spec_1_site", "K"}, {UNIMOD_Lys__Tyr, "approved", "0"}, {UNIMOD_Lys__Tyr, "delta_composition", "H(-3) C(3) N(-1) O"}, {UNIMOD_Lys__Tyr, "spec_1_classification", "AA substitution"}, {UNIMOD_Lys__Tyr, "spec_1_hidden", "1"}, {UNIMOD_Lys__Tyr, "spec_1_position", "Anywhere"}, {UNIMOD_Lys__Tyr, "spec_1_site", "K"}, {UNIMOD_Met__Ala, "approved", "0"}, {UNIMOD_Met__Ala, "delta_composition", "H(-4) C(-2) S(-1)"}, {UNIMOD_Met__Ala, "spec_1_classification", "AA substitution"}, {UNIMOD_Met__Ala, "spec_1_hidden", "1"}, {UNIMOD_Met__Ala, "spec_1_position", "Anywhere"}, {UNIMOD_Met__Ala, "spec_1_site", "M"}, {UNIMOD_Met__Cys, "approved", "0"}, {UNIMOD_Met__Cys, "delta_composition", "H(-4) C(-2)"}, {UNIMOD_Met__Cys, "spec_1_classification", "AA substitution"}, {UNIMOD_Met__Cys, "spec_1_hidden", "1"}, {UNIMOD_Met__Cys, "spec_1_position", "Anywhere"}, {UNIMOD_Met__Cys, "spec_1_site", "M"}, {UNIMOD_Met__Asp, "approved", "0"}, {UNIMOD_Met__Asp, "delta_composition", "H(-4) C(-1) O(2) S(-1)"}, {UNIMOD_Met__Asp, "spec_1_classification", "AA substitution"}, {UNIMOD_Met__Asp, "spec_1_hidden", "1"}, {UNIMOD_Met__Asp, "spec_1_position", "Anywhere"}, {UNIMOD_Met__Asp, "spec_1_site", "M"}, {UNIMOD_Met__Glu, "approved", "0"}, {UNIMOD_Met__Glu, "delta_composition", "H(-2) O(2) S(-1)"}, {UNIMOD_Met__Glu, "spec_1_classification", "AA substitution"}, {UNIMOD_Met__Glu, "spec_1_hidden", "1"}, {UNIMOD_Met__Glu, "spec_1_position", "Anywhere"}, {UNIMOD_Met__Glu, "spec_1_site", "M"}, {UNIMOD_Met__Phe, "approved", "0"}, {UNIMOD_Met__Phe, "delta_composition", "C(4) S(-1)"}, {UNIMOD_Met__Phe, "spec_1_classification", "AA substitution"}, {UNIMOD_Met__Phe, "spec_1_hidden", "1"}, {UNIMOD_Met__Phe, "spec_1_position", "Anywhere"}, {UNIMOD_Met__Phe, "spec_1_site", "M"}, {UNIMOD_Met__Gly, "approved", "0"}, {UNIMOD_Met__Gly, "delta_composition", "H(-6) C(-3) S(-1)"}, {UNIMOD_Met__Gly, "spec_1_classification", "AA substitution"}, {UNIMOD_Met__Gly, "spec_1_hidden", "1"}, {UNIMOD_Met__Gly, "spec_1_position", "Anywhere"}, {UNIMOD_Met__Gly, "spec_1_site", "M"}, {UNIMOD_Met__His, "approved", "0"}, {UNIMOD_Met__His, "delta_composition", "H(-2) C N(2) S(-1)"}, {UNIMOD_Met__His, "spec_1_classification", "AA substitution"}, {UNIMOD_Met__His, "spec_1_hidden", "1"}, {UNIMOD_Met__His, "spec_1_position", "Anywhere"}, {UNIMOD_Met__His, "spec_1_site", "M"}, {UNIMOD_Met__Asn, "approved", "0"}, {UNIMOD_Met__Asn, "delta_composition", "H(-3) C(-1) N O S(-1)"}, {UNIMOD_Met__Asn, "spec_1_classification", "AA substitution"}, {UNIMOD_Met__Asn, "spec_1_hidden", "1"}, {UNIMOD_Met__Asn, "spec_1_position", "Anywhere"}, {UNIMOD_Met__Asn, "spec_1_site", "M"}, {UNIMOD_Met__Pro, "approved", "0"}, {UNIMOD_Met__Pro, "delta_composition", "H(-2) S(-1)"}, {UNIMOD_Met__Pro, "spec_1_classification", "AA substitution"}, {UNIMOD_Met__Pro, "spec_1_hidden", "1"}, {UNIMOD_Met__Pro, "spec_1_position", "Anywhere"}, {UNIMOD_Met__Pro, "spec_1_site", "M"}, {UNIMOD_Met__Gln, "approved", "0"}, {UNIMOD_Met__Gln, "delta_composition", "H(-1) N O S(-1)"}, {UNIMOD_Met__Gln, "spec_1_classification", "AA substitution"}, {UNIMOD_Met__Gln, "spec_1_hidden", "1"}, {UNIMOD_Met__Gln, "spec_1_position", "Anywhere"}, {UNIMOD_Met__Gln, "spec_1_site", "M"}, {UNIMOD_Met__Ser, "approved", "0"}, {UNIMOD_Met__Ser, "delta_composition", "H(-4) C(-2) O S(-1)"}, {UNIMOD_Met__Ser, "spec_1_classification", "AA substitution"}, {UNIMOD_Met__Ser, "spec_1_hidden", "1"}, {UNIMOD_Met__Ser, "spec_1_position", "Anywhere"}, {UNIMOD_Met__Ser, "spec_1_site", "M"}, {UNIMOD_Met__Trp, "approved", "0"}, {UNIMOD_Met__Trp, "delta_composition", "H C(6) N S(-1)"}, {UNIMOD_Met__Trp, "spec_1_classification", "AA substitution"}, {UNIMOD_Met__Trp, "spec_1_hidden", "1"}, {UNIMOD_Met__Trp, "spec_1_position", "Anywhere"}, {UNIMOD_Met__Trp, "spec_1_site", "M"}, {UNIMOD_Met__Tyr, "approved", "0"}, {UNIMOD_Met__Tyr, "delta_composition", "C(4) O S(-1)"}, {UNIMOD_Met__Tyr, "spec_1_classification", "AA substitution"}, {UNIMOD_Met__Tyr, "spec_1_hidden", "1"}, {UNIMOD_Met__Tyr, "spec_1_position", "Anywhere"}, {UNIMOD_Met__Tyr, "spec_1_site", "M"}, {UNIMOD_Asn__Ala, "approved", "0"}, {UNIMOD_Asn__Ala, "delta_composition", "H(-1) C(-1) N(-1) O(-1)"}, {UNIMOD_Asn__Ala, "spec_1_classification", "AA substitution"}, {UNIMOD_Asn__Ala, "spec_1_hidden", "1"}, {UNIMOD_Asn__Ala, "spec_1_position", "Anywhere"}, {UNIMOD_Asn__Ala, "spec_1_site", "N"}, {UNIMOD_Asn__Cys, "approved", "0"}, {UNIMOD_Asn__Cys, "delta_composition", "H(-1) C(-1) N(-1) O(-1) S"}, {UNIMOD_Asn__Cys, "spec_1_classification", "AA substitution"}, {UNIMOD_Asn__Cys, "spec_1_hidden", "1"}, {UNIMOD_Asn__Cys, "spec_1_position", "Anywhere"}, {UNIMOD_Asn__Cys, "spec_1_site", "N"}, {UNIMOD_Asn__Glu, "approved", "0"}, {UNIMOD_Asn__Glu, "delta_composition", "H C N(-1) O"}, {UNIMOD_Asn__Glu, "spec_1_classification", "AA substitution"}, {UNIMOD_Asn__Glu, "spec_1_hidden", "1"}, {UNIMOD_Asn__Glu, "spec_1_position", "Anywhere"}, {UNIMOD_Asn__Glu, "spec_1_site", "N"}, {UNIMOD_Asn__Phe, "approved", "0"}, {UNIMOD_Asn__Phe, "delta_composition", "H(3) C(5) N(-1) O(-1)"}, {UNIMOD_Asn__Phe, "spec_1_classification", "AA substitution"}, {UNIMOD_Asn__Phe, "spec_1_hidden", "1"}, {UNIMOD_Asn__Phe, "spec_1_position", "Anywhere"}, {UNIMOD_Asn__Phe, "spec_1_site", "N"}, {UNIMOD_Asn__Gly, "approved", "0"}, {UNIMOD_Asn__Gly, "delta_composition", "H(-3) C(-2) N(-1) O(-1)"}, {UNIMOD_Asn__Gly, "spec_1_classification", "AA substitution"}, {UNIMOD_Asn__Gly, "spec_1_hidden", "1"}, {UNIMOD_Asn__Gly, "spec_1_position", "Anywhere"}, {UNIMOD_Asn__Gly, "spec_1_site", "N"}, {UNIMOD_Asn__Met, "approved", "0"}, {UNIMOD_Asn__Met, "delta_composition", "H(3) C N(-1) O(-1) S"}, {UNIMOD_Asn__Met, "spec_1_classification", "AA substitution"}, {UNIMOD_Asn__Met, "spec_1_hidden", "1"}, {UNIMOD_Asn__Met, "spec_1_position", "Anywhere"}, {UNIMOD_Asn__Met, "spec_1_site", "N"}, {UNIMOD_Asn__Pro, "approved", "0"}, {UNIMOD_Asn__Pro, "delta_composition", "H C N(-1) O(-1)"}, {UNIMOD_Asn__Pro, "spec_1_classification", "AA substitution"}, {UNIMOD_Asn__Pro, "spec_1_hidden", "1"}, {UNIMOD_Asn__Pro, "spec_1_position", "Anywhere"}, {UNIMOD_Asn__Pro, "spec_1_site", "N"}, {UNIMOD_Asn__Gln, "approved", "0"}, {UNIMOD_Asn__Gln, "delta_composition", "H(2) C"}, {UNIMOD_Asn__Gln, "spec_1_classification", "AA substitution"}, {UNIMOD_Asn__Gln, "spec_1_hidden", "1"}, {UNIMOD_Asn__Gln, "spec_1_position", "Anywhere"}, {UNIMOD_Asn__Gln, "spec_1_site", "N"}, {UNIMOD_Asn__Arg, "approved", "0"}, {UNIMOD_Asn__Arg, "delta_composition", "H(6) C(2) N(2) O(-1)"}, {UNIMOD_Asn__Arg, "spec_1_classification", "AA substitution"}, {UNIMOD_Asn__Arg, "spec_1_hidden", "1"}, {UNIMOD_Asn__Arg, "spec_1_position", "Anywhere"}, {UNIMOD_Asn__Arg, "spec_1_site", "N"}, {UNIMOD_Asn__Val, "approved", "0"}, {UNIMOD_Asn__Val, "delta_composition", "H(3) C N(-1) O(-1)"}, {UNIMOD_Asn__Val, "spec_1_classification", "AA substitution"}, {UNIMOD_Asn__Val, "spec_1_hidden", "1"}, {UNIMOD_Asn__Val, "spec_1_position", "Anywhere"}, {UNIMOD_Asn__Val, "spec_1_site", "N"}, {UNIMOD_Asn__Trp, "approved", "0"}, {UNIMOD_Asn__Trp, "delta_composition", "H(4) C(7) O(-1)"}, {UNIMOD_Asn__Trp, "spec_1_classification", "AA substitution"}, {UNIMOD_Asn__Trp, "spec_1_hidden", "1"}, {UNIMOD_Asn__Trp, "spec_1_position", "Anywhere"}, {UNIMOD_Asn__Trp, "spec_1_site", "N"}, {UNIMOD_Pro__Cys, "approved", "0"}, {UNIMOD_Pro__Cys, "delta_composition", "H(-2) C(-2) S"}, {UNIMOD_Pro__Cys, "spec_1_classification", "AA substitution"}, {UNIMOD_Pro__Cys, "spec_1_hidden", "1"}, {UNIMOD_Pro__Cys, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__Cys, "spec_1_site", "P"}, {UNIMOD_Pro__Asp, "approved", "0"}, {UNIMOD_Pro__Asp, "delta_composition", "H(-2) C(-1) O(2)"}, {UNIMOD_Pro__Asp, "spec_1_classification", "AA substitution"}, {UNIMOD_Pro__Asp, "spec_1_hidden", "1"}, {UNIMOD_Pro__Asp, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__Asp, "spec_1_site", "P"}, {UNIMOD_Pro__Glu, "approved", "0"}, {UNIMOD_Pro__Glu, "delta_composition", "O(2)"}, {UNIMOD_Pro__Glu, "spec_1_classification", "AA substitution"}, {UNIMOD_Pro__Glu, "spec_1_hidden", "1"}, {UNIMOD_Pro__Glu, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__Glu, "spec_1_site", "P"}, {UNIMOD_Pro__Phe, "approved", "0"}, {UNIMOD_Pro__Phe, "delta_composition", "H(2) C(4)"}, {UNIMOD_Pro__Phe, "spec_1_classification", "AA substitution"}, {UNIMOD_Pro__Phe, "spec_1_hidden", "1"}, {UNIMOD_Pro__Phe, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__Phe, "spec_1_site", "P"}, {UNIMOD_Pro__Gly, "approved", "0"}, {UNIMOD_Pro__Gly, "delta_composition", "H(-4) C(-3)"}, {UNIMOD_Pro__Gly, "spec_1_classification", "AA substitution"}, {UNIMOD_Pro__Gly, "spec_1_hidden", "1"}, {UNIMOD_Pro__Gly, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__Gly, "spec_1_site", "P"}, {UNIMOD_Pro__Lys, "approved", "0"}, {UNIMOD_Pro__Lys, "delta_composition", "H(5) C N"}, {UNIMOD_Pro__Lys, "spec_1_classification", "AA substitution"}, {UNIMOD_Pro__Lys, "spec_1_hidden", "1"}, {UNIMOD_Pro__Lys, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__Lys, "spec_1_site", "P"}, {UNIMOD_Pro__Met, "approved", "0"}, {UNIMOD_Pro__Met, "delta_composition", "H(2) S"}, {UNIMOD_Pro__Met, "spec_1_classification", "AA substitution"}, {UNIMOD_Pro__Met, "spec_1_hidden", "1"}, {UNIMOD_Pro__Met, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__Met, "spec_1_site", "P"}, {UNIMOD_Pro__Asn, "approved", "0"}, {UNIMOD_Pro__Asn, "delta_composition", "H(-1) C(-1) N O"}, {UNIMOD_Pro__Asn, "spec_1_classification", "AA substitution"}, {UNIMOD_Pro__Asn, "spec_1_hidden", "1"}, {UNIMOD_Pro__Asn, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__Asn, "spec_1_site", "P"}, {UNIMOD_Pro__Val, "approved", "0"}, {UNIMOD_Pro__Val, "delta_composition", "H(2)"}, {UNIMOD_Pro__Val, "spec_1_classification", "AA substitution"}, {UNIMOD_Pro__Val, "spec_1_hidden", "1"}, {UNIMOD_Pro__Val, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__Val, "spec_1_site", "P"}, {UNIMOD_Pro__Trp, "approved", "0"}, {UNIMOD_Pro__Trp, "delta_composition", "H(3) C(6) N"}, {UNIMOD_Pro__Trp, "spec_1_classification", "AA substitution"}, {UNIMOD_Pro__Trp, "spec_1_hidden", "1"}, {UNIMOD_Pro__Trp, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__Trp, "spec_1_site", "P"}, {UNIMOD_Pro__Tyr, "approved", "0"}, {UNIMOD_Pro__Tyr, "delta_composition", "H(2) C(4) O"}, {UNIMOD_Pro__Tyr, "spec_1_classification", "AA substitution"}, {UNIMOD_Pro__Tyr, "spec_1_hidden", "1"}, {UNIMOD_Pro__Tyr, "spec_1_position", "Anywhere"}, {UNIMOD_Pro__Tyr, "spec_1_site", "P"}, {UNIMOD_Gln__Ala, "approved", "0"}, {UNIMOD_Gln__Ala, "delta_composition", "H(-3) C(-2) N(-1) O(-1)"}, {UNIMOD_Gln__Ala, "spec_1_classification", "AA substitution"}, {UNIMOD_Gln__Ala, "spec_1_hidden", "1"}, {UNIMOD_Gln__Ala, "spec_1_position", "Anywhere"}, {UNIMOD_Gln__Ala, "spec_1_site", "Q"}, {UNIMOD_Gln__Cys, "approved", "0"}, {UNIMOD_Gln__Cys, "delta_composition", "H(-3) C(-2) N(-1) O(-1) S"}, {UNIMOD_Gln__Cys, "spec_1_classification", "AA substitution"}, {UNIMOD_Gln__Cys, "spec_1_hidden", "1"}, {UNIMOD_Gln__Cys, "spec_1_position", "Anywhere"}, {UNIMOD_Gln__Cys, "spec_1_site", "Q"}, {UNIMOD_Gln__Asp, "approved", "0"}, {UNIMOD_Gln__Asp, "delta_composition", "H(-3) C(-1) N(-1) O"}, {UNIMOD_Gln__Asp, "spec_1_classification", "AA substitution"}, {UNIMOD_Gln__Asp, "spec_1_hidden", "1"}, {UNIMOD_Gln__Asp, "spec_1_position", "Anywhere"}, {UNIMOD_Gln__Asp, "spec_1_site", "Q"}, {UNIMOD_Gln__Phe, "approved", "0"}, {UNIMOD_Gln__Phe, "delta_composition", "H C(4) N(-1) O(-1)"}, {UNIMOD_Gln__Phe, "spec_1_classification", "AA substitution"}, {UNIMOD_Gln__Phe, "spec_1_hidden", "1"}, {UNIMOD_Gln__Phe, "spec_1_position", "Anywhere"}, {UNIMOD_Gln__Phe, "spec_1_site", "Q"}, {UNIMOD_Gln__Gly, "approved", "0"}, {UNIMOD_Gln__Gly, "delta_composition", "H(-5) C(-3) N(-1) O(-1)"}, {UNIMOD_Gln__Gly, "spec_1_classification", "AA substitution"}, {UNIMOD_Gln__Gly, "spec_1_hidden", "1"}, {UNIMOD_Gln__Gly, "spec_1_position", "Anywhere"}, {UNIMOD_Gln__Gly, "spec_1_site", "Q"}, {UNIMOD_Gln__Met, "approved", "0"}, {UNIMOD_Gln__Met, "delta_composition", "H N(-1) O(-1) S"}, {UNIMOD_Gln__Met, "spec_1_classification", "AA substitution"}, {UNIMOD_Gln__Met, "spec_1_hidden", "1"}, {UNIMOD_Gln__Met, "spec_1_position", "Anywhere"}, {UNIMOD_Gln__Met, "spec_1_site", "Q"}, {UNIMOD_Gln__Asn, "approved", "0"}, {UNIMOD_Gln__Asn, "delta_composition", "H(-2) C(-1)"}, {UNIMOD_Gln__Asn, "spec_1_classification", "AA substitution"}, {UNIMOD_Gln__Asn, "spec_1_hidden", "1"}, {UNIMOD_Gln__Asn, "spec_1_position", "Anywhere"}, {UNIMOD_Gln__Asn, "spec_1_site", "Q"}, {UNIMOD_Gln__Ser, "approved", "0"}, {UNIMOD_Gln__Ser, "delta_composition", "H(-3) C(-2) N(-1)"}, {UNIMOD_Gln__Ser, "spec_1_classification", "AA substitution"}, {UNIMOD_Gln__Ser, "spec_1_hidden", "1"}, {UNIMOD_Gln__Ser, "spec_1_position", "Anywhere"}, {UNIMOD_Gln__Ser, "spec_1_site", "Q"}, {UNIMOD_Gln__Thr, "approved", "0"}, {UNIMOD_Gln__Thr, "delta_composition", "H(-1) C(-1) N(-1)"}, {UNIMOD_Gln__Thr, "spec_1_classification", "AA substitution"}, {UNIMOD_Gln__Thr, "spec_1_hidden", "1"}, {UNIMOD_Gln__Thr, "spec_1_position", "Anywhere"}, {UNIMOD_Gln__Thr, "spec_1_site", "Q"}, {UNIMOD_Gln__Val, "approved", "0"}, {UNIMOD_Gln__Val, "delta_composition", "H N(-1) O(-1)"}, {UNIMOD_Gln__Val, "spec_1_classification", "AA substitution"}, {UNIMOD_Gln__Val, "spec_1_hidden", "1"}, {UNIMOD_Gln__Val, "spec_1_position", "Anywhere"}, {UNIMOD_Gln__Val, "spec_1_site", "Q"}, {UNIMOD_Gln__Trp, "approved", "0"}, {UNIMOD_Gln__Trp, "delta_composition", "H(2) C(6) O(-1)"}, {UNIMOD_Gln__Trp, "spec_1_classification", "AA substitution"}, {UNIMOD_Gln__Trp, "spec_1_hidden", "1"}, {UNIMOD_Gln__Trp, "spec_1_position", "Anywhere"}, {UNIMOD_Gln__Trp, "spec_1_site", "Q"}, {UNIMOD_Gln__Tyr, "approved", "0"}, {UNIMOD_Gln__Tyr, "delta_composition", "H C(4) N(-1)"}, {UNIMOD_Gln__Tyr, "spec_1_classification", "AA substitution"}, {UNIMOD_Gln__Tyr, "spec_1_hidden", "1"}, {UNIMOD_Gln__Tyr, "spec_1_position", "Anywhere"}, {UNIMOD_Gln__Tyr, "spec_1_site", "Q"}, {UNIMOD_Arg__Ala, "approved", "0"}, {UNIMOD_Arg__Ala, "delta_composition", "H(-7) C(-3) N(-3)"}, {UNIMOD_Arg__Ala, "spec_1_classification", "AA substitution"}, {UNIMOD_Arg__Ala, "spec_1_hidden", "1"}, {UNIMOD_Arg__Ala, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__Ala, "spec_1_site", "R"}, {UNIMOD_Arg__Asp, "approved", "0"}, {UNIMOD_Arg__Asp, "delta_composition", "H(-7) C(-2) N(-3) O(2)"}, {UNIMOD_Arg__Asp, "spec_1_classification", "AA substitution"}, {UNIMOD_Arg__Asp, "spec_1_hidden", "1"}, {UNIMOD_Arg__Asp, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__Asp, "spec_1_site", "R"}, {UNIMOD_Arg__Glu, "approved", "0"}, {UNIMOD_Arg__Glu, "delta_composition", "H(-5) C(-1) N(-3) O(2)"}, {UNIMOD_Arg__Glu, "spec_1_classification", "AA substitution"}, {UNIMOD_Arg__Glu, "spec_1_hidden", "1"}, {UNIMOD_Arg__Glu, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__Glu, "spec_1_site", "R"}, {UNIMOD_Arg__Asn, "approved", "0"}, {UNIMOD_Arg__Asn, "delta_composition", "H(-6) C(-2) N(-2) O"}, {UNIMOD_Arg__Asn, "spec_1_classification", "AA substitution"}, {UNIMOD_Arg__Asn, "spec_1_hidden", "1"}, {UNIMOD_Arg__Asn, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__Asn, "spec_1_site", "R"}, {UNIMOD_Arg__Val, "approved", "0"}, {UNIMOD_Arg__Val, "delta_composition", "H(-3) C(-1) N(-3)"}, {UNIMOD_Arg__Val, "spec_1_classification", "AA substitution"}, {UNIMOD_Arg__Val, "spec_1_hidden", "1"}, {UNIMOD_Arg__Val, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__Val, "spec_1_site", "R"}, {UNIMOD_Arg__Tyr, "approved", "0"}, {UNIMOD_Arg__Tyr, "delta_composition", "H(-3) C(3) N(-3) O"}, {UNIMOD_Arg__Tyr, "spec_1_classification", "AA substitution"}, {UNIMOD_Arg__Tyr, "spec_1_hidden", "1"}, {UNIMOD_Arg__Tyr, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__Tyr, "spec_1_site", "R"}, {UNIMOD_Arg__Phe, "approved", "0"}, {UNIMOD_Arg__Phe, "delta_composition", "H(-3) C(3) N(-3)"}, {UNIMOD_Arg__Phe, "spec_1_classification", "AA substitution"}, {UNIMOD_Arg__Phe, "spec_1_hidden", "1"}, {UNIMOD_Arg__Phe, "spec_1_position", "Anywhere"}, {UNIMOD_Arg__Phe, "spec_1_site", "R"}, {UNIMOD_Ser__Asp, "approved", "0"}, {UNIMOD_Ser__Asp, "delta_composition", "C O"}, {UNIMOD_Ser__Asp, "spec_1_classification", "AA substitution"}, {UNIMOD_Ser__Asp, "spec_1_hidden", "1"}, {UNIMOD_Ser__Asp, "spec_1_position", "Anywhere"}, {UNIMOD_Ser__Asp, "spec_1_site", "S"}, {UNIMOD_Ser__Glu, "approved", "0"}, {UNIMOD_Ser__Glu, "delta_composition", "H(2) C(2) O"}, {UNIMOD_Ser__Glu, "spec_1_classification", "AA substitution"}, {UNIMOD_Ser__Glu, "spec_1_hidden", "1"}, {UNIMOD_Ser__Glu, "spec_1_position", "Anywhere"}, {UNIMOD_Ser__Glu, "spec_1_site", "S"}, {UNIMOD_Ser__His, "approved", "0"}, {UNIMOD_Ser__His, "delta_composition", "H(2) C(3) N(2) O(-1)"}, {UNIMOD_Ser__His, "spec_1_classification", "AA substitution"}, {UNIMOD_Ser__His, "spec_1_hidden", "1"}, {UNIMOD_Ser__His, "spec_1_position", "Anywhere"}, {UNIMOD_Ser__His, "spec_1_site", "S"}, {UNIMOD_Ser__Lys, "approved", "0"}, {UNIMOD_Ser__Lys, "delta_composition", "H(7) C(3) N O(-1)"}, {UNIMOD_Ser__Lys, "spec_1_classification", "AA substitution"}, {UNIMOD_Ser__Lys, "spec_1_hidden", "1"}, {UNIMOD_Ser__Lys, "spec_1_position", "Anywhere"}, {UNIMOD_Ser__Lys, "spec_1_site", "S"}, {UNIMOD_Ser__Met, "approved", "0"}, {UNIMOD_Ser__Met, "delta_composition", "H(4) C(2) O(-1) S"}, {UNIMOD_Ser__Met, "spec_1_classification", "AA substitution"}, {UNIMOD_Ser__Met, "spec_1_hidden", "1"}, {UNIMOD_Ser__Met, "spec_1_position", "Anywhere"}, {UNIMOD_Ser__Met, "spec_1_site", "S"}, {UNIMOD_Ser__Gln, "approved", "0"}, {UNIMOD_Ser__Gln, "delta_composition", "H(3) C(2) N"}, {UNIMOD_Ser__Gln, "spec_1_classification", "AA substitution"}, {UNIMOD_Ser__Gln, "spec_1_hidden", "1"}, {UNIMOD_Ser__Gln, "spec_1_position", "Anywhere"}, {UNIMOD_Ser__Gln, "spec_1_site", "S"}, {UNIMOD_Ser__Val, "approved", "0"}, {UNIMOD_Ser__Val, "delta_composition", "H(4) C(2) O(-1)"}, {UNIMOD_Ser__Val, "spec_1_classification", "AA substitution"}, {UNIMOD_Ser__Val, "spec_1_hidden", "1"}, {UNIMOD_Ser__Val, "spec_1_position", "Anywhere"}, {UNIMOD_Ser__Val, "spec_1_site", "S"}, {UNIMOD_Thr__Cys, "approved", "0"}, {UNIMOD_Thr__Cys, "delta_composition", "H(-2) C(-1) O(-1) S"}, {UNIMOD_Thr__Cys, "spec_1_classification", "AA substitution"}, {UNIMOD_Thr__Cys, "spec_1_hidden", "1"}, {UNIMOD_Thr__Cys, "spec_1_position", "Anywhere"}, {UNIMOD_Thr__Cys, "spec_1_site", "T"}, {UNIMOD_Thr__Asp, "approved", "0"}, {UNIMOD_Thr__Asp, "delta_composition", "H(-2) O"}, {UNIMOD_Thr__Asp, "spec_1_classification", "AA substitution"}, {UNIMOD_Thr__Asp, "spec_1_hidden", "1"}, {UNIMOD_Thr__Asp, "spec_1_position", "Anywhere"}, {UNIMOD_Thr__Asp, "spec_1_site", "T"}, {UNIMOD_Thr__Glu, "approved", "0"}, {UNIMOD_Thr__Glu, "delta_composition", "C O"}, {UNIMOD_Thr__Glu, "spec_1_classification", "AA substitution"}, {UNIMOD_Thr__Glu, "spec_1_hidden", "1"}, {UNIMOD_Thr__Glu, "spec_1_position", "Anywhere"}, {UNIMOD_Thr__Glu, "spec_1_site", "T"}, {UNIMOD_Thr__Phe, "approved", "0"}, {UNIMOD_Thr__Phe, "delta_composition", "H(2) C(5) O(-1)"}, {UNIMOD_Thr__Phe, "spec_1_classification", "AA substitution"}, {UNIMOD_Thr__Phe, "spec_1_hidden", "1"}, {UNIMOD_Thr__Phe, "spec_1_position", "Anywhere"}, {UNIMOD_Thr__Phe, "spec_1_site", "T"}, {UNIMOD_Thr__Gly, "approved", "0"}, {UNIMOD_Thr__Gly, "delta_composition", "H(-4) C(-2) O(-1)"}, {UNIMOD_Thr__Gly, "spec_1_classification", "AA substitution"}, {UNIMOD_Thr__Gly, "spec_1_hidden", "1"}, {UNIMOD_Thr__Gly, "spec_1_position", "Anywhere"}, {UNIMOD_Thr__Gly, "spec_1_site", "T"}, {UNIMOD_Thr__His, "approved", "0"}, {UNIMOD_Thr__His, "delta_composition", "C(2) N(2) O(-1)"}, {UNIMOD_Thr__His, "spec_1_classification", "AA substitution"}, {UNIMOD_Thr__His, "spec_1_hidden", "1"}, {UNIMOD_Thr__His, "spec_1_position", "Anywhere"}, {UNIMOD_Thr__His, "spec_1_site", "T"}, {UNIMOD_Thr__Gln, "approved", "0"}, {UNIMOD_Thr__Gln, "delta_composition", "H C N"}, {UNIMOD_Thr__Gln, "spec_1_classification", "AA substitution"}, {UNIMOD_Thr__Gln, "spec_1_hidden", "1"}, {UNIMOD_Thr__Gln, "spec_1_position", "Anywhere"}, {UNIMOD_Thr__Gln, "spec_1_site", "T"}, {UNIMOD_Thr__Val, "approved", "0"}, {UNIMOD_Thr__Val, "delta_composition", "H(2) C O(-1)"}, {UNIMOD_Thr__Val, "spec_1_classification", "AA substitution"}, {UNIMOD_Thr__Val, "spec_1_hidden", "1"}, {UNIMOD_Thr__Val, "spec_1_position", "Anywhere"}, {UNIMOD_Thr__Val, "spec_1_site", "T"}, {UNIMOD_Thr__Trp, "approved", "0"}, {UNIMOD_Thr__Trp, "delta_composition", "H(3) C(7) N O(-1)"}, {UNIMOD_Thr__Trp, "spec_1_classification", "AA substitution"}, {UNIMOD_Thr__Trp, "spec_1_hidden", "1"}, {UNIMOD_Thr__Trp, "spec_1_position", "Anywhere"}, {UNIMOD_Thr__Trp, "spec_1_site", "T"}, {UNIMOD_Thr__Tyr, "approved", "0"}, {UNIMOD_Thr__Tyr, "delta_composition", "H(2) C(5)"}, {UNIMOD_Thr__Tyr, "spec_1_classification", "AA substitution"}, {UNIMOD_Thr__Tyr, "spec_1_hidden", "1"}, {UNIMOD_Thr__Tyr, "spec_1_position", "Anywhere"}, {UNIMOD_Thr__Tyr, "spec_1_site", "T"}, {UNIMOD_Val__Cys, "approved", "0"}, {UNIMOD_Val__Cys, "delta_composition", "H(-4) C(-2) S"}, {UNIMOD_Val__Cys, "spec_1_classification", "AA substitution"}, {UNIMOD_Val__Cys, "spec_1_hidden", "1"}, {UNIMOD_Val__Cys, "spec_1_position", "Anywhere"}, {UNIMOD_Val__Cys, "spec_1_site", "V"}, {UNIMOD_Val__His, "approved", "0"}, {UNIMOD_Val__His, "delta_composition", "H(-2) C N(2)"}, {UNIMOD_Val__His, "spec_1_classification", "AA substitution"}, {UNIMOD_Val__His, "spec_1_hidden", "1"}, {UNIMOD_Val__His, "spec_1_position", "Anywhere"}, {UNIMOD_Val__His, "spec_1_site", "V"}, {UNIMOD_Val__Lys, "approved", "0"}, {UNIMOD_Val__Lys, "delta_composition", "H(3) C N"}, {UNIMOD_Val__Lys, "spec_1_classification", "AA substitution"}, {UNIMOD_Val__Lys, "spec_1_hidden", "1"}, {UNIMOD_Val__Lys, "spec_1_position", "Anywhere"}, {UNIMOD_Val__Lys, "spec_1_site", "V"}, {UNIMOD_Val__Asn, "approved", "0"}, {UNIMOD_Val__Asn, "delta_composition", "H(-3) C(-1) N O"}, {UNIMOD_Val__Asn, "spec_1_classification", "AA substitution"}, {UNIMOD_Val__Asn, "spec_1_hidden", "1"}, {UNIMOD_Val__Asn, "spec_1_position", "Anywhere"}, {UNIMOD_Val__Asn, "spec_1_site", "V"}, {UNIMOD_Val__Pro, "approved", "0"}, {UNIMOD_Val__Pro, "delta_composition", "H(-2)"}, {UNIMOD_Val__Pro, "spec_1_classification", "AA substitution"}, {UNIMOD_Val__Pro, "spec_1_hidden", "1"}, {UNIMOD_Val__Pro, "spec_1_position", "Anywhere"}, {UNIMOD_Val__Pro, "spec_1_site", "V"}, {UNIMOD_Val__Gln, "approved", "0"}, {UNIMOD_Val__Gln, "delta_composition", "H(-1) N O"}, {UNIMOD_Val__Gln, "spec_1_classification", "AA substitution"}, {UNIMOD_Val__Gln, "spec_1_hidden", "1"}, {UNIMOD_Val__Gln, "spec_1_position", "Anywhere"}, {UNIMOD_Val__Gln, "spec_1_site", "V"}, {UNIMOD_Val__Arg, "approved", "0"}, {UNIMOD_Val__Arg, "delta_composition", "H(3) C N(3)"}, {UNIMOD_Val__Arg, "spec_1_classification", "AA substitution"}, {UNIMOD_Val__Arg, "spec_1_hidden", "1"}, {UNIMOD_Val__Arg, "spec_1_position", "Anywhere"}, {UNIMOD_Val__Arg, "spec_1_site", "V"}, {UNIMOD_Val__Ser, "approved", "0"}, {UNIMOD_Val__Ser, "delta_composition", "H(-4) C(-2) O"}, {UNIMOD_Val__Ser, "spec_1_classification", "AA substitution"}, {UNIMOD_Val__Ser, "spec_1_hidden", "1"}, {UNIMOD_Val__Ser, "spec_1_position", "Anywhere"}, {UNIMOD_Val__Ser, "spec_1_site", "V"}, {UNIMOD_Val__Thr, "approved", "0"}, {UNIMOD_Val__Thr, "delta_composition", "H(-2) C(-1) O"}, {UNIMOD_Val__Thr, "spec_1_classification", "AA substitution"}, {UNIMOD_Val__Thr, "spec_1_hidden", "1"}, {UNIMOD_Val__Thr, "spec_1_position", "Anywhere"}, {UNIMOD_Val__Thr, "spec_1_site", "V"}, {UNIMOD_Val__Trp, "approved", "0"}, {UNIMOD_Val__Trp, "delta_composition", "H C(6) N"}, {UNIMOD_Val__Trp, "spec_1_classification", "AA substitution"}, {UNIMOD_Val__Trp, "spec_1_hidden", "1"}, {UNIMOD_Val__Trp, "spec_1_position", "Anywhere"}, {UNIMOD_Val__Trp, "spec_1_site", "V"}, {UNIMOD_Val__Tyr, "approved", "0"}, {UNIMOD_Val__Tyr, "delta_composition", "C(4) O"}, {UNIMOD_Val__Tyr, "spec_1_classification", "AA substitution"}, {UNIMOD_Val__Tyr, "spec_1_hidden", "1"}, {UNIMOD_Val__Tyr, "spec_1_position", "Anywhere"}, {UNIMOD_Val__Tyr, "spec_1_site", "V"}, {UNIMOD_Trp__Ala, "approved", "0"}, {UNIMOD_Trp__Ala, "delta_composition", "H(-5) C(-8) N(-1)"}, {UNIMOD_Trp__Ala, "spec_1_classification", "AA substitution"}, {UNIMOD_Trp__Ala, "spec_1_hidden", "1"}, {UNIMOD_Trp__Ala, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__Ala, "spec_1_site", "W"}, {UNIMOD_Trp__Asp, "approved", "0"}, {UNIMOD_Trp__Asp, "delta_composition", "H(-5) C(-7) N(-1) O(2)"}, {UNIMOD_Trp__Asp, "spec_1_classification", "AA substitution"}, {UNIMOD_Trp__Asp, "spec_1_hidden", "1"}, {UNIMOD_Trp__Asp, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__Asp, "spec_1_site", "W"}, {UNIMOD_Trp__Glu, "approved", "0"}, {UNIMOD_Trp__Glu, "delta_composition", "H(-3) C(-6) N(-1) O(2)"}, {UNIMOD_Trp__Glu, "spec_1_classification", "AA substitution"}, {UNIMOD_Trp__Glu, "spec_1_hidden", "1"}, {UNIMOD_Trp__Glu, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__Glu, "spec_1_site", "W"}, {UNIMOD_Trp__Phe, "approved", "0"}, {UNIMOD_Trp__Phe, "delta_composition", "H(-1) C(-2) N(-1)"}, {UNIMOD_Trp__Phe, "spec_1_classification", "AA substitution"}, {UNIMOD_Trp__Phe, "spec_1_hidden", "1"}, {UNIMOD_Trp__Phe, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__Phe, "spec_1_site", "W"}, {UNIMOD_Trp__His, "approved", "0"}, {UNIMOD_Trp__His, "delta_composition", "H(-3) C(-5) N"}, {UNIMOD_Trp__His, "spec_1_classification", "AA substitution"}, {UNIMOD_Trp__His, "spec_1_hidden", "1"}, {UNIMOD_Trp__His, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__His, "spec_1_site", "W"}, {UNIMOD_Trp__Lys, "approved", "0"}, {UNIMOD_Trp__Lys, "delta_composition", "H(2) C(-5)"}, {UNIMOD_Trp__Lys, "spec_1_classification", "AA substitution"}, {UNIMOD_Trp__Lys, "spec_1_hidden", "1"}, {UNIMOD_Trp__Lys, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__Lys, "spec_1_site", "W"}, {UNIMOD_Trp__Met, "approved", "0"}, {UNIMOD_Trp__Met, "delta_composition", "H(-1) C(-6) N(-1) S"}, {UNIMOD_Trp__Met, "spec_1_classification", "AA substitution"}, {UNIMOD_Trp__Met, "spec_1_hidden", "1"}, {UNIMOD_Trp__Met, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__Met, "spec_1_site", "W"}, {UNIMOD_Trp__Asn, "approved", "0"}, {UNIMOD_Trp__Asn, "delta_composition", "H(-4) C(-7) O"}, {UNIMOD_Trp__Asn, "spec_1_classification", "AA substitution"}, {UNIMOD_Trp__Asn, "spec_1_hidden", "1"}, {UNIMOD_Trp__Asn, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__Asn, "spec_1_site", "W"}, {UNIMOD_Trp__Pro, "approved", "0"}, {UNIMOD_Trp__Pro, "delta_composition", "H(-3) C(-6) N(-1)"}, {UNIMOD_Trp__Pro, "spec_1_classification", "AA substitution"}, {UNIMOD_Trp__Pro, "spec_1_hidden", "1"}, {UNIMOD_Trp__Pro, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__Pro, "spec_1_site", "W"}, {UNIMOD_Trp__Gln, "approved", "0"}, {UNIMOD_Trp__Gln, "delta_composition", "H(-2) C(-6) O"}, {UNIMOD_Trp__Gln, "spec_1_classification", "AA substitution"}, {UNIMOD_Trp__Gln, "spec_1_hidden", "1"}, {UNIMOD_Trp__Gln, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__Gln, "spec_1_site", "W"}, {UNIMOD_Trp__Thr, "approved", "0"}, {UNIMOD_Trp__Thr, "delta_composition", "H(-3) C(-7) N(-1) O"}, {UNIMOD_Trp__Thr, "spec_1_classification", "AA substitution"}, {UNIMOD_Trp__Thr, "spec_1_hidden", "1"}, {UNIMOD_Trp__Thr, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__Thr, "spec_1_site", "W"}, {UNIMOD_Trp__Val, "approved", "0"}, {UNIMOD_Trp__Val, "delta_composition", "H(-1) C(-6) N(-1)"}, {UNIMOD_Trp__Val, "spec_1_classification", "AA substitution"}, {UNIMOD_Trp__Val, "spec_1_hidden", "1"}, {UNIMOD_Trp__Val, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__Val, "spec_1_site", "W"}, {UNIMOD_Trp__Tyr, "approved", "0"}, {UNIMOD_Trp__Tyr, "delta_composition", "H(-1) C(-2) N(-1) O"}, {UNIMOD_Trp__Tyr, "spec_1_classification", "AA substitution"}, {UNIMOD_Trp__Tyr, "spec_1_hidden", "1"}, {UNIMOD_Trp__Tyr, "spec_1_position", "Anywhere"}, {UNIMOD_Trp__Tyr, "spec_1_site", "W"}, {UNIMOD_Tyr__Ala, "approved", "0"}, {UNIMOD_Tyr__Ala, "delta_composition", "H(-4) C(-6) O(-1)"}, {UNIMOD_Tyr__Ala, "spec_1_classification", "AA substitution"}, {UNIMOD_Tyr__Ala, "spec_1_hidden", "1"}, {UNIMOD_Tyr__Ala, "spec_1_position", "Anywhere"}, {UNIMOD_Tyr__Ala, "spec_1_site", "Y"}, {UNIMOD_Tyr__Glu, "approved", "0"}, {UNIMOD_Tyr__Glu, "delta_composition", "H(-2) C(-4) O"}, {UNIMOD_Tyr__Glu, "spec_1_classification", "AA substitution"}, {UNIMOD_Tyr__Glu, "spec_1_hidden", "1"}, {UNIMOD_Tyr__Glu, "spec_1_position", "Anywhere"}, {UNIMOD_Tyr__Glu, "spec_1_site", "Y"}, {UNIMOD_Tyr__Gly, "approved", "0"}, {UNIMOD_Tyr__Gly, "delta_composition", "H(-6) C(-7) O(-1)"}, {UNIMOD_Tyr__Gly, "spec_1_classification", "AA substitution"}, {UNIMOD_Tyr__Gly, "spec_1_hidden", "1"}, {UNIMOD_Tyr__Gly, "spec_1_position", "Anywhere"}, {UNIMOD_Tyr__Gly, "spec_1_site", "Y"}, {UNIMOD_Tyr__Lys, "approved", "0"}, {UNIMOD_Tyr__Lys, "delta_composition", "H(3) C(-3) N O(-1)"}, {UNIMOD_Tyr__Lys, "spec_1_classification", "AA substitution"}, {UNIMOD_Tyr__Lys, "spec_1_hidden", "1"}, {UNIMOD_Tyr__Lys, "spec_1_position", "Anywhere"}, {UNIMOD_Tyr__Lys, "spec_1_site", "Y"}, {UNIMOD_Tyr__Met, "approved", "0"}, {UNIMOD_Tyr__Met, "delta_composition", "C(-4) O(-1) S"}, {UNIMOD_Tyr__Met, "spec_1_classification", "AA substitution"}, {UNIMOD_Tyr__Met, "spec_1_hidden", "1"}, {UNIMOD_Tyr__Met, "spec_1_position", "Anywhere"}, {UNIMOD_Tyr__Met, "spec_1_site", "Y"}, {UNIMOD_Tyr__Pro, "approved", "0"}, {UNIMOD_Tyr__Pro, "delta_composition", "H(-2) C(-4) O(-1)"}, {UNIMOD_Tyr__Pro, "spec_1_classification", "AA substitution"}, {UNIMOD_Tyr__Pro, "spec_1_hidden", "1"}, {UNIMOD_Tyr__Pro, "spec_1_position", "Anywhere"}, {UNIMOD_Tyr__Pro, "spec_1_site", "Y"}, {UNIMOD_Tyr__Gln, "approved", "0"}, {UNIMOD_Tyr__Gln, "delta_composition", "H(-1) C(-4) N"}, {UNIMOD_Tyr__Gln, "spec_1_classification", "AA substitution"}, {UNIMOD_Tyr__Gln, "spec_1_hidden", "1"}, {UNIMOD_Tyr__Gln, "spec_1_position", "Anywhere"}, {UNIMOD_Tyr__Gln, "spec_1_site", "Y"}, {UNIMOD_Tyr__Arg, "approved", "0"}, {UNIMOD_Tyr__Arg, "delta_composition", "H(3) C(-3) N(3) O(-1)"}, {UNIMOD_Tyr__Arg, "spec_1_classification", "AA substitution"}, {UNIMOD_Tyr__Arg, "spec_1_hidden", "1"}, {UNIMOD_Tyr__Arg, "spec_1_position", "Anywhere"}, {UNIMOD_Tyr__Arg, "spec_1_site", "Y"}, {UNIMOD_Tyr__Thr, "approved", "0"}, {UNIMOD_Tyr__Thr, "delta_composition", "H(-2) C(-5)"}, {UNIMOD_Tyr__Thr, "spec_1_classification", "AA substitution"}, {UNIMOD_Tyr__Thr, "spec_1_hidden", "1"}, {UNIMOD_Tyr__Thr, "spec_1_position", "Anywhere"}, {UNIMOD_Tyr__Thr, "spec_1_site", "Y"}, {UNIMOD_Tyr__Val, "approved", "0"}, {UNIMOD_Tyr__Val, "delta_composition", "C(-4) O(-1)"}, {UNIMOD_Tyr__Val, "spec_1_classification", "AA substitution"}, {UNIMOD_Tyr__Val, "spec_1_hidden", "1"}, {UNIMOD_Tyr__Val, "spec_1_position", "Anywhere"}, {UNIMOD_Tyr__Val, "spec_1_site", "Y"}, {UNIMOD_Tyr__Trp, "approved", "0"}, {UNIMOD_Tyr__Trp, "delta_composition", "H C(2) N O(-1)"}, {UNIMOD_Tyr__Trp, "spec_1_classification", "AA substitution"}, {UNIMOD_Tyr__Trp, "spec_1_hidden", "1"}, {UNIMOD_Tyr__Trp, "spec_1_position", "Anywhere"}, {UNIMOD_Tyr__Trp, "spec_1_site", "Y"}, {UNIMOD_Tyr__Xle, "approved", "0"}, {UNIMOD_Tyr__Xle, "delta_composition", "H(2) C(-3) O(-1)"}, {UNIMOD_Tyr__Xle, "spec_1_classification", "AA substitution"}, {UNIMOD_Tyr__Xle, "spec_1_hidden", "1"}, {UNIMOD_Tyr__Xle, "spec_1_position", "Anywhere"}, {UNIMOD_Tyr__Xle, "spec_1_site", "Y"}, {UNIMOD_AHA_SS, "approved", "0"}, {UNIMOD_AHA_SS, "delta_composition", "H(9) C(7) N(5) O(2)"}, {UNIMOD_AHA_SS, "spec_1_classification", "Multiple"}, {UNIMOD_AHA_SS, "spec_1_hidden", "1"}, {UNIMOD_AHA_SS, "spec_1_position", "Anywhere"}, {UNIMOD_AHA_SS, "spec_1_site", "M"}, {UNIMOD_AHA_SS_CAM, "approved", "0"}, {UNIMOD_AHA_SS_CAM, "delta_composition", "H(12) C(9) N(6) O(3)"}, {UNIMOD_AHA_SS_CAM, "spec_1_classification", "Multiple"}, {UNIMOD_AHA_SS_CAM, "spec_1_hidden", "1"}, {UNIMOD_AHA_SS_CAM, "spec_1_position", "Anywhere"}, {UNIMOD_AHA_SS_CAM, "spec_1_site", "M"}, {UNIMOD_Biotin_Thermo_33033, "approved", "0"}, {UNIMOD_Biotin_Thermo_33033, "delta_composition", "H(36) C(25) N(6) O(4) S(2)"}, {UNIMOD_Biotin_Thermo_33033, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Biotin_Thermo_33033, "spec_1_hidden", "1"}, {UNIMOD_Biotin_Thermo_33033, "spec_1_position", "Anywhere"}, {UNIMOD_Biotin_Thermo_33033, "spec_1_site", "N-term"}, {UNIMOD_Biotin_Thermo_33033_H, "approved", "0"}, {UNIMOD_Biotin_Thermo_33033_H, "delta_composition", "H(34) C(25) N(6) O(4) S(2)"}, {UNIMOD_Biotin_Thermo_33033_H, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Biotin_Thermo_33033_H, "spec_1_hidden", "1"}, {UNIMOD_Biotin_Thermo_33033_H, "spec_1_position", "Anywhere"}, {UNIMOD_Biotin_Thermo_33033_H, "spec_1_site", "N-term"}, {UNIMOD_2_monomethylsuccinyl, "approved", "0"}, {UNIMOD_2_monomethylsuccinyl, "delta_composition", "H(6) C(5) O(4)"}, {UNIMOD_2_monomethylsuccinyl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_2_monomethylsuccinyl, "spec_1_hidden", "1"}, {UNIMOD_2_monomethylsuccinyl, "spec_1_position", "Anywhere"}, {UNIMOD_2_monomethylsuccinyl, "spec_1_site", "C"}, {UNIMOD_Saligenin, "approved", "0"}, {UNIMOD_Saligenin, "delta_composition", "H(6) C(7) O"}, {UNIMOD_Saligenin, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Saligenin, "spec_1_hidden", "1"}, {UNIMOD_Saligenin, "spec_1_position", "Anywhere"}, {UNIMOD_Saligenin, "spec_1_site", "H"}, {UNIMOD_Saligenin, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Saligenin, "spec_2_hidden", "1"}, {UNIMOD_Saligenin, "spec_2_position", "Anywhere"}, {UNIMOD_Saligenin, "spec_2_site", "K"}, {UNIMOD_Cresylphosphate, "approved", "0"}, {UNIMOD_Cresylphosphate, "delta_composition", "H(7) C(7) O(3) P"}, {UNIMOD_Cresylphosphate, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Cresylphosphate, "spec_1_hidden", "1"}, {UNIMOD_Cresylphosphate, "spec_1_position", "Anywhere"}, {UNIMOD_Cresylphosphate, "spec_1_site", "H"}, {UNIMOD_Cresylphosphate, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Cresylphosphate, "spec_2_hidden", "1"}, {UNIMOD_Cresylphosphate, "spec_2_position", "Anywhere"}, {UNIMOD_Cresylphosphate, "spec_2_site", "K"}, {UNIMOD_Cresylphosphate, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Cresylphosphate, "spec_3_hidden", "1"}, {UNIMOD_Cresylphosphate, "spec_3_position", "Anywhere"}, {UNIMOD_Cresylphosphate, "spec_3_site", "R"}, {UNIMOD_Cresylphosphate, "spec_4_classification", "Chemical derivative"}, {UNIMOD_Cresylphosphate, "spec_4_hidden", "1"}, {UNIMOD_Cresylphosphate, "spec_4_position", "Anywhere"}, {UNIMOD_Cresylphosphate, "spec_4_site", "S"}, {UNIMOD_Cresylphosphate, "spec_5_classification", "Chemical derivative"}, {UNIMOD_Cresylphosphate, "spec_5_hidden", "1"}, {UNIMOD_Cresylphosphate, "spec_5_position", "Anywhere"}, {UNIMOD_Cresylphosphate, "spec_5_site", "T"}, {UNIMOD_Cresylphosphate, "spec_6_classification", "Chemical derivative"}, {UNIMOD_Cresylphosphate, "spec_6_hidden", "1"}, {UNIMOD_Cresylphosphate, "spec_6_position", "Anywhere"}, {UNIMOD_Cresylphosphate, "spec_6_site", "Y"}, {UNIMOD_CresylSaligeninPhosphate, "approved", "0"}, {UNIMOD_CresylSaligeninPhosphate, "delta_composition", "H(13) C(14) O(4) P"}, {UNIMOD_CresylSaligeninPhosphate, "spec_1_classification", "Chemical derivative"}, {UNIMOD_CresylSaligeninPhosphate, "spec_1_hidden", "1"}, {UNIMOD_CresylSaligeninPhosphate, "spec_1_position", "Anywhere"}, {UNIMOD_CresylSaligeninPhosphate, "spec_1_site", "H"}, {UNIMOD_CresylSaligeninPhosphate, "spec_2_classification", "Chemical derivative"}, {UNIMOD_CresylSaligeninPhosphate, "spec_2_hidden", "1"}, {UNIMOD_CresylSaligeninPhosphate, "spec_2_position", "Anywhere"}, {UNIMOD_CresylSaligeninPhosphate, "spec_2_site", "K"}, {UNIMOD_CresylSaligeninPhosphate, "spec_3_classification", "Chemical derivative"}, {UNIMOD_CresylSaligeninPhosphate, "spec_3_hidden", "1"}, {UNIMOD_CresylSaligeninPhosphate, "spec_3_position", "Anywhere"}, {UNIMOD_CresylSaligeninPhosphate, "spec_3_site", "R"}, {UNIMOD_CresylSaligeninPhosphate, "spec_4_classification", "Chemical derivative"}, {UNIMOD_CresylSaligeninPhosphate, "spec_4_hidden", "1"}, {UNIMOD_CresylSaligeninPhosphate, "spec_4_position", "Anywhere"}, {UNIMOD_CresylSaligeninPhosphate, "spec_4_site", "S"}, {UNIMOD_CresylSaligeninPhosphate, "spec_5_classification", "Chemical derivative"}, {UNIMOD_CresylSaligeninPhosphate, "spec_5_hidden", "1"}, {UNIMOD_CresylSaligeninPhosphate, "spec_5_position", "Anywhere"}, {UNIMOD_CresylSaligeninPhosphate, "spec_5_site", "T"}, {UNIMOD_CresylSaligeninPhosphate, "spec_6_classification", "Chemical derivative"}, {UNIMOD_CresylSaligeninPhosphate, "spec_6_hidden", "1"}, {UNIMOD_CresylSaligeninPhosphate, "spec_6_position", "Anywhere"}, {UNIMOD_CresylSaligeninPhosphate, "spec_6_site", "Y"}, {UNIMOD_Ub_Br2, "approved", "0"}, {UNIMOD_Ub_Br2, "delta_composition", "H(8) C(4) N(2) O"}, {UNIMOD_Ub_Br2, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Ub_Br2, "spec_1_hidden", "1"}, {UNIMOD_Ub_Br2, "spec_1_position", "Anywhere"}, {UNIMOD_Ub_Br2, "spec_1_site", "C"}, {UNIMOD_Ub_VME, "approved", "0"}, {UNIMOD_Ub_VME, "delta_composition", "H(13) C(7) N(2) O(3)"}, {UNIMOD_Ub_VME, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Ub_VME, "spec_1_hidden", "1"}, {UNIMOD_Ub_VME, "spec_1_position", "Anywhere"}, {UNIMOD_Ub_VME, "spec_1_site", "C"}, {UNIMOD_Ub_amide, "approved", "0"}, {UNIMOD_Ub_amide, "delta_composition", "H(14) C(9) N(3) O(2)"}, {UNIMOD_Ub_amide, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Ub_amide, "spec_1_hidden", "1"}, {UNIMOD_Ub_amide, "spec_1_position", "Anywhere"}, {UNIMOD_Ub_amide, "spec_1_site", "C"}, {UNIMOD_Ub_fluorescein, "approved", "0"}, {UNIMOD_Ub_fluorescein, "delta_composition", "H(29) C(31) N(6) O(7)"}, {UNIMOD_Ub_fluorescein, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Ub_fluorescein, "spec_1_hidden", "1"}, {UNIMOD_Ub_fluorescein, "spec_1_position", "Anywhere"}, {UNIMOD_Ub_fluorescein, "spec_1_site", "C"}, {UNIMOD_2_dimethylsuccinyl, "approved", "0"}, {UNIMOD_2_dimethylsuccinyl, "delta_composition", "H(8) C(6) O(4)"}, {UNIMOD_2_dimethylsuccinyl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_2_dimethylsuccinyl, "spec_1_hidden", "1"}, {UNIMOD_2_dimethylsuccinyl, "spec_1_position", "Anywhere"}, {UNIMOD_2_dimethylsuccinyl, "spec_1_site", "C"}, {UNIMOD_Gly, "approved", "0"}, {UNIMOD_Gly, "delta_composition", "H(3) C(2) N O"}, {UNIMOD_Gly, "spec_1_classification", "Other"}, {UNIMOD_Gly, "spec_1_hidden", "1"}, {UNIMOD_Gly, "spec_1_position", "Anywhere"}, {UNIMOD_Gly, "spec_1_site", "K"}, {UNIMOD_Gly, "spec_2_classification", "Other"}, {UNIMOD_Gly, "spec_2_hidden", "1"}, {UNIMOD_Gly, "spec_2_position", "Anywhere"}, {UNIMOD_Gly, "spec_2_site", "S"}, {UNIMOD_Gly, "spec_3_classification", "Other"}, {UNIMOD_Gly, "spec_3_hidden", "1"}, {UNIMOD_Gly, "spec_3_position", "Anywhere"}, {UNIMOD_Gly, "spec_3_site", "T"}, {UNIMOD_pupylation, "approved", "0"}, {UNIMOD_pupylation, "delta_composition", "H(13) C(9) N(3) O(5)"}, {UNIMOD_pupylation, "spec_1_classification", "Post-translational"}, {UNIMOD_pupylation, "spec_1_hidden", "1"}, {UNIMOD_pupylation, "spec_1_position", "Anywhere"}, {UNIMOD_pupylation, "spec_1_site", "K"}, {UNIMOD_Label_13C_4_, "approved", "0"}, {UNIMOD_Label_13C_4_, "delta_composition", "C(-4) 13C(4)"}, {UNIMOD_Label_13C_4_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_4_, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_4_, "spec_1_site", "M"}, {UNIMOD_Label_13C_4__Oxidation, "approved", "0"}, {UNIMOD_Label_13C_4__Oxidation, "delta_composition", "C(-4) 13C(4) O"}, {UNIMOD_Label_13C_4__Oxidation, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_4__Oxidation, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_4__Oxidation, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_4__Oxidation, "spec_1_site", "M"}, {UNIMOD_HCysThiolactone, "approved", "0"}, {UNIMOD_HCysThiolactone, "delta_composition", "H(7) C(4) N O S"}, {UNIMOD_HCysThiolactone, "spec_1_classification", "Post-translational"}, {UNIMOD_HCysThiolactone, "spec_1_hidden", "1"}, {UNIMOD_HCysThiolactone, "spec_1_position", "Anywhere"}, {UNIMOD_HCysThiolactone, "spec_1_site", "K"}, {UNIMOD_HCysteinyl, "approved", "0"}, {UNIMOD_HCysteinyl, "delta_composition", "H(7) C(4) N O(2) S"}, {UNIMOD_HCysteinyl, "spec_1_classification", "Post-translational"}, {UNIMOD_HCysteinyl, "spec_1_hidden", "1"}, {UNIMOD_HCysteinyl, "spec_1_position", "Anywhere"}, {UNIMOD_HCysteinyl, "spec_1_site", "C"}, {UNIMOD_UgiJoullie, "approved", "0"}, {UNIMOD_UgiJoullie, "delta_composition", "H(60) C(47) N(23) O(10)"}, {UNIMOD_UgiJoullie, "spec_1_classification", "Chemical derivative"}, {UNIMOD_UgiJoullie, "spec_1_hidden", "1"}, {UNIMOD_UgiJoullie, "spec_1_position", "Anywhere"}, {UNIMOD_UgiJoullie, "spec_1_site", "D"}, {UNIMOD_UgiJoullie, "spec_2_classification", "Chemical derivative"}, {UNIMOD_UgiJoullie, "spec_2_hidden", "1"}, {UNIMOD_UgiJoullie, "spec_2_position", "Anywhere"}, {UNIMOD_UgiJoullie, "spec_2_site", "E"}, {UNIMOD_Dipyridyl, "approved", "0"}, {UNIMOD_Dipyridyl, "delta_composition", "H(11) C(13) N(3) O"}, {UNIMOD_Dipyridyl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Dipyridyl, "spec_1_hidden", "1"}, {UNIMOD_Dipyridyl, "spec_1_position", "Anywhere"}, {UNIMOD_Dipyridyl, "spec_1_site", "C"}, {UNIMOD_Furan, "approved", "0"}, {UNIMOD_Furan, "delta_composition", "H(2) C(4) O"}, {UNIMOD_Furan, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Furan, "spec_1_hidden", "1"}, {UNIMOD_Furan, "spec_1_position", "Anywhere"}, {UNIMOD_Furan, "spec_1_site", "Y"}, {UNIMOD_Difuran, "approved", "0"}, {UNIMOD_Difuran, "delta_composition", "H(4) C(8) O(2)"}, {UNIMOD_Difuran, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Difuran, "spec_1_hidden", "1"}, {UNIMOD_Difuran, "spec_1_position", "Anywhere"}, {UNIMOD_Difuran, "spec_1_site", "Y"}, {UNIMOD_BMP_piperidinol, "approved", "0"}, {UNIMOD_BMP_piperidinol, "delta_composition", "H(17) C(18) N O"}, {UNIMOD_BMP_piperidinol, "spec_1_classification", "Chemical derivative"}, {UNIMOD_BMP_piperidinol, "spec_1_hidden", "1"}, {UNIMOD_BMP_piperidinol, "spec_1_position", "Anywhere"}, {UNIMOD_BMP_piperidinol, "spec_1_site", "M"}, {UNIMOD_BMP_piperidinol, "spec_2_classification", "Chemical derivative"}, {UNIMOD_BMP_piperidinol, "spec_2_hidden", "1"}, {UNIMOD_BMP_piperidinol, "spec_2_position", "Anywhere"}, {UNIMOD_BMP_piperidinol, "spec_2_site", "C"}, {UNIMOD_UgiJoullieProGly, "approved", "0"}, {UNIMOD_UgiJoullieProGly, "delta_composition", "H(10) C(7) N(2) O(2)"}, {UNIMOD_UgiJoullieProGly, "spec_1_classification", "Chemical derivative"}, {UNIMOD_UgiJoullieProGly, "spec_1_hidden", "1"}, {UNIMOD_UgiJoullieProGly, "spec_1_position", "Anywhere"}, {UNIMOD_UgiJoullieProGly, "spec_1_site", "D"}, {UNIMOD_UgiJoullieProGly, "spec_2_classification", "Chemical derivative"}, {UNIMOD_UgiJoullieProGly, "spec_2_hidden", "1"}, {UNIMOD_UgiJoullieProGly, "spec_2_position", "Anywhere"}, {UNIMOD_UgiJoullieProGly, "spec_2_site", "E"}, {UNIMOD_UgiJoullieProGlyProGly, "approved", "0"}, {UNIMOD_UgiJoullieProGlyProGly, "delta_composition", "H(20) C(14) N(4) O(4)"}, {UNIMOD_UgiJoullieProGlyProGly, "spec_1_classification", "Chemical derivative"}, {UNIMOD_UgiJoullieProGlyProGly, "spec_1_hidden", "1"}, {UNIMOD_UgiJoullieProGlyProGly, "spec_1_position", "Anywhere"}, {UNIMOD_UgiJoullieProGlyProGly, "spec_1_site", "D"}, {UNIMOD_UgiJoullieProGlyProGly, "spec_2_classification", "Chemical derivative"}, {UNIMOD_UgiJoullieProGlyProGly, "spec_2_hidden", "1"}, {UNIMOD_UgiJoullieProGlyProGly, "spec_2_position", "Anywhere"}, {UNIMOD_UgiJoullieProGlyProGly, "spec_2_site", "E"}, {UNIMOD_IMEHex_2_NeuAc_1_, "approved", "0"}, {UNIMOD_IMEHex_2_NeuAc_1_, "delta_composition", "H(3) C(2) N S Hex(2) NeuAc"}, {UNIMOD_IMEHex_2_NeuAc_1_, "spec_1_classification", "Other glycosylation"}, {UNIMOD_IMEHex_2_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_IMEHex_2_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_IMEHex_2_NeuAc_1_, "spec_1_site", "K"}, {UNIMOD_Arg_loss, "approved", "0"}, {UNIMOD_Arg_loss, "delta_composition", "H(-12) C(-6) N(-4) O(-1)"}, {UNIMOD_Arg_loss, "spec_1_classification", "Other"}, {UNIMOD_Arg_loss, "spec_1_hidden", "1"}, {UNIMOD_Arg_loss, "spec_1_position", "Any C-term"}, {UNIMOD_Arg_loss, "spec_1_site", "R"}, {UNIMOD_Arg, "approved", "0"}, {UNIMOD_Arg, "delta_composition", "H(12) C(6) N(4) O"}, {UNIMOD_Arg, "spec_1_classification", "Other"}, {UNIMOD_Arg, "spec_1_hidden", "1"}, {UNIMOD_Arg, "spec_1_position", "Any N-term"}, {UNIMOD_Arg, "spec_1_site", "N-term"}, {UNIMOD_Butyryl, "approved", "0"}, {UNIMOD_Butyryl, "delta_composition", "H(6) C(4) O"}, {UNIMOD_Butyryl, "spec_1_classification", "Post-translational"}, {UNIMOD_Butyryl, "spec_1_hidden", "1"}, {UNIMOD_Butyryl, "spec_1_position", "Anywhere"}, {UNIMOD_Butyryl, "spec_1_site", "K"}, {UNIMOD_Dicarbamidomethyl, "approved", "0"}, {UNIMOD_Dicarbamidomethyl, "delta_composition", "H(6) C(4) N(2) O(2)"}, {UNIMOD_Dicarbamidomethyl, "spec_1_classification", "Artefact"}, {UNIMOD_Dicarbamidomethyl, "spec_1_hidden", "1"}, {UNIMOD_Dicarbamidomethyl, "spec_1_position", "Anywhere"}, {UNIMOD_Dicarbamidomethyl, "spec_1_site", "C"}, {UNIMOD_Dicarbamidomethyl, "spec_2_classification", "Artefact"}, {UNIMOD_Dicarbamidomethyl, "spec_2_hidden", "1"}, {UNIMOD_Dicarbamidomethyl, "spec_2_position", "Anywhere"}, {UNIMOD_Dicarbamidomethyl, "spec_2_site", "H"}, {UNIMOD_Dicarbamidomethyl, "spec_3_classification", "Artefact"}, {UNIMOD_Dicarbamidomethyl, "spec_3_hidden", "1"}, {UNIMOD_Dicarbamidomethyl, "spec_3_position", "Anywhere"}, {UNIMOD_Dicarbamidomethyl, "spec_3_site", "K"}, {UNIMOD_Dicarbamidomethyl, "spec_4_classification", "Artefact"}, {UNIMOD_Dicarbamidomethyl, "spec_4_hidden", "1"}, {UNIMOD_Dicarbamidomethyl, "spec_4_position", "Anywhere"}, {UNIMOD_Dicarbamidomethyl, "spec_4_site", "R"}, {UNIMOD_Dicarbamidomethyl, "spec_5_classification", "Artefact"}, {UNIMOD_Dicarbamidomethyl, "spec_5_hidden", "1"}, {UNIMOD_Dicarbamidomethyl, "spec_5_position", "Any N-term"}, {UNIMOD_Dicarbamidomethyl, "spec_5_site", "N-term"}, {UNIMOD_Dimethyl_2H_6_, "approved", "0"}, {UNIMOD_Dimethyl_2H_6_, "delta_composition", "H(-2) 2H(6) C(2)"}, {UNIMOD_Dimethyl_2H_6_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Dimethyl_2H_6_, "spec_1_hidden", "1"}, {UNIMOD_Dimethyl_2H_6_, "spec_1_position", "Anywhere"}, {UNIMOD_Dimethyl_2H_6_, "spec_1_site", "K"}, {UNIMOD_Dimethyl_2H_6_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Dimethyl_2H_6_, "spec_2_hidden", "1"}, {UNIMOD_Dimethyl_2H_6_, "spec_2_position", "Any N-term"}, {UNIMOD_Dimethyl_2H_6_, "spec_2_site", "N-term"}, {UNIMOD_Dimethyl_2H_6_, "spec_3_classification", "Isotopic label"}, {UNIMOD_Dimethyl_2H_6_, "spec_3_hidden", "1"}, {UNIMOD_Dimethyl_2H_6_, "spec_3_position", "Anywhere"}, {UNIMOD_Dimethyl_2H_6_, "spec_3_site", "R"}, {UNIMOD_GGQ, "approved", "0"}, {UNIMOD_GGQ, "delta_composition", "H(14) C(9) N(4) O(4)"}, {UNIMOD_GGQ, "spec_1_classification", "Other"}, {UNIMOD_GGQ, "spec_1_hidden", "1"}, {UNIMOD_GGQ, "spec_1_position", "Anywhere"}, {UNIMOD_GGQ, "spec_1_site", "K"}, {UNIMOD_QTGG, "approved", "0"}, {UNIMOD_QTGG, "delta_composition", "H(21) C(13) N(5) O(6)"}, {UNIMOD_QTGG, "spec_1_classification", "Other"}, {UNIMOD_QTGG, "spec_1_hidden", "1"}, {UNIMOD_QTGG, "spec_1_position", "Anywhere"}, {UNIMOD_QTGG, "spec_1_site", "K"}, {UNIMOD_Label_13C_3_, "approved", "0"}, {UNIMOD_Label_13C_3_, "delta_composition", "C(-3) 13C(3)"}, {UNIMOD_Label_13C_3_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_3_, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_3_, "spec_1_site", "A"}, {UNIMOD_Label_13C_3_15N_1_, "approved", "0"}, {UNIMOD_Label_13C_3_15N_1_, "delta_composition", "C(-3) 13C(3) N(-1) 15N"}, {UNIMOD_Label_13C_3_15N_1_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_3_15N_1_, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_3_15N_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_3_15N_1_, "spec_1_site", "A"}, {UNIMOD_Label_13C_4_15N_1_, "approved", "0"}, {UNIMOD_Label_13C_4_15N_1_, "delta_composition", "C(-4) 13C(4) N(-1) 15N"}, {UNIMOD_Label_13C_4_15N_1_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_13C_4_15N_1_, "spec_1_hidden", "1"}, {UNIMOD_Label_13C_4_15N_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_13C_4_15N_1_, "spec_1_site", "D"}, {UNIMOD_Label_2H_10_, "approved", "0"}, {UNIMOD_Label_2H_10_, "delta_composition", "H(-10) 2H(10)"}, {UNIMOD_Label_2H_10_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_2H_10_, "spec_1_hidden", "1"}, {UNIMOD_Label_2H_10_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_2H_10_, "spec_1_site", "L"}, {UNIMOD_Label_2H_4_13C_1_, "approved", "0"}, {UNIMOD_Label_2H_4_13C_1_, "delta_composition", "H(-4) 2H(4) C(-1) 13C"}, {UNIMOD_Label_2H_4_13C_1_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_2H_4_13C_1_, "spec_1_hidden", "1"}, {UNIMOD_Label_2H_4_13C_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_2H_4_13C_1_, "spec_1_site", "R"}, {UNIMOD_Lys, "approved", "1"}, {UNIMOD_Lys, "delta_composition", "H(12) C(6) N(2) O"}, {UNIMOD_Lys, "spec_1_classification", "Other"}, {UNIMOD_Lys, "spec_1_hidden", "1"}, {UNIMOD_Lys, "spec_1_position", "Any N-term"}, {UNIMOD_Lys, "spec_1_site", "N-term"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "approved", "0"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "delta_composition", "H(12) C 13C(6) 15N(2) O"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_1_classification", "Isotopic label"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_1_hidden", "0"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_1_position", "Anywhere"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_1_site", "K"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_2_classification", "Isotopic label"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_2_hidden", "0"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_2_position", "Any N-term"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_2_site", "N-term"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_3_classification", "Isotopic label"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_3_hidden", "0"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_3_position", "Anywhere"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_3_site", "Y"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_4_classification", "Isotopic label"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_4_hidden", "1"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_4_position", "Anywhere"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_4_site", "H"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_5_classification", "Isotopic label"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_5_hidden", "1"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_5_position", "Anywhere"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_5_site", "S"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_6_classification", "Isotopic label"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_6_hidden", "1"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_6_position", "Anywhere"}, {UNIMOD_mTRAQ_13C_6_15N_2_, "spec_6_site", "T"}, {UNIMOD_NeuAc, "approved", "0"}, {UNIMOD_NeuAc, "delta_composition", "NeuAc"}, {UNIMOD_NeuAc, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_NeuAc, "spec_1_hidden", "1"}, {UNIMOD_NeuAc, "spec_1_position", "Anywhere"}, {UNIMOD_NeuAc, "spec_1_site", "N"}, {UNIMOD_NeuAc, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_NeuAc, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_NeuAc, "spec_2_hidden", "1"}, {UNIMOD_NeuAc, "spec_2_hidden", "1"}, {UNIMOD_NeuAc, "spec_2_position", "Anywhere"}, {UNIMOD_NeuAc, "spec_2_position", "Anywhere"}, {UNIMOD_NeuAc, "spec_2_site", "T"}, {UNIMOD_NeuAc, "spec_2_site", "S"}, {UNIMOD_NeuGc, "approved", "0"}, {UNIMOD_NeuGc, "delta_composition", "NeuGc"}, {UNIMOD_NeuGc, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_NeuGc, "spec_1_hidden", "1"}, {UNIMOD_NeuGc, "spec_1_position", "Anywhere"}, {UNIMOD_NeuGc, "spec_1_site", "N"}, {UNIMOD_NeuGc, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_NeuGc, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_NeuGc, "spec_2_hidden", "1"}, {UNIMOD_NeuGc, "spec_2_hidden", "1"}, {UNIMOD_NeuGc, "spec_2_position", "Anywhere"}, {UNIMOD_NeuGc, "spec_2_position", "Anywhere"}, {UNIMOD_NeuGc, "spec_2_site", "T"}, {UNIMOD_NeuGc, "spec_2_site", "S"}, {UNIMOD_Propyl, "approved", "0"}, {UNIMOD_Propyl, "delta_composition", "H(6) C(3)"}, {UNIMOD_Propyl, "spec_1_classification", "Isotopic label"}, {UNIMOD_Propyl, "spec_1_hidden", "1"}, {UNIMOD_Propyl, "spec_1_position", "Any N-term"}, {UNIMOD_Propyl, "spec_1_site", "N-term"}, {UNIMOD_Propyl, "spec_2_classification", "Isotopic label"}, {UNIMOD_Propyl, "spec_2_hidden", "1"}, {UNIMOD_Propyl, "spec_2_position", "Anywhere"}, {UNIMOD_Propyl, "spec_2_site", "K"}, {UNIMOD_Propyl, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Propyl, "spec_3_hidden", "1"}, {UNIMOD_Propyl, "spec_3_position", "Anywhere"}, {UNIMOD_Propyl, "spec_3_site", "D"}, {UNIMOD_Propyl, "spec_4_classification", "Chemical derivative"}, {UNIMOD_Propyl, "spec_4_hidden", "1"}, {UNIMOD_Propyl, "spec_4_position", "Anywhere"}, {UNIMOD_Propyl, "spec_4_site", "E"}, {UNIMOD_Propyl, "spec_5_classification", "Chemical derivative"}, {UNIMOD_Propyl, "spec_5_hidden", "1"}, {UNIMOD_Propyl, "spec_5_position", "Any C-term"}, {UNIMOD_Propyl, "spec_5_site", "C-term"}, {UNIMOD_Propyl, "spec_6_classification", "Chemical derivative"}, {UNIMOD_Propyl, "spec_6_hidden", "1"}, {UNIMOD_Propyl, "spec_6_position", "Protein C-term"}, {UNIMOD_Propyl, "spec_6_site", "C-term"}, {UNIMOD_Propyl_2H_6_, "approved", "0"}, {UNIMOD_Propyl_2H_6_, "delta_composition", "2H(6) C(3)"}, {UNIMOD_Propyl_2H_6_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Propyl_2H_6_, "spec_1_hidden", "1"}, {UNIMOD_Propyl_2H_6_, "spec_1_position", "Any N-term"}, {UNIMOD_Propyl_2H_6_, "spec_1_site", "N-term"}, {UNIMOD_Propyl_2H_6_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Propyl_2H_6_, "spec_2_hidden", "1"}, {UNIMOD_Propyl_2H_6_, "spec_2_position", "Anywhere"}, {UNIMOD_Propyl_2H_6_, "spec_2_site", "K"}, {UNIMOD_Propiophenone, "approved", "0"}, {UNIMOD_Propiophenone, "delta_composition", "H(8) C(9) O"}, {UNIMOD_Propiophenone, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Propiophenone, "spec_1_hidden", "1"}, {UNIMOD_Propiophenone, "spec_1_position", "Anywhere"}, {UNIMOD_Propiophenone, "spec_1_site", "H"}, {UNIMOD_Propiophenone, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Propiophenone, "spec_2_hidden", "1"}, {UNIMOD_Propiophenone, "spec_2_position", "Anywhere"}, {UNIMOD_Propiophenone, "spec_2_site", "K"}, {UNIMOD_Propiophenone, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Propiophenone, "spec_3_hidden", "1"}, {UNIMOD_Propiophenone, "spec_3_position", "Anywhere"}, {UNIMOD_Propiophenone, "spec_3_site", "R"}, {UNIMOD_Propiophenone, "spec_4_classification", "Chemical derivative"}, {UNIMOD_Propiophenone, "spec_4_hidden", "1"}, {UNIMOD_Propiophenone, "spec_4_position", "Anywhere"}, {UNIMOD_Propiophenone, "spec_4_site", "S"}, {UNIMOD_Propiophenone, "spec_5_classification", "Chemical derivative"}, {UNIMOD_Propiophenone, "spec_5_hidden", "1"}, {UNIMOD_Propiophenone, "spec_5_position", "Anywhere"}, {UNIMOD_Propiophenone, "spec_5_site", "T"}, {UNIMOD_Propiophenone, "spec_6_classification", "Chemical derivative"}, {UNIMOD_Propiophenone, "spec_6_hidden", "1"}, {UNIMOD_Propiophenone, "spec_6_position", "Anywhere"}, {UNIMOD_Propiophenone, "spec_6_site", "W"}, {UNIMOD_Propiophenone, "spec_7_classification", "Chemical derivative"}, {UNIMOD_Propiophenone, "spec_7_hidden", "1"}, {UNIMOD_Propiophenone, "spec_7_position", "Anywhere"}, {UNIMOD_Propiophenone, "spec_7_site", "C"}, {UNIMOD_Delta_H_6_C_3_O_1_, "approved", "0"}, {UNIMOD_Delta_H_6_C_3_O_1_, "delta_composition", "H(6) C(3) O"}, {UNIMOD_Delta_H_6_C_3_O_1_, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Delta_H_6_C_3_O_1_, "spec_1_hidden", "1"}, {UNIMOD_Delta_H_6_C_3_O_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Delta_H_6_C_3_O_1_, "spec_1_site", "C"}, {UNIMOD_Delta_H_6_C_3_O_1_, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Delta_H_6_C_3_O_1_, "spec_2_hidden", "1"}, {UNIMOD_Delta_H_6_C_3_O_1_, "spec_2_position", "Anywhere"}, {UNIMOD_Delta_H_6_C_3_O_1_, "spec_2_site", "H"}, {UNIMOD_Delta_H_6_C_3_O_1_, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Delta_H_6_C_3_O_1_, "spec_3_hidden", "1"}, {UNIMOD_Delta_H_6_C_3_O_1_, "spec_3_position", "Anywhere"}, {UNIMOD_Delta_H_6_C_3_O_1_, "spec_3_site", "K"}, {UNIMOD_Delta_H_6_C_3_O_1_, "spec_4_classification", "Chemical derivative"}, {UNIMOD_Delta_H_6_C_3_O_1_, "spec_4_hidden", "1"}, {UNIMOD_Delta_H_6_C_3_O_1_, "spec_4_position", "Protein N-term"}, {UNIMOD_Delta_H_6_C_3_O_1_, "spec_4_site", "N-term"}, {UNIMOD_Delta_H_8_C_6_O_1_, "approved", "0"}, {UNIMOD_Delta_H_8_C_6_O_1_, "delta_composition", "H(8) C(6) O"}, {UNIMOD_Delta_H_8_C_6_O_1_, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Delta_H_8_C_6_O_1_, "spec_1_hidden", "1"}, {UNIMOD_Delta_H_8_C_6_O_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Delta_H_8_C_6_O_1_, "spec_1_site", "L"}, {UNIMOD_Delta_H_8_C_6_O_1_, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Delta_H_8_C_6_O_1_, "spec_2_hidden", "1"}, {UNIMOD_Delta_H_8_C_6_O_1_, "spec_2_position", "Protein N-term"}, {UNIMOD_Delta_H_8_C_6_O_1_, "spec_2_site", "N-term"}, {UNIMOD_biotinAcrolein298, "approved", "0"}, {UNIMOD_biotinAcrolein298, "delta_composition", "H(22) C(13) N(4) O(2) S"}, {UNIMOD_biotinAcrolein298, "spec_1_classification", "Chemical derivative"}, {UNIMOD_biotinAcrolein298, "spec_1_hidden", "1"}, {UNIMOD_biotinAcrolein298, "spec_1_position", "Anywhere"}, {UNIMOD_biotinAcrolein298, "spec_1_site", "C"}, {UNIMOD_biotinAcrolein298, "spec_2_classification", "Chemical derivative"}, {UNIMOD_biotinAcrolein298, "spec_2_hidden", "1"}, {UNIMOD_biotinAcrolein298, "spec_2_position", "Anywhere"}, {UNIMOD_biotinAcrolein298, "spec_2_site", "H"}, {UNIMOD_biotinAcrolein298, "spec_3_classification", "Chemical derivative"}, {UNIMOD_biotinAcrolein298, "spec_3_hidden", "1"}, {UNIMOD_biotinAcrolein298, "spec_3_position", "Anywhere"}, {UNIMOD_biotinAcrolein298, "spec_3_site", "K"}, {UNIMOD_biotinAcrolein298, "spec_4_classification", "Chemical derivative"}, {UNIMOD_biotinAcrolein298, "spec_4_hidden", "1"}, {UNIMOD_biotinAcrolein298, "spec_4_position", "Protein N-term"}, {UNIMOD_biotinAcrolein298, "spec_4_site", "N-term"}, {UNIMOD_MM_diphenylpentanone, "approved", "0"}, {UNIMOD_MM_diphenylpentanone, "delta_composition", "H(19) C(18) N O"}, {UNIMOD_MM_diphenylpentanone, "spec_1_classification", "Chemical derivative"}, {UNIMOD_MM_diphenylpentanone, "spec_1_hidden", "1"}, {UNIMOD_MM_diphenylpentanone, "spec_1_position", "Anywhere"}, {UNIMOD_MM_diphenylpentanone, "spec_1_site", "C"}, {UNIMOD_EHD_diphenylpentanone, "approved", "0"}, {UNIMOD_EHD_diphenylpentanone, "delta_composition", "H(18) C(18) O(2)"}, {UNIMOD_EHD_diphenylpentanone, "spec_1_classification", "Chemical derivative"}, {UNIMOD_EHD_diphenylpentanone, "spec_1_hidden", "1"}, {UNIMOD_EHD_diphenylpentanone, "spec_1_position", "Anywhere"}, {UNIMOD_EHD_diphenylpentanone, "spec_1_site", "C"}, {UNIMOD_EHD_diphenylpentanone, "spec_2_classification", "Chemical derivative"}, {UNIMOD_EHD_diphenylpentanone, "spec_2_hidden", "1"}, {UNIMOD_EHD_diphenylpentanone, "spec_2_position", "Anywhere"}, {UNIMOD_EHD_diphenylpentanone, "spec_2_site", "M"}, {UNIMOD_Biotin_Thermo_21901_2H2O, "approved", "0"}, {UNIMOD_Biotin_Thermo_21901_2H2O, "delta_composition", "H(39) C(23) N(5) O(9) S"}, {UNIMOD_Biotin_Thermo_21901_2H2O, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Biotin_Thermo_21901_2H2O, "spec_1_hidden", "1"}, {UNIMOD_Biotin_Thermo_21901_2H2O, "spec_1_position", "Anywhere"}, {UNIMOD_Biotin_Thermo_21901_2H2O, "spec_1_site", "C"}, {UNIMOD_DiLeu4plex115, "approved", "0"}, {UNIMOD_DiLeu4plex115, "delta_composition", "H(15) C(7) 13C 15N 18O"}, {UNIMOD_DiLeu4plex115, "spec_1_classification", "Isotopic label"}, {UNIMOD_DiLeu4plex115, "spec_1_hidden", "1"}, {UNIMOD_DiLeu4plex115, "spec_1_position", "Anywhere"}, {UNIMOD_DiLeu4plex115, "spec_1_site", "K"}, {UNIMOD_DiLeu4plex115, "spec_2_classification", "Isotopic label"}, {UNIMOD_DiLeu4plex115, "spec_2_hidden", "1"}, {UNIMOD_DiLeu4plex115, "spec_2_position", "Any N-term"}, {UNIMOD_DiLeu4plex115, "spec_2_site", "N-term"}, {UNIMOD_DiLeu4plex115, "spec_3_classification", "Isotopic label"}, {UNIMOD_DiLeu4plex115, "spec_3_hidden", "1"}, {UNIMOD_DiLeu4plex115, "spec_3_position", "Anywhere"}, {UNIMOD_DiLeu4plex115, "spec_3_site", "Y"}, {UNIMOD_DiLeu4plex, "approved", "0"}, {UNIMOD_DiLeu4plex, "delta_composition", "H(13) 2H(2) C(8) N 18O"}, {UNIMOD_DiLeu4plex, "spec_1_classification", "Isotopic label"}, {UNIMOD_DiLeu4plex, "spec_1_hidden", "0"}, {UNIMOD_DiLeu4plex, "spec_1_position", "Anywhere"}, {UNIMOD_DiLeu4plex, "spec_1_site", "K"}, {UNIMOD_DiLeu4plex, "spec_2_classification", "Isotopic label"}, {UNIMOD_DiLeu4plex, "spec_2_hidden", "0"}, {UNIMOD_DiLeu4plex, "spec_2_position", "Any N-term"}, {UNIMOD_DiLeu4plex, "spec_2_site", "N-term"}, {UNIMOD_DiLeu4plex, "spec_3_classification", "Isotopic label"}, {UNIMOD_DiLeu4plex, "spec_3_hidden", "0"}, {UNIMOD_DiLeu4plex, "spec_3_position", "Anywhere"}, {UNIMOD_DiLeu4plex, "spec_3_site", "Y"}, {UNIMOD_DiLeu4plex117, "approved", "0"}, {UNIMOD_DiLeu4plex117, "delta_composition", "H(13) 2H(2) C(7) 13C 15N O"}, {UNIMOD_DiLeu4plex117, "spec_1_classification", "Isotopic label"}, {UNIMOD_DiLeu4plex117, "spec_1_hidden", "1"}, {UNIMOD_DiLeu4plex117, "spec_1_position", "Anywhere"}, {UNIMOD_DiLeu4plex117, "spec_1_site", "K"}, {UNIMOD_DiLeu4plex117, "spec_2_classification", "Isotopic label"}, {UNIMOD_DiLeu4plex117, "spec_2_hidden", "1"}, {UNIMOD_DiLeu4plex117, "spec_2_position", "Any N-term"}, {UNIMOD_DiLeu4plex117, "spec_2_site", "N-term"}, {UNIMOD_DiLeu4plex117, "spec_3_classification", "Isotopic label"}, {UNIMOD_DiLeu4plex117, "spec_3_hidden", "1"}, {UNIMOD_DiLeu4plex117, "spec_3_position", "Anywhere"}, {UNIMOD_DiLeu4plex117, "spec_3_site", "Y"}, {UNIMOD_DiLeu4plex118, "approved", "0"}, {UNIMOD_DiLeu4plex118, "delta_composition", "H(11) 2H(4) C(8) N O"}, {UNIMOD_DiLeu4plex118, "spec_1_classification", "Isotopic label"}, {UNIMOD_DiLeu4plex118, "spec_1_hidden", "1"}, {UNIMOD_DiLeu4plex118, "spec_1_position", "Anywhere"}, {UNIMOD_DiLeu4plex118, "spec_1_site", "K"}, {UNIMOD_DiLeu4plex118, "spec_2_classification", "Isotopic label"}, {UNIMOD_DiLeu4plex118, "spec_2_hidden", "1"}, {UNIMOD_DiLeu4plex118, "spec_2_position", "Any N-term"}, {UNIMOD_DiLeu4plex118, "spec_2_site", "N-term"}, {UNIMOD_DiLeu4plex118, "spec_3_classification", "Isotopic label"}, {UNIMOD_DiLeu4plex118, "spec_3_hidden", "1"}, {UNIMOD_DiLeu4plex118, "spec_3_position", "Anywhere"}, {UNIMOD_DiLeu4plex118, "spec_3_site", "Y"}, {UNIMOD_NEMsulfur, "approved", "0"}, {UNIMOD_NEMsulfur, "delta_composition", "H(7) C(6) N O(2) S"}, {UNIMOD_NEMsulfur, "spec_1_classification", "Chemical derivative"}, {UNIMOD_NEMsulfur, "spec_1_hidden", "1"}, {UNIMOD_NEMsulfur, "spec_1_position", "Anywhere"}, {UNIMOD_NEMsulfur, "spec_1_site", "C"}, {UNIMOD_SulfurDioxide, "approved", "0"}, {UNIMOD_SulfurDioxide, "delta_composition", "O(2) S"}, {UNIMOD_SulfurDioxide, "spec_1_classification", "Post-translational"}, {UNIMOD_SulfurDioxide, "spec_1_hidden", "1"}, {UNIMOD_SulfurDioxide, "spec_1_position", "Anywhere"}, {UNIMOD_SulfurDioxide, "spec_1_site", "C"}, {UNIMOD_NEMsulfurWater, "approved", "0"}, {UNIMOD_NEMsulfurWater, "delta_composition", "H(9) C(6) N O(3) S"}, {UNIMOD_NEMsulfurWater, "spec_1_classification", "Chemical derivative"}, {UNIMOD_NEMsulfurWater, "spec_1_hidden", "1"}, {UNIMOD_NEMsulfurWater, "spec_1_position", "Anywhere"}, {UNIMOD_NEMsulfurWater, "spec_1_site", "C"}, {UNIMOD_bisANS_sulfonates, "approved", "0"}, {UNIMOD_bisANS_sulfonates, "delta_composition", "H(25) C(32) N(2)"}, {UNIMOD_bisANS_sulfonates, "spec_1_classification", "Chemical derivative"}, {UNIMOD_bisANS_sulfonates, "spec_1_hidden", "1"}, {UNIMOD_bisANS_sulfonates, "spec_1_position", "Anywhere"}, {UNIMOD_bisANS_sulfonates, "spec_1_site", "K"}, {UNIMOD_bisANS_sulfonates, "spec_2_classification", "Chemical derivative"}, {UNIMOD_bisANS_sulfonates, "spec_2_hidden", "1"}, {UNIMOD_bisANS_sulfonates, "spec_2_position", "Anywhere"}, {UNIMOD_bisANS_sulfonates, "spec_2_site", "S"}, {UNIMOD_bisANS_sulfonates, "spec_3_classification", "Chemical derivative"}, {UNIMOD_bisANS_sulfonates, "spec_3_hidden", "1"}, {UNIMOD_bisANS_sulfonates, "spec_3_position", "Anywhere"}, {UNIMOD_bisANS_sulfonates, "spec_3_site", "T"}, {UNIMOD_DNCB_hapten, "approved", "0"}, {UNIMOD_DNCB_hapten, "delta_composition", "H(2) C(6) N(2) O(4)"}, {UNIMOD_DNCB_hapten, "spec_1_classification", "Chemical derivative"}, {UNIMOD_DNCB_hapten, "spec_1_hidden", "1"}, {UNIMOD_DNCB_hapten, "spec_1_position", "Anywhere"}, {UNIMOD_DNCB_hapten, "spec_1_site", "C"}, {UNIMOD_DNCB_hapten, "spec_2_classification", "Chemical derivative"}, {UNIMOD_DNCB_hapten, "spec_2_hidden", "1"}, {UNIMOD_DNCB_hapten, "spec_2_position", "Anywhere"}, {UNIMOD_DNCB_hapten, "spec_2_site", "H"}, {UNIMOD_DNCB_hapten, "spec_3_classification", "Chemical derivative"}, {UNIMOD_DNCB_hapten, "spec_3_hidden", "1"}, {UNIMOD_DNCB_hapten, "spec_3_position", "Anywhere"}, {UNIMOD_DNCB_hapten, "spec_3_site", "K"}, {UNIMOD_DNCB_hapten, "spec_4_classification", "Chemical derivative"}, {UNIMOD_DNCB_hapten, "spec_4_hidden", "1"}, {UNIMOD_DNCB_hapten, "spec_4_position", "Anywhere"}, {UNIMOD_DNCB_hapten, "spec_4_site", "Y"}, {UNIMOD_Biotin_Thermo_21911, "approved", "0"}, {UNIMOD_Biotin_Thermo_21911, "delta_composition", "H(71) C(41) N(5) O(16) S"}, {UNIMOD_Biotin_Thermo_21911, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Biotin_Thermo_21911, "spec_1_hidden", "1"}, {UNIMOD_Biotin_Thermo_21911, "spec_1_position", "Anywhere"}, {UNIMOD_Biotin_Thermo_21911, "spec_1_site", "C"}, {UNIMOD_iodoTMT, "approved", "0"}, {UNIMOD_iodoTMT, "delta_composition", "H(28) C(16) N(4) O(3)"}, {UNIMOD_iodoTMT, "spec_1_classification", "Chemical derivative"}, {UNIMOD_iodoTMT, "spec_1_hidden", "1"}, {UNIMOD_iodoTMT, "spec_1_position", "Anywhere"}, {UNIMOD_iodoTMT, "spec_1_site", "C"}, {UNIMOD_iodoTMT, "spec_2_classification", "Chemical derivative"}, {UNIMOD_iodoTMT, "spec_2_hidden", "1"}, {UNIMOD_iodoTMT, "spec_2_position", "Anywhere"}, {UNIMOD_iodoTMT, "spec_2_site", "D"}, {UNIMOD_iodoTMT, "spec_3_classification", "Chemical derivative"}, {UNIMOD_iodoTMT, "spec_3_hidden", "1"}, {UNIMOD_iodoTMT, "spec_3_position", "Anywhere"}, {UNIMOD_iodoTMT, "spec_3_site", "E"}, {UNIMOD_iodoTMT, "spec_4_classification", "Chemical derivative"}, {UNIMOD_iodoTMT, "spec_4_hidden", "1"}, {UNIMOD_iodoTMT, "spec_4_position", "Anywhere"}, {UNIMOD_iodoTMT, "spec_4_site", "H"}, {UNIMOD_iodoTMT, "spec_5_classification", "Chemical derivative"}, {UNIMOD_iodoTMT, "spec_5_hidden", "1"}, {UNIMOD_iodoTMT, "spec_5_position", "Anywhere"}, {UNIMOD_iodoTMT, "spec_5_site", "K"}, {UNIMOD_iodoTMT6plex, "approved", "0"}, {UNIMOD_iodoTMT6plex, "delta_composition", "H(28) C(12) 13C(4) N(3) 15N O(3)"}, {UNIMOD_iodoTMT6plex, "spec_1_classification", "Chemical derivative"}, {UNIMOD_iodoTMT6plex, "spec_1_hidden", "1"}, {UNIMOD_iodoTMT6plex, "spec_1_position", "Anywhere"}, {UNIMOD_iodoTMT6plex, "spec_1_site", "C"}, {UNIMOD_iodoTMT6plex, "spec_2_classification", "Chemical derivative"}, {UNIMOD_iodoTMT6plex, "spec_2_hidden", "1"}, {UNIMOD_iodoTMT6plex, "spec_2_position", "Anywhere"}, {UNIMOD_iodoTMT6plex, "spec_2_site", "D"}, {UNIMOD_iodoTMT6plex, "spec_3_classification", "Chemical derivative"}, {UNIMOD_iodoTMT6plex, "spec_3_hidden", "1"}, {UNIMOD_iodoTMT6plex, "spec_3_position", "Anywhere"}, {UNIMOD_iodoTMT6plex, "spec_3_site", "E"}, {UNIMOD_iodoTMT6plex, "spec_4_classification", "Chemical derivative"}, {UNIMOD_iodoTMT6plex, "spec_4_hidden", "1"}, {UNIMOD_iodoTMT6plex, "spec_4_position", "Anywhere"}, {UNIMOD_iodoTMT6plex, "spec_4_site", "H"}, {UNIMOD_iodoTMT6plex, "spec_5_classification", "Chemical derivative"}, {UNIMOD_iodoTMT6plex, "spec_5_hidden", "1"}, {UNIMOD_iodoTMT6plex, "spec_5_position", "Anywhere"}, {UNIMOD_iodoTMT6plex, "spec_5_site", "K"}, {UNIMOD_Gluconoylation, "approved", "0"}, {UNIMOD_Gluconoylation, "delta_composition", "H(10) C(6) O(6)"}, {UNIMOD_Gluconoylation, "spec_1_classification", "Post-translational"}, {UNIMOD_Gluconoylation, "spec_1_hidden", "1"}, {UNIMOD_Gluconoylation, "spec_1_position", "Anywhere"}, {UNIMOD_Gluconoylation, "spec_1_site", "K"}, {UNIMOD_Gluconoylation, "spec_2_classification", "Post-translational"}, {UNIMOD_Gluconoylation, "spec_2_hidden", "1"}, {UNIMOD_Gluconoylation, "spec_2_position", "Any N-term"}, {UNIMOD_Gluconoylation, "spec_2_site", "N-term"}, {UNIMOD_Phosphogluconoylation, "approved", "0"}, {UNIMOD_Phosphogluconoylation, "delta_composition", "H(11) C(6) O(9) P"}, {UNIMOD_Phosphogluconoylation, "spec_1_classification", "Post-translational"}, {UNIMOD_Phosphogluconoylation, "spec_1_hidden", "1"}, {UNIMOD_Phosphogluconoylation, "spec_1_position", "Anywhere"}, {UNIMOD_Phosphogluconoylation, "spec_1_site", "K"}, {UNIMOD_Phosphogluconoylation, "spec_2_classification", "Post-translational"}, {UNIMOD_Phosphogluconoylation, "spec_2_hidden", "1"}, {UNIMOD_Phosphogluconoylation, "spec_2_position", "Any N-term"}, {UNIMOD_Phosphogluconoylation, "spec_2_site", "N-term"}, {UNIMOD_PS_Hapten, "approved", "0"}, {UNIMOD_PS_Hapten, "delta_composition", "H(4) C(7) O(2)"}, {UNIMOD_PS_Hapten, "spec_1_classification", "Chemical derivative"}, {UNIMOD_PS_Hapten, "spec_1_hidden", "1"}, {UNIMOD_PS_Hapten, "spec_1_position", "Anywhere"}, {UNIMOD_PS_Hapten, "spec_1_site", "C"}, {UNIMOD_PS_Hapten, "spec_2_classification", "Chemical derivative"}, {UNIMOD_PS_Hapten, "spec_2_hidden", "1"}, {UNIMOD_PS_Hapten, "spec_2_position", "Anywhere"}, {UNIMOD_PS_Hapten, "spec_2_site", "H"}, {UNIMOD_PS_Hapten, "spec_3_classification", "Chemical derivative"}, {UNIMOD_PS_Hapten, "spec_3_hidden", "1"}, {UNIMOD_PS_Hapten, "spec_3_position", "Anywhere"}, {UNIMOD_PS_Hapten, "spec_3_site", "K"}, {UNIMOD_Cy3_maleimide, "approved", "0"}, {UNIMOD_Cy3_maleimide, "delta_composition", "H(45) C(37) N(4) O(9) S(2)"}, {UNIMOD_Cy3_maleimide, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Cy3_maleimide, "spec_1_hidden", "1"}, {UNIMOD_Cy3_maleimide, "spec_1_position", "Anywhere"}, {UNIMOD_Cy3_maleimide, "spec_1_site", "C"}, {UNIMOD_benzylguanidine, "approved", "0"}, {UNIMOD_benzylguanidine, "delta_composition", "H(8) C(8) N(2)"}, {UNIMOD_benzylguanidine, "spec_1_classification", "Chemical derivative"}, {UNIMOD_benzylguanidine, "spec_1_hidden", "1"}, {UNIMOD_benzylguanidine, "spec_1_position", "Anywhere"}, {UNIMOD_benzylguanidine, "spec_1_site", "K"}, {UNIMOD_CarboxymethylDMAP, "approved", "0"}, {UNIMOD_CarboxymethylDMAP, "delta_composition", "H(10) C(9) N(2) O"}, {UNIMOD_CarboxymethylDMAP, "spec_1_classification", "Chemical derivative"}, {UNIMOD_CarboxymethylDMAP, "spec_1_hidden", "1"}, {UNIMOD_CarboxymethylDMAP, "spec_1_position", "Any N-term"}, {UNIMOD_CarboxymethylDMAP, "spec_1_site", "N-term"}, {UNIMOD_azole, "approved", "0"}, {UNIMOD_azole, "delta_composition", "H(-4) O(-1)"}, {UNIMOD_azole, "spec_1_classification", "Post-translational"}, {UNIMOD_azole, "spec_1_hidden", "1"}, {UNIMOD_azole, "spec_1_position", "Anywhere"}, {UNIMOD_azole, "spec_1_site", "S"}, {UNIMOD_azole, "spec_2_classification", "Post-translational"}, {UNIMOD_azole, "spec_2_hidden", "1"}, {UNIMOD_azole, "spec_2_position", "Anywhere"}, {UNIMOD_azole, "spec_2_site", "C"}, {UNIMOD_phosphoRibosyl, "approved", "0"}, {UNIMOD_phosphoRibosyl, "delta_composition", "H(9) C(5) O(7) P"}, {UNIMOD_phosphoRibosyl, "spec_1_classification", "Post-translational"}, {UNIMOD_phosphoRibosyl, "spec_1_hidden", "1"}, {UNIMOD_phosphoRibosyl, "spec_1_position", "Anywhere"}, {UNIMOD_phosphoRibosyl, "spec_1_site", "D"}, {UNIMOD_phosphoRibosyl, "spec_2_classification", "Post-translational"}, {UNIMOD_phosphoRibosyl, "spec_2_hidden", "1"}, {UNIMOD_phosphoRibosyl, "spec_2_position", "Anywhere"}, {UNIMOD_phosphoRibosyl, "spec_2_site", "E"}, {UNIMOD_phosphoRibosyl, "spec_3_classification", "Post-translational"}, {UNIMOD_phosphoRibosyl, "spec_3_hidden", "1"}, {UNIMOD_phosphoRibosyl, "spec_3_position", "Anywhere"}, {UNIMOD_phosphoRibosyl, "spec_3_site", "R"}, {UNIMOD_NEM_2H_5__H2O, "approved", "0"}, {UNIMOD_NEM_2H_5__H2O, "delta_composition", "H(4) 2H(5) C(6) N O(3)"}, {UNIMOD_NEM_2H_5__H2O, "spec_1_classification", "Chemical derivative"}, {UNIMOD_NEM_2H_5__H2O, "spec_1_hidden", "1"}, {UNIMOD_NEM_2H_5__H2O, "spec_1_position", "Anywhere"}, {UNIMOD_NEM_2H_5__H2O, "spec_1_site", "C"}, {UNIMOD_Crotonyl, "approved", "0"}, {UNIMOD_Crotonyl, "delta_composition", "H(4) C(4) O"}, {UNIMOD_Crotonyl, "spec_1_classification", "Post-translational"}, {UNIMOD_Crotonyl, "spec_1_hidden", "0"}, {UNIMOD_Crotonyl, "spec_1_position", "Anywhere"}, {UNIMOD_Crotonyl, "spec_1_site", "K"}, {UNIMOD_O_Et_N_diMePhospho, "approved", "0"}, {UNIMOD_O_Et_N_diMePhospho, "delta_composition", "H(10) C(4) N O(2) P"}, {UNIMOD_O_Et_N_diMePhospho, "spec_1_classification", "Chemical derivative"}, {UNIMOD_O_Et_N_diMePhospho, "spec_1_hidden", "1"}, {UNIMOD_O_Et_N_diMePhospho, "spec_1_position", "Anywhere"}, {UNIMOD_O_Et_N_diMePhospho, "spec_1_site", "S"}, {UNIMOD_N_dimethylphosphate, "approved", "0"}, {UNIMOD_N_dimethylphosphate, "delta_composition", "H(6) C(2) N O(2) P"}, {UNIMOD_N_dimethylphosphate, "spec_1_classification", "Chemical derivative"}, {UNIMOD_N_dimethylphosphate, "spec_1_hidden", "1"}, {UNIMOD_N_dimethylphosphate, "spec_1_position", "Anywhere"}, {UNIMOD_N_dimethylphosphate, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_1_, "delta_composition", "dHex Hex"}, {UNIMOD_dHex_1_Hex_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_1_, "spec_1_site", "S"}, {UNIMOD_Methyl_2H_3__Acetyl_2H_3_, "approved", "0"}, {UNIMOD_Methyl_2H_3__Acetyl_2H_3_, "delta_composition", "H(-2) 2H(6) C(3) O"}, {UNIMOD_Methyl_2H_3__Acetyl_2H_3_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Methyl_2H_3__Acetyl_2H_3_, "spec_1_hidden", "1"}, {UNIMOD_Methyl_2H_3__Acetyl_2H_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Methyl_2H_3__Acetyl_2H_3_, "spec_1_site", "K"}, {UNIMOD_Label_2H_3__Oxidation, "approved", "0"}, {UNIMOD_Label_2H_3__Oxidation, "delta_composition", "H(-3) 2H(3) O"}, {UNIMOD_Label_2H_3__Oxidation, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_2H_3__Oxidation, "spec_1_hidden", "1"}, {UNIMOD_Label_2H_3__Oxidation, "spec_1_position", "Anywhere"}, {UNIMOD_Label_2H_3__Oxidation, "spec_1_site", "M"}, {UNIMOD_Trimethyl_2H_9_, "approved", "0"}, {UNIMOD_Trimethyl_2H_9_, "delta_composition", "H(-3) 2H(9) C(3)"}, {UNIMOD_Trimethyl_2H_9_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Trimethyl_2H_9_, "spec_1_hidden", "1"}, {UNIMOD_Trimethyl_2H_9_, "spec_1_position", "Anywhere"}, {UNIMOD_Trimethyl_2H_9_, "spec_1_site", "K"}, {UNIMOD_Trimethyl_2H_9_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Trimethyl_2H_9_, "spec_2_hidden", "1"}, {UNIMOD_Trimethyl_2H_9_, "spec_2_position", "Anywhere"}, {UNIMOD_Trimethyl_2H_9_, "spec_2_site", "R"}, {UNIMOD_Acetyl_13C_2_, "approved", "0"}, {UNIMOD_Acetyl_13C_2_, "delta_composition", "H(2) 13C(2) O"}, {UNIMOD_Acetyl_13C_2_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Acetyl_13C_2_, "spec_1_hidden", "1"}, {UNIMOD_Acetyl_13C_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Acetyl_13C_2_, "spec_1_site", "K"}, {UNIMOD_Acetyl_13C_2_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Acetyl_13C_2_, "spec_2_hidden", "1"}, {UNIMOD_Acetyl_13C_2_, "spec_2_position", "Protein N-term"}, {UNIMOD_Acetyl_13C_2_, "spec_2_site", "N-term"}, {UNIMOD_dHex_1_Hex_2_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_, "delta_composition", "dHex Hex(2)"}, {UNIMOD_dHex_1_Hex_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_2_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_3_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_, "delta_composition", "dHex Hex(3)"}, {UNIMOD_dHex_1_Hex_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_3_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_4_, "approved", "0"}, {UNIMOD_dHex_1_Hex_4_, "delta_composition", "dHex Hex(4)"}, {UNIMOD_dHex_1_Hex_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_4_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_5_, "approved", "0"}, {UNIMOD_dHex_1_Hex_5_, "delta_composition", "dHex Hex(5)"}, {UNIMOD_dHex_1_Hex_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_5_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_5_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_5_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_5_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_5_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_5_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_6_, "approved", "0"}, {UNIMOD_dHex_1_Hex_6_, "delta_composition", "dHex Hex(6)"}, {UNIMOD_dHex_1_Hex_6_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_6_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_6_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_6_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_6_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_6_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_6_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_6_, "spec_1_site", "S"}, {UNIMOD_methylsulfonylethyl, "approved", "0"}, {UNIMOD_methylsulfonylethyl, "delta_composition", "H(6) C(3) O(2) S"}, {UNIMOD_methylsulfonylethyl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_methylsulfonylethyl, "spec_1_hidden", "1"}, {UNIMOD_methylsulfonylethyl, "spec_1_position", "Anywhere"}, {UNIMOD_methylsulfonylethyl, "spec_1_site", "C"}, {UNIMOD_methylsulfonylethyl, "spec_2_classification", "Chemical derivative"}, {UNIMOD_methylsulfonylethyl, "spec_2_hidden", "1"}, {UNIMOD_methylsulfonylethyl, "spec_2_position", "Anywhere"}, {UNIMOD_methylsulfonylethyl, "spec_2_site", "H"}, {UNIMOD_methylsulfonylethyl, "spec_3_classification", "Chemical derivative"}, {UNIMOD_methylsulfonylethyl, "spec_3_hidden", "1"}, {UNIMOD_methylsulfonylethyl, "spec_3_position", "Anywhere"}, {UNIMOD_methylsulfonylethyl, "spec_3_site", "K"}, {UNIMOD_ethylsulfonylethyl, "approved", "0"}, {UNIMOD_ethylsulfonylethyl, "delta_composition", "H(8) C(4) O(2) S"}, {UNIMOD_ethylsulfonylethyl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_ethylsulfonylethyl, "spec_1_hidden", "1"}, {UNIMOD_ethylsulfonylethyl, "spec_1_position", "Anywhere"}, {UNIMOD_ethylsulfonylethyl, "spec_1_site", "C"}, {UNIMOD_ethylsulfonylethyl, "spec_2_classification", "Chemical derivative"}, {UNIMOD_ethylsulfonylethyl, "spec_2_hidden", "1"}, {UNIMOD_ethylsulfonylethyl, "spec_2_position", "Anywhere"}, {UNIMOD_ethylsulfonylethyl, "spec_2_site", "H"}, {UNIMOD_ethylsulfonylethyl, "spec_3_classification", "Chemical derivative"}, {UNIMOD_ethylsulfonylethyl, "spec_3_hidden", "1"}, {UNIMOD_ethylsulfonylethyl, "spec_3_position", "Anywhere"}, {UNIMOD_ethylsulfonylethyl, "spec_3_site", "K"}, {UNIMOD_phenylsulfonylethyl, "approved", "0"}, {UNIMOD_phenylsulfonylethyl, "delta_composition", "H(8) C(8) O(2) S"}, {UNIMOD_phenylsulfonylethyl, "spec_1_classification", "Chemical derivative"}, {UNIMOD_phenylsulfonylethyl, "spec_1_hidden", "1"}, {UNIMOD_phenylsulfonylethyl, "spec_1_position", "Anywhere"}, {UNIMOD_phenylsulfonylethyl, "spec_1_site", "C"}, {UNIMOD_PyridoxalPhosphateH2, "approved", "0"}, {UNIMOD_PyridoxalPhosphateH2, "delta_composition", "H(10) C(8) N O(5) P"}, {UNIMOD_PyridoxalPhosphateH2, "spec_1_classification", "Chemical derivative"}, {UNIMOD_PyridoxalPhosphateH2, "spec_1_hidden", "1"}, {UNIMOD_PyridoxalPhosphateH2, "spec_1_position", "Anywhere"}, {UNIMOD_PyridoxalPhosphateH2, "spec_1_site", "K"}, {UNIMOD_Homocysteic_acid, "approved", "0"}, {UNIMOD_Homocysteic_acid, "delta_composition", "H(-2) C(-1) O(3)"}, {UNIMOD_Homocysteic_acid, "spec_1_classification", "Artefact"}, {UNIMOD_Homocysteic_acid, "spec_1_hidden", "1"}, {UNIMOD_Homocysteic_acid, "spec_1_position", "Anywhere"}, {UNIMOD_Homocysteic_acid, "spec_1_site", "M"}, {UNIMOD_Hydroxamic_acid, "approved", "0"}, {UNIMOD_Hydroxamic_acid, "delta_composition", "H N"}, {UNIMOD_Hydroxamic_acid, "spec_1_classification", "Artefact"}, {UNIMOD_Hydroxamic_acid, "spec_1_classification", "Artefact"}, {UNIMOD_Hydroxamic_acid, "spec_1_hidden", "1"}, {UNIMOD_Hydroxamic_acid, "spec_1_hidden", "1"}, {UNIMOD_Hydroxamic_acid, "spec_1_position", "Anywhere"}, {UNIMOD_Hydroxamic_acid, "spec_1_position", "Anywhere"}, {UNIMOD_Hydroxamic_acid, "spec_1_site", "E"}, {UNIMOD_Hydroxamic_acid, "spec_1_site", "D"}, {UNIMOD_3_phosphoglyceryl, "approved", "0"}, {UNIMOD_3_phosphoglyceryl, "delta_composition", "H(5) C(3) O(6) P"}, {UNIMOD_3_phosphoglyceryl, "spec_1_classification", "Post-translational"}, {UNIMOD_3_phosphoglyceryl, "spec_1_hidden", "1"}, {UNIMOD_3_phosphoglyceryl, "spec_1_position", "Anywhere"}, {UNIMOD_3_phosphoglyceryl, "spec_1_site", "K"}, {UNIMOD_HN2_mustard, "approved", "0"}, {UNIMOD_HN2_mustard, "delta_composition", "H(11) C(5) N O"}, {UNIMOD_HN2_mustard, "spec_1_classification", "Post-translational"}, {UNIMOD_HN2_mustard, "spec_1_hidden", "1"}, {UNIMOD_HN2_mustard, "spec_1_position", "Anywhere"}, {UNIMOD_HN2_mustard, "spec_1_site", "C"}, {UNIMOD_HN2_mustard, "spec_2_classification", "Post-translational"}, {UNIMOD_HN2_mustard, "spec_2_hidden", "1"}, {UNIMOD_HN2_mustard, "spec_2_position", "Anywhere"}, {UNIMOD_HN2_mustard, "spec_2_site", "H"}, {UNIMOD_HN2_mustard, "spec_3_classification", "Post-translational"}, {UNIMOD_HN2_mustard, "spec_3_hidden", "1"}, {UNIMOD_HN2_mustard, "spec_3_position", "Anywhere"}, {UNIMOD_HN2_mustard, "spec_3_site", "K"}, {UNIMOD_HN3_mustard, "approved", "0"}, {UNIMOD_HN3_mustard, "delta_composition", "H(13) C(6) N O(2)"}, {UNIMOD_HN3_mustard, "spec_1_classification", "Post-translational"}, {UNIMOD_HN3_mustard, "spec_1_hidden", "1"}, {UNIMOD_HN3_mustard, "spec_1_position", "Anywhere"}, {UNIMOD_HN3_mustard, "spec_1_site", "C"}, {UNIMOD_HN3_mustard, "spec_2_classification", "Post-translational"}, {UNIMOD_HN3_mustard, "spec_2_hidden", "1"}, {UNIMOD_HN3_mustard, "spec_2_position", "Anywhere"}, {UNIMOD_HN3_mustard, "spec_2_site", "H"}, {UNIMOD_HN3_mustard, "spec_3_classification", "Post-translational"}, {UNIMOD_HN3_mustard, "spec_3_hidden", "1"}, {UNIMOD_HN3_mustard, "spec_3_position", "Anywhere"}, {UNIMOD_HN3_mustard, "spec_3_site", "K"}, {UNIMOD_Oxidation_NEM, "approved", "0"}, {UNIMOD_Oxidation_NEM, "delta_composition", "H(7) C(6) N O(3)"}, {UNIMOD_Oxidation_NEM, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Oxidation_NEM, "spec_1_hidden", "1"}, {UNIMOD_Oxidation_NEM, "spec_1_position", "Anywhere"}, {UNIMOD_Oxidation_NEM, "spec_1_site", "C"}, {UNIMOD_NHS_fluorescein, "approved", "0"}, {UNIMOD_NHS_fluorescein, "delta_composition", "H(21) C(27) N O(7)"}, {UNIMOD_NHS_fluorescein, "spec_1_classification", "Chemical derivative"}, {UNIMOD_NHS_fluorescein, "spec_1_hidden", "1"}, {UNIMOD_NHS_fluorescein, "spec_1_position", "Anywhere"}, {UNIMOD_NHS_fluorescein, "spec_1_site", "K"}, {UNIMOD_DiART6plex, "approved", "0"}, {UNIMOD_DiART6plex, "delta_composition", "H(20) C(7) 13C(4) N 15N O(2)"}, {UNIMOD_DiART6plex, "spec_1_classification", "Isotopic label"}, {UNIMOD_DiART6plex, "spec_1_hidden", "0"}, {UNIMOD_DiART6plex, "spec_1_position", "Anywhere"}, {UNIMOD_DiART6plex, "spec_1_site", "K"}, {UNIMOD_DiART6plex, "spec_2_classification", "Isotopic label"}, {UNIMOD_DiART6plex, "spec_2_hidden", "0"}, {UNIMOD_DiART6plex, "spec_2_position", "Any N-term"}, {UNIMOD_DiART6plex, "spec_2_site", "N-term"}, {UNIMOD_DiART6plex, "spec_3_classification", "Isotopic label"}, {UNIMOD_DiART6plex, "spec_3_hidden", "0"}, {UNIMOD_DiART6plex, "spec_3_position", "Protein N-term"}, {UNIMOD_DiART6plex, "spec_3_site", "N-term"}, {UNIMOD_DiART6plex, "spec_4_classification", "Isotopic label"}, {UNIMOD_DiART6plex, "spec_4_hidden", "0"}, {UNIMOD_DiART6plex, "spec_4_position", "Anywhere"}, {UNIMOD_DiART6plex, "spec_4_site", "Y"}, {UNIMOD_DiART6plex115, "approved", "0"}, {UNIMOD_DiART6plex115, "delta_composition", "H(20) C(8) 13C(3) 15N(2) O(2)"}, {UNIMOD_DiART6plex115, "spec_1_classification", "Isotopic label"}, {UNIMOD_DiART6plex115, "spec_1_hidden", "1"}, {UNIMOD_DiART6plex115, "spec_1_position", "Anywhere"}, {UNIMOD_DiART6plex115, "spec_1_site", "K"}, {UNIMOD_DiART6plex115, "spec_2_classification", "Isotopic label"}, {UNIMOD_DiART6plex115, "spec_2_hidden", "1"}, {UNIMOD_DiART6plex115, "spec_2_position", "Any N-term"}, {UNIMOD_DiART6plex115, "spec_2_site", "N-term"}, {UNIMOD_DiART6plex115, "spec_3_classification", "Isotopic label"}, {UNIMOD_DiART6plex115, "spec_3_hidden", "1"}, {UNIMOD_DiART6plex115, "spec_3_position", "Protein N-term"}, {UNIMOD_DiART6plex115, "spec_3_site", "N-term"}, {UNIMOD_DiART6plex115, "spec_4_classification", "Isotopic label"}, {UNIMOD_DiART6plex115, "spec_4_hidden", "1"}, {UNIMOD_DiART6plex115, "spec_4_position", "Anywhere"}, {UNIMOD_DiART6plex115, "spec_4_site", "Y"}, {UNIMOD_DiART6plex116_119, "approved", "0"}, {UNIMOD_DiART6plex116_119, "delta_composition", "H(18) 2H(2) C(9) 13C(2) N 15N O(2)"}, {UNIMOD_DiART6plex116_119, "spec_1_classification", "Isotopic label"}, {UNIMOD_DiART6plex116_119, "spec_1_hidden", "1"}, {UNIMOD_DiART6plex116_119, "spec_1_position", "Anywhere"}, {UNIMOD_DiART6plex116_119, "spec_1_site", "K"}, {UNIMOD_DiART6plex116_119, "spec_2_classification", "Isotopic label"}, {UNIMOD_DiART6plex116_119, "spec_2_hidden", "1"}, {UNIMOD_DiART6plex116_119, "spec_2_position", "Any N-term"}, {UNIMOD_DiART6plex116_119, "spec_2_site", "N-term"}, {UNIMOD_DiART6plex116_119, "spec_3_classification", "Isotopic label"}, {UNIMOD_DiART6plex116_119, "spec_3_hidden", "1"}, {UNIMOD_DiART6plex116_119, "spec_3_position", "Protein N-term"}, {UNIMOD_DiART6plex116_119, "spec_3_site", "N-term"}, {UNIMOD_DiART6plex116_119, "spec_4_classification", "Isotopic label"}, {UNIMOD_DiART6plex116_119, "spec_4_hidden", "1"}, {UNIMOD_DiART6plex116_119, "spec_4_position", "Anywhere"}, {UNIMOD_DiART6plex116_119, "spec_4_site", "Y"}, {UNIMOD_DiART6plex117, "approved", "0"}, {UNIMOD_DiART6plex117, "delta_composition", "H(18) 2H(2) C(10) 13C 15N(2) O(2)"}, {UNIMOD_DiART6plex117, "spec_1_classification", "Isotopic label"}, {UNIMOD_DiART6plex117, "spec_1_hidden", "1"}, {UNIMOD_DiART6plex117, "spec_1_position", "Anywhere"}, {UNIMOD_DiART6plex117, "spec_1_site", "K"}, {UNIMOD_DiART6plex117, "spec_2_classification", "Isotopic label"}, {UNIMOD_DiART6plex117, "spec_2_hidden", "1"}, {UNIMOD_DiART6plex117, "spec_2_position", "Any N-term"}, {UNIMOD_DiART6plex117, "spec_2_site", "N-term"}, {UNIMOD_DiART6plex117, "spec_3_classification", "Isotopic label"}, {UNIMOD_DiART6plex117, "spec_3_hidden", "1"}, {UNIMOD_DiART6plex117, "spec_3_position", "Protein N-term"}, {UNIMOD_DiART6plex117, "spec_3_site", "N-term"}, {UNIMOD_DiART6plex117, "spec_4_classification", "Isotopic label"}, {UNIMOD_DiART6plex117, "spec_4_hidden", "1"}, {UNIMOD_DiART6plex117, "spec_4_position", "Anywhere"}, {UNIMOD_DiART6plex117, "spec_4_site", "Y"}, {UNIMOD_DiART6plex118, "approved", "0"}, {UNIMOD_DiART6plex118, "delta_composition", "H(18) 2H(2) C(8) 13C(3) N(2) O(2)"}, {UNIMOD_DiART6plex118, "spec_1_classification", "Isotopic label"}, {UNIMOD_DiART6plex118, "spec_1_hidden", "1"}, {UNIMOD_DiART6plex118, "spec_1_position", "Anywhere"}, {UNIMOD_DiART6plex118, "spec_1_site", "K"}, {UNIMOD_DiART6plex118, "spec_2_classification", "Isotopic label"}, {UNIMOD_DiART6plex118, "spec_2_hidden", "1"}, {UNIMOD_DiART6plex118, "spec_2_position", "Any N-term"}, {UNIMOD_DiART6plex118, "spec_2_site", "N-term"}, {UNIMOD_DiART6plex118, "spec_3_classification", "Isotopic label"}, {UNIMOD_DiART6plex118, "spec_3_hidden", "1"}, {UNIMOD_DiART6plex118, "spec_3_position", "Protein N-term"}, {UNIMOD_DiART6plex118, "spec_3_site", "N-term"}, {UNIMOD_DiART6plex118, "spec_4_classification", "Isotopic label"}, {UNIMOD_DiART6plex118, "spec_4_hidden", "1"}, {UNIMOD_DiART6plex118, "spec_4_position", "Anywhere"}, {UNIMOD_DiART6plex118, "spec_4_site", "Y"}, {UNIMOD_Iodoacetanilide, "approved", "0"}, {UNIMOD_Iodoacetanilide, "delta_composition", "H(7) C(8) N O"}, {UNIMOD_Iodoacetanilide, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Iodoacetanilide, "spec_1_hidden", "1"}, {UNIMOD_Iodoacetanilide, "spec_1_position", "Anywhere"}, {UNIMOD_Iodoacetanilide, "spec_1_site", "C"}, {UNIMOD_Iodoacetanilide, "spec_2_classification", "Artefact"}, {UNIMOD_Iodoacetanilide, "spec_2_hidden", "1"}, {UNIMOD_Iodoacetanilide, "spec_2_position", "Anywhere"}, {UNIMOD_Iodoacetanilide, "spec_2_site", "K"}, {UNIMOD_Iodoacetanilide, "spec_3_classification", "Artefact"}, {UNIMOD_Iodoacetanilide, "spec_3_hidden", "1"}, {UNIMOD_Iodoacetanilide, "spec_3_position", "Any N-term"}, {UNIMOD_Iodoacetanilide, "spec_3_site", "N-term"}, {UNIMOD_Iodoacetanilide_13C_6_, "approved", "0"}, {UNIMOD_Iodoacetanilide_13C_6_, "delta_composition", "H(7) C(2) 13C(6) N O"}, {UNIMOD_Iodoacetanilide_13C_6_, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Iodoacetanilide_13C_6_, "spec_1_hidden", "1"}, {UNIMOD_Iodoacetanilide_13C_6_, "spec_1_position", "Anywhere"}, {UNIMOD_Iodoacetanilide_13C_6_, "spec_1_site", "C"}, {UNIMOD_Iodoacetanilide_13C_6_, "spec_2_classification", "Artefact"}, {UNIMOD_Iodoacetanilide_13C_6_, "spec_2_hidden", "1"}, {UNIMOD_Iodoacetanilide_13C_6_, "spec_2_position", "Anywhere"}, {UNIMOD_Iodoacetanilide_13C_6_, "spec_2_site", "K"}, {UNIMOD_Iodoacetanilide_13C_6_, "spec_3_classification", "Artefact"}, {UNIMOD_Iodoacetanilide_13C_6_, "spec_3_hidden", "1"}, {UNIMOD_Iodoacetanilide_13C_6_, "spec_3_position", "Any N-term"}, {UNIMOD_Iodoacetanilide_13C_6_, "spec_3_site", "N-term"}, {UNIMOD_Dap_DSP, "approved", "0"}, {UNIMOD_Dap_DSP, "delta_composition", "H(16) C(13) N(2) O(4) S(2)"}, {UNIMOD_Dap_DSP, "spec_1_classification", "Non-standard residue"}, {UNIMOD_Dap_DSP, "spec_1_hidden", "1"}, {UNIMOD_Dap_DSP, "spec_1_position", "Anywhere"}, {UNIMOD_Dap_DSP, "spec_1_site", "A"}, {UNIMOD_Dap_DSP, "spec_2_classification", "Non-standard residue"}, {UNIMOD_Dap_DSP, "spec_2_hidden", "1"}, {UNIMOD_Dap_DSP, "spec_2_position", "Anywhere"}, {UNIMOD_Dap_DSP, "spec_2_site", "E"}, {UNIMOD_Dap_DSP, "spec_3_classification", "Chemical derivative"}, {UNIMOD_Dap_DSP, "spec_3_hidden", "1"}, {UNIMOD_Dap_DSP, "spec_3_position", "Anywhere"}, {UNIMOD_Dap_DSP, "spec_3_site", "K"}, {UNIMOD_MurNAc, "approved", "0"}, {UNIMOD_MurNAc, "delta_composition", "O(-1) NeuAc"}, {UNIMOD_MurNAc, "spec_1_classification", "Other glycosylation"}, {UNIMOD_MurNAc, "spec_1_hidden", "1"}, {UNIMOD_MurNAc, "spec_1_position", "Anywhere"}, {UNIMOD_MurNAc, "spec_1_site", "A"}, {UNIMOD_Label_2H_7_15N_4_, "approved", "0"}, {UNIMOD_Label_2H_7_15N_4_, "delta_composition", "H(-7) 2H(7) N(-4) 15N(4)"}, {UNIMOD_Label_2H_7_15N_4_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_2H_7_15N_4_, "spec_1_hidden", "1"}, {UNIMOD_Label_2H_7_15N_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_2H_7_15N_4_, "spec_1_site", "R"}, {UNIMOD_Label_2H_6_15N_1_, "approved", "0"}, {UNIMOD_Label_2H_6_15N_1_, "delta_composition", "H(-6) 2H(6) N(-1) 15N"}, {UNIMOD_Label_2H_6_15N_1_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Label_2H_6_15N_1_, "spec_1_hidden", "1"}, {UNIMOD_Label_2H_6_15N_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Label_2H_6_15N_1_, "spec_1_site", "P"}, {UNIMOD_EEEDVIEVYQEQTGG, "approved", "0"}, {UNIMOD_EEEDVIEVYQEQTGG, "delta_composition", "H(107) C(72) N(17) O(31)"}, {UNIMOD_EEEDVIEVYQEQTGG, "spec_1_classification", "Chemical derivative"}, {UNIMOD_EEEDVIEVYQEQTGG, "spec_1_hidden", "1"}, {UNIMOD_EEEDVIEVYQEQTGG, "spec_1_position", "Anywhere"}, {UNIMOD_EEEDVIEVYQEQTGG, "spec_1_site", "K"}, {UNIMOD_EDEDTIDVFQQQTGG, "approved", "0"}, {UNIMOD_EDEDTIDVFQQQTGG, "delta_composition", "H(102) C(69) N(18) O(30)"}, {UNIMOD_EDEDTIDVFQQQTGG, "spec_1_classification", "Chemical derivative"}, {UNIMOD_EDEDTIDVFQQQTGG, "spec_1_hidden", "1"}, {UNIMOD_EDEDTIDVFQQQTGG, "spec_1_position", "Anywhere"}, {UNIMOD_EDEDTIDVFQQQTGG, "spec_1_site", "K"}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_2_, "approved", "0"}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_2_, "delta_composition", "Hex(5) HexNAc(4) NeuAc(2)"}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_2_, "spec_1_site", "N"}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_1_, "approved", "0"}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_1_, "delta_composition", "Hex(5) HexNAc(4) NeuAc"}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_NeuAc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_NeuAc_1_, "delta_composition", "dHex Hex(5) HexNAc(4) NeuAc"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_NeuAc_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_NeuAc_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_NeuAc_2_, "approved", "0"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_NeuAc_2_, "delta_composition", "dHex Hex(5) HexNAc(4) NeuAc(2)"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_NeuAc_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_NeuAc_2_, "spec_1_site", "N"}, {UNIMOD_s_GlcNAc, "approved", "0"}, {UNIMOD_s_GlcNAc, "delta_composition", "O(3) S HexNAc"}, {UNIMOD_s_GlcNAc, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_s_GlcNAc, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_s_GlcNAc, "spec_1_hidden", "1"}, {UNIMOD_s_GlcNAc, "spec_1_hidden", "1"}, {UNIMOD_s_GlcNAc, "spec_1_position", "Anywhere"}, {UNIMOD_s_GlcNAc, "spec_1_position", "Anywhere"}, {UNIMOD_s_GlcNAc, "spec_1_site", "T"}, {UNIMOD_s_GlcNAc, "spec_1_site", "S"}, {UNIMOD_PhosphoHex_2_, "approved", "0"}, {UNIMOD_PhosphoHex_2_, "delta_composition", "H O(3) P Hex(2)"}, {UNIMOD_PhosphoHex_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_PhosphoHex_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_PhosphoHex_2_, "spec_1_hidden", "1"}, {UNIMOD_PhosphoHex_2_, "spec_1_hidden", "1"}, {UNIMOD_PhosphoHex_2_, "spec_1_position", "Anywhere"}, {UNIMOD_PhosphoHex_2_, "spec_1_position", "Anywhere"}, {UNIMOD_PhosphoHex_2_, "spec_1_site", "T"}, {UNIMOD_PhosphoHex_2_, "spec_1_site", "S"}, {UNIMOD_PhosphoHex_2_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_PhosphoHex_2_, "spec_2_hidden", "1"}, {UNIMOD_PhosphoHex_2_, "spec_2_position", "Anywhere"}, {UNIMOD_PhosphoHex_2_, "spec_2_site", "N"}, {UNIMOD_Trimethyl_13C_3_2H_9_, "approved", "0"}, {UNIMOD_Trimethyl_13C_3_2H_9_, "delta_composition", "H(-3) 2H(9) 13C(3)"}, {UNIMOD_Trimethyl_13C_3_2H_9_, "spec_1_classification", "Isotopic label"}, {UNIMOD_Trimethyl_13C_3_2H_9_, "spec_1_hidden", "1"}, {UNIMOD_Trimethyl_13C_3_2H_9_, "spec_1_position", "Anywhere"}, {UNIMOD_Trimethyl_13C_3_2H_9_, "spec_1_site", "K"}, {UNIMOD_Trimethyl_13C_3_2H_9_, "spec_2_classification", "Isotopic label"}, {UNIMOD_Trimethyl_13C_3_2H_9_, "spec_2_hidden", "1"}, {UNIMOD_Trimethyl_13C_3_2H_9_, "spec_2_position", "Anywhere"}, {UNIMOD_Trimethyl_13C_3_2H_9_, "spec_2_site", "R"}, {UNIMOD_15N_oxobutanoic, "approved", "0"}, {UNIMOD_15N_oxobutanoic, "delta_composition", "H(-3) 15N(-1)"}, {UNIMOD_15N_oxobutanoic, "spec_1_classification", "Artefact"}, {UNIMOD_15N_oxobutanoic, "spec_1_hidden", "1"}, {UNIMOD_15N_oxobutanoic, "spec_1_position", "Any N-term"}, {UNIMOD_15N_oxobutanoic, "spec_1_site", "C"}, {UNIMOD_15N_oxobutanoic, "spec_2_classification", "Post-translational"}, {UNIMOD_15N_oxobutanoic, "spec_2_hidden", "1"}, {UNIMOD_15N_oxobutanoic, "spec_2_position", "Protein N-term"}, {UNIMOD_15N_oxobutanoic, "spec_2_site", "S"}, {UNIMOD_15N_oxobutanoic, "spec_3_classification", "Post-translational"}, {UNIMOD_15N_oxobutanoic, "spec_3_hidden", "1"}, {UNIMOD_15N_oxobutanoic, "spec_3_position", "Protein N-term"}, {UNIMOD_15N_oxobutanoic, "spec_3_site", "T"}, {UNIMOD_spermine, "approved", "0"}, {UNIMOD_spermine, "delta_composition", "H(23) C(10) N(3)"}, {UNIMOD_spermine, "spec_1_classification", "Chemical derivative"}, {UNIMOD_spermine, "spec_1_hidden", "1"}, {UNIMOD_spermine, "spec_1_position", "Anywhere"}, {UNIMOD_spermine, "spec_1_site", "Q"}, {UNIMOD_spermidine, "approved", "0"}, {UNIMOD_spermidine, "delta_composition", "H(16) C(7) N(2)"}, {UNIMOD_spermidine, "spec_1_classification", "Chemical derivative"}, {UNIMOD_spermidine, "spec_1_hidden", "1"}, {UNIMOD_spermidine, "spec_1_position", "Anywhere"}, {UNIMOD_spermidine, "spec_1_site", "Q"}, {UNIMOD_Biotin_Thermo_21330, "approved", "0"}, {UNIMOD_Biotin_Thermo_21330, "delta_composition", "H(35) C(21) N(3) O(7) S"}, {UNIMOD_Biotin_Thermo_21330, "spec_1_classification", "Chemical derivative"}, {UNIMOD_Biotin_Thermo_21330, "spec_1_hidden", "1"}, {UNIMOD_Biotin_Thermo_21330, "spec_1_position", "Anywhere"}, {UNIMOD_Biotin_Thermo_21330, "spec_1_site", "K"}, {UNIMOD_Biotin_Thermo_21330, "spec_2_classification", "Chemical derivative"}, {UNIMOD_Biotin_Thermo_21330, "spec_2_hidden", "1"}, {UNIMOD_Biotin_Thermo_21330, "spec_2_position", "Any N-term"}, {UNIMOD_Biotin_Thermo_21330, "spec_2_site", "N-term"}, {UNIMOD_Pentose, "approved", "0"}, {UNIMOD_Pentose, "delta_composition", "Pent"}, {UNIMOD_Pentose, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Pentose, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Pentose, "spec_1_hidden", "1"}, {UNIMOD_Pentose, "spec_1_hidden", "1"}, {UNIMOD_Pentose, "spec_1_position", "Anywhere"}, {UNIMOD_Pentose, "spec_1_position", "Anywhere"}, {UNIMOD_Pentose, "spec_1_site", "T"}, {UNIMOD_Pentose, "spec_1_site", "S"}, {UNIMOD_Hex_1_Pent_1_, "approved", "0"}, {UNIMOD_Hex_1_Pent_1_, "delta_composition", "Pent Hex"}, {UNIMOD_Hex_1_Pent_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_Pent_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_Pent_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_Pent_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexA_1_, "approved", "0"}, {UNIMOD_Hex_1_HexA_1_, "delta_composition", "Hex HexA"}, {UNIMOD_Hex_1_HexA_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexA_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexA_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexA_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexA_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexA_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexA_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexA_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_Pent_2_, "approved", "0"}, {UNIMOD_Hex_1_Pent_2_, "delta_composition", "Pent(2) Hex"}, {UNIMOD_Hex_1_Pent_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_Pent_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_Pent_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_Pent_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_Pent_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_Pent_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_Pent_2_, "spec_1_site", "T"}, {UNIMOD_Hex_1_Pent_2_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_1_Phos_1_, "approved", "1"}, {UNIMOD_Hex_1_HexNAc_1_Phos_1_, "delta_composition", "H O(3) P Hex HexNAc"}, {UNIMOD_Hex_1_HexNAc_1_Phos_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_Phos_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_Phos_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_Phos_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_Phos_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_Phos_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_Phos_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_Phos_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_1_Sulf_1_, "approved", "1"}, {UNIMOD_Hex_1_HexNAc_1_Sulf_1_, "delta_composition", "O(3) S Hex HexNAc"}, {UNIMOD_Hex_1_HexNAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_NeuAc_1_, "approved", "0"}, {UNIMOD_Hex_1_NeuAc_1_, "delta_composition", "Hex NeuAc"}, {UNIMOD_Hex_1_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_NeuGc_1_, "approved", "0"}, {UNIMOD_Hex_1_NeuGc_1_, "delta_composition", "Hex NeuGc"}, {UNIMOD_Hex_1_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_HexNAc_3_, "approved", "1"}, {UNIMOD_HexNAc_3_, "delta_composition", "HexNAc(3)"}, {UNIMOD_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_3_, "spec_1_site", "T"}, {UNIMOD_HexNAc_3_, "spec_1_site", "S"}, {UNIMOD_HexNAc_1_NeuAc_1_, "approved", "0"}, {UNIMOD_HexNAc_1_NeuAc_1_, "delta_composition", "HexNAc NeuAc"}, {UNIMOD_HexNAc_1_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_1_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_1_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_1_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_1_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_1_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_1_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_HexNAc_1_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_HexNAc_1_NeuGc_1_, "approved", "0"}, {UNIMOD_HexNAc_1_NeuGc_1_, "delta_composition", "HexNAc NeuGc"}, {UNIMOD_HexNAc_1_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_1_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_1_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_1_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_1_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_1_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_1_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_HexNAc_1_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_1_, "approved", "1"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_1_, "delta_composition", "Me dHex Hex HexNAc"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_2_, "approved", "1"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_2_, "delta_composition", "Me(2) dHex Hex HexNAc"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_2_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_2_, "spec_2_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_2_, "spec_2_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_2_, "spec_2_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_2_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_2_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_2_, "spec_2_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_2_, "spec_2_site", "S"}, {UNIMOD_Hex_2_HexNAc_1_, "approved", "1"}, {UNIMOD_Hex_2_HexNAc_1_, "delta_composition", "Hex(2) HexNAc"}, {UNIMOD_Hex_2_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexA_1_HexNAc_1_, "approved", "0"}, {UNIMOD_Hex_1_HexA_1_HexNAc_1_, "delta_composition", "Hex HexA HexNAc"}, {UNIMOD_Hex_1_HexA_1_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexA_1_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexA_1_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexA_1_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexA_1_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexA_1_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexA_1_HexNAc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexA_1_HexNAc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_1_Me_1_, "approved", "1"}, {UNIMOD_Hex_2_HexNAc_1_Me_1_, "delta_composition", "Me Hex(2) HexNAc"}, {UNIMOD_Hex_2_HexNAc_1_Me_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_1_Me_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_1_Me_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_1_Me_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_1_Me_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_1_Me_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_1_Me_1_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_1_Me_1_, "spec_1_site", "S"}, {UNIMOD_Hex_3_Phos_1_, "approved", "1"}, {UNIMOD_Hex_3_Phos_1_, "delta_composition", "H O(3) P Hex(3)"}, {UNIMOD_Hex_3_Phos_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_Phos_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_Phos_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_Phos_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_Phos_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_Phos_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_Phos_1_, "spec_1_site", "T"}, {UNIMOD_Hex_3_Phos_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_NeuAc_1_Pent_1_, "approved", "0"}, {UNIMOD_Hex_1_NeuAc_1_Pent_1_, "delta_composition", "Pent Hex NeuAc"}, {UNIMOD_Hex_1_NeuAc_1_Pent_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_NeuAc_1_Pent_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_NeuAc_1_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_NeuAc_1_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_NeuAc_1_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_NeuAc_1_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_NeuAc_1_Pent_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_NeuAc_1_Pent_1_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_1_Sulf_1_, "approved", "1"}, {UNIMOD_Hex_2_HexNAc_1_Sulf_1_, "delta_composition", "O(3) S Hex(2) HexNAc"}, {UNIMOD_Hex_2_HexNAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_Hex_2_NeuAc_1_, "approved", "0"}, {UNIMOD_Hex_2_NeuAc_1_, "delta_composition", "Hex(2) NeuAc"}, {UNIMOD_Hex_2_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_2_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_2_, "approved", "0"}, {UNIMOD_dHex_2_Hex_2_, "delta_composition", "dHex(2) Hex(2)"}, {UNIMOD_dHex_2_Hex_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_2_HexA_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexA_1_, "delta_composition", "dHex Hex(2) HexA"}, {UNIMOD_dHex_1_Hex_2_HexA_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexA_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexA_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexA_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexA_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexA_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexA_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexA_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_2_Sulf_1_, "approved", "1"}, {UNIMOD_Hex_1_HexNAc_2_Sulf_1_, "delta_composition", "O(3) S Hex HexNAc(2)"}, {UNIMOD_Hex_1_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_2_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_Hex_4_, "approved", "0"}, {UNIMOD_Hex_4_, "delta_composition", "Hex(4)"}, {UNIMOD_Hex_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_, "spec_1_site", "S"}, {UNIMOD_Hex_4_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_Pent_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_Pent_1_, "delta_composition", "dHex(1) Hex(2) HexNAc(2) Pent(1)"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_Pent_1_, "spec_1_site", "N"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_1_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_1_, "delta_composition", "Hex(2) HexNAc(2) NeuAc(1)"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_1_, "spec_1_site", "N"}, {UNIMOD_Hex_3_HexNAc_2_Pent_1_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_2_Pent_1_, "delta_composition", "Hex(3) HexNAc(2) Pent(1)"}, {UNIMOD_Hex_3_HexNAc_2_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_2_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_2_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_2_Pent_1_, "spec_1_site", "N"}, {UNIMOD_Hex_4_HexNAc_2_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_2_, "delta_composition", "Hex(4) HexNAc(2)"}, {UNIMOD_Hex_4_HexNAc_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_2_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_4_HexNAc_1_Pent_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_4_HexNAc_1_Pent_1_, "delta_composition", "dHex(1) Hex(4) HexNAc(1) Pent(1)"}, {UNIMOD_dHex_1_Hex_4_HexNAc_1_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_1_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_1_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_1_Pent_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Pent_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Pent_1_, "delta_composition", "dHex(1) Hex(3) HexNAc(2) Pent(1)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Pent_1_, "spec_1_site", "N"}, {UNIMOD_Hex_3_HexNAc_2_NeuAc_1_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_2_NeuAc_1_, "delta_composition", "Hex(3) HexNAc(2) NeuAc(1)"}, {UNIMOD_Hex_3_HexNAc_2_NeuAc_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_2_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_2_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_2_NeuAc_1_, "spec_1_site", "N"}, {UNIMOD_Hex_4_HexNAc_2_Pent_1_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_2_Pent_1_, "delta_composition", "Hex(4) HexNAc(2) Pent(1)"}, {UNIMOD_Hex_4_HexNAc_2_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_2_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_2_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_2_Pent_1_, "spec_1_site", "N"}, {UNIMOD_Hex_3_HexNAc_3_Pent_1_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_3_Pent_1_, "delta_composition", "Hex(3) HexNAc(3) Pent(1)"}, {UNIMOD_Hex_3_HexNAc_3_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_3_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_3_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_3_Pent_1_, "spec_1_site", "N"}, {UNIMOD_Hex_5_HexNAc_2_Phos_1_, "approved", "0"}, {UNIMOD_Hex_5_HexNAc_2_Phos_1_, "delta_composition", "H O(3) P Hex(5) HexNAc(2)"}, {UNIMOD_Hex_5_HexNAc_2_Phos_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_5_HexNAc_2_Phos_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_HexNAc_2_Phos_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_HexNAc_2_Phos_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_Pent_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_Pent_1_, "delta_composition", "dHex(1) Hex(4) HexNAc(2) Pent(1)"}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_Pent_1_, "spec_1_site", "N"}, {UNIMOD_Hex_7_HexNAc_1_, "approved", "0"}, {UNIMOD_Hex_7_HexNAc_1_, "delta_composition", "Hex(7) HexNAc(1)"}, {UNIMOD_Hex_7_HexNAc_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_7_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_7_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_7_HexNAc_1_, "spec_1_site", "N"}, {UNIMOD_Hex_4_HexNAc_2_NeuAc_1_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_2_NeuAc_1_, "delta_composition", "Hex(4) HexNAc(2) NeuAc(1)"}, {UNIMOD_Hex_4_HexNAc_2_NeuAc_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_2_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_2_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_2_NeuAc_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_5_HexNAc_2_, "approved", "0"}, {UNIMOD_dHex_1_Hex_5_HexNAc_2_, "delta_composition", "dHex(1) Hex(5) HexNAc(2)"}, {UNIMOD_dHex_1_Hex_5_HexNAc_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_5_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_5_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_5_HexNAc_2_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_1_, "delta_composition", "dHex(1) Hex(3) HexNAc(3) Pent(1)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_1_, "spec_1_site", "N"}, {UNIMOD_Hex_3_HexNAc_4_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_4_Sulf_1_, "delta_composition", "O(3) S Hex(3) HexNAc(4)"}, {UNIMOD_Hex_3_HexNAc_4_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_4_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_4_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_4_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_Hex_6_HexNAc_2_, "approved", "0"}, {UNIMOD_Hex_6_HexNAc_2_, "delta_composition", "Hex(6) HexNAc(2)"}, {UNIMOD_Hex_6_HexNAc_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_6_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_6_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_6_HexNAc_2_, "spec_1_site", "N"}, {UNIMOD_Hex_4_HexNAc_3_Pent_1_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_3_Pent_1_, "delta_composition", "Hex(4) HexNAc(3) Pent(1)"}, {UNIMOD_Hex_4_HexNAc_3_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_3_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_3_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_3_Pent_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_, "approved", "0"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_, "delta_composition", "dHex(1) Hex(4) HexNAc(3)"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_, "spec_1_site", "N"}, {UNIMOD_Hex_5_HexNAc_3_, "approved", "0"}, {UNIMOD_Hex_5_HexNAc_3_, "delta_composition", "Hex(5) HexNAc(3)"}, {UNIMOD_Hex_5_HexNAc_3_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_5_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_HexNAc_3_, "spec_1_site", "N"}, {UNIMOD_Hex_3_HexNAc_4_Pent_1_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_4_Pent_1_, "delta_composition", "Hex(3) HexNAc(4) Pent(1)"}, {UNIMOD_Hex_3_HexNAc_4_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_4_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_4_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_4_Pent_1_, "spec_1_site", "N"}, {UNIMOD_Hex_6_HexNAc_2_Phos_1_, "approved", "0"}, {UNIMOD_Hex_6_HexNAc_2_Phos_1_, "delta_composition", "H O(3) P Hex(6) HexNAc(2)"}, {UNIMOD_Hex_6_HexNAc_2_Phos_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_6_HexNAc_2_Phos_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_6_HexNAc_2_Phos_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_6_HexNAc_2_Phos_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_Sulf_1_, "delta_composition", "O(3) S dHex Hex(4) HexNAc(3)"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_5_HexNAc_2_Pent_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_5_HexNAc_2_Pent_1_, "delta_composition", "dHex(1) Hex(5) HexNAc(2) Pent(1)"}, {UNIMOD_dHex_1_Hex_5_HexNAc_2_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_5_HexNAc_2_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_5_HexNAc_2_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_5_HexNAc_2_Pent_1_, "spec_1_site", "N"}, {UNIMOD_Hex_8_HexNAc_1_, "approved", "0"}, {UNIMOD_Hex_8_HexNAc_1_, "delta_composition", "Hex(8) HexNAc(1)"}, {UNIMOD_Hex_8_HexNAc_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_8_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_8_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_8_HexNAc_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_2_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_2_, "delta_composition", "dHex(1) Hex(3) HexNAc(3) Pent(2)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_2_, "spec_1_site", "N"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_Pent_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_Pent_1_, "delta_composition", "dHex(2) Hex(3) HexNAc(3) Pent(1)"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_Pent_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Sulf_1_, "delta_composition", "O(3) S dHex Hex(3) HexNAc(4)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_6_HexNAc_2_, "approved", "0"}, {UNIMOD_dHex_1_Hex_6_HexNAc_2_, "delta_composition", "dHex(1) Hex(6) HexNAc(2)"}, {UNIMOD_dHex_1_Hex_6_HexNAc_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_6_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_6_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_6_HexNAc_2_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_Pent_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_Pent_1_, "delta_composition", "dHex(1) Hex(4) HexNAc(3) Pent(1)"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_Pent_1_, "spec_1_site", "N"}, {UNIMOD_Hex_4_HexNAc_4_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_4_Sulf_1_, "delta_composition", "O(3) S Hex(4) HexNAc(4)"}, {UNIMOD_Hex_4_HexNAc_4_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_4_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_4_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_4_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_Hex_7_HexNAc_2_, "approved", "0"}, {UNIMOD_Hex_7_HexNAc_2_, "delta_composition", "Hex(7) HexNAc(2)"}, {UNIMOD_Hex_7_HexNAc_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_7_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_7_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_7_HexNAc_2_, "spec_1_site", "N"}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_, "approved", "0"}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_, "delta_composition", "dHex(2) Hex(4) HexNAc(3)"}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_, "spec_1_site", "N"}, {UNIMOD_Hex_5_HexNAc_3_Pent_1_, "approved", "0"}, {UNIMOD_Hex_5_HexNAc_3_Pent_1_, "delta_composition", "Hex(5) HexNAc(3) Pent(1)"}, {UNIMOD_Hex_5_HexNAc_3_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_5_HexNAc_3_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_HexNAc_3_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_HexNAc_3_Pent_1_, "spec_1_site", "N"}, {UNIMOD_Hex_4_HexNAc_3_NeuGc_1_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_3_NeuGc_1_, "delta_composition", "Hex(4) HexNAc(3) NeuGc(1)"}, {UNIMOD_Hex_4_HexNAc_3_NeuGc_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_3_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_3_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_3_NeuGc_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_, "approved", "0"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_, "delta_composition", "dHex(1) Hex(5) HexNAc(3)"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_1_, "delta_composition", "dHex(1) Hex(3) HexNAc(4) Pent(1)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_1_, "spec_1_site", "N"}, {UNIMOD_Hex_3_HexNAc_5_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_5_Sulf_1_, "delta_composition", "O(3) S Hex(3) HexNAc(5)"}, {UNIMOD_Hex_3_HexNAc_5_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_5_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_5_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_5_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_Hex_6_HexNAc_3_, "approved", "0"}, {UNIMOD_Hex_6_HexNAc_3_, "delta_composition", "Hex(6) HexNAc(3)"}, {UNIMOD_Hex_6_HexNAc_3_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_6_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_6_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_6_HexNAc_3_, "spec_1_site", "N"}, {UNIMOD_Hex_3_HexNAc_4_NeuAc_1_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_4_NeuAc_1_, "delta_composition", "Hex(3) HexNAc(4) NeuAc(1)"}, {UNIMOD_Hex_3_HexNAc_4_NeuAc_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_4_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_4_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_4_NeuAc_1_, "spec_1_site", "N"}, {UNIMOD_Hex_4_HexNAc_4_Pent_1_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_4_Pent_1_, "delta_composition", "Hex(4) HexNAc(4) Pent(1)"}, {UNIMOD_Hex_4_HexNAc_4_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_4_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_4_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_4_Pent_1_, "spec_1_site", "N"}, {UNIMOD_Hex_7_HexNAc_2_Phos_1_, "approved", "0"}, {UNIMOD_Hex_7_HexNAc_2_Phos_1_, "delta_composition", "H O(3) P Hex(7) HexNAc(2)"}, {UNIMOD_Hex_7_HexNAc_2_Phos_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_7_HexNAc_2_Phos_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_7_HexNAc_2_Phos_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_7_HexNAc_2_Phos_1_, "spec_1_site", "N"}, {UNIMOD_Hex_4_HexNAc_4_Me_2_Pent_1_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_4_Me_2_Pent_1_, "delta_composition", "Hex(4) HexNAc(4) Me(2) Pent(1)"}, {UNIMOD_Hex_4_HexNAc_4_Me_2_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_4_Me_2_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_4_Me_2_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_4_Me_2_Pent_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_3_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_3_, "delta_composition", "dHex(1) Hex(3) HexNAc(3) Pent(3)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_3_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_3_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_Sulf_1_, "delta_composition", "O(3) S dHex Hex(5) HexNAc(3)"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_Pent_2_, "approved", "0"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_Pent_2_, "delta_composition", "dHex(2) Hex(3) HexNAc(3) Pent(2)"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_Pent_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_Pent_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_Pent_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_Pent_2_, "spec_1_site", "N"}, {UNIMOD_Hex_6_HexNAc_3_Phos_1_, "approved", "0"}, {UNIMOD_Hex_6_HexNAc_3_Phos_1_, "delta_composition", "H O(3) P Hex(6) HexNAc(3)"}, {UNIMOD_Hex_6_HexNAc_3_Phos_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_6_HexNAc_3_Phos_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_6_HexNAc_3_Phos_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_6_HexNAc_3_Phos_1_, "spec_1_site", "N"}, {UNIMOD_Hex_4_HexNAc_5_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_5_, "delta_composition", "Hex(4) HexNAc(5)"}, {UNIMOD_Hex_4_HexNAc_5_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_5_, "spec_1_site", "N"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_Pent_1_, "approved", "0"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_Pent_1_, "delta_composition", "dHex(3) Hex(3) HexNAc(3) Pent(1)"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_Pent_1_, "spec_1_site", "N"}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_Pent_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_Pent_1_, "delta_composition", "dHex(2) Hex(4) HexNAc(3) Pent(1)"}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_Pent_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_Sulf_1_, "delta_composition", "O(3) S dHex Hex(4) HexNAc(4)"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_7_HexNAc_2_, "approved", "0"}, {UNIMOD_dHex_1_Hex_7_HexNAc_2_, "delta_composition", "dHex(1) Hex(7) HexNAc(2)"}, {UNIMOD_dHex_1_Hex_7_HexNAc_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_7_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_7_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_7_HexNAc_2_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuAc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuAc_1_, "delta_composition", "dHex(1) Hex(4) HexNAc(3) NeuAc(1)"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuAc_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuAc_1_, "spec_1_site", "N"}, {UNIMOD_Hex_7_HexNAc_2_Phos_2_, "approved", "0"}, {UNIMOD_Hex_7_HexNAc_2_Phos_2_, "delta_composition", "H(2) O(6) P(2) Hex(7) HexNAc(2)"}, {UNIMOD_Hex_7_HexNAc_2_Phos_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_7_HexNAc_2_Phos_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_7_HexNAc_2_Phos_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_7_HexNAc_2_Phos_2_, "spec_1_site", "N"}, {UNIMOD_Hex_5_HexNAc_4_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_5_HexNAc_4_Sulf_1_, "delta_composition", "O(3) S Hex(5) HexNAc(4)"}, {UNIMOD_Hex_5_HexNAc_4_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_5_HexNAc_4_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_HexNAc_4_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_HexNAc_4_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_Hex_8_HexNAc_2_, "approved", "0"}, {UNIMOD_Hex_8_HexNAc_2_, "delta_composition", "Hex(8) HexNAc(2)"}, {UNIMOD_Hex_8_HexNAc_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_8_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_8_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_8_HexNAc_2_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_2_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_2_, "delta_composition", "dHex(1) Hex(3) HexNAc(4) Pent(2)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_2_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuGc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuGc_1_, "delta_composition", "dHex(1) Hex(4) HexNAc(3) NeuGc(1)"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuGc_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuGc_1_, "spec_1_site", "N"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_Pent_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_Pent_1_, "delta_composition", "dHex(2) Hex(3) HexNAc(4) Pent(1)"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_Pent_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_Sulf_1_, "delta_composition", "O(3) S dHex Hex(3) HexNAc(5)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_6_HexNAc_3_, "approved", "0"}, {UNIMOD_dHex_1_Hex_6_HexNAc_3_, "delta_composition", "dHex(1) Hex(6) HexNAc(3)"}, {UNIMOD_dHex_1_Hex_6_HexNAc_3_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_6_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_6_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_6_HexNAc_3_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_NeuAc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_NeuAc_1_, "delta_composition", "dHex(1) Hex(3) HexNAc(4) NeuAc(1)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_NeuAc_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_NeuAc_1_, "spec_1_site", "N"}, {UNIMOD_dHex_3_Hex_3_HexNAc_4_, "approved", "0"}, {UNIMOD_dHex_3_Hex_3_HexNAc_4_, "delta_composition", "dHex(3) Hex(3) HexNAc(4)"}, {UNIMOD_dHex_3_Hex_3_HexNAc_4_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_3_Hex_3_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_3_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_3_HexNAc_4_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_Pent_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_Pent_1_, "delta_composition", "dHex(1) Hex(4) HexNAc(4) Pent(1)"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_Pent_1_, "spec_1_site", "N"}, {UNIMOD_Hex_4_HexNAc_5_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_5_Sulf_1_, "delta_composition", "O(3) S Hex(4) HexNAc(5)"}, {UNIMOD_Hex_4_HexNAc_5_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_5_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_5_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_5_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_Hex_7_HexNAc_3_, "approved", "0"}, {UNIMOD_Hex_7_HexNAc_3_, "delta_composition", "Hex(7) HexNAc(3)"}, {UNIMOD_Hex_7_HexNAc_3_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_7_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_7_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_7_HexNAc_3_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuAc_1_Sulf_1_, "delta_composition", "O(3) S dHex Hex(4) HexNAc(3) NeuAc"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_Hex_5_HexNAc_4_Me_2_Pent_1_, "approved", "0"}, {UNIMOD_Hex_5_HexNAc_4_Me_2_Pent_1_, "delta_composition", "Hex(5) HexNAc(4) Me(2) Pent(1)"}, {UNIMOD_Hex_5_HexNAc_4_Me_2_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_5_HexNAc_4_Me_2_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_HexNAc_4_Me_2_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_HexNAc_4_Me_2_Pent_1_, "spec_1_site", "N"}, {UNIMOD_Hex_3_HexNAc_6_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_6_Sulf_1_, "delta_composition", "O(3) S Hex(3) HexNAc(6)"}, {UNIMOD_Hex_3_HexNAc_6_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_6_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_6_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_6_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_6_HexNAc_3_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_6_HexNAc_3_Sulf_1_, "delta_composition", "O(3) S dHex Hex(6) HexNAc(3)"}, {UNIMOD_dHex_1_Hex_6_HexNAc_3_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_6_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_6_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_6_HexNAc_3_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_4_HexNAc_5_, "approved", "0"}, {UNIMOD_dHex_1_Hex_4_HexNAc_5_, "delta_composition", "dHex(1) Hex(4) HexNAc(5)"}, {UNIMOD_dHex_1_Hex_4_HexNAc_5_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_5_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_5_HexA_1_HexNAc_3_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_5_HexA_1_HexNAc_3_Sulf_1_, "delta_composition", "O(3) S dHex Hex(5) HexA HexNAc(3)"}, {UNIMOD_dHex_1_Hex_5_HexA_1_HexNAc_3_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_5_HexA_1_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_5_HexA_1_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_5_HexA_1_HexNAc_3_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_Hex_7_HexNAc_3_Phos_1_, "approved", "0"}, {UNIMOD_Hex_7_HexNAc_3_Phos_1_, "delta_composition", "H O(3) P Hex(7) HexNAc(3)"}, {UNIMOD_Hex_7_HexNAc_3_Phos_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_7_HexNAc_3_Phos_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_7_HexNAc_3_Phos_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_7_HexNAc_3_Phos_1_, "spec_1_site", "N"}, {UNIMOD_Hex_6_HexNAc_4_Me_3_, "approved", "0"}, {UNIMOD_Hex_6_HexNAc_4_Me_3_, "delta_composition", "Hex(6) HexNAc(4) Me(3)"}, {UNIMOD_Hex_6_HexNAc_4_Me_3_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_6_HexNAc_4_Me_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_6_HexNAc_4_Me_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_6_HexNAc_4_Me_3_, "spec_1_site", "N"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_Sulf_1_, "delta_composition", "O(3) S dHex(2) Hex(4) HexNAc(4)"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_2_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_2_, "delta_composition", "Hex(4) HexNAc(3) NeuAc(2)"}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_2_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_3_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_3_, "delta_composition", "dHex(1) Hex(3) HexNAc(4) Pent(3)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_3_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_3_, "spec_1_site", "N"}, {UNIMOD_dHex_2_Hex_5_HexNAc_3_Pent_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_5_HexNAc_3_Pent_1_, "delta_composition", "dHex(2) Hex(5) HexNAc(3) Pent(1)"}, {UNIMOD_dHex_2_Hex_5_HexNAc_3_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_2_Hex_5_HexNAc_3_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_5_HexNAc_3_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_5_HexNAc_3_Pent_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Sulf_1_, "delta_composition", "O(3) S dHex Hex(5) HexNAc(4)"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_Pent_2_, "approved", "0"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_Pent_2_, "delta_composition", "dHex(2) Hex(3) HexNAc(4) Pent(2)"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_Pent_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_Pent_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_Pent_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_Pent_2_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuAc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuAc_1_, "delta_composition", "dHex(1) Hex(5) HexNAc(3) NeuAc(1)"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuAc_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuAc_1_, "spec_1_site", "N"}, {UNIMOD_Hex_3_HexNAc_6_Sulf_2_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_6_Sulf_2_, "delta_composition", "O(6) S(2) Hex(3) HexNAc(6)"}, {UNIMOD_Hex_3_HexNAc_6_Sulf_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_6_Sulf_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_6_Sulf_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_6_Sulf_2_, "spec_1_site", "N"}, {UNIMOD_Hex_9_HexNAc_2_, "approved", "0"}, {UNIMOD_Hex_9_HexNAc_2_, "delta_composition", "Hex(9) HexNAc(2)"}, {UNIMOD_Hex_9_HexNAc_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_9_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_9_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_9_HexNAc_2_, "spec_1_site", "N"}, {UNIMOD_Hex_4_HexNAc_6_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_6_, "delta_composition", "Hex(4) HexNAc(6)"}, {UNIMOD_Hex_4_HexNAc_6_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_6_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_6_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_6_, "spec_1_site", "N"}, {UNIMOD_dHex_3_Hex_3_HexNAc_4_Pent_1_, "approved", "0"}, {UNIMOD_dHex_3_Hex_3_HexNAc_4_Pent_1_, "delta_composition", "dHex(3) Hex(3) HexNAc(4) Pent(1)"}, {UNIMOD_dHex_3_Hex_3_HexNAc_4_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_3_Hex_3_HexNAc_4_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_3_HexNAc_4_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_3_HexNAc_4_Pent_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuGc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuGc_1_, "delta_composition", "dHex(1) Hex(5) HexNAc(3) NeuGc(1)"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuGc_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuGc_1_, "spec_1_site", "N"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_Pent_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_Pent_1_, "delta_composition", "dHex(2) Hex(4) HexNAc(4) Pent(1)"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_Pent_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_4_HexNAc_5_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_4_HexNAc_5_Sulf_1_, "delta_composition", "O(3) S dHex Hex(4) HexNAc(5)"}, {UNIMOD_dHex_1_Hex_4_HexNAc_5_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_5_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_5_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_5_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_, "approved", "0"}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_, "delta_composition", "dHex(1) Hex(7) HexNAc(3)"}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Pent_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Pent_1_, "delta_composition", "dHex(1) Hex(5) HexNAc(4) Pent(1)"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Pent_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_5_HexA_1_HexNAc_3_Sulf_2_, "approved", "0"}, {UNIMOD_dHex_1_Hex_5_HexA_1_HexNAc_3_Sulf_2_, "delta_composition", "O(6) S(2) dHex Hex(5) HexA HexNAc(3)"}, {UNIMOD_dHex_1_Hex_5_HexA_1_HexNAc_3_Sulf_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_5_HexA_1_HexNAc_3_Sulf_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_5_HexA_1_HexNAc_3_Sulf_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_5_HexA_1_HexNAc_3_Sulf_2_, "spec_1_site", "N"}, {UNIMOD_Hex_3_HexNAc_7_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_7_, "delta_composition", "Hex(3) HexNAc(7)"}, {UNIMOD_Hex_3_HexNAc_7_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_7_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_7_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_7_, "spec_1_site", "N"}, {UNIMOD_dHex_2_Hex_5_HexNAc_4_, "approved", "0"}, {UNIMOD_dHex_2_Hex_5_HexNAc_4_, "delta_composition", "dHex(2) Hex(5) HexNAc(4)"}, {UNIMOD_dHex_2_Hex_5_HexNAc_4_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_2_Hex_5_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_5_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_5_HexNAc_4_, "spec_1_site", "N"}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_NeuAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_NeuAc_1_Sulf_1_, "delta_composition", "O(3) S dHex(2) Hex(4) HexNAc(3) NeuAc"}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_4_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Sulf_2_, "approved", "0"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Sulf_2_, "delta_composition", "O(6) S(2) dHex Hex(5) HexNAc(4)"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Sulf_2_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Sulf_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Sulf_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Sulf_2_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Me_2_Pent_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Me_2_Pent_1_, "delta_composition", "dHex(1) Hex(5) HexNAc(4) Me(2) Pent(1)"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Me_2_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Me_2_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Me_2_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_5_HexNAc_4_Me_2_Pent_1_, "spec_1_site", "N"}, {UNIMOD_Hex_5_HexNAc_4_NeuGc_1_, "approved", "0"}, {UNIMOD_Hex_5_HexNAc_4_NeuGc_1_, "delta_composition", "Hex(5) HexNAc(4) NeuGc(1)"}, {UNIMOD_Hex_5_HexNAc_4_NeuGc_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_5_HexNAc_4_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_HexNAc_4_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_HexNAc_4_NeuGc_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_Sulf_1_, "delta_composition", "O(3) S dHex Hex(3) HexNAc(6)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_6_HexNAc_4_, "approved", "0"}, {UNIMOD_dHex_1_Hex_6_HexNAc_4_, "delta_composition", "dHex(1) Hex(6) HexNAc(4)"}, {UNIMOD_dHex_1_Hex_6_HexNAc_4_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_6_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_6_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_6_HexNAc_4_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuAc_1_Sulf_1_, "delta_composition", "O(3) S dHex Hex(5) HexNAc(3) NeuAc"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_Hex_7_HexNAc_4_, "approved", "0"}, {UNIMOD_Hex_7_HexNAc_4_, "delta_composition", "Hex(7) HexNAc(4)"}, {UNIMOD_Hex_7_HexNAc_4_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_7_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_Hex_7_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_7_HexNAc_4_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuGc_1_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuGc_1_Sulf_1_, "delta_composition", "O(3) S dHex Hex(5) HexNAc(3) NeuGc"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuGc_1_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuGc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuGc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuGc_1_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_Hex_4_HexNAc_5_NeuAc_1_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_5_NeuAc_1_, "delta_composition", "Hex(4) HexNAc(5) NeuAc(1)"}, {UNIMOD_Hex_4_HexNAc_5_NeuAc_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_5_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_5_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_5_NeuAc_1_, "spec_1_site", "N"}, {UNIMOD_Hex_6_HexNAc_4_Me_3_Pent_1_, "approved", "0"}, {UNIMOD_Hex_6_HexNAc_4_Me_3_Pent_1_, "delta_composition", "Hex(6) HexNAc(4) Me(3) Pent(1)"}, {UNIMOD_Hex_6_HexNAc_4_Me_3_Pent_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_6_HexNAc_4_Me_3_Pent_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_6_HexNAc_4_Me_3_Pent_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_6_HexNAc_4_Me_3_Pent_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_Sulf_1_, "delta_composition", "O(3) S dHex Hex(7) HexNAc(3)"}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_Phos_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_Phos_1_, "delta_composition", "H O(3) P dHex Hex(7) HexNAc(3)"}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_Phos_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_Phos_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_Phos_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_7_HexNAc_3_Phos_1_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_5_HexNAc_5_, "approved", "0"}, {UNIMOD_dHex_1_Hex_5_HexNAc_5_, "delta_composition", "dHex(1) Hex(5) HexNAc(5)"}, {UNIMOD_dHex_1_Hex_5_HexNAc_5_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_5_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_5_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_5_HexNAc_5_, "spec_1_site", "N"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_Sulf_1_, "delta_composition", "O(3) S dHex Hex(4) HexNAc(4) NeuAc"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_Sulf_1_, "delta_composition", "O(3) S dHex(3) Hex(4) HexNAc(4)"}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_Hex_3_HexNAc_7_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_7_Sulf_1_, "delta_composition", "O(3) S Hex(3) HexNAc(7)"}, {UNIMOD_Hex_3_HexNAc_7_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_7_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_7_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_7_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_Hex_6_HexNAc_5_, "approved", "0"}, {UNIMOD_Hex_6_HexNAc_5_, "delta_composition", "Hex(6) HexNAc(5)"}, {UNIMOD_Hex_6_HexNAc_5_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_6_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_Hex_6_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_6_HexNAc_5_, "spec_1_site", "N"}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_1_Sulf_1_, "delta_composition", "O(3) S Hex(5) HexNAc(4) NeuAc"}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_1_Sulf_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_HexNAc_4_NeuAc_1_Sulf_1_, "spec_1_site", "N"}, {UNIMOD_Hex_3_HexNAc_6_NeuAc_1_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_6_NeuAc_1_, "delta_composition", "Hex(3) HexNAc(6) NeuAc(1)"}, {UNIMOD_Hex_3_HexNAc_6_NeuAc_1_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_6_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_6_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_6_NeuAc_1_, "spec_1_site", "N"}, {UNIMOD_dHex_2_Hex_3_HexNAc_6_, "approved", "0"}, {UNIMOD_dHex_2_Hex_3_HexNAc_6_, "delta_composition", "dHex(2) Hex(3) HexNAc(6)"}, {UNIMOD_dHex_2_Hex_3_HexNAc_6_, "spec_1_classification", "N-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_6_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_6_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_6_, "spec_1_site", "N"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_1_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_1_, "delta_composition", "Hex(1) HexNAc(1) NeuGc(1)"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_, "delta_composition", "dHex(1) Hex(2) HexNAc(1)"}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_, "spec_1_site", "T"}, {UNIMOD_HexNAc_3_Sulf_1_, "approved", "0"}, {UNIMOD_HexNAc_3_Sulf_1_, "delta_composition", "O(3) S HexNAc(3)"}, {UNIMOD_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_3_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_HexNAc_3_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_Hex_3_HexNAc_1_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_1_, "delta_composition", "Hex(3) HexNAc(1)"}, {UNIMOD_Hex_3_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_3_HexNAc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_Kdn_1_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_1_Kdn_1_Sulf_1_, "delta_composition", "O(3) S Hex HexNAc Kdn"}, {UNIMOD_Hex_1_HexNAc_1_Kdn_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_Kdn_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_Kdn_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_Kdn_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_Kdn_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_Kdn_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_Kdn_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_Kdn_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_HexNAc_2_NeuAc_1_, "approved", "0"}, {UNIMOD_HexNAc_2_NeuAc_1_, "delta_composition", "HexNAc(2) NeuAc(1)"}, {UNIMOD_HexNAc_2_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_2_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_2_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_2_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_2_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_2_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_2_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_HexNAc_2_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_HexNAc_1_Kdn_2_, "approved", "0"}, {UNIMOD_HexNAc_1_Kdn_2_, "delta_composition", "HexNAc Kdn(2)"}, {UNIMOD_HexNAc_1_Kdn_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_1_Kdn_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_1_Kdn_2_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_1_Kdn_2_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_1_Kdn_2_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_1_Kdn_2_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_1_Kdn_2_, "spec_1_site", "T"}, {UNIMOD_HexNAc_1_Kdn_2_, "spec_1_site", "S"}, {UNIMOD_Hex_3_HexNAc_1_Me_1_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_1_Me_1_, "delta_composition", "Hex(3) HexNAc(1) Me(1)"}, {UNIMOD_Hex_3_HexNAc_1_Me_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_1_Me_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_1_Me_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_1_Me_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_1_Me_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_1_Me_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_1_Me_1_, "spec_1_site", "S"}, {UNIMOD_Hex_3_HexNAc_1_Me_1_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexA_1_Pent_1_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_2_HexA_1_Pent_1_Sulf_1_, "delta_composition", "O(3) S Pent Hex(2) HexA"}, {UNIMOD_Hex_2_HexA_1_Pent_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexA_1_Pent_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexA_1_Pent_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexA_1_Pent_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexA_1_Pent_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexA_1_Pent_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexA_1_Pent_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexA_1_Pent_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_HexNAc_2_NeuGc_1_, "approved", "0"}, {UNIMOD_HexNAc_2_NeuGc_1_, "delta_composition", "HexNAc(2) NeuGc(1)"}, {UNIMOD_HexNAc_2_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_2_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_2_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_2_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_2_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_2_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_2_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_HexNAc_2_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_4_Phos_1_, "approved", "0"}, {UNIMOD_Hex_4_Phos_1_, "delta_composition", "H O(3) P Hex(4)"}, {UNIMOD_Hex_4_Phos_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_Phos_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_Phos_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_Phos_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_Phos_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_Phos_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_Phos_1_, "spec_1_site", "T"}, {UNIMOD_Hex_4_Phos_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Sulf_1_, "delta_composition", "O(3) S Hex HexNAc NeuAc"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexA_1_HexNAc_2_, "approved", "0"}, {UNIMOD_Hex_1_HexA_1_HexNAc_2_, "delta_composition", "Hex(1) HexA(1) HexNAc(2)"}, {UNIMOD_Hex_1_HexA_1_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexA_1_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexA_1_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexA_1_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexA_1_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexA_1_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexA_1_HexNAc_2_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexA_1_HexNAc_2_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_Sulf_1_, "delta_composition", "O(3) S dHex Hex(2) HexNAc"}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_2_HexNAc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_HexNAc_3_, "approved", "0"}, {UNIMOD_dHex_1_HexNAc_3_, "delta_composition", "dHex(1) HexNAc(3)"}, {UNIMOD_dHex_1_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_HexNAc_3_, "spec_1_site", "S"}, {UNIMOD_dHex_1_HexNAc_3_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_Kdn_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_Kdn_1_, "delta_composition", "dHex Hex HexNAc Kdn"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_Kdn_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_Kdn_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_3_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_3_, "delta_composition", "Hex(1) HexNAc(3)"}, {UNIMOD_Hex_1_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_3_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_3_, "spec_1_site", "T"}, {UNIMOD_HexNAc_2_NeuAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_HexNAc_2_NeuAc_1_Sulf_1_, "delta_composition", "O(3) S HexNAc(2) NeuAc"}, {UNIMOD_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_3_, "approved", "0"}, {UNIMOD_dHex_2_Hex_3_, "delta_composition", "dHex(2) Hex(3)"}, {UNIMOD_dHex_2_Hex_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_3_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "delta_composition", "O(3) S Hex(2) HexA HexNAc"}, {UNIMOD_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexA_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_2_HexA_1_, "delta_composition", "dHex(2) Hex(2) HexA(1)"}, {UNIMOD_dHex_2_Hex_2_HexA_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexA_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexA_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexA_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexA_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexA_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexA_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexA_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Sulf_1_, "delta_composition", "O(3) S dHex Hex HexNAc(2)"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuAc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuAc_1_, "delta_composition", "dHex(1) Hex(1) HexNAc(1) NeuAc(1)"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_2_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_2_Sulf_1_, "delta_composition", "O(3) S Hex(2) HexNAc(2)"}, {UNIMOD_Hex_2_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_2_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_2_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_Hex_5_, "approved", "0"}, {UNIMOD_Hex_5_, "delta_composition", "Hex(5)"}, {UNIMOD_Hex_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_5_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_, "spec_1_site", "S"}, {UNIMOD_Hex_5_, "spec_1_site", "T"}, {UNIMOD_HexNAc_4_, "approved", "0"}, {UNIMOD_HexNAc_4_, "delta_composition", "HexNAc(4)"}, {UNIMOD_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_4_, "spec_1_site", "S"}, {UNIMOD_HexNAc_4_, "spec_1_site", "T"}, {UNIMOD_HexNAc_1_NeuGc_2_, "approved", "0"}, {UNIMOD_HexNAc_1_NeuGc_2_, "delta_composition", "HexNAc(1) NeuGc(2)"}, {UNIMOD_HexNAc_1_NeuGc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_1_NeuGc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_1_NeuGc_2_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_1_NeuGc_2_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_1_NeuGc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_1_NeuGc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_1_NeuGc_2_, "spec_1_site", "S"}, {UNIMOD_HexNAc_1_NeuGc_2_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuGc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuGc_1_, "delta_composition", "dHex(1) Hex(1) HexNAc(1) NeuGc(1)"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_2_HexNAc_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_2_HexNAc_1_, "delta_composition", "dHex(2) Hex(2) HexNAc(1)"}, {UNIMOD_dHex_2_Hex_2_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexNAc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_1_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_1_, "delta_composition", "Hex(2) HexNAc(1) NeuGc(1)"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_, "delta_composition", "dHex(1) Hex(3) HexNAc(1)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_, "delta_composition", "dHex(1) Hex(2) HexA(1) HexNAc(1)"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_3_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_3_Sulf_1_, "delta_composition", "O(3) S Hex HexNAc(3)"}, {UNIMOD_Hex_1_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_3_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_3_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_Hex_4_HexNAc_1_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_1_, "delta_composition", "Hex(4) HexNAc(1)"}, {UNIMOD_Hex_4_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_4_HexNAc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_, "delta_composition", "Hex(1) HexNAc(2) NeuAc(1)"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_2_NeuGc_1_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_2_NeuGc_1_, "delta_composition", "Hex(1) HexNAc(2) NeuGc(1)"}, {UNIMOD_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_5_Phos_1_, "approved", "0"}, {UNIMOD_Hex_5_Phos_1_, "delta_composition", "H O(3) P Hex(5)"}, {UNIMOD_Hex_5_Phos_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_5_Phos_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_5_Phos_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_Phos_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_Phos_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_Phos_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_Phos_1_, "spec_1_site", "T"}, {UNIMOD_Hex_5_Phos_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_1_HexNAc_1_Kdn_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_1_HexNAc_1_Kdn_1_, "delta_composition", "dHex(2) Hex HexNAc Kdn"}, {UNIMOD_dHex_2_Hex_1_HexNAc_1_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_1_HexNAc_1_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_1_HexNAc_1_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_1_HexNAc_1_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_1_HexNAc_1_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_1_HexNAc_1_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_1_HexNAc_1_Kdn_1_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_1_HexNAc_1_Kdn_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_Sulf_1_, "delta_composition", "O(3) S dHex Hex(3) HexNAc"}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_3_HexNAc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_, "approved", "0"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_, "delta_composition", "dHex(1) Hex(1) HexNAc(3)"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "delta_composition", "O(3) S dHex Hex(2) HexA HexNAc"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_3_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_3_, "delta_composition", "Hex(2) HexNAc(3)"}, {UNIMOD_Hex_2_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_3_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_3_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "delta_composition", "O(3) S Hex HexNAc(2) NeuAc"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_4_, "approved", "0"}, {UNIMOD_dHex_2_Hex_4_, "delta_composition", "dHex(2) Hex(4)"}, {UNIMOD_dHex_2_Hex_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_4_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_4_, "spec_1_site", "T"}, {UNIMOD_dHex_2_HexNAc_2_Kdn_1_, "approved", "0"}, {UNIMOD_dHex_2_HexNAc_2_Kdn_1_, "delta_composition", "dHex(2) HexNAc(2) Kdn"}, {UNIMOD_dHex_2_HexNAc_2_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_HexNAc_2_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_HexNAc_2_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_HexNAc_2_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_HexNAc_2_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_HexNAc_2_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_HexNAc_2_Kdn_1_, "spec_1_site", "T"}, {UNIMOD_dHex_2_HexNAc_2_Kdn_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_Sulf_1_, "delta_composition", "O(3) S dHex Hex(2) HexNAc(2)"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_HexNAc_4_, "approved", "0"}, {UNIMOD_dHex_1_HexNAc_4_, "delta_composition", "dHex(1) HexNAc(4)"}, {UNIMOD_dHex_1_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_HexNAc_4_, "spec_1_site", "S"}, {UNIMOD_dHex_1_HexNAc_4_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_NeuGc_1_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_NeuGc_1_, "delta_composition", "Hex(1) HexNAc(1) NeuAc(1) NeuGc(1)"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Kdn_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Kdn_1_, "delta_composition", "dHex Hex HexNAc(2) Kdn"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Kdn_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_Kdn_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_2_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_2_, "delta_composition", "Hex(1) HexNAc(1) NeuGc(2)"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_2_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_2_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_1_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_1_, "delta_composition", "Ac Hex HexNAc NeuAc(2)"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_1_, "delta_composition", "dHex(2) Hex(2) HexA(1) HexNAc(1)"}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_Sulf_1_, "delta_composition", "O(3) S dHex Hex HexNAc(3)"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexA_1_NeuAc_1_Pent_1_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_2_HexA_1_NeuAc_1_Pent_1_Sulf_1_, "delta_composition", "O(3) S Pent Hex(2) HexA NeuAc"}, {UNIMOD_Hex_2_HexA_1_NeuAc_1_Pent_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexA_1_NeuAc_1_Pent_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexA_1_NeuAc_1_Pent_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexA_1_NeuAc_1_Pent_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexA_1_NeuAc_1_Pent_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexA_1_NeuAc_1_Pent_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexA_1_NeuAc_1_Pent_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexA_1_NeuAc_1_Pent_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_, "delta_composition", "dHex(1) Hex(1) HexNAc(2) NeuAc(1)"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_, "delta_composition", "dHex(1) Hex(3) HexA(1) HexNAc(1)"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_3_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_3_Sulf_1_, "delta_composition", "O(3) S Hex(2) HexNAc(3)"}, {UNIMOD_Hex_2_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_3_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_3_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_Hex_5_HexNAc_1_, "approved", "0"}, {UNIMOD_Hex_5_HexNAc_1_, "delta_composition", "Hex(5) HexNAc(1)"}, {UNIMOD_Hex_5_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_5_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_5_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_HexNAc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_5_HexNAc_1_, "spec_1_site", "T"}, {UNIMOD_HexNAc_5_, "approved", "0"}, {UNIMOD_HexNAc_5_, "delta_composition", "HexNAc(5)"}, {UNIMOD_HexNAc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_HexNAc_5_, "spec_1_site", "S"}, {UNIMOD_HexNAc_5_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuGc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuGc_1_, "delta_composition", "dHex(1) Hex(1) HexNAc(2) NeuGc(1)"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_2_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_2_, "delta_composition", "Ac(2) Hex HexNAc NeuAc(2)"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_2_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_2_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_2_NeuGc_1_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_2_NeuGc_1_, "delta_composition", "Hex(2) HexNAc(2) NeuGc(1)"}, {UNIMOD_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_5_Phos_3_, "approved", "0"}, {UNIMOD_Hex_5_Phos_3_, "delta_composition", "H(3) O(9) P(3) Hex(5)"}, {UNIMOD_Hex_5_Phos_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_5_Phos_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_5_Phos_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_Phos_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_Phos_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_Phos_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_Phos_3_, "spec_1_site", "T"}, {UNIMOD_Hex_5_Phos_3_, "spec_1_site", "S"}, {UNIMOD_Hex_6_Phos_1_, "approved", "0"}, {UNIMOD_Hex_6_Phos_1_, "delta_composition", "H O(3) P Hex(6)"}, {UNIMOD_Hex_6_Phos_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_6_Phos_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_6_Phos_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_6_Phos_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_6_Phos_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_6_Phos_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_6_Phos_1_, "spec_1_site", "T"}, {UNIMOD_Hex_6_Phos_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_2_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_2_, "delta_composition", "dHex(1) Hex(2) HexA(1) HexNAc(2)"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_2_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_2_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_3_HexNAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_3_HexNAc_1_Sulf_1_, "delta_composition", "O(3) S dHex(2) Hex(3) HexNAc"}, {UNIMOD_dHex_2_Hex_3_HexNAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_3_HexNAc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_1_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_1_, "delta_composition", "Hex(1) HexNAc(3) NeuAc(1)"}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_1_HexNAc_3_, "approved", "0"}, {UNIMOD_dHex_2_Hex_1_HexNAc_3_, "delta_composition", "dHex(2) Hex(1) HexNAc(3)"}, {UNIMOD_dHex_2_Hex_1_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_1_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_1_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_1_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_1_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_1_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_1_HexNAc_3_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_1_HexNAc_3_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_3_NeuGc_1_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_3_NeuGc_1_, "delta_composition", "Hex(1) HexNAc(3) NeuGc(1)"}, {UNIMOD_Hex_1_HexNAc_3_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_3_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_3_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_3_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_3_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_3_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_3_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_3_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "delta_composition", "O(3) S dHex Hex HexNAc(2) NeuAc"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "delta_composition", "O(3) S dHex Hex(3) HexA HexNAc"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_1_HexA_1_HexNAc_3_, "approved", "0"}, {UNIMOD_dHex_1_Hex_1_HexA_1_HexNAc_3_, "delta_composition", "dHex(1) Hex(1) HexA(1) HexNAc(3)"}, {UNIMOD_dHex_1_Hex_1_HexA_1_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexA_1_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexA_1_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexA_1_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexA_1_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexA_1_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexA_1_HexNAc_3_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_1_HexA_1_HexNAc_3_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "delta_composition", "O(3) S Hex(2) HexNAc(2) NeuAc"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_1_, "delta_composition", "O(3) S dHex(2) Hex(2) HexNAc(2)"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_Kdn_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_Kdn_1_, "delta_composition", "dHex(2) Hex HexNAc(2) Kdn"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_Kdn_1_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_Kdn_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_1_HexNAc_4_, "approved", "0"}, {UNIMOD_dHex_1_Hex_1_HexNAc_4_, "delta_composition", "dHex(1) Hex(1) HexNAc(4)"}, {UNIMOD_dHex_1_Hex_1_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_4_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_1_HexNAc_4_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_4_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_4_, "delta_composition", "Hex(2) HexNAc(4)"}, {UNIMOD_Hex_2_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_4_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_4_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_2_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_2_, "delta_composition", "Hex(2) HexNAc(1) NeuGc(2)"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_2_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_2_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_4_HexNAc_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_4_HexNAc_1_, "delta_composition", "dHex(2) Hex(4) HexNAc(1)"}, {UNIMOD_dHex_2_Hex_4_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_4_HexNAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_4_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_4_HexNAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_4_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_4_HexNAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_4_HexNAc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_4_HexNAc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_, "delta_composition", "Hex(1) HexNAc(2) NeuAc(2)"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuAc_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuAc_1_, "delta_composition", "dHex(2) Hex(1) HexNAc(2) NeuAc(1)"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_Sulf_1_, "delta_composition", "O(3) S dHex Hex(2) HexNAc(3)"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_HexNAc_5_, "approved", "0"}, {UNIMOD_dHex_1_HexNAc_5_, "delta_composition", "dHex(1) HexNAc(5)"}, {UNIMOD_dHex_1_HexNAc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_HexNAc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_HexNAc_5_, "spec_1_site", "S"}, {UNIMOD_dHex_1_HexNAc_5_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuGc_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuGc_1_, "delta_composition", "dHex(2) Hex(1) HexNAc(2) NeuGc(1)"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_, "approved", "0"}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_, "delta_composition", "dHex(3) Hex(2) HexNAc(2)"}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_, "spec_1_site", "S"}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_, "spec_1_site", "T"}, {UNIMOD_Hex_3_HexNAc_3_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_3_Sulf_1_, "delta_composition", "O(3) S Hex(3) HexNAc(3)"}, {UNIMOD_Hex_3_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_3_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_Hex_3_HexNAc_3_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_2_, "approved", "0"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_2_, "delta_composition", "O(6) S(2) dHex(2) Hex(2) HexNAc(2)"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_2_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_2_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_1_, "delta_composition", "dHex(1) Hex(2) HexNAc(2) NeuGc(1)"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_, "delta_composition", "dHex(1) Hex(1) HexNAc(3) NeuAc(1)"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_6_Phos_3_, "approved", "0"}, {UNIMOD_Hex_6_Phos_3_, "delta_composition", "H(3) O(9) P(3) Hex(6)"}, {UNIMOD_Hex_6_Phos_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_6_Phos_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_6_Phos_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_6_Phos_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_6_Phos_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_6_Phos_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_6_Phos_3_, "spec_1_site", "T"}, {UNIMOD_Hex_6_Phos_3_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_, "delta_composition", "dHex(1) Hex(3) HexA(1) HexNAc(2)"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuGc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuGc_1_, "delta_composition", "dHex(1) Hex(1) HexNAc(3) NeuGc(1)"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_Sulf_1_, "delta_composition", "O(3) S Hex HexNAc(2) NeuAc(2)"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "delta_composition", "O(3) S dHex(2) Hex(3) HexA HexNAc"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_3_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_3_, "delta_composition", "Hex(1) HexNAc(1) NeuAc(3)"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_3_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_3_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_1_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_1_, "delta_composition", "Hex(2) HexNAc(3) NeuGc(1)"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "delta_composition", "O(3) S dHex Hex(2) HexNAc(2) NeuAc"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_3_Hex_1_HexNAc_2_Kdn_1_, "approved", "0"}, {UNIMOD_dHex_3_Hex_1_HexNAc_2_Kdn_1_, "delta_composition", "dHex(3) Hex HexNAc(2) Kdn"}, {UNIMOD_dHex_3_Hex_1_HexNAc_2_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_1_HexNAc_2_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_1_HexNAc_2_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_1_HexNAc_2_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_1_HexNAc_2_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_1_HexNAc_2_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_1_HexNAc_2_Kdn_1_, "spec_1_site", "T"}, {UNIMOD_dHex_3_Hex_1_HexNAc_2_Kdn_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_Sulf_1_, "delta_composition", "O(3) S dHex(2) Hex(3) HexNAc(2)"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Kdn_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Kdn_1_, "delta_composition", "dHex(2) Hex(2) HexNAc(2) Kdn"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Kdn_1_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_Kdn_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "delta_composition", "O(3) S dHex(2) Hex(2) HexA HexNAc(2)"}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_, "delta_composition", "dHex(1) Hex(2) HexNAc(4)"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_3_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_3_, "delta_composition", "Hex(1) HexNAc(1) NeuGc(3)"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_3_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_3_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_Sulf_1_, "delta_composition", "O(3) S dHex Hex HexNAc(3) NeuAc"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "delta_composition", "O(3) S dHex Hex(3) HexA HexNAc(2)"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_2_, "approved", "0"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_2_, "delta_composition", "dHex(1) Hex(1) HexNAc(2) NeuAc(2)"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_2_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_2_, "spec_1_site", "T"}, {UNIMOD_dHex_3_HexNAc_3_Kdn_1_, "approved", "0"}, {UNIMOD_dHex_3_HexNAc_3_Kdn_1_, "delta_composition", "dHex(3) HexNAc(3) Kdn"}, {UNIMOD_dHex_3_HexNAc_3_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_HexNAc_3_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_HexNAc_3_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_HexNAc_3_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_HexNAc_3_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_HexNAc_3_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_HexNAc_3_Kdn_1_, "spec_1_site", "T"}, {UNIMOD_dHex_3_HexNAc_3_Kdn_1_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "delta_composition", "O(3) S Hex(2) HexNAc(3) NeuAc"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_Sulf_1_, "delta_composition", "O(3) S dHex(2) Hex(2) HexNAc(3)"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_HexNAc_5_, "approved", "0"}, {UNIMOD_dHex_2_HexNAc_5_, "delta_composition", "dHex(2) HexNAc(5)"}, {UNIMOD_dHex_2_HexNAc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_HexNAc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_HexNAc_5_, "spec_1_site", "S"}, {UNIMOD_dHex_2_HexNAc_5_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_, "delta_composition", "Hex(2) HexNAc(2) NeuAc(2)"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_, "delta_composition", "dHex(2) Hex(2) HexNAc(2) NeuAc(1)"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Sulf_1_, "delta_composition", "O(3) S dHex Hex(3) HexNAc(3)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuGc_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuGc_1_, "delta_composition", "dHex(2) Hex(2) HexNAc(2) NeuGc(1)"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_5_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_5_, "delta_composition", "Hex(2) HexNAc(5)"}, {UNIMOD_Hex_2_HexNAc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_5_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_5_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_NeuGc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_NeuGc_1_, "delta_composition", "dHex(1) Hex(3) HexNAc(2) NeuGc(1)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_2_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_2_, "delta_composition", "Hex(1) HexNAc(3) NeuAc(2)"}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_2_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_3_NeuAc_2_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_, "delta_composition", "dHex(1) Hex(2) HexNAc(3) NeuAc(1)"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_, "approved", "0"}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_, "delta_composition", "dHex(3) Hex(2) HexNAc(3)"}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_, "spec_1_site", "S"}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_, "spec_1_site", "T"}, {UNIMOD_Hex_7_Phos_3_, "approved", "0"}, {UNIMOD_Hex_7_Phos_3_, "delta_composition", "H(3) O(9) P(3) Hex(7)"}, {UNIMOD_Hex_7_Phos_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_7_Phos_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_7_Phos_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_7_Phos_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_7_Phos_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_7_Phos_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_7_Phos_3_, "spec_1_site", "T"}, {UNIMOD_Hex_7_Phos_3_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_2_, "approved", "0"}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_2_, "delta_composition", "dHex(1) Hex(4) HexA(1) HexNAc(2)"}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_2_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_2_, "spec_1_site", "T"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_, "delta_composition", "Hex(3) HexNAc(3) NeuAc(1)"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_3_HexA_2_HexNAc_2_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexA_2_HexNAc_2_, "delta_composition", "dHex(1) Hex(3) HexA(2) HexNAc(2)"}, {UNIMOD_dHex_1_Hex_3_HexA_2_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexA_2_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexA_2_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexA_2_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexA_2_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexA_2_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexA_2_HexNAc_2_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_3_HexA_2_HexNAc_2_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "delta_composition", "O(3) S Hex(2) HexNAc(2) NeuAc(2)"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "delta_composition", "O(3) S dHex(2) Hex(2) HexNAc(2) NeuAc"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_, "delta_composition", "Hex(3) HexNAc(3) NeuGc(1)"}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_4_Hex_1_HexNAc_2_Kdn_1_, "approved", "0"}, {UNIMOD_dHex_4_Hex_1_HexNAc_2_Kdn_1_, "delta_composition", "dHex(4) Hex HexNAc(2) Kdn"}, {UNIMOD_dHex_4_Hex_1_HexNAc_2_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_4_Hex_1_HexNAc_2_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_4_Hex_1_HexNAc_2_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_4_Hex_1_HexNAc_2_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_4_Hex_1_HexNAc_2_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_4_Hex_1_HexNAc_2_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_4_Hex_1_HexNAc_2_Kdn_1_, "spec_1_site", "T"}, {UNIMOD_dHex_4_Hex_1_HexNAc_2_Kdn_1_, "spec_1_site", "S"}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_Kdn_1_, "approved", "0"}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_Kdn_1_, "delta_composition", "dHex(3) Hex(2) HexNAc(2) Kdn"}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_Kdn_1_, "spec_1_site", "T"}, {UNIMOD_dHex_3_Hex_2_HexNAc_2_Kdn_1_, "spec_1_site", "S"}, {UNIMOD_dHex_3_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_3_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "delta_composition", "O(3) S dHex(3) Hex(2) HexA HexNAc(2)"}, {UNIMOD_dHex_3_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_3_Hex_2_HexA_1_HexNAc_2_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_4_NeuAc_1_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_4_NeuAc_1_, "delta_composition", "Hex(2) HexNAc(4) NeuAc(1)"}, {UNIMOD_Hex_2_HexNAc_4_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_4_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_4_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_4_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_4_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_4_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_4_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_4_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_2_HexNAc_4_, "approved", "0"}, {UNIMOD_dHex_2_Hex_2_HexNAc_4_, "delta_composition", "dHex(2) Hex(2) HexNAc(4)"}, {UNIMOD_dHex_2_Hex_2_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_4_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexNAc_4_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "delta_composition", "O(3) S dHex(2) Hex(3) HexA HexNAc(2)"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_2_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_4_HexNAc_3_Kdn_1_, "approved", "0"}, {UNIMOD_dHex_4_HexNAc_3_Kdn_1_, "delta_composition", "dHex(4) HexNAc(3) Kdn"}, {UNIMOD_dHex_4_HexNAc_3_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_4_HexNAc_3_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_4_HexNAc_3_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_4_HexNAc_3_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_4_HexNAc_3_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_4_HexNAc_3_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_4_HexNAc_3_Kdn_1_, "spec_1_site", "T"}, {UNIMOD_dHex_4_HexNAc_3_Kdn_1_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_3_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_3_, "delta_composition", "Hex(2) HexNAc(1) NeuGc(3)"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_3_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_3_, "spec_1_site", "T"}, {UNIMOD_dHex_4_Hex_1_HexNAc_1_Kdn_2_, "approved", "0"}, {UNIMOD_dHex_4_Hex_1_HexNAc_1_Kdn_2_, "delta_composition", "dHex(4) Hex HexNAc Kdn(2)"}, {UNIMOD_dHex_4_Hex_1_HexNAc_1_Kdn_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_4_Hex_1_HexNAc_1_Kdn_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_4_Hex_1_HexNAc_1_Kdn_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_4_Hex_1_HexNAc_1_Kdn_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_4_Hex_1_HexNAc_1_Kdn_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_4_Hex_1_HexNAc_1_Kdn_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_4_Hex_1_HexNAc_1_Kdn_2_, "spec_1_site", "T"}, {UNIMOD_dHex_4_Hex_1_HexNAc_1_Kdn_2_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "delta_composition", "O(3) S dHex Hex(2) HexNAc(3) NeuAc"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_, "delta_composition", "dHex(1) Hex(2) HexNAc(2) NeuAc(2)"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_, "spec_1_site", "T"}, {UNIMOD_dHex_3_Hex_1_HexNAc_3_Kdn_1_, "approved", "0"}, {UNIMOD_dHex_3_Hex_1_HexNAc_3_Kdn_1_, "delta_composition", "dHex(3) Hex HexNAc(3) Kdn"}, {UNIMOD_dHex_3_Hex_1_HexNAc_3_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_1_HexNAc_3_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_1_HexNAc_3_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_1_HexNAc_3_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_1_HexNAc_3_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_1_HexNAc_3_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_1_HexNAc_3_Kdn_1_, "spec_1_site", "T"}, {UNIMOD_dHex_3_Hex_1_HexNAc_3_Kdn_1_, "spec_1_site", "S"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_Sulf_1_, "delta_composition", "O(3) S Hex(3) HexNAc(3) NeuAc"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_Hex_3_HexNAc_2_NeuAc_2_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_2_NeuAc_2_, "delta_composition", "Hex(3) HexNAc(2) NeuAc(2)"}, {UNIMOD_Hex_3_HexNAc_2_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_2_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_2_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_2_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_2_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_2_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_2_NeuAc_2_, "spec_1_site", "S"}, {UNIMOD_Hex_3_HexNAc_2_NeuAc_2_, "spec_1_site", "T"}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_Sulf_1_, "delta_composition", "O(3) S Hex(3) HexNAc(3) NeuGc"}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_Hex_3_HexNAc_3_NeuGc_1_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_2_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_2_, "delta_composition", "dHex(1) Hex(2) HexNAc(2) NeuGc(2)"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_2_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_2_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_NeuGc_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_NeuGc_1_, "delta_composition", "dHex(2) Hex(3) HexNAc(2) NeuGc(1)"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "delta_composition", "O(3) S dHex Hex(3) HexA HexNAc(3)"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_2_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_2_, "delta_composition", "Hex(2) HexNAc(3) NeuAc(2)"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_2_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_2_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuAc_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuAc_1_, "delta_composition", "dHex(2) Hex(2) HexNAc(3) NeuAc(1)"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_4_Hex_2_HexNAc_3_, "approved", "0"}, {UNIMOD_dHex_4_Hex_2_HexNAc_3_, "delta_composition", "dHex(4) Hex(2) HexNAc(3)"}, {UNIMOD_dHex_4_Hex_2_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_4_Hex_2_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_4_Hex_2_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_4_Hex_2_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_4_Hex_2_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_4_Hex_2_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_4_Hex_2_HexNAc_3_, "spec_1_site", "S"}, {UNIMOD_dHex_4_Hex_2_HexNAc_3_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_NeuGc_1_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_NeuGc_1_, "delta_composition", "Hex(2) HexNAc(3) NeuAc(1) NeuGc(1)"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_1_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuGc_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuGc_1_, "delta_composition", "dHex(2) Hex(2) HexNAc(3) NeuGc(1)"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_, "approved", "0"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_, "delta_composition", "dHex(3) Hex(3) HexNAc(3)"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_, "spec_1_site", "S"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_, "spec_1_site", "T"}, {UNIMOD_Hex_8_Phos_3_, "approved", "0"}, {UNIMOD_Hex_8_Phos_3_, "delta_composition", "H(3) O(9) P(3) Hex(8)"}, {UNIMOD_Hex_8_Phos_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_8_Phos_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_8_Phos_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_8_Phos_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_8_Phos_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_8_Phos_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_8_Phos_3_, "spec_1_site", "T"}, {UNIMOD_Hex_8_Phos_3_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "delta_composition", "O(3) S dHex Hex(2) HexNAc(2) NeuAc(2)"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_2_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_2_, "delta_composition", "Hex(2) HexNAc(3) NeuGc(2)"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_2_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_2_, "spec_1_site", "T"}, {UNIMOD_dHex_4_Hex_2_HexNAc_2_Kdn_1_, "approved", "0"}, {UNIMOD_dHex_4_Hex_2_HexNAc_2_Kdn_1_, "delta_composition", "dHex(4) Hex(2) HexNAc(2) Kdn"}, {UNIMOD_dHex_4_Hex_2_HexNAc_2_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_4_Hex_2_HexNAc_2_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_4_Hex_2_HexNAc_2_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_4_Hex_2_HexNAc_2_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_4_Hex_2_HexNAc_2_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_4_Hex_2_HexNAc_2_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_4_Hex_2_HexNAc_2_Kdn_1_, "spec_1_site", "T"}, {UNIMOD_dHex_4_Hex_2_HexNAc_2_Kdn_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_1_, "delta_composition", "dHex(1) Hex(2) HexNAc(4) NeuAc(1)"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_3_Hex_2_HexNAc_4_, "approved", "0"}, {UNIMOD_dHex_3_Hex_2_HexNAc_4_, "delta_composition", "dHex(3) Hex(2) HexNAc(4)"}, {UNIMOD_dHex_3_Hex_2_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_2_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_2_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_2_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_2_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_2_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_2_HexNAc_4_, "spec_1_site", "S"}, {UNIMOD_dHex_3_Hex_2_HexNAc_4_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_4_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_4_, "delta_composition", "Hex(1) HexNAc(1) NeuGc(4)"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_4_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_4_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_4_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_4_, "spec_1_site", "T"}, {UNIMOD_dHex_4_Hex_1_HexNAc_3_Kdn_1_, "approved", "0"}, {UNIMOD_dHex_4_Hex_1_HexNAc_3_Kdn_1_, "delta_composition", "dHex(4) Hex HexNAc(3) Kdn"}, {UNIMOD_dHex_4_Hex_1_HexNAc_3_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_4_Hex_1_HexNAc_3_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_4_Hex_1_HexNAc_3_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_4_Hex_1_HexNAc_3_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_4_Hex_1_HexNAc_3_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_4_Hex_1_HexNAc_3_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_4_Hex_1_HexNAc_3_Kdn_1_, "spec_1_site", "T"}, {UNIMOD_dHex_4_Hex_1_HexNAc_3_Kdn_1_, "spec_1_site", "S"}, {UNIMOD_Hex_4_HexNAc_4_Sulf_2_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_4_Sulf_2_, "delta_composition", "O(6) S(2) Hex(4) HexNAc(4)"}, {UNIMOD_Hex_4_HexNAc_4_Sulf_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_4_Sulf_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_4_Sulf_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_4_Sulf_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_4_Sulf_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_4_Sulf_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_4_Sulf_2_, "spec_1_site", "T"}, {UNIMOD_Hex_4_HexNAc_4_Sulf_2_, "spec_1_site", "S"}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_Kdn_1_, "approved", "0"}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_Kdn_1_, "delta_composition", "dHex(3) Hex(2) HexNAc(3) Kdn"}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_Kdn_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_Kdn_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_Kdn_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_Kdn_1_, "spec_1_site", "T"}, {UNIMOD_dHex_3_Hex_2_HexNAc_3_Kdn_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexNAc_5_, "approved", "0"}, {UNIMOD_dHex_2_Hex_2_HexNAc_5_, "delta_composition", "dHex(2) Hex(2) HexNAc(5)"}, {UNIMOD_dHex_2_Hex_2_HexNAc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_5_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexNAc_5_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "delta_composition", "O(3) S dHex(2) Hex(3) HexA HexNAc(3)"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_3_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "delta_composition", "O(3) S dHex Hex(4) HexA HexNAc(3)"}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_, "delta_composition", "Hex(3) HexNAc(3) NeuAc(2)"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_site", "S"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_1_, "delta_composition", "dHex(2) Hex(3) HexNAc(3) NeuAc(1)"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_4_Hex_3_HexNAc_3_, "approved", "0"}, {UNIMOD_dHex_4_Hex_3_HexNAc_3_, "delta_composition", "dHex(4) Hex(3) HexNAc(3)"}, {UNIMOD_dHex_4_Hex_3_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_4_Hex_3_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_4_Hex_3_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_4_Hex_3_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_4_Hex_3_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_4_Hex_3_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_4_Hex_3_HexNAc_3_, "spec_1_site", "S"}, {UNIMOD_dHex_4_Hex_3_HexNAc_3_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuGc_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuGc_1_, "delta_composition", "dHex(2) Hex(3) HexNAc(3) NeuGc(1)"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuGc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuGc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuGc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuGc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuGc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_9_Phos_3_, "approved", "0"}, {UNIMOD_Hex_9_Phos_3_, "delta_composition", "H(3) O(9) P(3) Hex(9)"}, {UNIMOD_Hex_9_Phos_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_9_Phos_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_9_Phos_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_9_Phos_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_9_Phos_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_9_Phos_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_9_Phos_3_, "spec_1_site", "T"}, {UNIMOD_Hex_9_Phos_3_, "spec_1_site", "S"}, {UNIMOD_dHex_2_HexNAc_7_, "approved", "0"}, {UNIMOD_dHex_2_HexNAc_7_, "delta_composition", "dHex(2) HexNAc(7)"}, {UNIMOD_dHex_2_HexNAc_7_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_HexNAc_7_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_HexNAc_7_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_HexNAc_7_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_HexNAc_7_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_HexNAc_7_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_HexNAc_7_, "spec_1_site", "S"}, {UNIMOD_dHex_2_HexNAc_7_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_4_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_4_, "delta_composition", "Hex(2) HexNAc(1) NeuGc(4)"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_4_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_4_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_4_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_1_NeuGc_4_, "spec_1_site", "T"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_Sulf_1_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_Sulf_1_, "delta_composition", "O(3) S Hex(3) HexNAc(3) NeuAc(2)"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_Hex_3_HexNAc_3_NeuAc_2_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_3_HexNAc_5_, "approved", "0"}, {UNIMOD_dHex_2_Hex_3_HexNAc_5_, "delta_composition", "dHex(2) Hex(3) HexNAc(5)"}, {UNIMOD_dHex_2_Hex_3_HexNAc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_5_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_3_HexNAc_5_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_3_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_3_, "delta_composition", "dHex(1) Hex(2) HexNAc(2) NeuGc(3)"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_3_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_3_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_2_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "delta_composition", "O(3) S dHex(2) Hex(4) HexA HexNAc(3)"}, {UNIMOD_dHex_2_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_4_HexA_1_HexNAc_3_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_3_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_3_, "delta_composition", "Hex(2) HexNAc(3) NeuAc(3)"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_3_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_3_NeuAc_3_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_NeuAc_2_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_NeuAc_2_, "delta_composition", "dHex(1) Hex(3) HexNAc(3) NeuAc(2)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_site", "T"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_NeuAc_1_, "approved", "0"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_NeuAc_1_, "delta_composition", "dHex(3) Hex(3) HexNAc(3) NeuAc(1)"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_3_Hex_3_HexNAc_3_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_3_, "approved", "0"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_3_, "delta_composition", "Hex(2) HexNAc(3) NeuGc(3)"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_3_, "spec_1_site", "S"}, {UNIMOD_Hex_2_HexNAc_3_NeuGc_3_, "spec_1_site", "T"}, {UNIMOD_Hex_10_Phos_3_, "approved", "0"}, {UNIMOD_Hex_10_Phos_3_, "delta_composition", "H(3) O(9) P(3) Hex(10)"}, {UNIMOD_Hex_10_Phos_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_10_Phos_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_10_Phos_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_10_Phos_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_10_Phos_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_10_Phos_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_10_Phos_3_, "spec_1_site", "T"}, {UNIMOD_Hex_10_Phos_3_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_2_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_2_, "delta_composition", "dHex(1) Hex(2) HexNAc(4) NeuAc(2)"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_2_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_2_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_5_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_5_, "delta_composition", "Hex(1) HexNAc(1) NeuGc(5)"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_5_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_5_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_5_, "spec_1_site", "S"}, {UNIMOD_Hex_1_HexNAc_1_NeuGc_5_, "spec_1_site", "T"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_2_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_2_, "delta_composition", "O(6) S(2) Hex(4) HexNAc(4) NeuAc"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_2_, "spec_1_site", "T"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_2_, "spec_1_site", "S"}, {UNIMOD_Hex_4_HexNAc_4_NeuGc_1_Sulf_2_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_4_NeuGc_1_Sulf_2_, "delta_composition", "O(6) S(2) Hex(4) HexNAc(4) NeuGc"}, {UNIMOD_Hex_4_HexNAc_4_NeuGc_1_Sulf_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_4_NeuGc_1_Sulf_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_4_NeuGc_1_Sulf_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_4_NeuGc_1_Sulf_2_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_4_NeuGc_1_Sulf_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_4_NeuGc_1_Sulf_2_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_4_NeuGc_1_Sulf_2_, "spec_1_site", "T"}, {UNIMOD_Hex_4_HexNAc_4_NeuGc_1_Sulf_2_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_2_, "approved", "0"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_2_, "delta_composition", "dHex(2) Hex(3) HexNAc(3) NeuAc(2)"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_2_, "spec_1_site", "T"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_3_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_3_, "delta_composition", "O(9) S(3) Hex(4) HexNAc(4) NeuAc"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_3_, "spec_1_site", "T"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_3_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_, "approved", "0"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_, "delta_composition", "dHex(2) Hex(2) HexNAc(2)"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_, "spec_2_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_2_, "spec_2_site", "N"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_, "delta_composition", "dHex(1) Hex(3) HexNAc(2)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_, "spec_2_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_, "spec_2_site", "N"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_, "approved", "0"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_, "delta_composition", "dHex(1) Hex(2) HexNAc(3)"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_, "spec_2_hidden", "1"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_2_HexNAc_3_, "spec_2_site", "N"}, {UNIMOD_Hex_3_HexNAc_3_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_3_, "delta_composition", "Hex(3) HexNAc(3)"}, {UNIMOD_Hex_3_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_3_, "spec_1_site", "S"}, {UNIMOD_Hex_3_HexNAc_3_, "spec_1_site", "T"}, {UNIMOD_Hex_3_HexNAc_3_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_3_, "spec_2_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_3_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_3_, "spec_2_site", "N"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Sulf_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Sulf_1_, "delta_composition", "O(3) S dHex Hex(3) HexNAc(2)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Sulf_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Sulf_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Sulf_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Sulf_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Sulf_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Sulf_1_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Sulf_1_, "spec_2_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Sulf_1_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_2_Sulf_1_, "spec_2_site", "N"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_, "approved", "0"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_, "delta_composition", "dHex(2) Hex(3) HexNAc(2)"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_, "spec_2_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_2_, "spec_2_site", "N"}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_, "approved", "0"}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_, "delta_composition", "dHex(1) Hex(4) HexNAc(2)"}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_, "spec_2_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_2_, "spec_2_site", "N"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_, "approved", "0"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_, "delta_composition", "dHex(2) Hex(2) HexNAc(3)"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_, "spec_2_hidden", "1"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_2_HexNAc_3_, "spec_2_site", "N"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_, "delta_composition", "dHex(1) Hex(3) HexNAc(3)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_, "spec_2_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_3_, "spec_2_site", "N"}, {UNIMOD_Hex_4_HexNAc_3_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_3_, "delta_composition", "Hex(4) HexNAc(3)"}, {UNIMOD_Hex_4_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_3_, "spec_1_site", "S"}, {UNIMOD_Hex_4_HexNAc_3_, "spec_1_site", "T"}, {UNIMOD_Hex_4_HexNAc_3_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_3_, "spec_2_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_3_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_3_, "spec_2_site", "N"}, {UNIMOD_dHex_2_Hex_4_HexNAc_2_, "approved", "0"}, {UNIMOD_dHex_2_Hex_4_HexNAc_2_, "delta_composition", "dHex(2) Hex(4) HexNAc(2)"}, {UNIMOD_dHex_2_Hex_4_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_4_HexNAc_2_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_4_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_4_HexNAc_2_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_4_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_4_HexNAc_2_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_4_HexNAc_2_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_4_HexNAc_2_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_4_HexNAc_2_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_dHex_2_Hex_4_HexNAc_2_, "spec_2_hidden", "1"}, {UNIMOD_dHex_2_Hex_4_HexNAc_2_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_4_HexNAc_2_, "spec_2_site", "N"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_, "approved", "0"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_, "delta_composition", "dHex(2) Hex(3) HexNAc(3)"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_, "spec_2_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_3_, "spec_2_site", "N"}, {UNIMOD_Hex_3_HexNAc_5_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_5_, "delta_composition", "Hex(3) HexNAc(5)"}, {UNIMOD_Hex_3_HexNAc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_5_, "spec_1_site", "S"}, {UNIMOD_Hex_3_HexNAc_5_, "spec_1_site", "T"}, {UNIMOD_Hex_3_HexNAc_5_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_5_, "spec_2_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_5_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_5_, "spec_2_site", "N"}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_1_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_1_, "delta_composition", "Hex(4) HexNAc(3) NeuAc(1)"}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_1_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_1_, "spec_2_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_1_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_3_NeuAc_1_, "spec_2_site", "N"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_, "approved", "0"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_, "delta_composition", "dHex(2) Hex(3) HexNAc(4)"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_, "spec_2_hidden", "1"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_3_HexNAc_4_, "spec_2_site", "N"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_, "delta_composition", "dHex(1) Hex(3) HexNAc(5)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_, "spec_2_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_, "spec_2_site", "N"}, {UNIMOD_Hex_3_HexNAc_6_, "approved", "0"}, {UNIMOD_Hex_3_HexNAc_6_, "delta_composition", "Hex(3) HexNAc(6)"}, {UNIMOD_Hex_3_HexNAc_6_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_6_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_6_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_6_, "spec_1_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_6_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_6_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_6_, "spec_1_site", "S"}, {UNIMOD_Hex_3_HexNAc_6_, "spec_1_site", "T"}, {UNIMOD_Hex_3_HexNAc_6_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_Hex_3_HexNAc_6_, "spec_2_hidden", "1"}, {UNIMOD_Hex_3_HexNAc_6_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_3_HexNAc_6_, "spec_2_site", "N"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_, "approved", "0"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_, "delta_composition", "Hex(4) HexNAc(4) NeuAc(1)"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_, "spec_2_hidden", "1"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_4_HexNAc_4_NeuAc_1_, "spec_2_site", "N"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_, "approved", "0"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_, "delta_composition", "dHex(2) Hex(4) HexNAc(4)"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_, "spec_2_hidden", "1"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_4_HexNAc_4_, "spec_2_site", "N"}, {UNIMOD_Hex_6_HexNAc_4_, "approved", "0"}, {UNIMOD_Hex_6_HexNAc_4_, "delta_composition", "Hex(6) HexNAc(4)"}, {UNIMOD_Hex_6_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_6_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_6_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_Hex_6_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_Hex_6_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_6_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_6_HexNAc_4_, "spec_1_site", "S"}, {UNIMOD_Hex_6_HexNAc_4_, "spec_1_site", "T"}, {UNIMOD_Hex_6_HexNAc_4_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_Hex_6_HexNAc_4_, "spec_2_hidden", "1"}, {UNIMOD_Hex_6_HexNAc_4_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_6_HexNAc_4_, "spec_2_site", "N"}, {UNIMOD_Hex_5_HexNAc_5_, "approved", "0"}, {UNIMOD_Hex_5_HexNAc_5_, "delta_composition", "Hex(5) HexNAc(5)"}, {UNIMOD_Hex_5_HexNAc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_5_HexNAc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_5_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_Hex_5_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_5_HexNAc_5_, "spec_1_site", "S"}, {UNIMOD_Hex_5_HexNAc_5_, "spec_1_site", "T"}, {UNIMOD_Hex_5_HexNAc_5_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_Hex_5_HexNAc_5_, "spec_2_hidden", "1"}, {UNIMOD_Hex_5_HexNAc_5_, "spec_2_position", "Anywhere"}, {UNIMOD_Hex_5_HexNAc_5_, "spec_2_site", "N"}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_, "delta_composition", "dHex(1) Hex(3) HexNAc(6)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_, "spec_2_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_6_, "spec_2_site", "N"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_, "delta_composition", "dHex(1) Hex(4) HexNAc(4) NeuAc(1)"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_, "spec_2_hidden", "1"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_, "spec_2_site", "N"}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_, "approved", "0"}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_, "delta_composition", "dHex(3) Hex(4) HexNAc(4)"}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_, "spec_1_hidden", "1"}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_, "spec_1_site", "S"}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_, "spec_1_site", "T"}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_, "spec_2_hidden", "1"}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_3_Hex_4_HexNAc_4_, "spec_2_site", "N"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_NeuAc_1_, "approved", "0"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_NeuAc_1_, "delta_composition", "dHex(1) Hex(3) HexNAc(5) NeuAc(1)"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_NeuAc_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_NeuAc_1_, "spec_1_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_NeuAc_1_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_NeuAc_1_, "spec_1_site", "S"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_NeuAc_1_, "spec_1_site", "T"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_NeuAc_1_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_NeuAc_1_, "spec_2_hidden", "1"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_NeuAc_1_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_1_Hex_3_HexNAc_5_NeuAc_1_, "spec_2_site", "N"}, {UNIMOD_dHex_2_Hex_4_HexNAc_5_, "approved", "0"}, {UNIMOD_dHex_2_Hex_4_HexNAc_5_, "delta_composition", "dHex(2) Hex(4) HexNAc(5)"}, {UNIMOD_dHex_2_Hex_4_HexNAc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_4_HexNAc_5_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_dHex_2_Hex_4_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_4_HexNAc_5_, "spec_1_hidden", "1"}, {UNIMOD_dHex_2_Hex_4_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_4_HexNAc_5_, "spec_1_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_4_HexNAc_5_, "spec_1_site", "S"}, {UNIMOD_dHex_2_Hex_4_HexNAc_5_, "spec_1_site", "T"}, {UNIMOD_dHex_2_Hex_4_HexNAc_5_, "spec_2_classification", "N-linked glycosylation"}, {UNIMOD_dHex_2_Hex_4_HexNAc_5_, "spec_2_hidden", "1"}, {UNIMOD_dHex_2_Hex_4_HexNAc_5_, "spec_2_position", "Anywhere"}, {UNIMOD_dHex_2_Hex_4_HexNAc_5_, "spec_2_site", "N"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Ac_1_, "approved", "0"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Ac_1_, "delta_composition", "Ac Hex HexNAc NeuAc"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Ac_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Ac_1_, "spec_1_classification", "O-linked glycosylation"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Ac_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Ac_1_, "spec_1_hidden", "1"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Ac_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Ac_1_, "spec_1_position", "Anywhere"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Ac_1_, "spec_1_site", "T"}, {UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Ac_1_, "spec_1_site", "S"}, }; // propertyValue_ const size_t propertyValueSize_ = sizeof(propertyValue_)/sizeof(PropertyValuePair); class CVTermData : public boost::singleton { public: CVTermData(boost::restricted) { for (const TermInfo* it=termInfos_; it!=termInfos_+termInfosSize_; ++it) { CVTermInfo temp; temp.cvid = it->cvid; temp.id = it->id; temp.name = it->name; temp.def = it->def; temp.isObsolete = it->isObsolete; infoMap_[temp.cvid] = temp; cvids_.push_back(it->cvid); } for (const CVIDPair* it=relationsIsA_; it!=relationsIsA_+relationsIsASize_; ++it) infoMap_[it->first].parentsIsA.push_back(it->second); for (const CVIDPair* it=relationsPartOf_; it!=relationsPartOf_+relationsPartOfSize_; ++it) infoMap_[it->first].parentsPartOf.push_back(it->second); for (const OtherRelationPair* it=relationsOther_; it!=relationsOther_+relationsOtherSize_; ++it) infoMap_[it->subject].otherRelations.insert(make_pair(it->relation, it->object)); for (const CVIDStringPair* it=relationsExactSynonym_; it!=relationsExactSynonym_+relationsExactSynonymSize_; ++it) infoMap_[it->first].exactSynonyms.push_back(it->second); for (const PropertyValuePair* it=propertyValue_; it!=propertyValue_+propertyValueSize_; ++it) infoMap_[it->term].propertyValues.insert(make_pair(it->name, it->value)); cvMap_["MS"].fullName = "Proteomics Standards Initiative Mass Spectrometry Ontology"; cvMap_["MS"].URI = "http://psidev.cvs.sourceforge.net/*checkout*/psidev/psi/psi-ms/mzML/controlledVocabulary/psi-ms.obo"; cvMap_["UO"].fullName = "Unit Ontology"; cvMap_["UO"].URI = "http://obo.cvs.sourceforge.net/*checkout*/obo/obo/ontology/phenotype/unit.obo"; cvMap_["UNIMOD"].fullName = "UNIMOD"; cvMap_["UNIMOD"].URI = "http://www.unimod.org/obo/unimod.obo"; cvMap_["MS"].id = "MS"; cvMap_["MS"].version = "3.79.0"; cvMap_["UNIMOD"].id = "UNIMOD"; cvMap_["UNIMOD"].version = "2015-05-06"; cvMap_["UO"].id = "UO"; cvMap_["UO"].version = "12:10:2011"; } inline const map& infoMap() const {return infoMap_;} inline const map& cvMap() const {return cvMap_;} inline const vector& cvids() const {return cvids_;} private: map infoMap_; map cvMap_; vector cvids_; }; const char* oboPrefixes_[] = { "MS", "UNIMOD", "UO", }; const size_t oboPrefixesSize_ = sizeof(oboPrefixes_)/sizeof(const char*); const size_t enumBlockSize_ = 100000000; struct StringEquals { bool operator()(const string& yours) {return mine==yours;} string mine; StringEquals(const string& _mine) : mine(_mine) {} }; } // namespace #include "cv.inl" // code and data that doesn't change with CV releases } // namespace cv } // namespace pwiz pwiz/pwiz/data/common/ParamTypesTest.cpp0000664000175100017510000002256312664775620022405 0ustar teamcityteamcity00000000000000// // $Id: ParamTypesTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "ParamTypes.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::cv; using namespace pwiz::util; using namespace pwiz::data; ostream* os_ = 0; class WriteCVParam { public: WriteCVParam(ostream& os) : os_(os) {} void operator()(const CVParam& param) { os_ << "\n"; } private: ostream& os_; }; const char* mzmlScanTime = "\n"; const char* mzmlCollisionEnergy = "\n"; void test() { vector params; params.push_back(CVParam(MS_lowest_observed_m_z, 420)); params.push_back(CVParam(MS_highest_observed_m_z, 2000.012345)); params.push_back(CVParam(MS_m_z, "goober")); params.push_back(CVParam(MS_scan_start_time, 5.890500, UO_minute)); params.push_back(CVParam(MS_collision_energy, 35.00, UO_electronvolt)); params.push_back(CVParam(MS_deisotoping, true)); params.push_back(CVParam(MS_peak_picking, false)); if (os_) { *os_ << "params:\n"; copy(params.begin(), params.end(), ostream_iterator(*os_, "\n")); *os_ << endl; *os_ << "as mzML elements:\n"; for_each(params.begin(), params.end(), WriteCVParam(*os_)); *os_ << endl; *os_ << "value casting:\n"; int temp = params[0].valueAs(); *os_ << temp << endl; float temp2 = params[1].valueAs(); *os_ << temp2 << endl; string temp3 = params[2].valueAs(); *os_ << temp3 << "\n\n"; } // verify simple things unit_assert(420 == params[0].valueAs()); unit_assert(2000.012345 == params[1].valueAs()); unit_assert("goober" == params[2].value); unit_assert(5.890500 == params[3].valueAs()); unit_assert(35.00 == params[4].valueAs()); unit_assert(params[0] == CVParam(MS_lowest_observed_m_z, 420)); unit_assert(params[1] != CVParam(MS_lowest_observed_m_z, 420)); unit_assert(CVParam(MS_m_z) == MS_m_z); unit_assert(params[5].valueAs() == true); unit_assert(params[6].valueAs() == false); // verify manual mzml writing -- this is to verify that we have enough // info to write elements as required by mzML ostringstream ossScanTime; CVParam scanTime(MS_scan_start_time, "5.890500", UO_minute); (WriteCVParam(ossScanTime))(scanTime); if (os_) *os_ << "mzmlScanTime: " << mzmlScanTime << endl << "ossScanTime: " << ossScanTime.str() << endl; unit_assert(ossScanTime.str() == mzmlScanTime); if (os_) *os_ << "scan time in seconds: " << scanTime.timeInSeconds() << endl; unit_assert_equal(scanTime.timeInSeconds(), 5.8905 * 60, 1e-10); ostringstream ossCollisionEnergy; (WriteCVParam(ossCollisionEnergy))(CVParam(MS_collision_energy, "35.00", UO_electronvolt)); if (os_) *os_ << "mzmlCollisionEnergy: " << mzmlCollisionEnergy << endl << "ossCollisionEnergy: " << ossCollisionEnergy.str() << endl; unit_assert(ossCollisionEnergy.str() == mzmlCollisionEnergy); } void testIs() { vector params; params.push_back(CVParam(MS_plasma_desorption)); params.push_back(CVParam(MS_lowest_observed_m_z, 420)); params.push_back(CVParam(MS_collision_induced_dissociation)); vector::const_iterator it = find_if(params.begin(), params.end(), CVParamIs(MS_lowest_observed_m_z)); unit_assert(it->value == "420"); } void testIsChildOf() { // example of how to search through a collection of CVParams // to find the first one whose cvid IsA specified CVID vector params; params.push_back(CVParam(MS_lowest_observed_m_z, 420)); params.push_back(CVParam(MS_plasma_desorption)); params.push_back(CVParam(MS_collision_induced_dissociation)); params.push_back(CVParam(UO_electronvolt)); params.push_back(CVParam(MS_highest_observed_m_z, 2400.0)); vector::const_iterator itDiss = find_if(params.begin(), params.end(), CVParamIsChildOf(MS_dissociation_method)); vector::const_iterator itUnit = find_if(params.begin(), params.end(), CVParamIsChildOf(UO_unit)); if (os_) { *os_ << "find dissociation method: " << (itDiss!=params.end() ? cvTermInfo(itDiss->cvid).name : "not found") << endl; *os_ << "find unit: " << (itUnit!=params.end() ? cvTermInfo(itUnit->cvid).name : "not found") << endl; } unit_assert(itDiss!=params.end() && itDiss->cvid==MS_plasma_desorption); unit_assert(itUnit!=params.end() && itUnit->cvid==UO_electronvolt); } void testParamContainer() { ParamContainer pc; pc.cvParams.push_back(MS_reflectron_on); pc.cvParams.push_back(MS_MSn_spectrum); pc.cvParams.push_back(MS_reflectron_off); pc.cvParams.push_back(CVParam(MS_ionization_type, 420)); pc.userParams.push_back(UserParam("name1", "1", "type1", UO_second)); pc.userParams.push_back(UserParam("name2", "2", "type2", UO_minute)); ParamGroupPtr pg(new ParamGroup); pg->cvParams.push_back(CVParam(UO_dalton, 666)); pc.paramGroupPtrs.push_back(pg); unit_assert(pc.hasCVParam(MS_reflectron_off)); unit_assert(!pc.hasCVParam(MS_spectrum_type)); unit_assert(pc.hasCVParam(UO_dalton)); unit_assert(!pc.hasCVParam(UO_mass_unit)); unit_assert(pc.hasCVParamChild(MS_spectrum_type)); unit_assert(pc.hasCVParamChild(UO_mass_unit)); unit_assert(pc.cvParam(MS_selected_ion_m_z) == CVID_Unknown); unit_assert(pc.cvParam(MS_reflectron_off) == MS_reflectron_off); unit_assert(pc.cvParam(UO_mass_unit) == CVID_Unknown); unit_assert(pc.cvParam(UO_dalton).cvid == UO_dalton); unit_assert(pc.cvParamChild(MS_spectrum_type) == MS_MSn_spectrum); unit_assert(pc.cvParamChild(UO_mass_unit).cvid == UO_dalton); string result = "goober"; result = pc.cvParam(MS_selected_ion_m_z).value; unit_assert(result == ""); result = pc.cvParam(MS_ionization_type).value; unit_assert(result == "420"); result = pc.cvParam(UO_dalton).value; unit_assert(result == "666"); UserParam userParam = pc.userParam("name"); unit_assert(userParam.empty()); userParam = pc.userParam("name1"); unit_assert(userParam.name == "name1"); unit_assert(userParam.valueAs() == 1); unit_assert(userParam.type == "type1"); unit_assert(userParam.units == UO_second); userParam = pc.userParam("name2"); unit_assert(userParam.name == "name2"); unit_assert(userParam.valueAs() == 2); unit_assert(userParam.type == "type2"); unit_assert(userParam.units == UO_minute); unit_assert(pc.userParam("goober").valueAs() == 0); pc.set(MS_ms_level, 2); unit_assert(pc.cvParam(MS_ms_level).valueAs() == 2); pc.set(MS_ms_level, 3); unit_assert(pc.cvParam(MS_ms_level).valueAs() == 3); pc.set(MS_deisotoping, true); unit_assert(pc.cvParam(MS_deisotoping).valueAs() == true); pc.set(MS_deisotoping, false); unit_assert(pc.cvParam(MS_deisotoping).valueAs() == false); pc.set(MS_CID); pc.set(MS_ETD); pg->set(MS_PQD); vector dissociationMethods = pc.cvParamChildren(MS_dissociation_method); unit_assert(dissociationMethods.size() == 3); unit_assert(dissociationMethods[0] == MS_CID); unit_assert(dissociationMethods[1] == MS_ETD); unit_assert(dissociationMethods[2] == MS_PQD); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); testIs(); testIsChildOf(); testParamContainer(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/common/CVTranslator.cpp0000664000175100017510000001210212664775620022026 0ustar teamcityteamcity00000000000000// // $Id: CVTranslator.cpp 7331 2015-03-24 16:11:12Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // #define PWIZ_SOURCE #include "CVTranslator.hpp" #include "boost/algorithm/string/predicate.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace data { using namespace pwiz::cv; // // default extra translations // namespace { struct ExtraEntry { const char* text; CVID cvid; }; ExtraEntry defaultExtraEntries_[] = { {"ITMS", MS_ion_trap}, {"FTMS", MS_FT_ICR}, }; size_t defaultExtraEntriesSize_ = sizeof(defaultExtraEntries_)/sizeof(ExtraEntry); } // namespace // // CVTranslator::Impl // class CVTranslator::Impl { public: Impl(); void insert(const string& text, CVID cvid); CVID translate(const string& text) const; private: typedef map Map; Map map_; void insertCVTerms(); void insertDefaultExtraEntries(); }; CVTranslator::Impl::Impl() { insertCVTerms(); insertDefaultExtraEntries(); } namespace { inline char alnum_lower(char c) { // c -> lower-case, whitespace, or + return isalnum(c) ? static_cast(tolower(c)) : c == '+' ? c : ' '; } string preprocess(const string& s) { string result = s; transform(result.begin(), result.end(), result.begin(), alnum_lower); return result; } string canonicalize(const string& s) { // remove non-alnum characters istringstream iss(preprocess(s)); // remove whitespace around tokens vector tokens; copy(istream_iterator(iss), istream_iterator(), back_inserter(tokens)); // concatenate with underscores ostringstream oss; copy(tokens.begin(), tokens.end(), ostream_iterator(oss, "_")); return oss.str(); } } // namespace bool shouldIgnore(const string& key, CVID value, CVID cvid) { return (key=="unit_" && value==MS_unit_OBSOLETE && cvid==UO_unit || key=="pi_" && value==MS_PI && cvid==UO_pi || // MS_PI==photoionization, UO_pi==3.14 key=="pi_" && value==MS_PI && cvid==MS_pI || // MS_pI==isoelectric point key=="de_" && value==MS_DE && cvid==1001274); // conflict between 1000246 and 1001274 } bool shouldReplace(const string& key, CVID value, CVID cvid) { return false; } void CVTranslator::Impl::insert(const string& text, CVID cvid) { string key = canonicalize(text); if (map_.count(key)) { if (shouldIgnore(key, map_[key], cvid)) return; if (!shouldReplace(key, map_[key], cvid)) { throw runtime_error("[CVTranslator::insert()] Collision: " + lexical_cast(map_[key]) + " " + lexical_cast(cvid)); } } map_[key] = cvid; } CVID CVTranslator::Impl::translate(const string& text) const { Map::const_iterator it = map_.find(canonicalize(text)); if (it != map_.end()) return it->second; return CVID_Unknown; } void CVTranslator::Impl::insertCVTerms() { for (vector::const_iterator cvid=cvids().begin(); cvid!=cvids().end(); ++cvid) { const CVTermInfo& info = cvTermInfo(*cvid); if (info.isObsolete) continue; if (!(bal::starts_with(info.id, "MS") || bal::starts_with(info.id, "UO"))) continue; // insert name insert(info.name, *cvid); // insert synonyms if (*cvid < 100000000) // prefix == "MS" { for (vector::const_iterator syn=info.exactSynonyms.begin(); syn!=info.exactSynonyms.end(); ++syn) insert(*syn, *cvid); } } } void CVTranslator::Impl::insertDefaultExtraEntries() { for (const ExtraEntry* it=defaultExtraEntries_; it!=defaultExtraEntries_+defaultExtraEntriesSize_; ++it) insert(it->text, it->cvid); } // // CVTranslator // PWIZ_API_DECL CVTranslator::CVTranslator() : impl_(new Impl) {} PWIZ_API_DECL void CVTranslator::insert(const string& text, CVID cvid) {impl_->insert(text, cvid);} PWIZ_API_DECL CVID CVTranslator::translate(const string& text) const {return impl_->translate(text);} } // namespace data } // namespace pwiz pwiz/pwiz/data/common/Index.hpp0000664000175100017510000000437112664775620020531 0ustar teamcityteamcity00000000000000// // $Id: Index.hpp 1704 2010-01-15 23:42:49Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _INDEX_HPP_ #define _INDEX_HPP_ #include "pwiz/utility/misc/Export.hpp" #include #include #include #include #include namespace pwiz { namespace data { /// generic interface for creating and using an index on a stream of serialized objects class PWIZ_API_DECL Index { public: typedef boost::iostreams::stream_offset stream_offset; /// generic type identifying an indexed item by string id, ordinal index, and stream offset struct PWIZ_API_DECL Entry { std::string id; boost::uint64_t index; stream_offset offset; }; typedef boost::shared_ptr EntryPtr; /// create the index from specified list of entries; /// the list is non-const because the index implementation may resort the list virtual void create(std::vector& entries) = 0; /// returns the number of entries in the index virtual size_t size() const = 0; /// returns the entry for the specified string id, or null if the id is not in the index virtual EntryPtr find(const std::string& id) const = 0; /// returns the entry for the specified ordinal index, or null if the ordinal is not in the index virtual EntryPtr find(size_t index) const = 0; virtual ~Index() {} }; typedef boost::shared_ptr IndexPtr; } // namespace data } // namespace pwiz #endif // _INDEX_HPP_ pwiz/pwiz/data/common/CVTranslatorTest.cpp0000664000175100017510000000472712664775620022704 0ustar teamcityteamcity00000000000000// // $Id: CVTranslatorTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "CVTranslator.hpp" #include "pwiz/utility/misc/unit.hpp" #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::cv; using namespace pwiz::data; ostream* os_ = 0; void test(const CVTranslator& translator, const string& text, CVID correct) { CVID result = translator.translate(text); if (os_) *os_ << text << " -> (" << cvTermInfo(result).id << ", \"" << cvTermInfo(result).name << "\")\n"; unit_assert(result == correct); } void test() { if (os_) *os_ << "test()\n"; CVTranslator translator; test(translator, "FT-ICR", MS_FT_ICR); test(translator, " \nFT - \tICR\t", MS_FT_ICR); test(translator, " Total \t\n iOn @#$CurRENT", MS_TIC); unit_assert(translator.translate("Darren Kessner") == CVID_Unknown); translator.insert("DARREN.#$@#$^KESSNER", MS_software); test(translator, "dARren kESSner", MS_software); // test collision detection bool caught = false; try { translator.insert("darren kessner", MS_m_z); } catch (exception& ) { caught = true; } if (os_) *os_ << "collision caught: " << boolalpha << caught << endl; unit_assert(caught); // test default extra entries test(translator, " itms ", MS_ion_trap); test(translator, " FTmS\n", MS_FT_ICR); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; test(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/common/MemoryIndex.hpp0000664000175100017510000000274512664775620021725 0ustar teamcityteamcity00000000000000// // $Id: MemoryIndex.hpp 1621 2009-12-15 17:43:15Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _MEMORYINDEX_HPP_ #define _MEMORYINDEX_HPP_ #include "Index.hpp" namespace pwiz { namespace data { /// index implementation in memory; /// find(string id) is O(logN); /// find(ordinal index) is O(1); /// memory footprint is basically (number of entries * 2) class PWIZ_API_DECL MemoryIndex : public Index { public: MemoryIndex(); virtual void create(std::vector& entries); virtual size_t size() const; virtual EntryPtr find(const std::string& id) const; virtual EntryPtr find(size_t index) const; private: class Impl; boost::shared_ptr impl_; }; } // namespace data } // namespace pwiz #endif // _MEMORYINDEX_HPP_ pwiz/pwiz/data/common/BinaryIndexStream.cpp0000664000175100017510000002760212664775620023047 0ustar teamcityteamcity00000000000000// // $Id: BinaryIndexStream.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "BinaryIndexStream.hpp" #include "pwiz/utility/misc/Std.hpp" #include #include using boost::shared_ptr; namespace pwiz { namespace data { namespace { template struct stream_vector_reader { istream& operator() (istream& is, _Ty& value) const {return is >> value;} }; template > class stream_vector_const_iterator { public: typedef stream_vector_const_iterator<_Ty, reader_type> _Myt; typedef std::random_access_iterator_tag iterator_category; typedef _Ty value_type; typedef std::ptrdiff_t difference_type; typedef value_type* pointer; typedef value_type& reference; typedef const value_type* const_pointer; typedef const value_type& const_reference; typedef boost::iostreams::stream_offset stream_offset; stream_vector_const_iterator() : begin_(0), end_(0), next_(0) { } stream_vector_const_iterator(boost::shared_ptr streamPtr, size_t value_size, reader_type reader, stream_offset begin = 0, stream_offset end = std::numeric_limits::max()) : streamPtr_(streamPtr), value_size_(value_size), begin_(begin), end_(end), next_(begin_), cur_(end), reader_(reader) { } reference operator*() const { if (cur_ != next_) { cur_ = next_; streamPtr_->seekg(next_); reader_(*streamPtr_, curItem_); } return curItem_; } pointer operator->() const { return &curItem_; } _Myt& operator++() { next_ += value_size_; return (*this); } _Myt operator++(int) { _Myt _Tmp = *this; ++*this; return (_Tmp); } _Myt& operator--() { next_ -= value_size_; return (*this); } _Myt operator--(int) { _Myt _Tmp = *this; --*this; return (_Tmp); } _Myt& operator+=(difference_type _Off) { next_ += _Off * value_size_; return (*this); } _Myt operator+(difference_type _Off) const { _Myt _Tmp = *this; return (_Tmp += _Off); } _Myt& operator-=(difference_type _Off) { return (*this += -_Off); } _Myt operator-(difference_type _Off) const { _Myt _Tmp = *this; return (_Tmp -= _Off); } difference_type operator-(const _Myt& that) const { bool gotThis = this->streamPtr_.get() != NULL; bool gotThat = that.streamPtr_.get() != NULL; if (gotThis && gotThat) return (next_ - that.next_) / value_size_; else if (!gotThis && !gotThat) // end() - end() return 0; else if (gotThis) return -(end_ - begin_) / value_size_; else // gotThat return (that.end_ - that.begin_) / that.value_size_; } reference operator[](difference_type _Off) const { next_ = _Off * value_size_; return (**this); } bool operator==(const _Myt& that) const { bool gotThis = this->streamPtr_.get() != NULL; bool gotThat = that.streamPtr_.get() != NULL; if (gotThis && gotThat) return next_ == that.next_; else if (!gotThis && !gotThat) // end() == end() return true; else if (gotThis) return next_ >= end_; else // gotThat return that.next_ >= that.end_; } bool operator!=(const _Myt& _Right) const { return (!(*this == _Right)); } bool operator<(const _Myt& _Right) const { return (next_ < _Right.next_); } bool operator>(const _Myt& _Right) const { return (_Right < *this); } bool operator<=(const _Myt& _Right) const { return (!(_Right < *this)); } bool operator>=(const _Myt& _Right) const { return (!(*this < _Right)); } private: boost::shared_ptr streamPtr_; size_t value_size_; boost::iostreams::stream_offset begin_, end_, next_; mutable boost::iostreams::stream_offset cur_; mutable _Ty curItem_; reader_type reader_; }; } // namespace class BinaryIndexStream::Impl { shared_ptr isPtr_; stream_offset streamLength_; boost::uint64_t maxIdLength_; size_t size_; size_t entrySize_; // space-padded so entries are constant-length struct EntryIdLessThan { bool operator() (const Entry& lhs, const Entry& rhs) const {return lhs.id < rhs.id;} }; struct EntryIndexLessThan { bool operator() (const Entry& lhs, const Entry& rhs) const {return lhs.index < rhs.index;} }; // the index structure: // // stream length (if overwriting an existing index in the same stream, the existing index may be longer // than the new index, so the length marks the correct end point) // // size_t indicating maximum id length + 1 (all ids are padded with spaces to this length) // // a vector of index entries sorted by index (O(1) access) // // a vector of index entries sorted by id (O(logN) access) struct EntryReader { EntryReader(boost::uint64_t maxIdLength = 0) : maxIdLength_(maxIdLength) {} istream& operator() (istream& is, Entry& entry) const { is >> entry.id; is.seekg(maxIdLength_ - entry.id.length(), std::ios::cur); is.read(reinterpret_cast(&entry.index), sizeof(entry.index)); is.read(reinterpret_cast(&entry.offset), sizeof(entry.offset)); return is; } private: boost::uint64_t maxIdLength_; }; typedef stream_vector_const_iterator IndexStreamIterator; EntryReader entryReader_; mutable boost::mutex io_mutex; public: Impl(shared_ptr isPtr) : isPtr_(isPtr) { if (!isPtr_.get()) throw runtime_error("[BinaryIndexStream::ctor] Stream is null"); isPtr_->clear(); isPtr_->seekg(0); isPtr_->read(reinterpret_cast(&streamLength_), sizeof(streamLength_)); isPtr_->read(reinterpret_cast(&maxIdLength_), sizeof(maxIdLength_)); if (*isPtr_) { // calculate entry size (depends on max. id length) entrySize_ = maxIdLength_ + sizeof(streamLength_) + sizeof(maxIdLength_); size_t headerSize = sizeof(streamLength_) + sizeof(maxIdLength_); // calculate number of entries (depends on entry size and stream length) size_ = (streamLength_ - headerSize) / (entrySize_ * 2); entryReader_ = EntryReader(maxIdLength_); } else size_ = maxIdLength_ = streamLength_ = 0; } virtual void create(std::vector& entries) { isPtr_->clear(); isPtr_->seekp(0); isPtr_->clear(); size_ = entries.size(); // determine max. id length maxIdLength_ = 0; BOOST_FOREACH(const Entry& entry, entries) maxIdLength_ = std::max(maxIdLength_, (boost::uint64_t) entry.id.length()); ++maxIdLength_; // space-terminated // entry size depends on max. id length entrySize_ = maxIdLength_ + sizeof(streamLength_) + sizeof(maxIdLength_); size_t headerSize = sizeof(streamLength_) + sizeof(maxIdLength_); // write stream length (depends on entry size and number of entries) streamLength_ = headerSize + entrySize_ * size_ * 2; isPtr_->write(reinterpret_cast(&streamLength_), sizeof(streamLength_)); // write max. id length isPtr_->write(reinterpret_cast(&maxIdLength_), sizeof(maxIdLength_)); // padding buffer string padding(maxIdLength_, ' '); // sort entries by index sort(entries.begin(), entries.end(), EntryIndexLessThan()); // write entries sorted by index BOOST_FOREACH(const Entry& entry, entries) { isPtr_->write(entry.id.c_str(), entry.id.length()); isPtr_->write(padding.c_str(), maxIdLength_ - entry.id.length()); isPtr_->write(reinterpret_cast(&entry.index), sizeof(entry.index)); isPtr_->write(reinterpret_cast(&entry.offset), sizeof(entry.offset)); } // sort entries by id sort(entries.begin(), entries.end(), EntryIdLessThan()); // write entries sorted by id BOOST_FOREACH(const Entry& entry, entries) { isPtr_->write(entry.id.c_str(), entry.id.length()); isPtr_->write(padding.c_str(), maxIdLength_ - entry.id.length()); isPtr_->write(reinterpret_cast(&entry.index), sizeof(entry.index)); isPtr_->write(reinterpret_cast(&entry.offset), sizeof(entry.offset)); } // flush stream isPtr_->sync(); entryReader_ = EntryReader(maxIdLength_); } virtual size_t size() const { return size_; } virtual EntryPtr find(const std::string& id) const { if (size_ == 0) return EntryPtr(); EntryPtr entryPtr(new Entry); entryPtr->id = id; const stream_offset indexBegin = sizeof(streamLength_) + sizeof(maxIdLength_) + entrySize_ * size_; const stream_offset indexEnd = streamLength_; { boost::mutex::scoped_lock io_lock(io_mutex); isPtr_->clear(); // binary search is done directly on the index stream IndexStreamIterator itr(isPtr_, entrySize_, entryReader_, indexBegin, indexEnd); itr = lower_bound(itr, IndexStreamIterator(), *entryPtr, EntryIdLessThan()); // return null if search went to indexEnd if (itr == IndexStreamIterator()) return EntryPtr(); // update entry from iterator *entryPtr = *itr; } // return null if the returned iterator isn't exactly equal to the queried one if (entryPtr->id != id) return EntryPtr(); return entryPtr; } virtual EntryPtr find(size_t index) const { if (index >= size_) return EntryPtr(); EntryPtr entryPtr(new Entry); const stream_offset indexBegin = sizeof(streamLength_) + sizeof(maxIdLength_); const stream_offset entryOffset = indexBegin + index * entrySize_; { boost::mutex::scoped_lock io_lock(io_mutex); isPtr_->clear(); isPtr_->seekg(entryOffset); entryReader_(*isPtr_, *entryPtr); } return entryPtr; } }; PWIZ_API_DECL BinaryIndexStream::BinaryIndexStream(shared_ptr isPtr) : impl_(new Impl(isPtr)) {} PWIZ_API_DECL void BinaryIndexStream::create(vector& entries) {impl_->create(entries);} PWIZ_API_DECL size_t BinaryIndexStream::size() const {return impl_->size();} PWIZ_API_DECL Index::EntryPtr BinaryIndexStream::find(const string& id) const {return impl_->find(id);} PWIZ_API_DECL Index::EntryPtr BinaryIndexStream::find(size_t index) const {return impl_->find(index);} } // namespace data } // namespace pwiz pwiz/pwiz/data/common/ParamTypes.cpp0000664000175100017510000002211612664775620021537 0ustar teamcityteamcity00000000000000// // $Id: ParamTypes.cpp 6212 2014-05-20 22:38:47Z pcbrefugee $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "ParamTypes.hpp" #include "diff_std.hpp" #include "pwiz/utility/misc/Std.hpp" #include namespace pwiz { namespace data { // // CVParam // PWIZ_API_DECL CVParam::~CVParam() {} PWIZ_API_DECL string CVParam::name() const { return cvTermInfo(cvid).name; } PWIZ_API_DECL string CVParam::unitsName() const { return cvTermInfo(units).name; } double timeInSecondsHelper(CVID units, double value) { if (units == UO_second) return value; else if (units == UO_minute) return value * 60; else if (units == UO_hour) return value * 3600; else if (units == UO_millisecond) return value * 1e-3; else if (units == UO_microsecond) return value * 1e-6; else if (units == UO_nanosecond) return value * 1e-9; else if (units == UO_picosecond) return value * 1e-12; else if (units == MS_second_OBSOLETE) // mzML 1.0 support return value; else if (units == MS_minute_OBSOLETE) // mzML 1.0 support return value * 60; return 0; } PWIZ_API_DECL double CVParam::timeInSeconds() const { return timeInSecondsHelper(units, valueAs()); } template struct nosci_policy : boost::spirit::karma::real_policies { // we want to generate up to 12 fractional digits static unsigned int precision(T) { return 12; } // we want the numbers always to be in fixed format static int floatfield(T) { return boost::spirit::karma::real_policies::fmtflags::fixed; } }; /// convenience function to return value without scientific notation (throws if not a double) PWIZ_API_DECL std::string CVParam::valueFixedNotation() const { std::string result = value; if (std::string::npos != result.find_first_of("eE")) { using namespace boost::spirit::karma; typedef real_generator > nosci_type; static const nosci_type nosci = nosci_type(); char buffer[256]; char* p = buffer; double d = valueAs(); generate(p, nosci, d); *p = 0; result = buffer; } return result; } PWIZ_API_DECL ostream& operator<<(ostream& os, const CVParam& param) { os << cvTermInfo(param.cvid).name; if (!param.value.empty()) os << ": " << param.value; if (param.units != CVID_Unknown) os << " " << cvTermInfo(param.units).name << "(s)"; return os; } // // UserParam // PWIZ_API_DECL UserParam::UserParam(const string& _name, const string& _value, const string& _type, CVID _units) : name(_name), value(_value), type(_type), units(_units) {} PWIZ_API_DECL UserParam::~UserParam() {} PWIZ_API_DECL UserParam::UserParam(const UserParam& other) {*this = other;} PWIZ_API_DECL UserParam& UserParam::operator=(const UserParam& rhs) { name = rhs.name; value = rhs.value; type = rhs.type; units = rhs.units; return *this; } PWIZ_API_DECL double UserParam::timeInSeconds() const { return timeInSecondsHelper(units, valueAs()); } PWIZ_API_DECL bool UserParam::empty() const { return name.empty() && value.empty() && type.empty() && units==CVID_Unknown; } PWIZ_API_DECL bool UserParam::operator==(const UserParam& that) const { return (name==that.name && value==that.value && type==that.type && units==that.units); } PWIZ_API_DECL bool UserParam::operator!=(const UserParam& that) const { return !operator==(that); } // // ParamContainer // PWIZ_API_DECL CVParam ParamContainer::cvParam(CVID cvid) const { // first look in our own cvParams vector::const_iterator it = find_if(cvParams.begin(), cvParams.end(), CVParamIs(cvid)); if (it!=cvParams.end()) return *it; // then recurse into paramGroupPtrs for (vector::const_iterator jt=paramGroupPtrs.begin(); jt!=paramGroupPtrs.end(); ++jt) { CVParam result = jt->get() ? (*jt)->cvParam(cvid) : CVParam(); if (result.cvid != CVID_Unknown) return result; } return CVParam(); } PWIZ_API_DECL CVParam ParamContainer::cvParamChild(CVID cvid) const { // first look in our own cvParams vector::const_iterator it = find_if(cvParams.begin(), cvParams.end(), CVParamIsChildOf(cvid)); if (it!=cvParams.end()) return *it; // then recurse into paramGroupPtrs for (vector::const_iterator jt=paramGroupPtrs.begin(); jt!=paramGroupPtrs.end(); ++jt) { CVParam result = jt->get() ? (*jt)->cvParamChild(cvid) : CVParam(); if (result.cvid != CVID_Unknown) return result; } return CVParam(); } PWIZ_API_DECL vector ParamContainer::cvParamChildren(CVID cvid) const { vector results; // first look in our own cvParams vector::const_iterator it; BOOST_FOREACH(const CVParam& cvParam, cvParams) { if (cvIsA(cvParam.cvid, cvid)) results.push_back(cvParam); } // then recurse into paramGroupPtrs BOOST_FOREACH(const ParamGroupPtr& paramGroupPtr, paramGroupPtrs) { vector pgResults = paramGroupPtr->cvParamChildren(cvid); results.insert(results.end(), pgResults.begin(), pgResults.end()); } return results; } PWIZ_API_DECL bool ParamContainer::hasCVParam(CVID cvid) const { CVParam param = cvParam(cvid); return (param.cvid != CVID_Unknown); } PWIZ_API_DECL bool ParamContainer::hasCVParamChild(CVID cvid) const { CVParam param = cvParamChild(cvid); return (param.cvid != CVID_Unknown); } namespace { struct HasName { string name_; HasName(const string& name) : name_(name) {} bool operator()(const UserParam& userParam) {return name_ == userParam.name;} }; } // namespace PWIZ_API_DECL UserParam ParamContainer::userParam(const string& name) const { vector::const_iterator it = find_if(userParams.begin(), userParams.end(), HasName(name)); return it!=userParams.end() ? *it : UserParam(); } PWIZ_API_DECL void ParamContainer::set(CVID cvid, const string& value, CVID units) { vector::iterator it = find_if(cvParams.begin(), cvParams.end(), CVParamIs(cvid)); if (it!=cvParams.end()) { it->value = value; it->units = units; return; } cvParams.push_back(CVParam(cvid, value, units)); } template struct double12_policy : boost::spirit::karma::real_policies { // we want to generate up to 12 fractional digits static unsigned int precision(T) { return 12; } }; PWIZ_API_DECL void ParamContainer::set(CVID cvid, double value, CVID units) { // HACK: karma has a stack overflow on subnormal values, so we clamp to normalized values if (value > 0) value = max(numeric_limits::min(), value); else if (value < 0) value = min(-numeric_limits::min(), value); using namespace boost::spirit::karma; typedef real_generator > double12_type; static const double12_type double12 = double12_type(); char buffer[256]; char* p = buffer; generate(p, double12, value); set(cvid, std::string(&buffer[0], p), units); } PWIZ_API_DECL void ParamContainer::set(CVID cvid, int value, CVID units) { using namespace boost::spirit::karma; static const int_generator intgen = int_generator(); char buffer[256]; char* p = buffer; generate(p, intgen, value); set(cvid, std::string(&buffer[0], p), units); } PWIZ_API_DECL bool ParamContainer::empty() const { return paramGroupPtrs.empty() && cvParams.empty() && userParams.empty(); } PWIZ_API_DECL void ParamContainer::clear() { paramGroupPtrs.clear(); cvParams.clear(); userParams.clear(); } PWIZ_API_DECL bool ParamContainer::operator==(const ParamContainer& that) const { return !Diff(*this, that); } PWIZ_API_DECL bool ParamContainer::operator!=(const ParamContainer& that) const { return !(*this == that); } // // ParamGroup // PWIZ_API_DECL ParamGroup::ParamGroup(const string& _id) : id(_id) {} PWIZ_API_DECL bool ParamGroup::empty() const { return id.empty() && ParamContainer::empty(); } } // namespace data } // namespace pwiz pwiz/pwiz/data/common/obo.cpp0000664000175100017510000002556212664775620020241 0ustar teamcityteamcity00000000000000// // $Id: obo.cpp 6909 2014-11-19 17:18:29Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "obo.hpp" #include "boost/xpressive/xpressive_dynamic.hpp" #include "pwiz/utility/misc/Std.hpp" namespace bxp = boost::xpressive; namespace pwiz { namespace data { const Term::id_type Term::MAX_ID = std::numeric_limits::max(); namespace { // [Term] // id: MS:1000001 // name: sample number // def: "A reference number relevant to the sample under study." [PSI:MS] // relationship: part_of MS:1000548 ! sample attribute // The functions parseValue_* could be replaced by a general function that parses the whole // line into [tag, value, dbxrefs, comment] if the OBO grammar were more regular. // regex notes: // parentheses are used for submatch captures // \\d matches digit // \\s matches whitespace // \\w matches [a-zA-Z_] // OBO format has some escape characters that C++ doesn't, // so we unescape them when reading in a tag:value pair. // http://www.geneontology.org/GO.format.obo-1_2.shtml#S.1.5 string& unescape(string& str) { bal::replace_all(str, "\\!", "!"); bal::replace_all(str, "\\:", ":"); bal::replace_all(str, "\\,", ","); bal::replace_all(str, "\\(", "("); bal::replace_all(str, "\\)", ")"); bal::replace_all(str, "\\[", "["); bal::replace_all(str, "\\]", "]"); bal::replace_all(str, "\\{", "{"); bal::replace_all(str, "\\}", "}"); return str; } string unescape_copy(const string& str) { string copy(str); unescape(copy); return copy; } istream& getcleanline(istream& is, string& buffer) { if (getline(is, buffer)) bal::trim(buffer); return is; } void parse_id(const string& line, Term& term) { static const bxp::sregex e = bxp::sregex::compile("id:\\s*(\\w+):(\\d+)\\s*"); bxp::smatch what; if (!bxp::regex_match(line, what, e)) throw runtime_error("Error matching term id on line: \"" + line + "\""); term.prefix = unescape_copy(what[1]); string id = what[2]; bal::trim_left_if(id, bal::is_any_of("0")); // trim leading zeros if(id.empty()) term.id = 0; // id was all zeros else term.id = lexical_cast(unescape(id)); } void parse_name(const string& line, Term& term) { static const bxp::sregex e = bxp::sregex::compile("name:\\s*(.*?)\\s*"); bxp::smatch what; if (!bxp::regex_match(line, what, e)) throw runtime_error("Error matching term name on line: \"" + line + "\""); term.name = unescape_copy(what[1]); } void parse_def(const string& line, Term& term) { static const bxp::sregex e = bxp::sregex::compile("def:\\s*\"(OBSOLETE )?(.*)\"\\s*\\[.*\\].*"); bxp::smatch what; if (!bxp::regex_match(line, what, e)) throw runtime_error("Error matching term def on line: \"" + line + "\""); term.def = what[2]; term.isObsolete = what[1].matched; } void parse_relationship(const string& line, Term& term) { static const bxp::sregex e = bxp::sregex::compile("relationship:\\s*(\\w+) (\\w+):(\\d+).*"); bxp::smatch what; if (!bxp::regex_match(line, what, e)) throw runtime_error("Error matching term relationship on line: \"" + line + "\""); if (what[1] == "part_of") { if (what[2].str() != term.prefix) cerr << "[obo] Ignoring part_of relationship with different prefix:\n " << line << endl; else term.parentsPartOf.push_back(lexical_cast(what[3])); return; } term.relations.insert(make_pair(unescape_copy(what[1]), make_pair(what[2], lexical_cast(what[3])))); } void parse_is_obsolete(const string& line, Term& term) { static const bxp::sregex e = bxp::sregex::compile("is_obsolete:\\s*(\\w+)\\s*"); bxp::smatch what; if (!bxp::regex_match(line, what, e)) throw runtime_error("Error matching term is_obsolete on line: \"" + line + "\""); term.isObsolete = (what[1] == "true"); } void parse_is_a(const string& line, Term& term) { static const bxp::sregex e = bxp::sregex::compile("is_a:\\s*(\\w+):(\\d+).*"); bxp::smatch what; if (!bxp::regex_match(line, what, e)) throw runtime_error("Error matching term is_a on line: \"" + line + "\""); if (what[1].str() != term.prefix) { cerr << "[obo] Ignoring is_a with different prefix:\n " << line << endl; return; } term.parentsIsA.push_back(lexical_cast(what[2])); } void parse_exact_synonym(const string& line, Term& term) { static const bxp::sregex e = bxp::sregex::compile("exact_synonym:\\s*\"(.*)\".*"); bxp::smatch what; if (!bxp::regex_match(line, what, e)) throw runtime_error("Error matching term exact_synonym on line: \"" + line + "\""); term.exactSynonyms.push_back(unescape_copy(what[1])); } void parse_synonym(const string& line, Term& term) { static const bxp::sregex e = bxp::sregex::compile("synonym:\\s*\"(.*)\"\\s*(\\w+)?.*"); bxp::smatch what; if (!bxp::regex_match(line, what, e)) throw runtime_error("Error matching term synonym on line: \"" + line + "\""); if (what[2] == "EXACT") term.exactSynonyms.push_back(unescape_copy(what[1])); } void parse_property_value(const string& line, Term& term) { static const bxp::sregex e = bxp::sregex::compile("property_value:\\s*(\\S+?)\\s*[=:]?\\s*\"(.*)\".*"); bxp::smatch what; if (!bxp::regex_match(line, what, e)) throw runtime_error("Error matching term property_value on line: \"" + line + "\""); term.propertyValues.insert(make_pair(what[1], what[2])); } void parse_xref(const string& line, Term& term) { static const bxp::sregex e = bxp::sregex::compile("xref:\\s*(\\S+?)\\s*\"(.*)\".*"); bxp::smatch what; if (!bxp::regex_match(line, what, e)) throw runtime_error("Error matching term xref on line: \"" + line + "\""); term.propertyValues.insert(make_pair(unescape_copy(what[1]), unescape_copy(what[2]))); } void parseTagValuePair(const string& line, Term& term) { string::size_type tagSize = line.find(':'); if (tagSize==0 || tagSize==string::npos) throw runtime_error("[parseTagValuePair()]: No tag found on line: \"" + line + "\""); string tag = line.substr(0, tagSize); if (tag == "id") parse_id(line, term); else if (tag == "name") parse_name(line, term); else if (tag == "def") parse_def(line, term); else if (tag == "relationship") parse_relationship(line, term); else if (tag == "is_obsolete") parse_is_obsolete(line, term); else if (tag == "is_a") parse_is_a(line, term); else if (tag == "exact_synonym") parse_exact_synonym(line, term); else if (tag == "synonym") parse_synonym(line, term); else if (tag == "property_value") parse_property_value(line, term); else if (tag == "xref") parse_xref(line, term); else if (tag == "related_synonym" || tag == "narrow_synonym" || tag == "comment" || tag == "alt_id" || tag == "namespace" || tag == "xref_analog" || tag == "replaced_by" || tag == "created_by" || tag == "has_domain" || // first appeared in psi-ms.obo 3.52.0 tag == "has_order" || // first appeared in psi-ms.obo 3.52.0 tag == "subset" || // first appeared in unit.obo in rev 2755 tag == "creation_date") ; // ignore these tags else cerr << "[obo] Unknown tag \"" << tag << "\":\n " << line << endl; } Term parseTerm(istream& is) { Term result; for (string line; getcleanline(is,line) && !line.empty();) parseTagValuePair(line, result); return result; } void parseStanza(istream& is, OBO& obo) { string stanzaType; while (is && stanzaType.empty()) getcleanline(is, stanzaType); if (stanzaType == "[Term]") { Term term = parseTerm(is); // validate prefix if (obo.prefix.empty()) { obo.prefix = term.prefix; } else { if (term.prefix != obo.prefix) throw runtime_error("[obo] Prefix mismatch: " + obo.prefix + ", " + term.prefix + ":" + lexical_cast(term.id)); } // add all terms, even obsolete ones obo.terms.insert(term); } else { // ignore stanza for (string buffer; getcleanline(is,buffer) && !buffer.empty();); } } void parse(const string& filename, OBO& obo) { ifstream is(filename.c_str()); if (!is) throw runtime_error(("[obo] Unable to open file " + filename).c_str()); // read header lines until blank line for (string buffer; getcleanline(is,buffer) && !buffer.empty();) obo.header.push_back(buffer); // parse stanzas to end of file while (is) parseStanza(is, obo); } } // namespace PWIZ_API_DECL OBO::OBO(const string& _filename) : filename(_filename) { parse(filename, *this); } PWIZ_API_DECL ostream& operator<<(ostream& os, const Term& term) { os << "[Term]\n" << "id: " << term.prefix << ":" << term.id << endl << "name: " << term.name << endl << "def: \"" << term.def << "\"\n"; for (Term::id_list::const_iterator it=term.parentsIsA.begin(); it!=term.parentsIsA.end(); ++it) os << "is_a: " << term.prefix << ":" << *it << endl; for (Term::id_list::const_iterator it=term.parentsPartOf.begin(); it!=term.parentsPartOf.end(); ++it) os << "relationship: part_of " << term.prefix << ":" << *it << endl; for (Term::relation_map::const_iterator it=term.relations.begin(); it!=term.relations.end(); ++it) os << "relationship: " << it->first << " " << it->second.first << ":" << it->second.second << endl; return os; } PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const OBO& obo) { copy(obo.header.begin(), obo.header.end(), ostream_iterator(os,"\n")); os << endl; copy(obo.terms.begin(), obo.terms.end(), ostream_iterator(os,"\n")); return os; } } // namespace data } // namespace pwiz pwiz/pwiz/data/common/cvtest.cpp0000664000175100017510000001514312664775620020764 0ustar teamcityteamcity00000000000000// // $Id: cvtest.cpp 6478 2014-07-08 20:01:38Z chambm $ // // // Original author: Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/unit.hpp" #include "cv.hpp" #include "pwiz/utility/misc/Std.hpp" #include "boost/thread/thread.hpp" #include "boost/thread/barrier.hpp" #include using namespace pwiz::cv; using namespace pwiz::util; ostream* os_ = 0; void test() { if (os_) { *os_ << "name: " << cvTermInfo(MS_sample_number).name << endl << "def: " << cvTermInfo(MS_sample_number).def << "\n\n"; *os_ << "name: " << cvTermInfo(MS_scan_polarity).name << endl << "def: " << cvTermInfo(MS_scan_polarity).def << endl; } // some simple tests unit_assert(cvTermInfo(MS_sample_number).name == "sample number"); unit_assert(cvTermInfo(MS_contact_email).name == "contact email"); unit_assert(cvTermInfo(MS_contact_email).def == "Email address of the contact person or organization."); unit_assert(cvTermInfo(MS_zlib_compression).parentsIsA.size() == 1 && cvTermInfo(MS_zlib_compression).parentsIsA[0] == MS_binary_data_compression_type); unit_assert(cvTermInfo(MS_instrument_model).parentsPartOf.size() == 1 && cvTermInfo(MS_instrument_model).parentsPartOf[0] == MS_instrument); unit_assert(cvTermInfo(MS_None____OBSOLETE).isObsolete); unit_assert(cvTermInfo(MS_regular_expressions_for_a_GUID).def == "([A-Fa-f0-9]\\{8\\}-([A-Fa-f0-9]\\{4\\}-)\\{3\\}[A-Fa-f0-9]\\{12\\})."); } void testIsA() { unit_assert(cvIsA(UO_dalton, UO_mass_unit)); unit_assert(cvIsA(UO_mass_unit, UO_unit)); unit_assert(cvIsA(UO_dalton, UO_unit)); unit_assert(!cvIsA(UO_dalton, UO_energy_unit)); unit_assert(cvIsA(MS_m_z, MS_m_z)); unit_assert(cvIsA(MS_FT_ICR, MS_mass_analyzer_type)); unit_assert(cvIsA(MS_ion_trap, MS_mass_analyzer_type)); unit_assert(cvIsA(MS_linear_ion_trap, MS_mass_analyzer_type)); unit_assert(cvIsA(MS_linear_ion_trap, MS_ion_trap)); unit_assert(cvIsA(MS_radial_ejection_linear_ion_trap, MS_mass_analyzer_type)); unit_assert(cvIsA(MS_radial_ejection_linear_ion_trap, MS_ion_trap)); unit_assert(cvIsA(MS_radial_ejection_linear_ion_trap, MS_linear_ion_trap)); } void testOtherRelations() { const CVTermInfo& info = cvTermInfo(MS_accuracy); unit_assert(info.otherRelations.size() == 2); unit_assert(info.otherRelations.begin()->first == "has_units"); unit_assert(info.otherRelations.begin()->second == MS_m_z); unit_assert(info.otherRelations.rbegin()->first == "has_units"); unit_assert(info.otherRelations.rbegin()->second == UO_parts_per_million); const CVTermInfo& info2 = cvTermInfo(MS_Trypsin); unit_assert(info2.otherRelations.size() == 1); unit_assert(info2.otherRelations.begin()->first == "has_regexp"); unit_assert(info2.otherRelations.begin()->second == MS______KR_____P_); } void testSynonyms() { const CVTermInfo& info = cvTermInfo(MS_B); unit_assert(info.name == "magnetic field strength"); unit_assert(info.exactSynonyms.size() == 1); unit_assert(info.exactSynonyms[0] == "B"); unit_assert(cvTermInfo(MS_QIT).exactSynonyms.size() == 3); unit_assert(cvTermInfo(MS_chemical_ionization).shortName() == "CI"); unit_assert(cvTermInfo(MS_FT_ICR).shortName() == "FT_ICR"); unit_assert(cvTermInfo(MS_fourier_transform_ion_cyclotron_resonance_mass_spectrometer).shortName() == "FT_ICR"); unit_assert(cvTermInfo(CVID_Unknown).shortName() == "Unknown"); } void testIDTranslation() { unit_assert(cvTermInfo("MS:1000025").cvid == MS_B); unit_assert(cvTermInfo("MS:1000042").cvid == MS_peak_intensity); unit_assert(cvTermInfo("UO:0000231").cvid == UO_information_unit); unit_assert(cvTermInfo("XX:0000231").cvid == CVID_Unknown); unit_assert(cvTermInfo("FOO:").cvid == CVID_Unknown); unit_assert(cvTermInfo(":FOO").cvid == CVID_Unknown); unit_assert(cvTermInfo("MS").cvid == CVID_Unknown); } void testPropertyValues() { CVTermInfo phospho = cvTermInfo(UNIMOD_Phospho); unit_assert_operator_equal(1, phospho.propertyValues.count("delta_composition")); unit_assert_operator_equal("H O(3) P", phospho.propertyValues.find("delta_composition")->second); unit_assert_operator_equal(2, phospho.propertyValues.count("spec_1_site")); unit_assert_operator_equal("T", phospho.propertyValues.equal_range("spec_1_site").first->second); unit_assert_operator_equal("S", (--phospho.propertyValues.equal_range("spec_1_site").second)->second); unit_assert_operator_equal(1, phospho.propertyValues.count("spec_2_site")); unit_assert_operator_equal("Y", phospho.propertyValues.find("spec_2_site")->second); } void testThreadSafetyWorker(boost::barrier* testBarrier) { testBarrier->wait(); // wait until all threads have started try { test(); testIsA(); testOtherRelations(); testSynonyms(); testIDTranslation(); testPropertyValues(); } catch (exception& e) { cerr << "Exception in worker thread: " << e.what() << endl; } catch (...) { cerr << "Unhandled exception in worker thread." << endl; } } void testThreadSafety(const int& testThreadCount) { boost::barrier testBarrier(testThreadCount); boost::thread_group testThreadGroup; for (int i=0; i < testThreadCount; ++i) testThreadGroup.add_thread(new boost::thread(&testThreadSafetyWorker, &testBarrier)); testThreadGroup.join_all(); } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; try { //testThreadSafety(1); // does not test thread-safety of singleton initialization testThreadSafety(2); testThreadSafety(4); testThreadSafety(8); testThreadSafety(16); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/common/CVTranslator.hpp0000664000175100017510000000323012664775620022035 0ustar teamcityteamcity00000000000000// // $Id: CVTranslator.hpp 1656 2009-12-30 20:54:17Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // #ifndef _CVTRANSLATOR_HPP_ #define _CVTRANSLATOR_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "cv.hpp" #include "boost/shared_ptr.hpp" namespace pwiz { namespace data { /// translates text to CV terms class PWIZ_API_DECL CVTranslator { public: /// constructor -- dictionary includes all /// CV term names and exact_synonyms CVTranslator(); /// insert a text-cvid pair into the dictionary void insert(const std::string& text, cv::CVID cvid); /// translate text -> CVID cv::CVID translate(const std::string& text) const; private: class Impl; boost::shared_ptr impl_; CVTranslator(CVTranslator&); CVTranslator& operator=(CVTranslator&); }; } // namespace data } // namespace pwiz #endif // _CVTRANSLATOR_HPP_ pwiz/pwiz/data/common/BinaryIndexStream.hpp0000664000175100017510000000312512664775620023046 0ustar teamcityteamcity00000000000000// // $Id: BinaryIndexStream.hpp 1621 2009-12-15 17:43:15Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _BINARYINDEX_HPP_ #define _BINARYINDEX_HPP_ #include "Index.hpp" #include namespace pwiz { namespace data { /// index implementation in a stream (intended for fstreams but any iostream works); /// find(string id) is O(logN); /// find(ordinal index) is O(1); /// memory footprint is negligible class PWIZ_API_DECL BinaryIndexStream : public Index { public: BinaryIndexStream(boost::shared_ptr indexStreamPtr); virtual void create(std::vector& entries); virtual size_t size() const; virtual EntryPtr find(const std::string& id) const; virtual EntryPtr find(size_t index) const; private: class Impl; boost::shared_ptr impl_; }; } // namespace data } // namespace pwiz #endif // _BINARYINDEX_HPP_ pwiz/pwiz/data/common/cv.inl0000664000175100017510000001063712664775620020067 0ustar teamcityteamcity00000000000000// // $Id: cv.inl 3333 2012-04-09 20:41:05Z bpratt $ // // // Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // NOTE: // This is a code fragment - it's meant to be #included in the // cvgen-created cv.cpp file. It won't compile by itself. // // The idea is to simplify the maintenance of non-generated cv access code // by placing it in its own file. This file's contents were formerly // written to cv.cpp by cvgen, which made maintenance somewhat confusing // and awkward. // PWIZ_API_DECL bool CV::operator==(const CV& that) const { return id == that.id && fullName == that.fullName && URI == that.URI && version == that.version; } PWIZ_API_DECL bool CV::empty() const { return id.empty() && fullName.empty() && URI.empty() && version.empty(); } PWIZ_API_DECL const CV& cv(const string& prefix) { const map& cvMap = CVTermData::instance->cvMap(); if (cvMap.find(prefix) == cvMap.end()) throw invalid_argument("[cv()] no CV associated with prefix \"" + prefix + "\""); return cvMap.find(prefix)->second; } PWIZ_API_DECL const string& CVTermInfo::shortName() const { const string* result = &name; for (vector::const_iterator it=exactSynonyms.begin(); it!=exactSynonyms.end(); ++it) if (result->size() > it->size()) result = &*it; return *result; } PWIZ_API_DECL string CVTermInfo::prefix() const { return id.substr(0, id.find_first_of(":")); } PWIZ_API_DECL const CVTermInfo& cvTermInfo(CVID cvid) { const map& infoMap = CVTermData::instance->infoMap(); map::const_iterator itr = infoMap.find(cvid); if (itr == infoMap.end()) throw invalid_argument("[cvTermInfo()] no term associated with CVID \"" + lexical_cast(cvid) + "\""); return itr->second; } inline unsigned int stringToCVID(const std::string& str) { errno = 0; const char* stringToConvert = str.c_str(); const char* endOfConversion = stringToConvert; unsigned int value = (unsigned int) strtoul (stringToConvert, const_cast(&endOfConversion), 10); if (( value == 0u && stringToConvert == endOfConversion) || // error: conversion could not be performed errno != 0 ) // error: overflow or underflow throw bad_lexical_cast(); return value; } PWIZ_API_DECL const CVTermInfo& cvTermInfo(const std::string& id) { return cvTermInfo(id.c_str()); } PWIZ_API_DECL const CVTermInfo& cvTermInfo(const char* id) { if (id) for (int o=0;o& infoMap = CVTermData::instance->infoMap(); map::const_iterator find = infoMap.find(cvid); if (find == infoMap.end()) { throw out_of_range("Invalid cvParam accession \"" + lexical_cast(cvid) + "\""); } return find->second; } } return CVTermData::instance->infoMap().find(CVID_Unknown)->second; } PWIZ_API_DECL bool cvIsA(CVID child, CVID parent) { if (child == parent) return true; const CVTermInfo& info = cvTermInfo(child); for (CVTermInfo::id_list::const_iterator it=info.parentsIsA.begin(); it!=info.parentsIsA.end(); ++it) if (cvIsA(*it,parent)) return true; return false; } PWIZ_API_DECL const vector& cvids() { return CVTermData::instance->cvids(); } pwiz/pwiz/data/common/cv.hpp0000664000175100017510000230444612664775620020102 0ustar teamcityteamcity00000000000000// // $Id: cv.hpp 8981 2015-10-12 20:20:31Z chambm $ // // // Darren Kessner // // Copyright 2007 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // This file was generated by cvgen. // // Do not edit this file! Your changes will be lost next time cvgen is run - // see pwiz/scripts/misc/update_cv.bat for info on how that works. // Instead, edit cvgen.cpp itself, or the cv.inl include file if adding static // code or data. // #ifndef _CV_HPP_ #define _CV_HPP_ #include #include #include #include "pwiz/utility/misc/Export.hpp" // [psi-ms.obo] #define _PSI_MS_OBO_ // format-version: 1.2 // data-version: 3.79.0 // date: 07:10:2015 10:15 // saved-by: Gerhard Mayer // auto-generated-by: OBO-Edit 2.3 // import: http://pato.googlecode.com/svn/trunk/quality.obo // import: http://unit-ontology.googlecode.com/svn/trunk/unit.obo // default-namespace: MS // namespace-id-rule: * MS:$sequence(7,0,9999999)$ // remark: namespace: MS // remark: version: 3.79.0 // remark: release date: 2015-10-07 // remark: coverage: Mass spectrometer output files and spectra interpretation // remark: creator: Matt Chambers vanderbilt.edu> // remark: creator: Andreas Bertsch informatik.uni-tuebingen.de> // remark: creator: Marius Kallhardt bdal.de> // remark: creator: Eric Deutsch systemsbiology.org> // remark: creator: Fredrik Levander immun.lth.se> // remark: creator: Pierre-Alain Binz chuv.ch> // remark: creator: Gerhard Mayer rub.de> // remark: publisher: HUPO Proteomics Standards Initiative Mass Spectrometry Standards Working Group and HUPO Proteomics Standards Initiative Proteomics Informatics Working Group // remark: When appropriate the definition and synonyms of a term are reported exactly as in the chapter 12 of IUPAC orange book. See http://www.iupac.org/projects/2003/2003-056-2-500.html and http://mass-spec.lsu.edu/msterms/index.php/Main_Page // remark: For any queries contact psidev-ms-vocab@lists.sourceforge.net // remark: URL: http://psidev.cvs.sourceforge.net/viewvc/psidev/psi/psi-ms/mzML/controlledVocabulary/psi-ms.obo // remark: This work is licensed under the Creative Commons Attribution 3.0 Unported License. // remark: To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/ or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. // ontology: ms // // [unimod.obo] #define _UNIMOD_OBO_ // format-version: 1.2 // date: 2015:05:06 10:56 // // [unit.obo] #define _UNIT_OBO_ // format-version: 1.2 // date: 12:10:2011 11:21 // saved-by: George Gkoutos // auto-generated-by: OBO-Edit 2.1-beta13 // subsetdef: unit_group_slim "unit group slim" // subsetdef: unit_slim "unit slim" // default-namespace: unit.ontology // namespace-id-rule: * UO:$sequence(7,0,9999999)$ // import: http://purl.obolibrary.org/obo/pato.obo // namespace pwiz { namespace cv { /// enumeration of controlled vocabulary (CV) terms, generated from OBO file(s) enum PWIZ_API_DECL CVID { CVID_Unknown = -1, /// Proteomics Standards Initiative Mass Spectrometry Vocabularies: Proteomics Standards Initiative Mass Spectrometry Vocabularies. MS_Proteomics_Standards_Initiative_Mass_Spectrometry_Vocabularies = 0, /// sample number: A reference number relevant to the sample under study. MS_sample_number = 1000001, /// sample name: A reference string relevant to the sample under study. MS_sample_name = 1000002, /// sample state: The chemical phase of a pure sample, or the state of a mixed sample. MS_sample_state = 1000003, /// sample mass: Total mass of sample used. MS_sample_mass = 1000004, /// sample volume: Total volume of solution used. MS_sample_volume = 1000005, /// sample concentration: Concentration of sample in picomol/ul, femtomol/ul or attomol/ul solution used. MS_sample_concentration = 1000006, /// inlet type: The nature of the sample inlet. MS_inlet_type = 1000007, /// ionization type: The method by which gas phase ions are generated from the sample. MS_ionization_type = 1000008, /// ionization mode: Whether positive or negative ions are selected for analysis by the spectrometer. MS_ionization_mode_OBSOLETE = 1000009, /// analyzer type: The common name of the particular analyzer stage being described. Synonym of mass analyzer, should be obsoleted. MS_analyzer_type_OBSOLETE = 1000010, /// mass resolution: Smallest mass difference between two equal magnitude peaks so that the valley between them is a specified fraction of the peak height. MS_mass_resolution = 1000011, /// resolution measurement method: Which of the available standard measures is used to define whether two peaks are separate. MS_resolution_measurement_method = 1000012, /// resolution type: Specify the nature of resolution for the mass analyzer. Resolution is usually either constant with respect to m/z or proportional to m/z. MS_resolution_type_OBSOLETE = 1000013, /// accuracy: Accuracy is the degree of conformity of a measured mass to its actual value. MS_accuracy = 1000014, /// scan rate: Rate in Th/sec for scanning analyzers. MS_scan_rate = 1000015, /// scan start time: The time that an analyzer started a scan, relative to the start of the MS run. MS_scan_start_time = 1000016, /// Scan Function: Describes the type of mass analysis being performed. Two primary modes are: typical acquisition over a range of masses (Mass Scan), and Selected Ion Detection. The primary difference is that Selected Ion Detection produces a single value for the signal at the selected mass rather than producing a mass spectrum. MS_Scan_Function_OBSOLETE = 1000017, /// scan direction: Direction in terms of m/z of the scan for scanning analyzers (low to high, or high to low). MS_scan_direction = 1000018, /// scan law: Describes the function in control of the m/z scan (for scanning instruments). Commonly the scan function is linear, but in principle any function can be used. MS_scan_law = 1000019, /// scanning method: Describes the acquisition data type produced by a tandem mass spectrometry experiment. MS_scanning_method_OBSOLETE = 1000020, /// reflectron state: Status of the reflectron, turned on or off. MS_reflectron_state = 1000021, /// TOF Total Path Length: The length of the field free drift space in a time of flight mass spectrometer. MS_TOF_Total_Path_Length = 1000022, /// isolation width: The total width (i.e. not half for plus-or-minus) of the gate applied around a selected precursor ion. MS_isolation_width_OBSOLETE = 1000023, /// final MS exponent: Final MS level achieved when performing PFF with the ion trap (e.g. MS E10). MS_final_MS_exponent = 1000024, /// magnetic field strength: A property of space that produces a force on a charged particle equal to qv x B where q is the particle charge and v its velocity. MS_magnetic_field_strength = 1000025, /// B (magnetic field strength): A property of space that produces a force on a charged particle equal to qv x B where q is the particle charge and v its velocity. MS_B = MS_magnetic_field_strength, /// detector type: Type of detector used in the mass spectrometer. MS_detector_type = 1000026, /// detector acquisition mode: Method by which detector signal is acquired by the data system. MS_detector_acquisition_mode = 1000027, /// detector resolution: The resolving power of the detector to detect the smallest difference between two ions so that the valley between them is a specified fraction of the peak height. MS_detector_resolution = 1000028, /// sampling frequency: The rate of signal sampling (measurement) with respect to time. MS_sampling_frequency = 1000029, /// vendor: Name of instrument vendor. MS_vendor_OBSOLETE = 1000030, /// instrument model: Instrument model name not including the vendor's name. MS_instrument_model = 1000031, /// customization: Free text description of a single customization made to the instrument; for several modifications, use several entries. MS_customization = 1000032, /// deisotoping: The removal of isotope peaks to represent the fragment ion as one data point and is commonly done to reduce complexity. It is done in conjunction with the charge state deconvolution. MS_deisotoping = 1000033, /// charge deconvolution: The determination of the mass of an ion based on the mass spectral peaks that represent multiple-charge ions. MS_charge_deconvolution = 1000034, /// peak picking: Spectral peak processing conducted on the acquired data to convert profile data to centroided data. MS_peak_picking = 1000035, /// scan mode: OBSOLETE. MS_scan_mode_OBSOLETE = 1000036, /// polarity: Terms to describe the polarity setting of the instrument. MS_polarity_OBSOLETE = 1000037, /// minute: Acquisition time in minutes. MS_minute_OBSOLETE = 1000038, /// second: Acquisition time in seconds. MS_second_OBSOLETE = 1000039, /// m/z: Three-character symbol m/z is used to denote the quantity formed by dividing the mass of an ion in unified atomic mass units by its charge number (regardless of sign). The symbol is written in italicized lower case letters with no spaces. Note 1: The term mass-to-charge-ratio is deprecated. Mass-to-charge ratio has been used for the abscissa of a mass spectrum, although the quantity measured is not the quotient of the ion's mass to its electric charge. The three-character symbol m/z is recommended for the quantity that is the independent variable in a mass spectrum Note 2: The proposed unit thomson (Th) is deprecated. MS_m_z = 1000040, /// mass-to-charge ratio (m/z): Three-character symbol m/z is used to denote the quantity formed by dividing the mass of an ion in unified atomic mass units by its charge number (regardless of sign). The symbol is written in italicized lower case letters with no spaces. Note 1: The term mass-to-charge-ratio is deprecated. Mass-to-charge ratio has been used for the abscissa of a mass spectrum, although the quantity measured is not the quotient of the ion's mass to its electric charge. The three-character symbol m/z is recommended for the quantity that is the independent variable in a mass spectrum Note 2: The proposed unit thomson (Th) is deprecated. MS_mass_to_charge_ratio = MS_m_z, /// Th (m/z): Three-character symbol m/z is used to denote the quantity formed by dividing the mass of an ion in unified atomic mass units by its charge number (regardless of sign). The symbol is written in italicized lower case letters with no spaces. Note 1: The term mass-to-charge-ratio is deprecated. Mass-to-charge ratio has been used for the abscissa of a mass spectrum, although the quantity measured is not the quotient of the ion's mass to its electric charge. The three-character symbol m/z is recommended for the quantity that is the independent variable in a mass spectrum Note 2: The proposed unit thomson (Th) is deprecated. MS_Th = MS_m_z, /// thomson (m/z): Three-character symbol m/z is used to denote the quantity formed by dividing the mass of an ion in unified atomic mass units by its charge number (regardless of sign). The symbol is written in italicized lower case letters with no spaces. Note 1: The term mass-to-charge-ratio is deprecated. Mass-to-charge ratio has been used for the abscissa of a mass spectrum, although the quantity measured is not the quotient of the ion's mass to its electric charge. The three-character symbol m/z is recommended for the quantity that is the independent variable in a mass spectrum Note 2: The proposed unit thomson (Th) is deprecated. MS_thomson = MS_m_z, /// charge state: The charge state of the ion, single or multiple and positive or negatively charged. MS_charge_state = 1000041, /// z (charge state): The charge state of the ion, single or multiple and positive or negatively charged. MS_z = MS_charge_state, /// peak intensity: Intensity of ions as measured by the height or area of a peak in a mass spectrum. MS_peak_intensity = 1000042, /// intensity unit: Intensity units are commonly arbitrary. Detected in counts per second (cps) when using counting detectors, but measured in volts when using analog detectors. MS_intensity_unit = 1000043, /// dissociation method: Fragmentation method used for dissociation or fragmentation. MS_dissociation_method = 1000044, /// collision energy: Energy for an ion experiencing collision with a stationary gas particle resulting in dissociation of the ion. MS_collision_energy = 1000045, /// energy unit: Energy units are represented in either eV or Joules. MS_energy_unit_OBSOLETE = 1000046, /// emulsion: State if the sample is in emulsion form. MS_emulsion = 1000047, /// gaseous sample state: State if the sample is in gaseous form. MS_gaseous_sample_state = 1000048, /// liquid sample state: State if the sample is in liquid form. MS_liquid_sample_state = 1000049, /// solid sample state: State if the sample is in solid form. MS_solid_sample_state = 1000050, /// solution: State if the sample is in solution form. MS_solution = 1000051, /// suspension: State if the sample is in suspension form. MS_suspension = 1000052, /// sample batch: Sample batch lot identifier. MS_sample_batch = 1000053, /// chromatography: Chromatographic conditions used to obtain the sample. MS_chromatography_OBSOLETE = 1000054, /// continuous flow fast atom bombardment: Fast atom bombardment ionization in which the analyte in solution is entrained in a flowing liquid matrix. MS_continuous_flow_fast_atom_bombardment = 1000055, /// CF-FAB (continuous flow fast atom bombardment): Fast atom bombardment ionization in which the analyte in solution is entrained in a flowing liquid matrix. MS_CF_FAB = MS_continuous_flow_fast_atom_bombardment, /// direct inlet: The sample is directly inserted into the ion source, usually on the end of a heatable probe. MS_direct_inlet = 1000056, /// electrospray inlet: Inlet used for introducing the liquid sample into an electrospray ionization source. MS_electrospray_inlet = 1000057, /// flow injection analysis: Sample is directly injected or infused into the ionization source. MS_flow_injection_analysis = 1000058, /// inductively coupled plasma: A gas discharge ion source in which the energy to the plasma is supplied by electromagnetic induction. MS_inductively_coupled_plasma = 1000059, /// infusion: The continuous flow of solution of a sample into the ionization source. MS_infusion = 1000060, /// jet separator: A device that separates carrier gas from gaseous analyte molecules on the basis of diffusivity. MS_jet_separator = 1000061, /// membrane separator: A device to separate carrier molecules from analyte molecules on the basis of ease of diffusion across a semipermeable membrane. MS_membrane_separator = 1000062, /// moving belt: Continuous moving surface in the form of a belt which passes through an ion source carrying analyte molecules. MS_moving_belt = 1000063, /// moving wire: Continuous moving surface in the form of a wire which passes through an ion source carrying analyte molecules. MS_moving_wire = 1000064, /// open split: A division of flowing stream of liquid into two streams. MS_open_split = 1000065, /// particle beam: Method for generating ions from a solution of an analyte. MS_particle_beam = 1000066, /// reservoir: A sample inlet method involving a reservoir. MS_reservoir = 1000067, /// septum: A disc composed of a flexible material that seals the entrance to the reservoir. Can also be entrance to the vacuum chamber. MS_septum = 1000068, /// thermospray inlet: A method for generating gas phase ions from a solution of an analyte by rapid heating of the sample. MS_thermospray_inlet = 1000069, /// atmospheric pressure chemical ionization: Chemical ionization that takes place at atmospheric pressure as opposed to the reduced pressure is normally used for chemical ionization. MS_atmospheric_pressure_chemical_ionization = 1000070, /// APCI (atmospheric pressure chemical ionization): Chemical ionization that takes place at atmospheric pressure as opposed to the reduced pressure is normally used for chemical ionization. MS_APCI = MS_atmospheric_pressure_chemical_ionization, /// chemical ionization: The formation of a new ion by the reaction of a neutral species with an ion. The process may involve transfer of an electron, a proton or other charged species between the reactants. When a positive ion results from chemical ionization the term may be used without qualification. When a negative ion results the term negative ion chemical ionization should be used. Note that this term is not synonymous with chemi-ionization. MS_chemical_ionization = 1000071, /// CI (chemical ionization): The formation of a new ion by the reaction of a neutral species with an ion. The process may involve transfer of an electron, a proton or other charged species between the reactants. When a positive ion results from chemical ionization the term may be used without qualification. When a negative ion results the term negative ion chemical ionization should be used. Note that this term is not synonymous with chemi-ionization. MS_CI = MS_chemical_ionization, /// Electronic Ionization: The ionization of an atom or molecule by electrons that are typically accelerated to energies between 50 and 150 eV. Usually 70 eV electrons are used to produce positive ions. The term 'electron impact' is not recommended. MS_Electronic_Ionization_OBSOLETE = 1000072, /// EI (Electronic Ionization): The ionization of an atom or molecule by electrons that are typically accelerated to energies between 50 and 150 eV. Usually 70 eV electrons are used to produce positive ions. The term 'electron impact' is not recommended. MS_EI_OBSOLETE = MS_Electronic_Ionization_OBSOLETE, /// electrospray ionization: A process in which ionized species in the gas phase are produced from an analyte-containing solution via highly charged fine droplets, by means of spraying the solution from a narrow-bore needle tip at atmospheric pressure in the presence of a high electric field. When a pressurized gas is used to aid in the formation of a stable spray, the term pneumatically assisted electrospray ionization is used. The term ion spray is not recommended. MS_electrospray_ionization = 1000073, /// ESI (electrospray ionization): A process in which ionized species in the gas phase are produced from an analyte-containing solution via highly charged fine droplets, by means of spraying the solution from a narrow-bore needle tip at atmospheric pressure in the presence of a high electric field. When a pressurized gas is used to aid in the formation of a stable spray, the term pneumatically assisted electrospray ionization is used. The term ion spray is not recommended. MS_ESI = MS_electrospray_ionization, /// fast atom bombardment ionization: The ionization of any species by the interaction of a focused beam of neutral atoms having a translational energy of several thousand eV with a sample that is typically dissolved in a solvent matrix. See also secondary ionization. MS_fast_atom_bombardment_ionization = 1000074, /// FAB (fast atom bombardment ionization): The ionization of any species by the interaction of a focused beam of neutral atoms having a translational energy of several thousand eV with a sample that is typically dissolved in a solvent matrix. See also secondary ionization. MS_FAB = MS_fast_atom_bombardment_ionization, /// matrix-assisted laser desorption ionization: The formation of gas-phase ions from molecules that are present in a solid or solvent matrix that is irradiated with a pulsed laser. See also laser desorption/ionization. MS_matrix_assisted_laser_desorption_ionization = 1000075, /// MALDI (matrix-assisted laser desorption ionization): The formation of gas-phase ions from molecules that are present in a solid or solvent matrix that is irradiated with a pulsed laser. See also laser desorption/ionization. MS_MALDI = MS_matrix_assisted_laser_desorption_ionization, /// negative ion mode: OBSOLETE. MS_negative_ion_mode_OBSOLETE = 1000076, /// positive ion mode: OBSOLETE. MS_positive_ion_mode_OBSOLETE = 1000077, /// axial ejection linear ion trap: A linear ion trap mass spectrometer where ions are ejected along the axis of the analyzer. MS_axial_ejection_linear_ion_trap = 1000078, /// fourier transform ion cyclotron resonance mass spectrometer: A mass spectrometer based on the principle of ion cyclotron resonance in which an ion in a magnetic field moves in a circular orbit at a frequency characteristic of its m/z value. Ions are coherently excited to a larger radius orbit using a pulse of radio frequency energy and their image charge is detected on receiver plates as a time domain signal. Fourier transformation of the time domain signal results in a frequency domain signal which is converted to a mass spectrum based in the inverse relationship between frequency and m/z. MS_fourier_transform_ion_cyclotron_resonance_mass_spectrometer = 1000079, /// FT_ICR (fourier transform ion cyclotron resonance mass spectrometer): A mass spectrometer based on the principle of ion cyclotron resonance in which an ion in a magnetic field moves in a circular orbit at a frequency characteristic of its m/z value. Ions are coherently excited to a larger radius orbit using a pulse of radio frequency energy and their image charge is detected on receiver plates as a time domain signal. Fourier transformation of the time domain signal results in a frequency domain signal which is converted to a mass spectrum based in the inverse relationship between frequency and m/z. MS_FT_ICR = MS_fourier_transform_ion_cyclotron_resonance_mass_spectrometer, /// magnetic sector: A device that produces a magnetic field perpendicular to a charged particle beam that deflects the beam to an extent that is proportional to the particle momentum per unit charge. For a monoenergetic beam, the deflection is proportional to m/z. MS_magnetic_sector = 1000080, /// quadrupole: A mass spectrometer that consists of four parallel rods whose centers form the corners of a square and whose opposing poles are connected. The voltage applied to the rods is a superposition of a static potential and a sinusoidal radio frequency potential. The motion of an ion in the x and y dimensions is described by the Matthieu equation whose solutions show that ions in a particular m/z range can be transmitted along the z axis. MS_quadrupole = 1000081, /// quadrupole ion trap: Quadrupole Ion Trap mass analyzer captures the ions in a three dimensional ion trap and then selectively ejects them by varying the RF and DC potentials. MS_quadrupole_ion_trap = 1000082, /// Paul Ion trap (quadrupole ion trap): Quadrupole Ion Trap mass analyzer captures the ions in a three dimensional ion trap and then selectively ejects them by varying the RF and DC potentials. MS_Paul_Ion_trap = MS_quadrupole_ion_trap, /// QIT (quadrupole ion trap): Quadrupole Ion Trap mass analyzer captures the ions in a three dimensional ion trap and then selectively ejects them by varying the RF and DC potentials. MS_QIT = MS_quadrupole_ion_trap, /// Quistor (quadrupole ion trap): Quadrupole Ion Trap mass analyzer captures the ions in a three dimensional ion trap and then selectively ejects them by varying the RF and DC potentials. MS_Quistor = MS_quadrupole_ion_trap, /// radial ejection linear ion trap: A linear ion trap mass spectrometer where ions are ejected along the radius of the analyzer. MS_radial_ejection_linear_ion_trap = 1000083, /// time-of-flight: Instrument that separates ions by m/z in a field-free region after acceleration to a fixed acceleration energy. MS_time_of_flight = 1000084, /// TOF (time-of-flight): Instrument that separates ions by m/z in a field-free region after acceleration to a fixed acceleration energy. MS_TOF = MS_time_of_flight, /// baseline: An attribute of resolution when recording the detector response in absence of the analyte. MS_baseline = 1000085, /// full width at half-maximum: A measure of resolution represented as width of the peak at half peak height. MS_full_width_at_half_maximum = 1000086, /// FWHM (full width at half-maximum): A measure of resolution represented as width of the peak at half peak height. MS_FWHM = MS_full_width_at_half_maximum, /// ten percent valley: An attribute of resolution when the ratio between adjacent signals is 10% of the signal height. MS_ten_percent_valley = 1000087, /// constant: When resolution is constant with respect to m/z. MS_constant_OBSOLETE = 1000088, /// proportional: When resolution is proportional with respect to m/z. MS_proportional_OBSOLETE = 1000089, /// mass scan: A variation of instrument where a selected mass is scanned. MS_mass_scan_OBSOLETE = 1000090, /// selected ion detection: Please see Single Ion Monitoring. MS_selected_ion_detection_OBSOLETE = 1000091, /// decreasing m/z scan: High to low direction in terms of m/z of the scan for scanning analyzers. MS_decreasing_m_z_scan = 1000092, /// increasing m/z scan: Low to high direction in terms of m/z of the scan for scanning analyzers. MS_increasing_m_z_scan = 1000093, /// exponential: The mass scan is done in exponential mode. MS_exponential = 1000094, /// linear: The mass scan is done in linear mode. MS_linear_OBSOLETE = 1000095, /// quadratic: The mass scan is done in quadratic mode. MS_quadratic = 1000096, /// constant neutral mass loss: A spectrum formed of all product ions that have been produced with a selected m/z decrement from any precursor ions. The spectrum shown correlates to the precursor ion spectrum. See also neutral loss spectrum. MS_constant_neutral_mass_loss_OBSOLETE = 1000097, /// multiple ion monitoring: Data acquired when monitoring the ion current of a few specific m/z values. Remap to MS:1000205 -Selected Ion Monitoring. MS_multiple_ion_monitoring_OBSOLETE = 1000098, /// multiple reaction monitoring: This term is not recommended. See Selected Reaction Monitoring. MS_multiple_reaction_monitoring_OBSOLETE = 1000099, /// MRM (multiple reaction monitoring): This term is not recommended. See Selected Reaction Monitoring. MS_MRM_OBSOLETE = MS_multiple_reaction_monitoring_OBSOLETE, /// precursor ion scan: The specific scan function or process that will record a precursor ion spectrum. MS_precursor_ion_scan_OBSOLETE = 1000100, /// product ion scan: The specific scan function or process that records product ion spectrum. MS_product_ion_scan_OBSOLETE = 1000101, /// single ion monitoring: The operation of a mass spectrometer to monitor a single ion rather than scanning entire mass spectrum. MS_single_ion_monitoring_OBSOLETE = 1000102, /// single reaction monitoring: This term is not recommended. See Selected Reaction Monitoring. MS_single_reaction_monitoring_OBSOLETE = 1000103, /// None ??: None. MS_None____OBSOLETE = 1000104, /// reflectron off: Reflectron is off. MS_reflectron_off = 1000105, /// reflectron on: Reflectron is on. MS_reflectron_on = 1000106, /// channeltron: A horn-shaped (or cone-shaped) continuous dynode particle multiplier. The ion strikes the inner surface of the device and induces the production of secondary electrons that in turn impinge on the inner surfaces to produce more secondary electrons. This avalanche effect produces an increase in signal in the final measured current pulse. MS_channeltron = 1000107, /// Channeltron Detector (channeltron): A horn-shaped (or cone-shaped) continuous dynode particle multiplier. The ion strikes the inner surface of the device and induces the production of secondary electrons that in turn impinge on the inner surfaces to produce more secondary electrons. This avalanche effect produces an increase in signal in the final measured current pulse. MS_Channeltron_Detector = MS_channeltron, /// conversion dynode electron multiplier: A surface that is held at high potential so that ions striking the surface produce electrons that are subsequently detected. MS_conversion_dynode_electron_multiplier = 1000108, /// conversion dynode photomultiplier: A detector in which ions strike a conversion dynode to produce electrons that in turn generate photons through a phosphorescent screen that are detected by a photomultiplier. MS_conversion_dynode_photomultiplier = 1000109, /// daly detector: Detector consisting of a conversion dynode, scintillator and photomultiplier. The metal knob at high potential emits secondary electrons when ions impinge on the surface. The secondary electrons are accelerated onto the scintillator that produces light that is then detected by the photomultiplier detector. MS_daly_detector = 1000110, /// Daly (daly detector): Detector consisting of a conversion dynode, scintillator and photomultiplier. The metal knob at high potential emits secondary electrons when ions impinge on the surface. The secondary electrons are accelerated onto the scintillator that produces light that is then detected by the photomultiplier detector. MS_Daly = MS_daly_detector, /// electron multiplier tube: A device to amplify the current of a beam or packet of charged particles or photons by incidence upon the surface of an electrode to produce secondary electrons. MS_electron_multiplier_tube = 1000111, /// EMT (electron multiplier tube): A device to amplify the current of a beam or packet of charged particles or photons by incidence upon the surface of an electrode to produce secondary electrons. MS_EMT = MS_electron_multiplier_tube, /// faraday cup: A conducting cup or chamber that intercepts a charged particle beam and is electrically connected to a current measuring device. MS_faraday_cup = 1000112, /// focal plane array: An array of detectors for spatially disperse ion beams in which all ions simultaneously impinge on the detector plane. MS_focal_plane_array = 1000113, /// microchannel plate detector: A thin plate that contains a closely spaced array of channels that each act as a continuous dynode particle multiplier. A charged particle, fast neutral particle, or photon striking the plate causes a cascade of secondary electrons that ultimately exits the opposite side of the plate. MS_microchannel_plate_detector = 1000114, /// multichannel plate (microchannel plate detector): A thin plate that contains a closely spaced array of channels that each act as a continuous dynode particle multiplier. A charged particle, fast neutral particle, or photon striking the plate causes a cascade of secondary electrons that ultimately exits the opposite side of the plate. MS_multichannel_plate = MS_microchannel_plate_detector, /// multi-collector: A detector system commonly used in inductively coupled plasma mass spectrometers. MS_multi_collector = 1000115, /// photomultiplier: A detector for conversion of the ion/electron signal into photon(s) which are then amplified and detected. MS_photomultiplier = 1000116, /// PMT (photomultiplier): A detector for conversion of the ion/electron signal into photon(s) which are then amplified and detected. MS_PMT = MS_photomultiplier, /// analog-digital converter: Analog-to-digital converter (abbreviated ADC, A/D or A to D) is an electronic integrated circuit (i/c) that converts continuous signals to discrete digital numbers. MS_analog_digital_converter = 1000117, /// ADC (analog-digital converter): Analog-to-digital converter (abbreviated ADC, A/D or A to D) is an electronic integrated circuit (i/c) that converts continuous signals to discrete digital numbers. MS_ADC = MS_analog_digital_converter, /// pulse counting: Definition to do. MS_pulse_counting = 1000118, /// time-digital converter: A device for converting a signal of sporadic pluses into a digital representation of their time indices. MS_time_digital_converter = 1000119, /// TDC (time-digital converter): A device for converting a signal of sporadic pluses into a digital representation of their time indices. MS_TDC = MS_time_digital_converter, /// transient recorder: A detector acquisition mode used for detecting transient signals. MS_transient_recorder = 1000120, /// SCIEX instrument model: The brand of instruments from the joint venture between Applied Biosystems and MDS Analytical Technologies (formerly MDS SCIEX). Previously branded as \"Applied Biosystems|MDS SCIEX\". MS_SCIEX_instrument_model = 1000121, /// Bruker Daltonics instrument model: Bruker Daltonics' instrument model. MS_Bruker_Daltonics_instrument_model = 1000122, /// IonSpec instrument model: IonSpec corporation instrument model. MS_IonSpec_instrument_model = 1000123, /// Shimadzu instrument model: Shimadzu corporation instrument model. MS_Shimadzu_instrument_model = 1000124, /// Thermo Finnigan instrument model: ThermoFinnigan from Thermo Electron Corporation instrument model. MS_Thermo_Finnigan_instrument_model = 1000125, /// Waters instrument model: Waters Corporation instrument model. MS_Waters_instrument_model = 1000126, /// centroid spectrum: Processing of profile data to produce spectra that contains discrete peaks of zero width. Often used to reduce the size of dataset. MS_centroid_spectrum = 1000127, /// Discrete Mass Spectrum (centroid spectrum): Processing of profile data to produce spectra that contains discrete peaks of zero width. Often used to reduce the size of dataset. MS_Discrete_Mass_Spectrum = MS_centroid_spectrum, /// profile spectrum: A profile mass spectrum is created when data is recorded with ion current (counts per second) on one axis and mass/charge ratio on another axis. MS_profile_spectrum = 1000128, /// continuous mass spectrum (profile spectrum): A profile mass spectrum is created when data is recorded with ion current (counts per second) on one axis and mass/charge ratio on another axis. MS_continuous_mass_spectrum = MS_profile_spectrum, /// Continuum Mass Spectrum (profile spectrum): A profile mass spectrum is created when data is recorded with ion current (counts per second) on one axis and mass/charge ratio on another axis. MS_Continuum_Mass_Spectrum = MS_profile_spectrum, /// negative scan: Polarity of the scan is negative. MS_negative_scan = 1000129, /// positive scan: Polarity of the scan is positive. MS_positive_scan = 1000130, /// number of detector counts: The number of counted events observed in one or a group of elements of a detector. MS_number_of_detector_counts = 1000131, /// percent of base peak: The magnitude of a peak or measurement element expressed in terms of the percentage of the magnitude of the base peak intensity. MS_percent_of_base_peak = 1000132, /// collision-induced dissociation: The dissociation of an ion after collisional excitation. The term collisional-activated dissociation is not recommended. MS_collision_induced_dissociation = 1000133, /// CID (collision-induced dissociation): The dissociation of an ion after collisional excitation. The term collisional-activated dissociation is not recommended. MS_CID = MS_collision_induced_dissociation, /// CAD (collision-induced dissociation): The dissociation of an ion after collisional excitation. The term collisional-activated dissociation is not recommended. MS_CAD = MS_collision_induced_dissociation, /// collisionally activated dissociation (collision-induced dissociation): The dissociation of an ion after collisional excitation. The term collisional-activated dissociation is not recommended. MS_collisionally_activated_dissociation = MS_collision_induced_dissociation, /// plasma desorption: The ionization of material in a solid sample by bombarding it with ionic or neutral atoms formed as a result of the fission of a suitable nuclide, typically 252Cf. Synonymous with fission fragment ionization. MS_plasma_desorption = 1000134, /// PD (plasma desorption): The ionization of material in a solid sample by bombarding it with ionic or neutral atoms formed as a result of the fission of a suitable nuclide, typically 252Cf. Synonymous with fission fragment ionization. MS_PD = MS_plasma_desorption, /// post-source decay: A technique specific to reflectron time-of-flight mass spectrometers where product ions of metastable transitions or collision-induced dissociations generated in the drift tube prior to entering the reflectron are m/z separated to yield product ion spectra. MS_post_source_decay = 1000135, /// PSD (post-source decay): A technique specific to reflectron time-of-flight mass spectrometers where product ions of metastable transitions or collision-induced dissociations generated in the drift tube prior to entering the reflectron are m/z separated to yield product ion spectra. MS_PSD = MS_post_source_decay, /// surface-induced dissociation: Fragmentation that results from the collision of an ion with a surface. MS_surface_induced_dissociation = 1000136, /// SID (surface-induced dissociation): Fragmentation that results from the collision of an ion with a surface. MS_SID = MS_surface_induced_dissociation, /// electron volt: A non-SI unit of energy (eV) defined as the energy acquired by a particle containing one unit of charge through a potential difference of one volt. An electron-volt is equal to 1.602 176 53(14) x 10^-19 J. MS_electron_volt_OBSOLETE = 1000137, /// eV (electron volt): A non-SI unit of energy (eV) defined as the energy acquired by a particle containing one unit of charge through a potential difference of one volt. An electron-volt is equal to 1.602 176 53(14) x 10^-19 J. MS_eV_OBSOLETE = MS_electron_volt_OBSOLETE, /// normalized collision energy: Instrument setting, expressed in percent, for adjusting collisional energies of ions in an effort to provide equivalent excitation of all ions. MS_normalized_collision_energy = 1000138, /// 4000 QTRAP: Applied Biosystems/MDS SCIEX Q 4000 TRAP MS. MS_4000_QTRAP = 1000139, /// 4700 Proteomics Analyzer: Applied Biosystems/MDS SCIEX 4700 Proteomics Analyzer MS. MS_4700_Proteomics_Analyzer = 1000140, /// apex IV: Bruker Daltonics' apex IV: ESI, MALDI, Nanospray, APCI, APPI, Qh-FT_ICR. MS_apex_IV = 1000141, /// apex Q: Bruker Daltonics' apex Q: ESI, MALDI, Nanospray, APCI, APPI, Qh-FT_ICR. MS_apex_Q = 1000142, /// API 150EX: Applied Biosystems/MDS SCIEX API 150EX MS. MS_API_150EX = 1000143, /// API 150EX Prep: Applied Biosystems/MDS SCIEX API 150EX Prep MS. MS_API_150EX_Prep = 1000144, /// API 2000: Applied Biosystems/MDS SCIEX API 2000 MS. MS_API_2000 = 1000145, /// API 3000: Applied Biosystems/MDS SCIEX API 3000 MS. MS_API_3000 = 1000146, /// API 4000: Applied Biosystems/MDS SCIEX API 4000 MS. MS_API_4000 = 1000147, /// autoflex II: Bruker Daltonics' autoflex II: MALDI TOF. MS_autoflex_II = 1000148, /// autoflex TOF/TOF: Bruker Daltonics' autoflex TOF/TOF MS: MALDI TOF. MS_autoflex_TOF_TOF = 1000149, /// Auto Spec Ultima NT: Waters AutoSpec Ultima NT MS. MS_Auto_Spec_Ultima_NT = 1000150, /// BioTOF II: Bruker Daltonics' BioTOF II: ESI TOF. MS_BioTOF_II = 1000151, /// BioTOF-Q: Bruker Daltonics' BioTOF-Q: ESI Q-TOF. MS_BioTOF_Q = 1000152, /// DELTA plusAdvantage: ThermoFinnigan DELTA plusAdvantage MS. MS_DELTA_plusAdvantage = 1000153, /// DELTAplusXP: ThermoFinnigan DELTAplusXP MS. MS_DELTAplusXP = 1000154, /// ELEMENT2: ThermoFinnigan ELEMENT2 MS. MS_ELEMENT2_OBSOLETE = 1000155, /// esquire 4000: Bruker Daltonics' esquire 4000: linear ion trap, ESI, MALDI, Nanospray, APCI, APPI. MS_esquire_4000 = 1000156, /// esquire 6000: Bruker Daltonics' esquire 6000: linear ion trap, ESI, MALDI, Nanospray, APCI, APPI. MS_esquire_6000 = 1000157, /// explorer: IonSpec Explorer MS. MS_explorer = 1000158, /// GCT: Waters oa-ToF based GCT. MS_GCT = 1000159, /// HCT: Bruker Daltonics' HCT: ESI Q-TOF, Nanospray, APCI, APPI. MS_HCT = 1000160, /// HCTplus: Bruker Daltonics' HCTplus: ESI Q-TOF, Nanospray, APCI, APPI. MS_HCTplus = 1000161, /// HiRes ESI: IonSpec HiResESI MS. MS_HiRes_ESI = 1000162, /// HiRes MALDI: IonSpec HiResMALDI MS. MS_HiRes_MALDI = 1000163, /// IsoPrime: Waters IsoPrime MS. MS_IsoPrime = 1000164, /// IsoProbe: Waters IsoProbe MS. MS_IsoProbe = 1000165, /// IsoProbe T: Waters IsoProbe T MS. MS_IsoProbe_T = 1000166, /// LCQ Advantage: ThermoFinnigan LCQ Advantage MS. MS_LCQ_Advantage = 1000167, /// LCQ Classic: ThermoFinnigan LCQ Classic MS. MS_LCQ_Classic = 1000168, /// LCQ Deca XP Plus: ThermoFinnigan LCQ Deca XP Plus MS. MS_LCQ_Deca_XP_Plus = 1000169, /// M@LDI L: Waters oa-ToF based MALDI L. MS_M_LDI_L = 1000170, /// M@LDI LR: Waters oa-ToF based MALDI LR. MS_M_LDI_LR = 1000171, /// MAT253: ThermoFinnigan MAT253 MS. MS_MAT253 = 1000172, /// MAT900XP: ThermoFinnigan MAT900XP MS. MS_MAT900XP = 1000173, /// MAT900XP Trap: ThermoFinnigan MAT900XP Trap MS. MS_MAT900XP_Trap = 1000174, /// MAT95XP: ThermoFinnigan MAT95XP MS. MS_MAT95XP = 1000175, /// MAT95XP Trap: ThermoFinnigan MAT95XP Trap MS. MS_MAT95XP_Trap = 1000176, /// microflex: Bruker Daltonics' microflex: MALDI TOF. MS_microflex = 1000177, /// microTOF LC: Bruker Daltonics' microTOF LC: ESI TOF, Nanospray, APCI, APPI. MS_microTOF_LC = 1000178, /// neptune: ThermoFinnigan NEPTUNE MS. MS_neptune = 1000179, /// NG-5400: Waters NG-5400 MS. MS_NG_5400 = 1000180, /// OMEGA: IonSpec OMEGA MS. MS_OMEGA = 1000181, /// OMEGA-2001: IonSpec OMEGA-2001 MS. MS_OMEGA_2001 = 1000182, /// OmniFlex: Bruker Daltonics' OmniFlex: MALDI TOF. MS_OmniFlex = 1000183, /// Platform ICP: Waters Platform ICP MS. MS_Platform_ICP = 1000184, /// PolarisQ: ThermoFinnigan PolarisQ MS. MS_PolarisQ = 1000185, /// proteomics solution 1: Applied Biosystems/MDS SCIEX Proteomics Solution 1 MS. MS_proteomics_solution_1 = 1000186, /// Q TRAP: Applied Biosystems/MDS SCIEX Q TRAP MS. MS_Q_TRAP = 1000187, /// Q-Tof micro: Waters oa-ToF based Q-Tof micro. MS_Q_Tof_micro = 1000188, /// Q-Tof ultima: Waters oa-ToF based Q-Tof Ultima. MS_Q_Tof_ultima = 1000189, /// QSTAR: Applied Biosystems/MDS SCIEX QSTAR MS. MS_QSTAR = 1000190, /// quattro micro: Waters oa-ToF based micro. MS_quattro_micro = 1000191, /// Quattro UItima: Waters oa-ToF based Ultima. MS_Quattro_UItima = 1000192, /// Surveyor MSQ: ThermoFinnigan Surveyor MSQ MS. MS_Surveyor_MSQ = 1000193, /// SymBiot I: Applied Biosystems/MDS SCIEX SymBiot I MS. MS_SymBiot_I = 1000194, /// SymBiot XVI: Applied Biosystems/MDS SCIEX SymBiot XVI MS. MS_SymBiot_XVI = 1000195, /// TEMPUS TOF: ThermoFinnigan TEMPUS TOF MS. MS_TEMPUS_TOF = 1000196, /// TRACE DSQ: ThermoFinnigan TRACE DSQ MS. MS_TRACE_DSQ = 1000197, /// TRITON: ThermoFinnigan TRITON MS. MS_TRITON = 1000198, /// TSQ Quantum: ThermoFinnigan TSQ Quantum MS. MS_TSQ_Quantum = 1000199, /// ultima: IonSpec Ultima MS. MS_ultima = 1000200, /// ultraflex: Bruker Daltonics' ultraflex: MALDI TOF. MS_ultraflex = 1000201, /// ultraflex TOF/TOF: Bruker Daltonics' ultraflex TOF/TOF: MALDI TOF. MS_ultraflex_TOF_TOF = 1000202, /// Voyager-DE PRO: Applied Biosystems/MDS SCIEX Voyager-DE PRO MS. MS_Voyager_DE_PRO = 1000203, /// Voyager-DE STR: Applied Biosystems/MDS SCIEX Voyager-DE STR MS. MS_Voyager_DE_STR = 1000204, /// selected ion monitoring: The operation of a mass spectrometer in which the intensities of several specific m/z values are recorded rather than the entire mass spectrum. MS_selected_ion_monitoring = 1000205, /// Multiple Ion Monitoring (selected ion monitoring): The operation of a mass spectrometer in which the intensities of several specific m/z values are recorded rather than the entire mass spectrum. MS_Multiple_Ion_Monitoring = MS_selected_ion_monitoring, /// SIM (selected ion monitoring): The operation of a mass spectrometer in which the intensities of several specific m/z values are recorded rather than the entire mass spectrum. MS_SIM = MS_selected_ion_monitoring, /// selected reaction monitoring: Data acquired from specific product ions corresponding to m/z selected precursor ions recorded via multiple stages of mass spectrometry. Selected reaction monitoring can be performed in time or in space. MS_selected_reaction_monitoring = 1000206, /// SRM (selected reaction monitoring): Data acquired from specific product ions corresponding to m/z selected precursor ions recorded via multiple stages of mass spectrometry. Selected reaction monitoring can be performed in time or in space. MS_SRM = MS_selected_reaction_monitoring, /// accurate mass: An experimentally determined mass that is can be to determine a unique elemental formula. For ions less than 200 u, a measurement with 5 ppm accuracy is sufficient to determine the elemental composition. MS_accurate_mass_OBSOLETE = 1000207, /// average mass: The mass of an ion or molecule calculated using the average mass of each element weighted for its natural isotopic abundance. MS_average_mass_OBSOLETE = 1000208, /// appearance energy: The minimum energy that must be imparted to an atom or molecule to produce a specified ion. The term appearance potential is not recommended. MS_appearance_energy_OBSOLETE = 1000209, /// AE (appearance energy): The minimum energy that must be imparted to an atom or molecule to produce a specified ion. The term appearance potential is not recommended. MS_AE_OBSOLETE = MS_appearance_energy_OBSOLETE, /// base peak: The peak in a mass spectrum that has the greatest intensity. This term may be applied to the spectra of pure substances or mixtures. MS_base_peak = 1000210, /// BP (base peak): The peak in a mass spectrum that has the greatest intensity. This term may be applied to the spectra of pure substances or mixtures. MS_BP = MS_base_peak, /// OBSOLETE charge number: OBSOLETE. The total charge on an ion divided by the electron charge e. OBSOLETED 2009-10-27 since this was viewed as a duplication of 00041 charge state. MS_OBSOLETE_charge_number_OBSOLETE = 1000211, /// z (OBSOLETE charge number): OBSOLETE. The total charge on an ion divided by the electron charge e. OBSOLETED 2009-10-27 since this was viewed as a duplication of 00041 charge state. MS_z_OBSOLETE = MS_OBSOLETE_charge_number_OBSOLETE, /// dalton: A non-SI unit of mass (symbol Da) that is equal to the unified atomic mass unit: 1.660 538 86(28) x 10^-27 kg. MS_dalton_OBSOLETE = 1000212, /// Da (dalton): A non-SI unit of mass (symbol Da) that is equal to the unified atomic mass unit: 1.660 538 86(28) x 10^-27 kg. MS_Da_OBSOLETE = MS_dalton_OBSOLETE, /// electron affinity: The electron affinity of M is the minimum energy required for the process M- ? M + e where M- and M are in their ground rotational, vibrational and electronic states and the electron has zero kinetic energy. MS_electron_affinity_OBSOLETE = 1000213, /// EA (electron affinity): The electron affinity of M is the minimum energy required for the process M- ? M + e where M- and M are in their ground rotational, vibrational and electronic states and the electron has zero kinetic energy. MS_EA_OBSOLETE = MS_electron_affinity_OBSOLETE, /// electron energy obsolete: The potential difference through which electrons are accelerated before they are used to bring about electron ionization. MS_electron_energy_obsolete_OBSOLETE = 1000214, /// exact mass: The calculated mass of an ion or molecule containing a single isotope of each atom. MS_exact_mass_OBSOLETE = 1000215, /// field-free region: A section of a mass spectrometer in which there are no electric or magnetic fields. MS_field_free_region = 1000216, /// FFR (field-free region): A section of a mass spectrometer in which there are no electric or magnetic fields. MS_FFR = MS_field_free_region, /// ionization cross section: A measure of the probability that a given ionization process will occur when an atom or molecule interacts with a photon, electron, atom or molecule. MS_ionization_cross_section_OBSOLETE = 1000217, /// ionization efficiency: The ratio of the number of ions formed to the number of electrons, molecules or photons used. MS_ionization_efficiency_OBSOLETE = 1000218, /// ionization energy: The minimum energy required to remove an electron from an atom or molecule to produce a positive ion. MS_ionization_energy_OBSOLETE = 1000219, /// IE (ionization energy): The minimum energy required to remove an electron from an atom or molecule to produce a positive ion. MS_IE_OBSOLETE = MS_ionization_energy_OBSOLETE, /// isotope dilution mass spectrometry: A quantitative mass spectrometry technique in which an isotopically enriched compound is used as an internal standard. MS_isotope_dilution_mass_spectrometry_OBSOLETE = 1000220, /// IDMS (isotope dilution mass spectrometry): A quantitative mass spectrometry technique in which an isotopically enriched compound is used as an internal standard. MS_IDMS_OBSOLETE = MS_isotope_dilution_mass_spectrometry_OBSOLETE, /// magnetic deflection: The deflection of charged particles in a magnetic field due to a force equal to qvxB where q is the particle charge, v its velocity and B the magnetic field. Magnetic deflection of an ion beam is used for m/z separation in a magnetic sector mass spectrometer. MS_magnetic_deflection = 1000221, /// mass defect: The difference between the monoisotopic and nominal mass of a molecule or atom. MS_mass_defect_OBSOLETE = 1000222, /// mass number: The sum of the protons and neutrons in an atom, molecule or ion. MS_mass_number_OBSOLETE = 1000223, /// molecular mass: The mass of one mole of a molecular substance (6.022 1415(10) x 10^23 molecules). MS_molecular_mass_OBSOLETE = 1000224, /// monoisotopic mass: The mass of an ion or molecule calculated using the mass of the most abundant isotope of each element. MS_monoisotopic_mass_OBSOLETE = 1000225, /// molecular beam mass spectrometry: A mass spectrometry technique in which the sample is introduced into the mass spectrometer as a molecular beam. MS_molecular_beam_mass_spectrometry_OBSOLETE = 1000226, /// MBMS (molecular beam mass spectrometry): A mass spectrometry technique in which the sample is introduced into the mass spectrometer as a molecular beam. MS_MBMS_OBSOLETE = MS_molecular_beam_mass_spectrometry_OBSOLETE, /// multiphoton ionization: Photoionization of an atom or molecule in which in two or more photons are absorbed. MS_multiphoton_ionization = 1000227, /// MPI (multiphoton ionization): Photoionization of an atom or molecule in which in two or more photons are absorbed. MS_MPI = MS_multiphoton_ionization, /// nitrogen rule: An organic molecule containing the elements C, H, O, S, P, or halogen has an odd nominal mass if it contains an odd number of nitrogen atoms. MS_nitrogen_rule_OBSOLETE = 1000228, /// nominal mass: The mass of an ion or molecule calculated using the mass of the most abundant isotope of each element rounded to the nearest integer value. MS_nominal_mass_OBSOLETE = 1000229, /// odd-electron rule: Odd-electron ions may dissociate to form either odd or even-electron ions, whereas even-electron ions generally form even-electron fragment ions. MS_odd_electron_rule_OBSOLETE = 1000230, /// peak: A localized region of relatively large ion signal in a mass spectrum. Although peaks are often associated with particular ions, the terms peak and ion should not be used interchangeably. MS_peak = 1000231, /// peak intensity: The height or area of a peak in a mass spectrum. MS_peak_intensity_OBSOLETE = 1000232, /// proton affinity: The proton affinity of a species M is defined as the negative of the enthalpy change for the reaction M + H+ ->[M+H]+, where all species are in their ground rotational, vibrational and electronic states. MS_proton_affinity_OBSOLETE = 1000233, /// PA (proton affinity): The proton affinity of a species M is defined as the negative of the enthalpy change for the reaction M + H+ ->[M+H]+, where all species are in their ground rotational, vibrational and electronic states. MS_PA_OBSOLETE = MS_proton_affinity_OBSOLETE, /// mass resolving power: In a mass spectrum, the observed mass divided by the difference between two masses that can be separated. The method by which delta m was obtained and the mass at which the measurement was made should be reported. MS_mass_resolving_power_OBSOLETE = 1000234, /// total ion current chromatogram: Chromatogram obtained by plotting the total ion current detected in each of a series of mass spectra recorded as a function of retention time. MS_total_ion_current_chromatogram = 1000235, /// TIC chromatogram (total ion current chromatogram): Chromatogram obtained by plotting the total ion current detected in each of a series of mass spectra recorded as a function of retention time. MS_TIC_chromatogram = MS_total_ion_current_chromatogram, /// transmission: The ratio of the number of ions leaving a region of a mass spectrometer to the number entering that region. MS_transmission = 1000236, /// unified atomic mass unit: A non-SI unit of mass (u) defined as one twelfth of ^12 C in its ground state and equal to 1.660 538 86(28) x 10^-27 kg. MS_unified_atomic_mass_unit_OBSOLETE = 1000237, /// u (unified atomic mass unit): A non-SI unit of mass (u) defined as one twelfth of ^12 C in its ground state and equal to 1.660 538 86(28) x 10^-27 kg. MS_u_OBSOLETE = MS_unified_atomic_mass_unit_OBSOLETE, /// accelerator mass spectrometry: A mass spectrometry technique in which atoms extracted from a sample are ionized, accelerated to MeV energies and separated according to their momentum, charge and energy. MS_accelerator_mass_spectrometry_OBSOLETE = 1000238, /// AMS (accelerator mass spectrometry): A mass spectrometry technique in which atoms extracted from a sample are ionized, accelerated to MeV energies and separated according to their momentum, charge and energy. MS_AMS_OBSOLETE = MS_accelerator_mass_spectrometry_OBSOLETE, /// atmospheric pressure matrix-assisted laser desorption ionization: Matrix-assisted laser desorption ionization in which the sample target is at atmospheric pressure and the ions formed by the pulsed laser are sampled through a small aperture into the mass spectrometer. MS_atmospheric_pressure_matrix_assisted_laser_desorption_ionization = 1000239, /// AP MALDI (atmospheric pressure matrix-assisted laser desorption ionization): Matrix-assisted laser desorption ionization in which the sample target is at atmospheric pressure and the ions formed by the pulsed laser are sampled through a small aperture into the mass spectrometer. MS_AP_MALDI = MS_atmospheric_pressure_matrix_assisted_laser_desorption_ionization, /// atmospheric pressure ionization: Any ionization process in which ions are formed in the gas phase at atmospheric pressure. MS_atmospheric_pressure_ionization = 1000240, /// API (atmospheric pressure ionization): Any ionization process in which ions are formed in the gas phase at atmospheric pressure. MS_API = MS_atmospheric_pressure_ionization, /// Atmostpheric Pressure Photoionization: Atmospheric pressure chemical ionization in which the reactant ions are generated by photo-ionization. MS_Atmostpheric_Pressure_Photoionization_OBSOLETE = 1000241, /// APPI (Atmostpheric Pressure Photoionization): Atmospheric pressure chemical ionization in which the reactant ions are generated by photo-ionization. MS_APPI_OBSOLETE = MS_Atmostpheric_Pressure_Photoionization_OBSOLETE, /// blackbody infrared radiative dissociation: A special case of infrared multiphoton dissociation wherein excitation of the reactant ion is caused by absorption of infrared photons radiating from heated blackbody surroundings, which are usually the walls of a vacuum chamber. See also infrared multiphoton dissociation. MS_blackbody_infrared_radiative_dissociation = 1000242, /// BIRD (blackbody infrared radiative dissociation): A special case of infrared multiphoton dissociation wherein excitation of the reactant ion is caused by absorption of infrared photons radiating from heated blackbody surroundings, which are usually the walls of a vacuum chamber. See also infrared multiphoton dissociation. MS_BIRD = MS_blackbody_infrared_radiative_dissociation, /// charge-remote fragmentation: A fragmentation of an even-electron ion in which the cleaved bond is not adjacent to the apparent charge site. MS_charge_remote_fragmentation_OBSOLETE = 1000243, /// CRF (charge-remote fragmentation): A fragmentation of an even-electron ion in which the cleaved bond is not adjacent to the apparent charge site. MS_CRF_OBSOLETE = MS_charge_remote_fragmentation_OBSOLETE, /// consecutive reaction monitoring: MSn experiment with three or more stages of m/z separation and in which a particular multi-step reaction path is monitored. MS_consecutive_reaction_monitoring_OBSOLETE_1000244 = 1000244, /// CRM (consecutive reaction monitoring): MSn experiment with three or more stages of m/z separation and in which a particular multi-step reaction path is monitored. MS_CRM_OBSOLETE = MS_consecutive_reaction_monitoring_OBSOLETE_1000244, /// charge stripping: The reaction of a positive ion with an atom or molecule that results in the removal of one or more electrons from the ion. MS_charge_stripping = 1000245, /// CS (charge stripping): The reaction of a positive ion with an atom or molecule that results in the removal of one or more electrons from the ion. MS_CS = MS_charge_stripping, /// delayed extraction: The application of the accelerating voltage pulse after a time delay in desorption ionization from a surface. The extraction delay can produce energy focusing in a time-of-flight mass spectrometer. MS_delayed_extraction = 1000246, /// DE (delayed extraction): The application of the accelerating voltage pulse after a time delay in desorption ionization from a surface. The extraction delay can produce energy focusing in a time-of-flight mass spectrometer. MS_DE = MS_delayed_extraction, /// desorption ionization: The formation of ions from a solid or liquid material after the rapid vaporization of that sample. MS_desorption_ionization = 1000247, /// DI (desorption ionization): The formation of ions from a solid or liquid material after the rapid vaporization of that sample. MS_DI = MS_desorption_ionization, /// direct insertion probe: A device for introducing a solid or liquid sample into a mass spectrometer ion source for desorption ionization. MS_direct_insertion_probe = 1000248, /// DIP (direct insertion probe): A device for introducing a solid or liquid sample into a mass spectrometer ion source for desorption ionization. MS_DIP = MS_direct_insertion_probe, /// direct liquid introduction: The delivery of a liquid sample into a mass spectrometer for spray or desorption ionization. MS_direct_liquid_introduction = 1000249, /// DLI (direct liquid introduction): The delivery of a liquid sample into a mass spectrometer for spray or desorption ionization. MS_DLI = MS_direct_liquid_introduction, /// electron capture dissociation: A process in which a multiply protonated molecules interacts with a low energy electrons. Capture of the electron leads the liberation of energy and a reduction in charge state of the ion with the production of the (M + nH) (n-1)+ odd electron ion, which readily fragments. MS_electron_capture_dissociation = 1000250, /// ECD (electron capture dissociation): A process in which a multiply protonated molecules interacts with a low energy electrons. Capture of the electron leads the liberation of energy and a reduction in charge state of the ion with the production of the (M + nH) (n-1)+ odd electron ion, which readily fragments. MS_ECD = MS_electron_capture_dissociation, /// even-electron ion: An ion containing no unpaired electrons in its ground electronic state, e.g. CH3+ in its ground state. MS_even_electron_ion_OBSOLETE = 1000251, /// EE (even-electron ion): An ion containing no unpaired electrons in its ground electronic state, e.g. CH3+ in its ground state. MS_EE_OBSOLETE = MS_even_electron_ion_OBSOLETE, /// electron-induced excitation in organics: The reaction of an ion with an electron in which the translational energy of the collision is converted into internal energy of the ion. MS_electron_induced_excitation_in_organics_OBSOLETE = 1000252, /// EIEIO (electron-induced excitation in organics): The reaction of an ion with an electron in which the translational energy of the collision is converted into internal energy of the ion. MS_EIEIO_OBSOLETE = MS_electron_induced_excitation_in_organics_OBSOLETE, /// electron multiplier: A device to amplify the current of a beam or packet of charged particles or photons by incidence upon the surface of an electrode to produce secondary electrons. The secondary electrons are then accelerated to other electrodes or parts of a continuous electrode to produce further secondary electrons. MS_electron_multiplier = 1000253, /// EM (electron multiplier): A device to amplify the current of a beam or packet of charged particles or photons by incidence upon the surface of an electrode to produce secondary electrons. The secondary electrons are then accelerated to other electrodes or parts of a continuous electrode to produce further secondary electrons. MS_EM = MS_electron_multiplier, /// electrostatic energy analyzer: A device consisting of conducting parallel plates, concentric cylinders or concentric spheres that separates charged particles according to their kinetic energy by means of an electric field that is constant in time. MS_electrostatic_energy_analyzer = 1000254, /// ESA (electrostatic energy analyzer): A device consisting of conducting parallel plates, concentric cylinders or concentric spheres that separates charged particles according to their kinetic energy by means of an electric field that is constant in time. MS_ESA = MS_electrostatic_energy_analyzer, /// flowing afterglow: An ion source immersed in a flow of helium or other inert buffer gas that carries the ions through a meter-long reactor at pressures around 100 Pa. MS_flowing_afterglow = 1000255, /// FA (flowing afterglow): An ion source immersed in a flow of helium or other inert buffer gas that carries the ions through a meter-long reactor at pressures around 100 Pa. MS_FA = MS_flowing_afterglow, /// high-field asymmetric waveform ion mobility spectrometry: The separation of ions between two concentric cylindrical electrodes due to application of a high voltage asymmetric waveform whereby ions migrate towards one of the two electrodes depending on the ratio of the high- to low-field mobility of the ion. MS_high_field_asymmetric_waveform_ion_mobility_spectrometry_OBSOLETE = 1000256, /// FAIMS (high-field asymmetric waveform ion mobility spectrometry): The separation of ions between two concentric cylindrical electrodes due to application of a high voltage asymmetric waveform whereby ions migrate towards one of the two electrodes depending on the ratio of the high- to low-field mobility of the ion. MS_FAIMS_OBSOLETE = MS_high_field_asymmetric_waveform_ion_mobility_spectrometry_OBSOLETE, /// field desorption: The formation of gas-phase ions from a material deposited on a solid surface in the presence of a high electric field. Because this process may encompass ionization by field ionization or other mechanisms, it is not recommended as a synonym for field desorption ionization. MS_field_desorption = 1000257, /// FD (field desorption): The formation of gas-phase ions from a material deposited on a solid surface in the presence of a high electric field. Because this process may encompass ionization by field ionization or other mechanisms, it is not recommended as a synonym for field desorption ionization. MS_FD = MS_field_desorption, /// field ionization: The removal of electrons from any species by interaction with a high electric field. MS_field_ionization = 1000258, /// FI (field ionization): The removal of electrons from any species by interaction with a high electric field. MS_FI = MS_field_ionization, /// glow discharge ionization: The formation of ions in the gas phase and from solid samples at the cathode by application of a voltage to a low pressure gas. MS_glow_discharge_ionization = 1000259, /// GD-MS (glow discharge ionization): The formation of ions in the gas phase and from solid samples at the cathode by application of a voltage to a low pressure gas. MS_GD_MS = MS_glow_discharge_ionization, /// ion kinetic energy spectrometry: A method of analysis in which a beam of ions is separated according to the ratio of its translational energy to charge. MS_ion_kinetic_energy_spectrometry_OBSOLETE = 1000260, /// IKES (ion kinetic energy spectrometry): A method of analysis in which a beam of ions is separated according to the ratio of its translational energy to charge. MS_IKES_OBSOLETE = MS_ion_kinetic_energy_spectrometry_OBSOLETE, /// ion mobility spectrometry: The separation of ions according to their velocity through a buffer gas under the influence of an electric field. MS_ion_mobility_spectrometry_OBSOLETE = 1000261, /// IMS (ion mobility spectrometry): The separation of ions according to their velocity through a buffer gas under the influence of an electric field. MS_IMS_OBSOLETE = MS_ion_mobility_spectrometry_OBSOLETE, /// infrared multiphoton dissociation: Multiphoton ionization where the reactant ion dissociates as a result of the absorption of multiple infrared photons. MS_infrared_multiphoton_dissociation = 1000262, /// IRMPD (infrared multiphoton dissociation): Multiphoton ionization where the reactant ion dissociates as a result of the absorption of multiple infrared photons. MS_IRMPD = MS_infrared_multiphoton_dissociation, /// isotope ratio mass spectrometry: The measurement of the relative quantity of the different isotopes of an element in a material with a mass spectrometer. MS_isotope_ratio_mass_spectrometry_OBSOLETE = 1000263, /// IRMS (isotope ratio mass spectrometry): The measurement of the relative quantity of the different isotopes of an element in a material with a mass spectrometer. MS_IRMS_OBSOLETE = MS_isotope_ratio_mass_spectrometry_OBSOLETE, /// ion trap: A device for spatially confining ions using electric and magnetic fields alone or in combination. MS_ion_trap = 1000264, /// IT (ion trap): A device for spatially confining ions using electric and magnetic fields alone or in combination. MS_IT = MS_ion_trap, /// kinetic energy release distribution: Distribution of values of translational kinetic energy release for an ensemble of metastable ions undergoing a specific dissociation reaction. MS_kinetic_energy_release_distribution_OBSOLETE = 1000265, /// KERD (kinetic energy release distribution): Distribution of values of translational kinetic energy release for an ensemble of metastable ions undergoing a specific dissociation reaction. MS_KERD_OBSOLETE = MS_kinetic_energy_release_distribution_OBSOLETE, /// Laser Desorption: The formation of ions through the interaction of a laser with a material or with gas-phase ions or molecules. MS_Laser_Desorption_OBSOLETE = 1000266, /// Laser Ionization MERGE (Laser Desorption): The formation of ions through the interaction of a laser with a material or with gas-phase ions or molecules. MS_Laser_Ionization_MERGE_OBSOLETE = MS_Laser_Desorption_OBSOLETE, /// LD (Laser Desorption): The formation of ions through the interaction of a laser with a material or with gas-phase ions or molecules. MS_LD_OBSOLETE = MS_Laser_Desorption_OBSOLETE, /// mass analyzed ion kinetic energy spectrometry: Spectra that are obtained from a sector mass spectrometer that incorporates at least one magnetic sector plus one electric sector in reverse geometry. The accelerating voltage, V, and the magnetic sector field, B, are set at fixed values to select the precursor ions, which are then allowed to dissociate or to react in a field free region between the two sectors. The kinetic energy product ions of m/z selected precursor ions is analyzed by scanning the electric sector field, E. The width of the product ion spectrum peaks is related to the kinetic energy release distribution (KERD) for the dissociation process. MS_mass_analyzed_ion_kinetic_energy_spectrometry_OBSOLETE = 1000267, /// MIKES (mass analyzed ion kinetic energy spectrometry): Spectra that are obtained from a sector mass spectrometer that incorporates at least one magnetic sector plus one electric sector in reverse geometry. The accelerating voltage, V, and the magnetic sector field, B, are set at fixed values to select the precursor ions, which are then allowed to dissociate or to react in a field free region between the two sectors. The kinetic energy product ions of m/z selected precursor ions is analyzed by scanning the electric sector field, E. The width of the product ion spectrum peaks is related to the kinetic energy release distribution (KERD) for the dissociation process. MS_MIKES_OBSOLETE = MS_mass_analyzed_ion_kinetic_energy_spectrometry_OBSOLETE, /// mass spectrometry: The branch of science that deals with all aspects of mass spectrometers and the results obtained with these instruments. MS_mass_spectrometry_OBSOLETE = 1000268, /// MS (mass spectrometry): The branch of science that deals with all aspects of mass spectrometers and the results obtained with these instruments. MS_MS_OBSOLETE = MS_mass_spectrometry_OBSOLETE, /// mass spectrometry/mass spectrometry: The acquisition, study and spectra of the electrically charged products or precursors of a m/z selected ion or ions. MS_mass_spectrometry_mass_spectrometry_OBSOLETE = 1000269, /// MS/MS (mass spectrometry/mass spectrometry): The acquisition, study and spectra of the electrically charged products or precursors of a m/z selected ion or ions. MS_MS_MS_OBSOLETE = MS_mass_spectrometry_mass_spectrometry_OBSOLETE, /// multiple stage mass spectrometry: Multiple stages of precursor ion m/z selection followed by product ion detection for successive progeny ions. MS_multiple_stage_mass_spectrometry_OBSOLETE = 1000270, /// MSn (multiple stage mass spectrometry): Multiple stages of precursor ion m/z selection followed by product ion detection for successive progeny ions. MS_MSn_OBSOLETE = MS_multiple_stage_mass_spectrometry_OBSOLETE, /// Negative Ion chemical ionization: Chemical ionization that results in the formation of negative ions. MS_Negative_Ion_chemical_ionization = 1000271, /// NICI (Negative Ion chemical ionization): Chemical ionization that results in the formation of negative ions. MS_NICI = MS_Negative_Ion_chemical_ionization, /// neutralization reionization mass spectrometry: With this technique, m/z selected ions form neutrals by charge transfer to a collision gas or by dissociation. The neutrals are separated from the remaining ions and ionized in collisions with a second gas. This method is used to investigate reaction intermediates and other unstable species. MS_neutralization_reionization_mass_spectrometry = 1000272, /// NRMS (neutralization reionization mass spectrometry): With this technique, m/z selected ions form neutrals by charge transfer to a collision gas or by dissociation. The neutrals are separated from the remaining ions and ionized in collisions with a second gas. This method is used to investigate reaction intermediates and other unstable species. MS_NRMS = MS_neutralization_reionization_mass_spectrometry, /// photoionization: The ionization of an atom or molecule by a photon, written M + h? ? M^+ + e. The term photon impact is not recommended. MS_photoionization = 1000273, /// PI (photoionization): The ionization of an atom or molecule by a photon, written M + h? ? M^+ + e. The term photon impact is not recommended. MS_PI = MS_photoionization, /// pyrolysis mass spectrometry: A mass spectrometry technique in which the sample is heated to the point of decomposition and the gaseous decomposition products are introduced into the ion source. MS_pyrolysis_mass_spectrometry = 1000274, /// PyMS (pyrolysis mass spectrometry): A mass spectrometry technique in which the sample is heated to the point of decomposition and the gaseous decomposition products are introduced into the ion source. MS_PyMS = MS_pyrolysis_mass_spectrometry, /// collision quadrupole: A transmission quadrupole to which an oscillating potential is applied so as to focus a beam of ions through a collision gas with no m/z separation. MS_collision_quadrupole = 1000275, /// q (collision quadrupole): A transmission quadrupole to which an oscillating potential is applied so as to focus a beam of ions through a collision gas with no m/z separation. MS_q = MS_collision_quadrupole, /// resonance enhanced multiphoton ionization: Multiphoton ionization in which the ionization cross section is significantly enhanced because the energy of the incident photons is resonant with an intermediate excited state of the neutral species. MS_resonance_enhanced_multiphoton_ionization = 1000276, /// REMPI (resonance enhanced multiphoton ionization): Multiphoton ionization in which the ionization cross section is significantly enhanced because the energy of the incident photons is resonant with an intermediate excited state of the neutral species. MS_REMPI = MS_resonance_enhanced_multiphoton_ionization, /// residual gas analyzer: A mass spectrometer used to measure the composition and pressure of gasses in an evacuated chamber. MS_residual_gas_analyzer_OBSOLETE = 1000277, /// RGA (residual gas analyzer): A mass spectrometer used to measure the composition and pressure of gasses in an evacuated chamber. MS_RGA_OBSOLETE = MS_residual_gas_analyzer_OBSOLETE, /// surface enhanced laser desorption ionization: The formation of ionized species in the gas phase from analytes deposited on a particular surface substrate which is irradiated with a laser beam of which wavelength is absorbed by the surface. See also desorption/ionization on silicon and laser desorption/ionization. MS_surface_enhanced_laser_desorption_ionization = 1000278, /// SELDI (surface enhanced laser desorption ionization): The formation of ionized species in the gas phase from analytes deposited on a particular surface substrate which is irradiated with a laser beam of which wavelength is absorbed by the surface. See also desorption/ionization on silicon and laser desorption/ionization. MS_SELDI = MS_surface_enhanced_laser_desorption_ionization, /// surface enhanced neat desorption: Matrix-assisted laser desorption ionization in which the matrix is covalently linked to the target surface. MS_surface_enhanced_neat_desorption = 1000279, /// SEND (surface enhanced neat desorption): Matrix-assisted laser desorption ionization in which the matrix is covalently linked to the target surface. MS_SEND = MS_surface_enhanced_neat_desorption, /// suface ionization: The ionization of a neutral species when it interacts with a solid surface with an appropriate work function and temperature. MS_suface_ionization_OBSOLETE = 1000280, /// SI (suface ionization): The ionization of a neutral species when it interacts with a solid surface with an appropriate work function and temperature. MS_SI_OBSOLETE = MS_suface_ionization_OBSOLETE, /// selected ion flow tube: A device in which m/z selected ions are entrained in an inert carrier gas and undergo ion-molecule reactions. MS_selected_ion_flow_tube = 1000281, /// SIFT (selected ion flow tube): A device in which m/z selected ions are entrained in an inert carrier gas and undergo ion-molecule reactions. MS_SIFT = MS_selected_ion_flow_tube, /// sustained off-resonance irradiation: A technique associated with Fourier transform ion cyclotron resonance (FT-ICR) mass spectrometry to carry out ion/neutral reactions such as low-energy collision-induced dissociation. A radio-frequency electric field of slightly off-resonance to the cyclotron frequency of the reactant ion cyclically accelerates and decelerates the reactant ion that is confined in the Penning ion trap. The ion's orbit does not exceed the dimensions of ion trap while the ion undergoes an ion/neutral species process that produces a high average translational energy for an extended time. MS_sustained_off_resonance_irradiation = 1000282, /// SORI (sustained off-resonance irradiation): A technique associated with Fourier transform ion cyclotron resonance (FT-ICR) mass spectrometry to carry out ion/neutral reactions such as low-energy collision-induced dissociation. A radio-frequency electric field of slightly off-resonance to the cyclotron frequency of the reactant ion cyclically accelerates and decelerates the reactant ion that is confined in the Penning ion trap. The ion's orbit does not exceed the dimensions of ion trap while the ion undergoes an ion/neutral species process that produces a high average translational energy for an extended time. MS_SORI = MS_sustained_off_resonance_irradiation, /// Spark Source Mass Spectrometry: Mass spectrometry using spark ionization. MS_Spark_Source_Mass_Spectrometry_OBSOLETE = 1000283, /// SSMS (Spark Source Mass Spectrometry): Mass spectrometry using spark ionization. MS_SSMS_OBSOLETE = MS_Spark_Source_Mass_Spectrometry_OBSOLETE, /// stored waveform inverse fourier transform: A technique to create excitation waveforms for ions in FT-ICR mass spectrometer or Paul ion trap. An excitation waveform in the time-domain is generated by taking the inverse Fourier transform of an appropriate frequency-domain programmed excitation spectrum, in which the resonance frequencies of ions to be excited are included. This technique may be used for selection of precursor ions in MS2 experiments. MS_stored_waveform_inverse_fourier_transform = 1000284, /// SWIFT (stored waveform inverse fourier transform): A technique to create excitation waveforms for ions in FT-ICR mass spectrometer or Paul ion trap. An excitation waveform in the time-domain is generated by taking the inverse Fourier transform of an appropriate frequency-domain programmed excitation spectrum, in which the resonance frequencies of ions to be excited are included. This technique may be used for selection of precursor ions in MS2 experiments. MS_SWIFT = MS_stored_waveform_inverse_fourier_transform, /// total ion current: The sum of all the separate ion currents carried by the ions of different m/z contributing to a complete mass spectrum or in a specified m/z range of a mass spectrum. MS_total_ion_current = 1000285, /// TIC (total ion current): The sum of all the separate ion currents carried by the ions of different m/z contributing to a complete mass spectrum or in a specified m/z range of a mass spectrum. MS_TIC = MS_total_ion_current, /// time lag focusing: Energy focusing in a time-of-flight mass spectrometer that is accomplished by introducing a time delay between the formation of the ions and the application of the accelerating voltage pulse. MS_time_lag_focusing = 1000286, /// TLF (time lag focusing): Energy focusing in a time-of-flight mass spectrometer that is accomplished by introducing a time delay between the formation of the ions and the application of the accelerating voltage pulse. MS_TLF = MS_time_lag_focusing, /// time-of-flight mass spectrometer: An instrument that separates ions by m/z in a field-free region after acceleration to a fixed kinetic energy. MS_time_of_flight_mass_spectrometer_OBSOLETE = 1000287, /// TOF-MS (time-of-flight mass spectrometer): An instrument that separates ions by m/z in a field-free region after acceleration to a fixed kinetic energy. MS_TOF_MS_OBSOLETE = MS_time_of_flight_mass_spectrometer_OBSOLETE, /// cyclotron: A device that uses an oscillating electric field and magnetic field to accelerate charged particles. MS_cyclotron = 1000288, /// double-focusing mass spectrometer: A mass spectrometer that uses a magnetic sector for m/z focusing and an electric sector for energy focusing of an ion beam. MS_double_focusing_mass_spectrometer_OBSOLETE = 1000289, /// hybrid mass spectrometer: A mass spectrometer that combines m/z analyzers of different types to perform tandem mass spectrometry. MS_hybrid_mass_spectrometer_OBSOLETE = 1000290, /// linear ion trap: A two dimensional Paul ion trap in which ions are confined in the axial dimension by means of an electric field at the ends of the trap. MS_linear_ion_trap = 1000291, /// mass spectrograph obsolete: An instrument that separates a beam of ions according to their mass-to-charge ratio in which the ions are directed onto a focal plane detector such as a photographic plate. MS_mass_spectrograph_obsolete_OBSOLETE = 1000292, /// mass spectrometer: An instrument that measures the mass-to-charge ratio and relative abundances of ions. MS_mass_spectrometer_OBSOLETE = 1000293, /// mass spectrum: A plot of the relative abundance of a beam or other collection of ions as a function of the mass-to-charge ratio (m/z). MS_mass_spectrum = 1000294, /// mattauch-herzog geometry: An arrangement for a double-focusing mass spectrometer in which a deflection of ?/(4 ?(2)) radians in a radial electric field is followed by a magnetic deflection of ?/2 radians. MS_mattauch_herzog_geometry_OBSOLETE = 1000295, /// nier-johnson geometry: An arrangement for a double-focusing mass spectrometer in which a deflection of ?/2 radians in a radial electric field analyzer is followed by a magnetic deflection of ?/3 radians. MS_nier_johnson_geometry_OBSOLETE = 1000296, /// paul ion trap: A device that permits the trapping of ions by means of an alternating current voltage. The ejection of ions with a m/z less than a prescribed value and retention of those with higher mass depends on the application of radio frequency voltages between a ring electrode and two end-cap electrodes to confine the ions in a circular path. The choice of these voltages determines the m/z below which ions are ejected. MS_paul_ion_trap_OBSOLETE = 1000297, /// prolate traochoidal mass spectrometer: A mass spectrometer in which the ions of different m/z are separated by means of crossed electric and magnetic fields in such a way that the selected ions follow a prolate trochoidal path. MS_prolate_traochoidal_mass_spectrometer_OBSOLETE = 1000298, /// quistor: An abbreviation of quadrupole ion storage trap. This term is synonymous with Paul Ion Trap. If so then add a synonym to paul and obsolete this term. MS_quistor_OBSOLETE = 1000299, /// reflectron: A time-of-flight mass spectrometer that uses a static electric field to reverse the direction of travel of the ions entering it. A reflectron improves mass resolution by assuring that ions of the same m/z but different kinetic energy arrive at the detector at the same time. MS_reflectron = 1000300, /// sector mass spectrometer: A mass spectrometer consisting of one or more magnetic sectors for m/z selection in a beam of ions. Such instruments may also have one or more electric sectors for energy selection. MS_sector_mass_spectrometer_OBSOLETE = 1000301, /// tandem mass spectrometer: A mass spectrometer designed for mass spectrometry/mass spectrometry. MS_tandem_mass_spectrometer_OBSOLETE = 1000302, /// transmission quadrupole mass spectrometer: A mass spectrometer that consists of four parallel rods whose centers form the corners of a square and whose opposing poles are connected. The voltage applied to the rods is a superposition of a static potential and a sinusoidal radio frequency potential. The motion of an ion in the x and y dimensions is described by the Matthieu equation whose solutions show that ions in a particular m/z range can be transmitted along the z axis. MS_transmission_quadrupole_mass_spectrometer_OBSOLETE = 1000303, /// accelerating voltage: The electrical potential used to impart kinetic energy to ions in a mass spectrometer. MS_accelerating_voltage = 1000304, /// cyclotron motion: The circular motion of a charged particle moving at velocity v in a magnetic field B that results from the force qvB. MS_cyclotron_motion_OBSOLETE = 1000305, /// dynamic mass spectrometry: A mass spectrometer in which m/z separation using one or more electric fields that vary with time. MS_dynamic_mass_spectrometry_OBSOLETE = 1000306, /// einzel lens: Three element charged particle lens in which the first and third elements are held at the same voltage. Such a lens produces focusing without changing the translational energy of the particle. MS_einzel_lens = 1000307, /// electric field strength: The magnitude of the force per unit charge at a given point in space. MS_electric_field_strength = 1000308, /// first stability region: The region of a Mathieu stability diagram closest to the origin. Ions within this region can traverse the full length of a transmission quadrupole. MS_first_stability_region = 1000309, /// fringing field: The electric or magnetic field that extends from the edge of a sector, lens or other ion optics element. MS_fringing_field = 1000310, /// kinetic energy analyzer: A device for measuring the kinetic energy of charged particles using a retarding field, time-of-flight, or the extent of deflection in an electric or magnetic field. MS_kinetic_energy_analyzer = 1000311, /// mass limit: The m/z value above which ions cannot be detected in a mass spectrometer. MS_mass_limit_OBSOLETE = 1000312, /// scan m/z range?: The limit of m/z over which a mass spectrometer can detect ions. MS_scan_m_z_range__OBSOLETE = 1000313, /// mass selective axial ejection: The use of mass selective instability to eject ions of selected m/z values from an ion trap. MS_mass_selective_axial_ejection_OBSOLETE = 1000314, /// mass selective instability: A method for selective ejection of ions according to their m/z value in an ion trap. MS_mass_selective_instability_OBSOLETE = 1000315, /// mathieu stability diagram: A graphical representation expressed in terms of reduced coordinates that describes charged particle motion in a quadrupole mass filter or quadrupole ion trap mass spectrometer. MS_mathieu_stability_diagram_OBSOLETE = 1000316, /// orthogonal extraction: The pulsed acceleration of ions perpendicular to their direction of travel into a time-of-flight mass spectrometer. Ions may be extracted from a directional ion source, drift tube or m/z separation stage. MS_orthogonal_extraction_OBSOLETE = 1000317, /// resonance ion ejection: A mode of ion ejection in a quadrupole ion trap that relies on a auxiliary radio frequency voltage that is applied to the end-cap electrodes. The voltage is tuned to the secular frequency of a particular ion to eject it. MS_resonance_ion_ejection_OBSOLETE = 1000318, /// space charge effect: The mutual repulsion of particles of like charge that limits the current in a charged-particle beam and causes beams or packets of charged particles to expand radially over time. MS_space_charge_effect = 1000319, /// static field: An electric or magnetic field that does not change in time. MS_static_field = 1000320, /// 2E Mass Spectrum: A mass spectrum obtained by setting the electric sector field E to twice the value required to transmit the main ion-beam thereby allowing ions with a kinetic energy-to-charge ratio twice that of the main ion-beam to be transmitted. Product ions resulting from partial charge transfer reactions such as m^2+ + N ? m^+ + N^+ that occur in a collision cell (containing a gas, N) located in a field-free region preceding a magnetic and electric sector combination are detected. When the magnetic sector field B is scanned, a mass spectrum of singly charged product ions of doubly charged precursor ions is obtained. MS_2E_Mass_Spectrum_OBSOLETE = 1000321, /// charge inversion mass spectrum: The measurement of the relative abundance of ions that result from a charge inversion reaction as a function of m/z. MS_charge_inversion_mass_spectrum = 1000322, /// constant neutral loss scan: Spectrum of all precursor ions that undergo a selected m/z decrement. MS_constant_neutral_loss_scan_OBSOLETE = 1000323, /// constant neutral gain scan: Spectrum of all precursor ions that undergo a selected m/z increment. MS_constant_neutral_gain_scan_OBSOLETE = 1000324, /// Constant Neutral Mass Gain Scan (constant neutral gain scan): Spectrum of all precursor ions that undergo a selected m/z increment. MS_Constant_Neutral_Mass_Gain_Scan_OBSOLETE = MS_constant_neutral_gain_scan_OBSOLETE, /// constant neutral gain spectrum: A spectrum formed of all product ions that have been produced by gain of a pre-selected neutral mass following the reaction with and addition of the gas in a collision cell. MS_constant_neutral_gain_spectrum = 1000325, /// constant neutral mass gain spectrum (constant neutral gain spectrum): A spectrum formed of all product ions that have been produced by gain of a pre-selected neutral mass following the reaction with and addition of the gas in a collision cell. MS_constant_neutral_mass_gain_spectrum = MS_constant_neutral_gain_spectrum, /// constant neutral loss spectrum: A spectrum formed of all product ions that have been produced with a selected m/z decrement from any precursor ions. The spectrum shown correlates to the precursor ion spectrum. See also neutral loss spectrum. MS_constant_neutral_loss_spectrum = 1000326, /// constant neutral mass loss spectrum (constant neutral loss spectrum): A spectrum formed of all product ions that have been produced with a selected m/z decrement from any precursor ions. The spectrum shown correlates to the precursor ion spectrum. See also neutral loss spectrum. MS_constant_neutral_mass_loss_spectrum = MS_constant_neutral_loss_spectrum, /// consecutive reaction monitoring: A type of MS2 experiments with three or more stages of m/z separation and in which a particular multi-step reaction path is monitored. MS_consecutive_reaction_monitoring_OBSOLETE_1000327 = 1000327, /// e/2 mass spectrum: A mass spectrum obtained using a sector mass spectrometer in which the electric sector field E is set to half the value required to transmit the main ion-beam. This spectrum records the signal from doubly charged product ions of charge-stripping reactions. MS_e_2_mass_spectrum = 1000328, /// linked scan: A scan in an instrument with two or more m/z analysers or in a sector mass spectrometer that incorporates at least one magnetic sector and one electric sector. Two or more of the analyzers are scanned simultaneously so as to preserve a predetermined relationship between scan parameters to produce a product ion, precursor ion or constant neutral loss spectrum. MS_linked_scan_OBSOLETE = 1000329, /// linked scan at constant b/e: A linked scan at constant B/E may be performed on a sector mass spectrometer that incorporates at least one magnetic sector plus one electric sector. The magnetic field B and the electric field E are scanned simultaneously while the accelerating voltage V is held constant, so as to maintain the ratio of the two fields constant. This linked scan may record a product ion spectrum of dissociation or other reactions occurring in a field free region preceding the two sectors. MS_linked_scan_at_constant_b_e_OBSOLETE = 1000330, /// Linked Scan at Constant E2/V: A linked scan performed on a sector instrument that incorporates at least one electric sector plus one magnetic sector. The electric sector field, E, and the accelerating voltage, V, are scanned simultaneously, so as to maintain the ratio E2/V at a constant value. This linked scan recordss a product ion spectrum of dissociation or other reactions occurring in a field free region (FFR) preceding the two sectors. MS_Linked_Scan_at_Constant_E2_V_OBSOLETE = 1000331, /// Linked Scan at Constant B2/E: A linked scan performed on a sector mass spectrometer that incorporates at least one electric sector plus one magnetic sector in either order. The accelerating voltage is fixed and the magnetic field, B, and the electric field, E, are scanned simultaneously so as to maintain the ratio B2/E at a constant value. This linked scan records a precursor ion spectrum of dissociation or other reactions occurring in the field free region preceding the two sectors. The term B2/E linked scan is not recommended. MS_Linked_Scan_at_Constant_B2_E_OBSOLETE = 1000332, /// Linked Scan at Constant B[1-(E/E0)]^1/2 / E: A linked scan performed on a sector instrument that incorporates at least one electric sector plus one magnetic sector placed in either order. The accelerating voltage is fixed while scanning the magnetic field, B, and electric field, E, simultaneously, so as to maintain the quantity B[1-(E/E0)]1/2/E at a constant value. This linked scan records a constant neutral mass loss (or gain) spectrum of dissociation or other reactions occurring in a field free region preceding the two sectors. E0 is the electric field required to transmit the singly charged analog of the desired neutral fragment. The term B[1-(E/E0)]1/2/E linked scan. MS_Linked_Scan_at_Constant_B_1__E_E0___1_2___E_OBSOLETE = 1000333, /// MS/MS in Time: A tandem mass spectrometry method in which product ion spectra are recorded in a single m/z analyzer (such as a Paul Ion Trap or FTMS) in discreet steps over time. Ions in a specific m/z range are selected, dissociated, and the product ions analyzed sequentially in time. MS_MS_MS_in_Time_OBSOLETE = 1000334, /// MS/MS in Space: A tandem mass spectrometry method in which product ion spectra are recorded in m/z analyzers separated in space. Specific m/z separation functions are designed such that in one section of the instrument ions are selected, dissociated in an intermediate region, and the product ions are then transmitted to another analyser for m/z separation and data acquisition. MS_MS_MS_in_Space_OBSOLETE = 1000335, /// neutral loss: The loss of an uncharged species during a rearrangement process. MS_neutral_loss = 1000336, /// nth generation product ion: Serial product ions from dissociation of selected precursor ions where n refers to the number of stages of dissociation. The term granddaughter ion is deprecated. MS_nth_generation_product_ion_OBSOLETE = 1000337, /// nth generation product ion scan: The specific scan functions or processes that record the appropriate generation of product ion or ions of any m/z selected precursor ions. MS_nth_generation_product_ion_scan_OBSOLETE = 1000338, /// nth generation product ion spectrum: The mass spectrum recorded from any mass spectrometer in which the appropriate scan function can be set to record the appropriate generation product ion or ions of m/z selected precursor ions. MS_nth_generation_product_ion_spectrum_OBSOLETE = 1000339, /// precursor ion: An ion that reacts to form particular product ions. The reaction can be unimolecular dissociation, ion/molecule reaction, isomerization, or change in charge state. The term parent ion is deprecated. MS_precursor_ion_OBSOLETE = 1000340, /// precursor ion spectrum: Spectrum generated by scanning precursor m/z while monitoring a fixed product m/z. MS_precursor_ion_spectrum = 1000341, /// product ion: An ion formed as the product of a reaction involving a particular precursor ion. The reaction can be unimolecular dissociation to form fragment ions, an ion/molecule reaction, or simply involve a change in the number of charges. The term fragment ion is deprecated. The term daughter ion is deprecated. MS_product_ion_OBSOLETE = 1000342, /// product ion spectrum: A mass spectrum recorded from any spectrometer in which the appropriate m/z separation scan function is set to record the product ion or ions of selected precursor ions. MS_product_ion_spectrum_OBSOLETE = 1000343, /// progeny ion: A charged product of a series of consecutive reactions that includes product ions, 1st generation product ions, 2nd generation product ions, etc. Given the sequential fragmentation scheme: M1+ -> M2+ -> M3+ -> M4+ -> M5+. M4+ is the precursor ion of M5+, a 1st generation product ion of M3+, a 2nd generation product ion of M2+ and a 3rd generation product ion of M1+. MS_progeny_ion_OBSOLETE = 1000344, /// Progeny Fragment Ion (progeny ion): A charged product of a series of consecutive reactions that includes product ions, 1st generation product ions, 2nd generation product ions, etc. Given the sequential fragmentation scheme: M1+ -> M2+ -> M3+ -> M4+ -> M5+. M4+ is the precursor ion of M5+, a 1st generation product ion of M3+, a 2nd generation product ion of M2+ and a 3rd generation product ion of M1+. MS_Progeny_Fragment_Ion_OBSOLETE = MS_progeny_ion_OBSOLETE, /// array detector: Detector comprising several ion collection elements, arranged in a line or grid where each element is an individual detector. MS_array_detector = 1000345, /// conversion dynode: A surface that is held at high potential such that ions striking the surface produce electrons that are subsequently detected. MS_conversion_dynode = 1000346, /// dynode: One of a series of electrodes in a photomultiplier tube. Such an arrangement is able to amplify the current emitted by the photocathode. MS_dynode = 1000347, /// focal plane collector: A detector for spatially disperse ion beams in which all ions simultaneously impinge on the detector plane. MS_focal_plane_collector = 1000348, /// ion-to-photon detector: A detector in which ions strike a conversion dynode to produce electrons that in turn strike a phosphor and the resulting photons are detected by a photomultiplier. MS_ion_to_photon_detector = 1000349, /// point collector: A detector in which the ion beam is focused onto a point and the individual ions arrive sequentially. MS_point_collector = 1000350, /// postacceleration detector: A detector in which the charged particles are accelerated to a high velocity and impinge on a conversion dynode, emitting secondary electrons. The electrons are accelerated onto a phosphor screen, which emits photons that are in turn detected using a photomultiplier or other photon detector. MS_postacceleration_detector = 1000351, /// secondary electron: Electrons that are ejected from a sample surface as a result of bombardment by a primary beam of atoms, ions or photons. WAS IN DETECTOR TYPE. Where should it go. MS_secondary_electron_OBSOLETE = 1000352, /// adduct ion: Ion formed by the interaction of an ion with one or more atoms or molecules to form an ion containing all the constituent atoms of the precursor ion as well as the additional atoms from the associated atoms or molecules. MS_adduct_ion_OBSOLETE = 1000353, /// aromatic ion: A planar cyclic ion that obeys the Hueckel (4n + 2) rule where n is a positive integer representing the number of conjugated Pi electrons. Charge delocalization leads to greater stability compared to a hypothetical localized structure. MS_aromatic_ion_OBSOLETE = 1000354, /// analog ion: Ions that have similar chemical valence, for example the acetyl cation CH3-CO+ and the thioacetyl cation CH3-CS+. MS_analog_ion_OBSOLETE = 1000355, /// anti-aromatic ion: A planar cyclic ion with 4n ? electrons and is therefore not aromatic. MS_anti_aromatic_ion_OBSOLETE = 1000356, /// cationized molecule: An ion formed by the association of a cation with a neutral molecule, M, for example [M+ Na]+ and [M + K]+. The terms quasi-molecular ion and pseudo-molecular ion should not be used. MS_cationized_molecule_OBSOLETE = 1000357, /// cluster ion: An ion formed by a multi-component atomic or molecular assembly of one or more ions with atoms or molecules, such as [(H20)nH]+, [(NaCl)nNa]+ and [(H3PO3)nHPO3]-. MS_cluster_ion_OBSOLETE = 1000358, /// Conventional ion: A radical cation or anion in which the charge site and the unpaired electron spin are both formally located in the same atom or group of atoms, as opposed to the spatially separate electronic configuration of distonic ions. The radical cation of methanol, CH3OH+, in which the charge and spin sites are formally located at the O atom is an example of a conventional ion, whereas .CH2-OH2+ is a distonic ion. MS_Conventional_ion_OBSOLETE = 1000359, /// diagnostic ion: A product ion whose formation reveals structural or compositional information of its precursor. For instance, the phenyl cation in an electron ionization mass spectrum is a diagnostic ion for benzene and derivatives. MS_diagnostic_ion_OBSOLETE = 1000360, /// dimeric ion: An ion formed by ionization of a dimer or by the association of an ion with its neutral counterpart such as [M2]+ or [M-H-M]+. MS_dimeric_ion_OBSOLETE = 1000361, /// distonic ion: A radical cation or anion in which the charge site and the unpaired electron spin cannot be both formally located in the same atom or group of atoms as it can be with a conventional ion. For example, CH2-OH2+ is a distonic ion whereas the radical cation of methanol, CH3OH+ is a conventional ion. MS_distonic_ion_OBSOLETE = 1000362, /// enium ion: A positively charged lower-valency ion of the nonmetallic elements. The methenium ion is CH3+. Other examples are the oxenium, sulfenium, nitrenium, phosphenium, and halenium ions. MS_enium_ion_OBSOLETE = 1000363, /// fragment ion: A product ion that results from the dissociation of a precursor ion. MS_fragment_ion_OBSOLETE = 1000364, /// ion?: An atomic or molecular species having a net positive or negative electric charge. MS_ion__OBSOLETE = 1000365, /// Isotopologue ion: An ion that differs only in the isotopic composition of one or more of its constituent atoms. For example CH4+ and CH3D+ or 10BF3 and 11BF3. The term isotopologue is a contraction of isotopic homologue. MS_Isotopologue_ion_OBSOLETE = 1000366, /// Isotopomeric ion: Isomeric ion having the same numbers of each isotopic atom but differing in their positions. Isotopomeric ions can be either configurational isomers in which two atomic isotopes exchange positions or isotopic stereoisomers. The term isotopomer is a shortening of isotopic isomer. MS_Isotopomeric_ion_OBSOLETE = 1000367, /// metastable ion: An ion that is formed with internal energy higher than the threshold for dissociation but with a lifetime great enough to allow it to exit the ion source and enter the mass spectrometer where it dissociates before detection. MS_metastable_ion_OBSOLETE = 1000368, /// molecular ion: An ion formed by the removal of one or more electrons to form a positive ion or the addition off one or more electrons to form a negative ion. MS_molecular_ion_OBSOLETE = 1000369, /// negative ion: An atomic or molecular species having a net negative electric charge. MS_negative_ion_OBSOLETE = 1000370, /// non-classical ion: Hyper-coordinated carbonium ion such as the penta-coordinated norbornyl cation. Note: Tri-coordinated carbenium ions are termed classical ions. MS_non_classical_ion_OBSOLETE = 1000371, /// onium ion: A positively charged hypervalent ion of the nonmetallic elements. Examples are the methonium ion CH5+, the hydrogenonium ion H3+ and the hydronium ion H3O+. Other examples are the carbonium, oxonium, sulfonium, nitronium, diazonium, phosphonium, and halonium ions. Onium ions are not limited to monopositive ions; multiply-charged onium ions exist such as the gitonic (proximal) oxonium dication H4O2+ and the distonic oxonium dication H2O+-CH2-CH2-OH2+. MS_onium_ion_OBSOLETE = 1000372, /// principal ion: Most abundant ion of an isotope cluster, such as the 11B79Br2 81Br+ ion of m/z 250 of the cluster of isotopologue molecular ions of BBr3. The term principal ion has also been used to describe ions that have been artificially isotopically enriched in one or more positions such as CH3 13CH3+ or CH2D2 +, but those are best defined as isotopologue ions. MS_principal_ion_OBSOLETE = 1000373, /// positive ion: An atomic or molecular species having a net positive electric charge. MS_positive_ion_OBSOLETE = 1000374, /// protonated molecule: An ion formed by interaction of a neutral molecule with a proton and represented by the symbol [M + H]+, where M is the neutral molecule. The term 'protonated molecular ion,' 'quasi-molecular ion' and 'pseudo-molecular ion' are not recommended. MS_protonated_molecule_OBSOLETE = 1000375, /// radical ion: An ion, either a cation or anion, containing unpaired electrons in its ground state. The unpaired electron is denoted by a superscript dot alongside the superscript symbol for charge, such as for the molecular ion of a molecule M, that is, M+. Radical ions with more than one charge and/or more than one unpaired electron are denoted such as M(2+)(2). Unless the positions of the unpaired electron and charge can be associated with specific atoms, superscript charge designation should be placed before the superscript dot designation. MS_radical_ion_OBSOLETE = 1000376, /// reference ion: A stable ion whose structure is known with certainty. These ions are usually formed by direct ionization of a neutral molecule of known structure and are used to verify by comparison the structure of an unknown ion. MS_reference_ion_OBSOLETE = 1000377, /// stable ion: An ion with internal energy sufficiently low that it does not rearrange or dissociate prior to detection in a mass spectrometer. MS_stable_ion_OBSOLETE = 1000378, /// unstable ion: An ion with sufficient energy to dissociate within the ion source. MS_unstable_ion_OBSOLETE = 1000379, /// adiabatic ionization: A process whereby an electron is removed from an atom, ion, or molecule to produce an ion in its lowest energy state. MS_adiabatic_ionization = 1000380, /// associative ionization: An ionization process in which two excited atoms or molecules react to form a single positive ion and an electron. MS_associative_ionization = 1000381, /// atmospheric pressure photoionization: Atmospheric pressure chemical ionization in which the reactant ions are generated by photo-ionization. MS_atmospheric_pressure_photoionization = 1000382, /// autodetachment: The formation of a neutral when a negative ion in a discrete state with an energy greater than the detachment threshold loses an electron spontaneously without further interaction with an energy source. MS_autodetachment = 1000383, /// autoionization: The formation of an ion when an atom or molecule in a discrete state with an energy greater than the ionization threshold loses an electron spontaneously without further interaction with an energy source. MS_autoionization = 1000384, /// charge exchange ionization: The interaction of an ion with an atom or molecule in which the charge on the ion is transferred to the neutral without the dissociation of either. Synonymous with charge transfer ionization. MS_charge_exchange_ionization = 1000385, /// chemi-ionization: The reaction of a neutral molecule with an internally excited molecule to form an ion. Note that this term is not synonymous with chemical ionization. MS_chemi_ionization = 1000386, /// desorption/ionization on silicon: The formation of ions by laser desorption ionization of a sample deposited on a porous silicon surface. MS_desorption_ionization_on_silicon = 1000387, /// dissociative ionization: The reaction of a gas-phase molecule that results in its decomposition to form products, one of which is an ion. MS_dissociative_ionization = 1000388, /// electron ionization: The ionization of an atom or molecule by electrons that are typically accelerated to energies between 50 and 150 eV. Usually 70 eV electrons are used to produce positive ions. The term 'electron impact' is not recommended. MS_electron_ionization = 1000389, /// ion desolvation: The removal of solvent molecules clustered around a gas-phase ion by means of heating and/or collisions with gas molecules. MS_ion_desolvation_OBSOLETE = 1000390, /// ion-pair formation: The reaction of a molecule to form both a positive ion and negative ion fragment among the products. MS_ion_pair_formation_OBSOLETE = 1000391, /// ionization efficiency: The ratio of the number of ions formed to the number of electrons, molecules or photons used. MS_ionization_efficiency = 1000392, /// laser desorption ionization: The formation of gas-phase ions by the interaction of a pulsed laser with a solid or liquid material. MS_laser_desorption_ionization = 1000393, /// liquid secondary ionization: The ionization of any species by the interaction of a focused beam of ions with a sample that is dissolved in a solvent matrix. See also fast atom bombardment and secondary ionization. MS_liquid_secondary_ionization = 1000395, /// membrane inlet: A semi-permeable membrane separator that permits the passage of gas sample directly to the mass spectrometer ion source. MS_membrane_inlet = 1000396, /// microelectrospray: Electrospray ionization at a solvent flow rate of 300-800 nL/min where the flow is a result of a mechanical pump. See nanoelectrospray. MS_microelectrospray = 1000397, /// nanoelectrospray: Electrospray ionization at a flow rate less than ~25 nL/min. Nanoelectrospray is synonymous with nanospray. The flow is dependent on the potenial on the tip of the electrospray needle and/or a gas presure to push the sample through the needle. See also electrospray ionization and microelectrospray. MS_nanoelectrospray = 1000398, /// nanospray (nanoelectrospray): Electrospray ionization at a flow rate less than ~25 nL/min. Nanoelectrospray is synonymous with nanospray. The flow is dependent on the potenial on the tip of the electrospray needle and/or a gas presure to push the sample through the needle. See also electrospray ionization and microelectrospray. MS_nanospray = MS_nanoelectrospray, /// penning ionization: Ionization that occurs through the interaction of two or more neutral gaseous species, at least one of which is internally excited. MS_penning_ionization = 1000399, /// plasma desorption ionization: The ionization of material in a solid sample by bombarding it with ionic or neutral atoms formed as a result of the fission of a suitable nuclide, typically 252Cf. Synonymous with fission fragment ionization. MS_plasma_desorption_ionization = 1000400, /// pre-ionization state: An electronic state capable of undergoing auto-Ionization. MS_pre_ionization_state_OBSOLETE = 1000401, /// secondary ionization: The process in which ions are ejected from a sample surface as a result of bombardment by a primary beam of atoms or ions. MS_secondary_ionization = 1000402, /// soft ionization: The formation of gas-phase ions without extensive fragmentation. MS_soft_ionization = 1000403, /// spark ionization: The formation of ions from a solid material by an intermittent electrical discharge. MS_spark_ionization = 1000404, /// surface-assisted laser desorption ionization: The formation of gas-phase ions from molecules that are deposited on a particular surface substrate that is irradiated with a pulsed laser. See also matrix-assisted laser desorption ionization. MS_surface_assisted_laser_desorption_ionization = 1000405, /// surface ionization: The ionization of a neutral species when it interacts with a solid surface with an appropriate work function and temperature. MS_surface_ionization = 1000406, /// thermal ionization: The ionization of a neutral species through contact with a high temperature surface. MS_thermal_ionization = 1000407, /// vertical ionization: A process in which an electron is removed from or added to a molecule without a change in the positions of the atoms. The resulting ion is typically in an excited vibrational state. MS_vertical_ionization = 1000408, /// association reaction: The reaction of an ion with a neutral species in which the reactants combine to form a single ion. MS_association_reaction_OBSOLETE = 1000409, /// alpha-cleavage: A homolytic cleavage where the bond fission occurs between at the atom adjacent to the atom at the apparent charge site and an atom removed from the aparent charge site by two bonds. MS_alpha_cleavage_OBSOLETE = 1000410, /// beta-cleavage: A homolytic cleavage where the bond fission occurs between at an atom removed from the apparent charge site atom by two bonds and an atom adjacent to that atom and removed from the aparent charge site by three bonds. MS_beta_cleavage_OBSOLETE = 1000411, /// buffer gas: An inert gas used for collisional deactivation of internally excited ions. MS_buffer_gas = 1000412, /// charge-induced fragmentation: Fragmentation of an odd electron ion in which the cleaved bond is adjacent to the apparent charge site. Synonymous with charge mediated fragmentation. MS_charge_induced_fragmentation_OBSOLETE = 1000413, /// charge inversion reaction: Reaction of an ion with a neutral species in which the charge on the product ion is reversed in sign with respect to the reactant ion. MS_charge_inversion_reaction_OBSOLETE = 1000414, /// charge permutation reaction: The reaction of an ion with a neutral species with a resulting change in the magnitude or sign of the charge on the reactant ion. MS_charge_permutation_reaction_OBSOLETE = 1000415, /// charge stripping reaction: Reaction of a positive ion with a neutral species in which the positive charge on the product ion is greater than that on the reactant ion. MS_charge_stripping_reaction_OBSOLETE = 1000416, /// charge transfer reaction: The reaction of an ion with a neutral species in which some or all of the charge of the reactant ion is transferred to the neutral species. MS_charge_transfer_reaction_OBSOLETE = 1000417, /// collisional excitation: The reaction of an ion with a neutral species in which the translational energy of the collision is converted into internal energy of the ion. MS_collisional_excitation_OBSOLETE = 1000418, /// collision gas: An inert gas used for collisional excitation. The term target gas is not recommended. MS_collision_gas = 1000419, /// heterolytic cleavage: Fragmentation of a molecule or ion in which both electrons forming the single bond that is broken remain on one of the atoms that were originally bonded. This term is synonymous with heterolysis. MS_heterolytic_cleavage_OBSOLETE = 1000420, /// high energy collision: Collision-induced dissociation process wherein the projectile ion has laboratory-frame translational energy higher than 1 keV. MS_high_energy_collision_OBSOLETE = 1000421, /// beam-type collision-induced dissociation: A collision-induced dissociation process that occurs in a beam-type collision cell. MS_beam_type_collision_induced_dissociation = 1000422, /// HCD (beam-type collision-induced dissociation): A collision-induced dissociation process that occurs in a beam-type collision cell. MS_HCD = MS_beam_type_collision_induced_dissociation, /// homolytic cleavage: Fragmentation of an odd electron ion that results from one of a pair of electrons that form a bond between two atoms moving to form a pair with the odd electron on the atom at the apparent charge site. Fragmentation results in the formation of an even electron ion and a radical. This reaction involves the movement of a single electron and is symbolized by a single-barbed arrow. Synonymous with Homolysis. MS_homolytic_cleavage_OBSOLETE = 1000423, /// hydrogen/deuterium exchange: Exchange of hydrogen atoms with deuterium atoms in a molecule or pre-formed ion in solution prior to introduction into a mass spectrometer, or by reaction of an ion with a deuterated collision gas inside a mass spectrometer. MS_hydrogen_deuterium_exchange_OBSOLETE = 1000424, /// ion energy loss spectrum: A plot of the relative abundance of a beam or other collection of ions as a function their loss of translational energy in reactions with neutral species. MS_ion_energy_loss_spectrum_OBSOLETE = 1000425, /// ionizing collision: The reaction of an ion with a neutral species in which one or more electrons are removed from either the ion or neutral. MS_ionizing_collision_OBSOLETE = 1000426, /// ion/molecule reaction: The reaction of an ion with a neutral molecule. The term ion-molecule reaction is not recommended because the hyphen suggests a single species that is that is both an ion and a molecule. MS_ion_molecule_reaction_OBSOLETE = 1000427, /// ion/neutral complex: A particular type of transition state that lies between precursor and product ions on the reaction coordinate of some ion reactions. MS_ion_neutral_complex_OBSOLETE = 1000428, /// ion/neutral species reaction: A process wherein a charged species interacts with a neutral reactant to produce either chemically different species or changes in the internal energy of one or both of the reactants. MS_ion_neutral_species_reaction_OBSOLETE = 1000429, /// ion/neutral species exchange reaction: In this reaction an association reaction is accompanied by the subsequent or simultaneous liberation of a different neutral species as a product. MS_ion_neutral_species_exchange_reaction_OBSOLETE = 1000430, /// kinetic method: An approach to determination of ion thermodynamic quantities by a bracketing procedure in which the relative probabilities of competing ion fragmentations are measured via the relative abundances of the reaction products. The extended kinetic method takes the associated entropy changes into account. MS_kinetic_method_OBSOLETE = 1000431, /// low energy collisions: A collision between an ion and neutral species with translational energy approximately 1000 eV or lower. MS_low_energy_collisions_OBSOLETE = 1000432, /// low-energy collision-induced dissociation: A collision-induced dissociation process wherein the precursor ion has the translational energy lower than approximately 1000 eV. This process typically requires multiple collisions and the collisional excitation is cumulative. MS_low_energy_collision_induced_dissociation = 1000433, /// McLafferty Rearrangement: A dissociation reaction triggered by transfer of a hydrogen atom via a 6-member transition state to the formal radical/charge site from a carbon atom four atoms removed from the charge/radical site (the gamma-carbon); subsequent rearrangement of electron density leads to expulsion of an olefin molecule. This term was originally applied to ketone ions where the charge/radical site is the carbonyl oxygen, but it is now more widely applied. MS_McLafferty_Rearrangement_OBSOLETE = 1000434, /// photodissociation: A process wherein the reactant ion is dissociated as a result of absorption of one or more photons. MS_photodissociation = 1000435, /// multiphoton dissociation (photodissociation): A process wherein the reactant ion is dissociated as a result of absorption of one or more photons. MS_multiphoton_dissociation = MS_photodissociation, /// MPD (photodissociation): A process wherein the reactant ion is dissociated as a result of absorption of one or more photons. MS_MPD = MS_photodissociation, /// partial charge transfer reaction: Reaction of an ion with a neutral species in which some but not all of the ion charge is transferred to the neutral. MS_partial_charge_transfer_reaction_OBSOLETE = 1000436, /// ion reaction: Chemical transformation involving an ion. MS_ion_reaction_OBSOLETE = 1000437, /// superelastic collision: Collision in which the translational energy of the fast-moving collision partner is increased at the expense of internal energy of one or both collision partners. MS_superelastic_collision_OBSOLETE = 1000438, /// surface-induced reaction: A process wherein a reactant ion interacts with a surface to produce either chemically different species or a change in the internal energy of the reactant ion. MS_surface_induced_reaction_OBSOLETE = 1000439, /// unimolecular dissociation: Fragmentation reaction in which the molecularity is treated as one, irrespective of whether the dissociative state is that of a metastable ion produced in the ion source or results from collisional excitation of a stable ion. MS_unimolecular_dissociation_OBSOLETE = 1000440, /// scan: Function or process of the mass spectrometer where it records a spectrum. MS_scan = 1000441, /// spectrum: A mass spectrum is an intensity vs m/z (mass-to-charge ratio) plot representing a chemical analysis. MS_spectrum = 1000442, /// mass analyzer type: Mass analyzer separates the ions according to their mass-to-charge ratio. MS_mass_analyzer_type = 1000443, /// m/z Separation Method: Mass/charge separation Method. MS_m_z_Separation_Method_OBSOLETE = 1000444, /// sequential m/z separation method: Sequential m/z separation method. MS_sequential_m_z_separation_method_OBSOLETE = 1000445, /// fast ion bombardment: The ionization of any species by the interaction of a focused beam of ions having a translational energy of several thousand eV with a solid sample. MS_fast_ion_bombardment = 1000446, /// FIB (fast ion bombardment): The ionization of any species by the interaction of a focused beam of ions having a translational energy of several thousand eV with a solid sample. MS_FIB = MS_fast_ion_bombardment, /// LTQ: Finnigan LTQ MS. MS_LTQ = 1000447, /// LTQ FT: Finnigan LTQ FT MS. MS_LTQ_FT = 1000448, /// LTQ Orbitrap: Finnigan LTQ Orbitrap MS. MS_LTQ_Orbitrap = 1000449, /// LXQ: Finnigan LXQ MS. MS_LXQ = 1000450, /// mass analyzer: Terms used to describe the Analyzer. MS_mass_analyzer = 1000451, /// analyzer (mass analyzer): Terms used to describe the Analyzer. MS_analyzer = MS_mass_analyzer, /// data transformation: Terms used to describe types of data processing. MS_data_transformation = 1000452, /// data processing (data transformation): Terms used to describe types of data processing. MS_data_processing = MS_data_transformation, /// detector: The device that detects ions. MS_detector = 1000453, /// instrument additional description: Additional terms to describe the instrument as outlined in the mass spec doc, Appendix 1, section 1.5. MS_instrument_additional_description_OBSOLETE = 1000454, /// ion selection attribute: Ion selection properties that are associated with a value. MS_ion_selection_attribute = 1000455, /// precursor activation: Terms to describe the precursor activation. MS_precursor_activation = 1000456, /// activation (precursor activation): Terms to describe the precursor activation. MS_activation = MS_precursor_activation, /// sample: Terms to describe the sample. MS_sample = 1000457, /// source: Terms to describe the source. MS_source = 1000458, /// spectrum instrument description: Terms used to describe the spectrum. MS_spectrum_instrument_description_OBSOLETE = 1000459, /// unit: Terms to describe units. MS_unit_OBSOLETE = 1000460, /// additional description: Terms to describe Additional. MS_additional_description_OBSOLETE = 1000461, /// ion optics: Device used in the construction of a mass spectrometer to focus, contain or otherwise manipulate ions. MS_ion_optics = 1000462, /// instrument: Description of the instrument or the mass spectrometer. MS_instrument = 1000463, /// instrument configuration (instrument): Description of the instrument or the mass spectrometer. MS_instrument_configuration = MS_instrument, /// mass unit: A unit of measurement for mass. MS_mass_unit_OBSOLETE = 1000464, /// scan polarity: An acquisition mode to which specifies weather polarity is negative, positive or alternating. MS_scan_polarity = 1000465, /// alternating: Alternating. MS_alternating_OBSOLETE = 1000466, /// 1200 series LC/MSD SL: The 1200 Series LC/MSD SL ion trap belongs to the Agilent LC/MSD ion trap family. It provides fast polarity switching and multisignal data acquisition capabilities in a single run while also providing 5 stages of automated data dependent MS2 and 11 stages of manual MS2. MS_1200_series_LC_MSD_SL = 1000467, /// 6110 Quadrupole LC/MS: The 6110 Quadrupole LC/MS system is a Agilent liquid chromatography instrument combined with an entry level single quadrupole mass spectrometer from the 6100 Series of Agilent quadrupole mass spectrometers. 6110 Quadrupole mass spectrometer has m/z range of 10-1500 and 2500 u/s scan speed. It proves useful for wide range of SIM quantitative applications. MS_6110_Quadrupole_LC_MS = 1000468, /// 6120 Quadrupole LC/MS: The 6120 Quadrupole LC/MS system is a Agilent liquid chromatography instrument combined with a single quadrupole mass spectrometer from the 6100 Series of Agilent mass spectrometers. 6120 quadrupole mass spectrometer has m/z range of 10-1500, 2500 u/s scan speed and utilizes multiple signal acquisition. MS_6120_Quadrupole_LC_MS = 1000469, /// 6130 Quadrupole LC/MS: The 6130 Quadrupole LC/MS system is a Agilent liquid chromatography instrument combined with a single quadrupole mass spectrometer from the 6100 series of Agilent mass spectrometers. The 6130 quadrupole mass spectrometer has m/z range of 2-3000, 2500 u/s scan speed in standard mode and 5250 u/s speed in fast-scan mode. It also uses multiple signal acquisition. MS_6130_Quadrupole_LC_MS = 1000470, /// 6140 Quadrupole LC/MS: The 6140 Quadrupole LC/MS system is a Agilent liquid chromatography instrument combined with a single quadrupole mass spectrometer from the 6100 Series of Agilent quadrupole mass spectrometers. 6140 Quadrupole mass spectrometer has m/z range of 10-1350, 2500 u/s scan speed in standard mode and 10000 u/s speed in fast-scan mode. It also uses multiple signal acquisition. MS_6140_Quadrupole_LC_MS = 1000471, /// 6210 Time-of-Flight LC/MS: The 6210 Time-of-Flight LC/MS is a Agilent liquid chromatography instrument combined with a Agilent time of flight mass spectrometer. This time of flight mass spectrometer has a m/z range of 50-12000, mass accuracy of less than 2 ppm and resolution greater than 13,000 at m/z 2722. It has multiple ion sources and can be used with multimode ion sources. MS_6210_Time_of_Flight_LC_MS = 1000472, /// 6310 Ion Trap LC/MS: The 6310 Ion Trap LC/MS is a Agilent liquid chromatography instrument combined with a 6300 series Agilent ion trap. It has a mass range of 50-2200 between 0.6 to 0.35 resolution and mass range of 200-4000 with resolution of 3-4. The scan speed varies from 1650-27000 for the respective mass ranges. MS_6310_Ion_Trap_LC_MS = 1000473, /// 6320 Ion Trap LC/MS: The 6320 Ion Trap LC/MS is a Agilent liquid chromatography instrument combined with a 6300 series Agilent ion trap. It has a mass range of 50-2200 between 0.6 to 0.25 resolution and mass range of 200-4000 with resolution of less than 3. The scan speed varies from 1650-27000 for the respective mass ranges. MS_6320_Ion_Trap_LC_MS = 1000474, /// 6330 Ion Trap LC/MS: The 6330 Ion Trap LC/MS is a Agilent liquid chromatography instrument combined with a 6300 series Agilent ion trap. It has a mass range of 50-2200 between 0.6 to 0.25 resolution and mass range of 200-4000 with resolution of less than 3. The scan speed varies from 1650-27000 for the respective mass ranges. MS_6330_Ion_Trap_LC_MS = 1000475, /// 6340 Ion Trap LC/MS: The 6340 Ion Trap LC/MS is a Agilent liquid chromatography instrument combined with a 6300 series Agilent ion trap. It has a mass range of 50-2200 between 0.6 to 0.25 resolution and mass range of 200-4000 with resolution of less than 3. The scan speed varies from 1650-27000 for the respective mass ranges. MS_6340_Ion_Trap_LC_MS = 1000476, /// 6410 Triple Quadrupole LC/MS: The 6410 Quadrupole LC/MS system is a Agilent liquid chromatography instrument combined with a Agilent triple quadrupole mass spectrometer. Mass range of the mass spectrometer is 15-1650 m/z, resolution is at three settings of 0.7 u (unit), 1.2 u (wide) and 2.5 u (widest). The mass accuracy for 6410 mass spectrometer is 0.1 across the mass range. The collision cell is a hexapole with linear acceleration. MS_6410_Triple_Quadrupole_LC_MS = 1000477, /// 6410 Triple Quad LC/MS (6410 Triple Quadrupole LC/MS): The 6410 Quadrupole LC/MS system is a Agilent liquid chromatography instrument combined with a Agilent triple quadrupole mass spectrometer. Mass range of the mass spectrometer is 15-1650 m/z, resolution is at three settings of 0.7 u (unit), 1.2 u (wide) and 2.5 u (widest). The mass accuracy for 6410 mass spectrometer is 0.1 across the mass range. The collision cell is a hexapole with linear acceleration. MS_6410_Triple_Quad_LC_MS = MS_6410_Triple_Quadrupole_LC_MS, /// 1200 series LC/MSD VL: The LC/MSD VL ion trap is part of the family of Agilent ion trap mass spectrometers. It has ESI, APCI and APPI ion sources and is a useful ion trap when the amount of sample is not the limiting factor. MS_1200_series_LC_MSD_VL = 1000478, /// purgatory: Terms that will likely become obsolete unless there are wails of dissent. MS_purgatory_OBSOLETE = 1000479, /// mass analyzer attribute: Analyzer properties that are associated with a value. MS_mass_analyzer_attribute = 1000480, /// detector attribute: Detector attribute recognized as a value. MS_detector_attribute = 1000481, /// source attribute: Property of a source device that need a value. MS_source_attribute = 1000482, /// Thermo Fisher Scientific instrument model: Thermo Fisher Scientific instrument model. The company has gone through several names including Thermo Finnigan, Thermo Scientific. MS_Thermo_Fisher_Scientific_instrument_model = 1000483, /// orbitrap: An ion trapping device that consists of an outer barrel-like electrode and a coaxial inner spindle-like electrode that form an electrostatic field with quadro-logarithmic potential distribution. The frequency of harmonic oscillations of the orbitally trapped ions along the axis of the electrostatic field is independent of the ion velocity and is inversely proportional to the square root of m/z so that the trap can be used as a mass analyzer. MS_orbitrap = 1000484, /// nanospray inlet: Nanospray Inlet. MS_nanospray_inlet = 1000485, /// source potential: Potential difference at the MS source in volts. MS_source_potential = 1000486, /// ion optics attribute: Ion optics involves components that help focus ion streams in mass spectrometry. MS_ion_optics_attribute = 1000487, /// Hitachi instrument model: Hitachi instrument model. MS_Hitachi_instrument_model = 1000488, /// Varian instrument model: Varian instrument model. MS_Varian_instrument_model = 1000489, /// Agilent instrument model: Agilent instrument model. MS_Agilent_instrument_model = 1000490, /// Dionex instrument model: Dionex instrument model. MS_Dionex_instrument_model = 1000491, /// Thermo Electron instrument model: Thermo Electron Corporation instrument model. MS_Thermo_Electron_instrument_model = 1000492, /// Finnigan MAT instrument model: Finnigan MAT instrument model. MS_Finnigan_MAT_instrument_model = 1000493, /// Thermo Scientific instrument model: Thermo Scientific instrument model. MS_Thermo_Scientific_instrument_model = 1000494, /// Applied Biosystems instrument model: Applied Biosystems instrument model. MS_Applied_Biosystems_instrument_model = 1000495, /// ABI (Applied Biosystems instrument model): Applied Biosystems instrument model. MS_ABI = MS_Applied_Biosystems_instrument_model, /// instrument attribute: Instrument properties that are associated with a value. MS_instrument_attribute = 1000496, /// zoom scan: Special scan mode, where data with improved resolution is acquired. This is typically achieved by scanning a more narrow m/z window or scanning with a lower scan rate. MS_zoom_scan = 1000497, /// enhanced resolution scan (zoom scan): Special scan mode, where data with improved resolution is acquired. This is typically achieved by scanning a more narrow m/z window or scanning with a lower scan rate. MS_enhanced_resolution_scan = MS_zoom_scan, /// full scan: Feature of the ion trap mass spectrometer where MS data is acquired over a mass range. MS_full_scan_OBSOLETE = 1000498, /// spectrum attribute: Spectrum properties that are associated with a value. MS_spectrum_attribute = 1000499, /// scan window upper limit: The lower m/z bound of a mass spectrometer scan window. MS_scan_window_upper_limit = 1000500, /// scan window lower limit: The upper m/z bound of a mass spectrometer scan window. MS_scan_window_lower_limit = 1000501, /// dwell time: The time spent gathering data across a peak. MS_dwell_time = 1000502, /// scan attribute: Scan properties that are associated with a value. MS_scan_attribute = 1000503, /// base peak m/z: M/z value of the signal of highest intensity in the mass spectrum. MS_base_peak_m_z = 1000504, /// base peak intensity: The intensity of the greatest peak in the mass spectrum. MS_base_peak_intensity = 1000505, /// ion role: Ion Role. MS_ion_role_OBSOLETE = 1000506, /// ion attribute: Ion properties that are associated with a value. MS_ion_attribute_OBSOLETE = 1000507, /// ion chemical type: Ion Type. MS_ion_chemical_type_OBSOLETE = 1000508, /// activation energy: Activation Energy. MS_activation_energy = 1000509, /// precursor activation attribute: Precursor Activation Attribute. MS_precursor_activation_attribute = 1000510, /// ms level: Stages of ms achieved in a multi stage mass spectrometry experiment. MS_ms_level = 1000511, /// filter string: A string unique to Thermo instrument describing instrument settings for the scan. MS_filter_string = 1000512, /// binary data array: A data array of values. MS_binary_data_array = 1000513, /// m/z array: A data array of m/z values. MS_m_z_array = 1000514, /// intensity array: A data array of intensity values. MS_intensity_array = 1000515, /// charge array: A data array of charge values. MS_charge_array = 1000516, /// signal to noise array: A data array of signal-to-noise values. MS_signal_to_noise_array = 1000517, /// binary data type: Encoding type of binary data specifying the binary representation and precision, e.g. 64-bit float. MS_binary_data_type = 1000518, /// 32-bit integer: Signed 32-bit little-endian integer. MS_32_bit_integer = 1000519, /// 16-bit float: Signed 16-bit float. MS_16_bit_float_OBSOLETE = 1000520, /// 32-bit float: 32-bit precision little-endian floating point conforming to IEEE-754. MS_32_bit_float = 1000521, /// 64-bit integer: Signed 64-bit little-endian integer. MS_64_bit_integer = 1000522, /// 64-bit float: 64-bit precision little-endian floating point conforming to IEEE-754. MS_64_bit_float = 1000523, /// data file content: Describes the data content on the file. MS_data_file_content = 1000524, /// spectrum representation: Way in which the spectrum is represented, either with regularly spaced data points or with a list of centroided peaks. MS_spectrum_representation = 1000525, /// Waters raw format: Waters data file format found in a Waters RAW directory, generated from an MS acquisition. MS_Waters_raw_format = 1000526, /// highest observed m/z: Highest m/z value observed in the m/z array. MS_highest_observed_m_z = 1000527, /// lowest observed m/z: Lowest m/z value observed in the m/z array. MS_lowest_observed_m_z = 1000528, /// instrument serial number: Serial Number of the instrument. MS_instrument_serial_number = 1000529, /// file format conversion: Conversion of one file format to another. MS_file_format_conversion = 1000530, /// software: Software related to the recording or transformation of spectra. MS_software = 1000531, /// Xcalibur: Thermo Finnigan software for data acquisition and analysis. MS_Xcalibur = 1000532, /// Bioworks: Thermo Finnigan software for data analysis of peptides and proteins. MS_Bioworks = 1000533, /// MassLynx: Micromass software for data acquisition and analysis. MS_MassLynx = 1000534, /// FlexAnalysis: Bruker software for data analysis. MS_FlexAnalysis = 1000535, /// Data Explorer: Applied Biosystems software for data acquisition and analysis. MS_Data_Explorer = 1000536, /// 4700 Explorer: Applied Biosystems software for data acquisition and analysis. MS_4700_Explorer = 1000537, /// massWolf: A software for converting Waters raw directory format to mzXML or mzML. MassWolf was originally developed at the Institute for Systems Biology. MS_massWolf = 1000538, /// wolf (massWolf): A software for converting Waters raw directory format to mzXML or mzML. MassWolf was originally developed at the Institute for Systems Biology. MS_wolf = MS_massWolf, /// Voyager Biospectrometry Workstation System: Applied Biosystems MALDI-TOF data acquisition and analysis system. MS_Voyager_Biospectrometry_Workstation_System = 1000539, /// FlexControl: Bruker software for data acquisition. MS_FlexControl = 1000540, /// ReAdW: A software program for converting Thermo Finnigan RAW file format to mzXML or mzML. ReAdW was originally developed at the Institute for Systems Biology. Its whimsical interleaved spelling and capitalization is pronounced \"readraw\". MS_ReAdW = 1000541, /// MzStar: A software program for converting Applied Biosystems wiff file format to mzXML format. MzStar was originally developed at the Institute for Systems Biology. It is now obsoleted by the MzWiff program. MS_MzStar = 1000542, /// data processing action: Data processing attribute used to describe the type of data processing performed on the data file. MS_data_processing_action = 1000543, /// Conversion to mzML: Conversion of a file format to Proteomics Standards Initiative mzML file format. MS_Conversion_to_mzML = 1000544, /// Conversion to mzXML: Conversion of a file format to Institute of Systems Biology mzXML file format. MS_Conversion_to_mzXML = 1000545, /// Conversion to mzData: Conversion of a file format to Proteomics Standards Initiative mzData file format. MS_Conversion_to_mzData = 1000546, /// object attribute: Object Attribute. MS_object_attribute = 1000547, /// sample attribute: Sample properties that are associated with a value. MS_sample_attribute = 1000548, /// selection window attribute: Selection window properties that are associated with a value. MS_selection_window_attribute = 1000549, /// time unit: Time Unit. MS_time_unit_OBSOLETE = 1000550, /// Analyst: SCIEX or Applied Biosystems|MDS SCIEX software for data acquisition. MS_Analyst = 1000551, /// maldi spot identifier: Maldi Spot Identifier. MS_maldi_spot_identifier_OBSOLETE = 1000552, /// Trapper: A software program for converting Agilent MassHunter format to mzXML or mzML. Trapper was originally developed at the Institute for Systems Biology. MS_Trapper = 1000553, /// LCQ Deca: ThermoFinnigan LCQ Deca. MS_LCQ_Deca = 1000554, /// LTQ Orbitrap Discovery: LTQ Orbitrap Discovery. MS_LTQ_Orbitrap_Discovery = 1000555, /// LTQ Orbitrap XL: LTQ Orbitrap XL. MS_LTQ_Orbitrap_XL = 1000556, /// LTQ FT Ultra: LTQ FT Ultra. MS_LTQ_FT_Ultra = 1000557, /// GC Quantum: GC Quantum. MS_GC_Quantum = 1000558, /// spectrum type: Spectrum type. MS_spectrum_type = 1000559, /// mass spectrometer file format: The format of the file being used. This could be a instrument or vendor specific proprietary file format or a converted open file format. MS_mass_spectrometer_file_format = 1000560, /// data file checksum type: Checksum is a form of redundancy check, a simple way to protect the integrity of data by detecting errors in data. MS_data_file_checksum_type = 1000561, /// ABI WIFF format: Applied Biosystems WIFF file format. MS_ABI_WIFF_format = 1000562, /// Thermo RAW format: Thermo Scientific RAW file format. MS_Thermo_RAW_format = 1000563, /// PSI mzData format: Proteomics Standards Inititative mzData file format. MS_PSI_mzData_format = 1000564, /// Micromass PKL format: Micromass PKL file format. MS_Micromass_PKL_format = 1000565, /// ISB mzXML format: Institute of Systems Biology mzXML file format. MS_ISB_mzXML_format = 1000566, /// Bruker/Agilent YEP format: Bruker/Agilent YEP file format. MS_Bruker_Agilent_YEP_format = 1000567, /// MD5: MD5 (Message-Digest algorithm 5) is a cryptographic hash function with a 128-bit hash value used to check the integrity of files. MS_MD5 = 1000568, /// SHA-1: SHA-1 (Secure Hash Algorithm-1) is a cryptographic hash function designed by the National Security Agency (NSA) and published by the NIST as a U. S. government standard. It is also used to verify file integrity. MS_SHA_1 = 1000569, /// spectra combination: Method used to combine the mass spectra. MS_spectra_combination = 1000570, /// sum of spectra: Spectra Sum. MS_sum_of_spectra = 1000571, /// binary data compression type: Compression Type. MS_binary_data_compression_type = 1000572, /// median of spectra: Spectra is combined by calculating the median of the spectra. MS_median_of_spectra = 1000573, /// zlib compression: Zlib. MS_zlib_compression = 1000574, /// mean of spectra: Spectra is combined by calculating the mean of the spectra. MS_mean_of_spectra = 1000575, /// no compression: No Compression. MS_no_compression = 1000576, /// raw data file: Describes the type of file and its content. MS_raw_data_file = 1000577, /// source file (raw data file): Describes the type of file and its content. MS_source_file = MS_raw_data_file, /// LCQ Fleet: LCQ Fleet. MS_LCQ_Fleet = 1000578, /// MS1 spectrum: Mass spectrum created by a single-stage MS experiment or the first stage of a multi-stage experiment. MS_MS1_spectrum = 1000579, /// full spectrum (MS1 spectrum): Mass spectrum created by a single-stage MS experiment or the first stage of a multi-stage experiment. MS_full_spectrum = MS_MS1_spectrum, /// Q1 spectrum (MS1 spectrum): Mass spectrum created by a single-stage MS experiment or the first stage of a multi-stage experiment. MS_Q1_spectrum = MS_MS1_spectrum, /// Q3 spectrum (MS1 spectrum): Mass spectrum created by a single-stage MS experiment or the first stage of a multi-stage experiment. MS_Q3_spectrum = MS_MS1_spectrum, /// Single-Stage Mass Spectrometry (MS1 spectrum): Mass spectrum created by a single-stage MS experiment or the first stage of a multi-stage experiment. MS_Single_Stage_Mass_Spectrometry = MS_MS1_spectrum, /// MSn spectrum: MSn refers to multi-stage MS2 experiments designed to record product ion spectra where n is the number of product ion stages (progeny ions). For ion traps, sequential MS/MS experiments can be undertaken where n > 2 whereas for a simple triple quadrupole system n=2. Use the term ms level (MS:1000511) for specifying n. MS_MSn_spectrum = 1000580, /// multiple-stage mass spectrometry spectrum (MSn spectrum): MSn refers to multi-stage MS2 experiments designed to record product ion spectra where n is the number of product ion stages (progeny ions). For ion traps, sequential MS/MS experiments can be undertaken where n > 2 whereas for a simple triple quadrupole system n=2. Use the term ms level (MS:1000511) for specifying n. MS_multiple_stage_mass_spectrometry_spectrum = MS_MSn_spectrum, /// nth generation product ion spectrum (MSn spectrum): MSn refers to multi-stage MS2 experiments designed to record product ion spectra where n is the number of product ion stages (progeny ions). For ion traps, sequential MS/MS experiments can be undertaken where n > 2 whereas for a simple triple quadrupole system n=2. Use the term ms level (MS:1000511) for specifying n. MS_nth_generation_product_ion_spectrum = MS_MSn_spectrum, /// product ion spectrum (MSn spectrum): MSn refers to multi-stage MS2 experiments designed to record product ion spectra where n is the number of product ion stages (progeny ions). For ion traps, sequential MS/MS experiments can be undertaken where n > 2 whereas for a simple triple quadrupole system n=2. Use the term ms level (MS:1000511) for specifying n. MS_product_ion_spectrum = MS_MSn_spectrum, /// CRM spectrum: Spectrum generated from MSn experiment with three or more stages of m/z separation and in which a particular multi-step reaction path is monitored. MS_CRM_spectrum = 1000581, /// SIM spectrum: Spectrum obtained with the operation of a mass spectrometer in which the abundances of one ion or several ions of specific m/z values are recorded rather than the entire mass spectrum (Selected Ion Monitoring). MS_SIM_spectrum = 1000582, /// MIM spectrum (SIM spectrum): Spectrum obtained with the operation of a mass spectrometer in which the abundances of one ion or several ions of specific m/z values are recorded rather than the entire mass spectrum (Selected Ion Monitoring). MS_MIM_spectrum = MS_SIM_spectrum, /// multiple ion monitoring spectrum (SIM spectrum): Spectrum obtained with the operation of a mass spectrometer in which the abundances of one ion or several ions of specific m/z values are recorded rather than the entire mass spectrum (Selected Ion Monitoring). MS_multiple_ion_monitoring_spectrum = MS_SIM_spectrum, /// selected ion monitoring spectrum (SIM spectrum): Spectrum obtained with the operation of a mass spectrometer in which the abundances of one ion or several ions of specific m/z values are recorded rather than the entire mass spectrum (Selected Ion Monitoring). MS_selected_ion_monitoring_spectrum = MS_SIM_spectrum, /// SRM spectrum: Spectrum obtained when data are acquired from specific product ions corresponding to m/z values of selected precursor ions a recorded via two or more stages of mass spectrometry. The precursor/product ion pair is called a transition pair. Data can be obtained for a single transition pair or multiple transition pairs. Multiple time segments of different transition pairs can exist in a single file. Single precursor ions can have multiple product ions consitituting multiple transition pairs. Selected reaction monitoring can be performed as tandem mass spectrometry in time or tandem mass spectrometry in space. MS_SRM_spectrum = 1000583, /// MRM spectrum (SRM spectrum): Spectrum obtained when data are acquired from specific product ions corresponding to m/z values of selected precursor ions a recorded via two or more stages of mass spectrometry. The precursor/product ion pair is called a transition pair. Data can be obtained for a single transition pair or multiple transition pairs. Multiple time segments of different transition pairs can exist in a single file. Single precursor ions can have multiple product ions consitituting multiple transition pairs. Selected reaction monitoring can be performed as tandem mass spectrometry in time or tandem mass spectrometry in space. MS_MRM_spectrum = MS_SRM_spectrum, /// multiple reaction monitoring spectrum (SRM spectrum): Spectrum obtained when data are acquired from specific product ions corresponding to m/z values of selected precursor ions a recorded via two or more stages of mass spectrometry. The precursor/product ion pair is called a transition pair. Data can be obtained for a single transition pair or multiple transition pairs. Multiple time segments of different transition pairs can exist in a single file. Single precursor ions can have multiple product ions consitituting multiple transition pairs. Selected reaction monitoring can be performed as tandem mass spectrometry in time or tandem mass spectrometry in space. MS_multiple_reaction_monitoring_spectrum = MS_SRM_spectrum, /// selected reaction monitoring spectrum (SRM spectrum): Spectrum obtained when data are acquired from specific product ions corresponding to m/z values of selected precursor ions a recorded via two or more stages of mass spectrometry. The precursor/product ion pair is called a transition pair. Data can be obtained for a single transition pair or multiple transition pairs. Multiple time segments of different transition pairs can exist in a single file. Single precursor ions can have multiple product ions consitituting multiple transition pairs. Selected reaction monitoring can be performed as tandem mass spectrometry in time or tandem mass spectrometry in space. MS_selected_reaction_monitoring_spectrum = MS_SRM_spectrum, /// mzML format: Proteomics Standards Inititative mzML file format. MS_mzML_format = 1000584, /// contact attribute: Details about a person or organization to contact in case of concern or discussion about the file. MS_contact_attribute = 1000585, /// contact name: Name of the contact person or organization. MS_contact_name = 1000586, /// contact address: Postal address of the contact person or organization. MS_contact_address = 1000587, /// contact URL: Uniform Resource Locator related to the contact person or organization. MS_contact_URL = 1000588, /// contact email: Email address of the contact person or organization. MS_contact_email = 1000589, /// contact affiliation: Home institution of the contact person. MS_contact_affiliation = 1000590, /// MzWiff: A software program for converting Applied Biosystems wiff file format to the mzXML or mzML format. MzWiff is currently maintained at the Institute for Systems Biology. It replaces the slower mzStar program. MS_MzWiff = 1000591, /// smoothing: A process of reducing spikes of intensity in order to reduce noise while preserving real peak signal. Many algorithms can be applied for this process. MS_smoothing = 1000592, /// baseline reduction: A process of removal of varying intensities generated due to variable energy absorption before further processing can take place. Baseline reduction facilitates meaningful comparision between intensities of m/z values. MS_baseline_reduction = 1000593, /// low intensity data point removal: The removal of very low intensity data points that are likely to be spurious noise rather than real signal. MS_low_intensity_data_point_removal = 1000594, /// thresholding (low intensity data point removal): The removal of very low intensity data points that are likely to be spurious noise rather than real signal. MS_thresholding = MS_low_intensity_data_point_removal, /// time array: A data array of relative time offset values from a reference time. MS_time_array = 1000595, /// measurement method: An attribute of resolution when recording the detector response in absence of the analyte. MS_measurement_method = 1000596, /// ion optics type: The electrical potential used to impart kinetic energy to ions in a mass spectrometer. MS_ion_optics_type = 1000597, /// electron transfer dissociation: A process to fragment ions in a mass spectrometer by inducing fragmentation of cations (e.g. peptides or proteins) by transferring electrons to them. MS_electron_transfer_dissociation = 1000598, /// ETD (electron transfer dissociation): A process to fragment ions in a mass spectrometer by inducing fragmentation of cations (e.g. peptides or proteins) by transferring electrons to them. MS_ETD = MS_electron_transfer_dissociation, /// pulsed q dissociation: A process that involves precursor ion activation at high Q, a time delay to allow the precursor to fragment, then a rapid pulse to low Q where all fragment ions are trapped. The product ions can then be scanned out of the ion trap and detected. MS_pulsed_q_dissociation = 1000599, /// PQD (pulsed q dissociation): A process that involves precursor ion activation at high Q, a time delay to allow the precursor to fragment, then a rapid pulse to low Q where all fragment ions are trapped. The product ions can then be scanned out of the ion trap and detected. MS_PQD = MS_pulsed_q_dissociation, /// Proteios: Database application and analysis platform for proteomics. MS_Proteios = 1000600, /// ProteinLynx Global Server: Waters software for data analysis. MS_ProteinLynx_Global_Server = 1000601, /// Shimadzu MALDI-TOF instrument model: Shimadzu MALDI-TOF instrument model. MS_Shimadzu_MALDI_TOF_instrument_model = 1000602, /// Shimadzu Scientific Instruments instrument model: Shimadzu Scientific Instruments instrument model. MS_Shimadzu_Scientific_Instruments_instrument_model = 1000603, /// LCMS-IT-TOF: Shimadzu Scientific Instruments LCMS-IT-TOF MS. MS_LCMS_IT_TOF = 1000604, /// LCMS-2010EV: Shimadzu Scientific Instruments LCMS-2010EV MS. MS_LCMS_2010EV = 1000605, /// LCMS-2010A: Shimadzu Scientific Instruments LCMS-2010A MS. MS_LCMS_2010A = 1000606, /// AXIMA CFR MALDI-TOF: Shimadzu Biotech AXIMA CFR MALDI-TOF MS. MS_AXIMA_CFR_MALDI_TOF = 1000607, /// AXIMA-QIT: Shimadzu Biotech AXIMA-QIT MS. MS_AXIMA_QIT = 1000608, /// AXIMA-CFR plus: Shimadzu Biotech AXIMA-CFR plus MS. MS_AXIMA_CFR_plus = 1000609, /// AXIMA Performance MALDI-TOF/TOF: Shimadzu Biotech AXIMA Performance MALDI-TOF/TOF MS. MS_AXIMA_Performance_MALDI_TOF_TOF = 1000610, /// AXIMA Confidence MALDI-TOF: Shimadzu Biotech AXIMA Confidence MALDI-TOF (curved field reflectron) MS. MS_AXIMA_Confidence_MALDI_TOF = 1000611, /// AXIMA Assurance Linear MALDI-TOF: Shimadzu Biotech AXIMA Assurance Linear MALDI-TOF MS. MS_AXIMA_Assurance_Linear_MALDI_TOF = 1000612, /// DTA format: SEQUEST DTA file format. MS_DTA_format = 1000613, /// ProteinLynx Global Server mass spectrum XML format: Peak list file format used by ProteinLynx Global Server. MS_ProteinLynx_Global_Server_mass_spectrum_XML_format = 1000614, /// ProteoWizard software: ProteoWizard software for data processing and analysis. Primarily developed by the labs of P. Malick and D. Tabb. MS_ProteoWizard_software = 1000615, /// pwiz (ProteoWizard software): ProteoWizard software for data processing and analysis. Primarily developed by the labs of P. Malick and D. Tabb. MS_pwiz = MS_ProteoWizard_software, /// preset scan configuration: A user-defined scan configuration that specifies the instrumental settings in which a spectrum is acquired. An instrument may cycle through a list of preset scan configurations to acquire data. This is a more generic term for the Thermo \"scan event\", which is defined in the Thermo Xcalibur glossary as: a mass spectrometer scan that is defined by choosing the necessary scan parameter settings. Multiple scan events can be defined for each segment of time. MS_preset_scan_configuration = 1000616, /// wavelength array: A data array of electromagnetic radiation wavelength values. MS_wavelength_array = 1000617, /// highest observed wavelength: Highest wavelength observed in an EMR spectrum. MS_highest_observed_wavelength = 1000618, /// lowest observed wavelength: Lowest wavelength observed in an EMR spectrum. MS_lowest_observed_wavelength = 1000619, /// PDA spectrum: Spectrum generated from a photodiode array detector (ultraviolet/visible spectrum). MS_PDA_spectrum_OBSOLETE = 1000620, /// photodiode array detector: An array detector used to record spectra in the ultraviolet and visible region of light. MS_photodiode_array_detector = 1000621, /// PDA (photodiode array detector): An array detector used to record spectra in the ultraviolet and visible region of light. MS_PDA = MS_photodiode_array_detector, /// Surveyor PDA: Surveyor PDA. MS_Surveyor_PDA = 1000622, /// Accela PDA: Accela PDA. MS_Accela_PDA = 1000623, /// inductive detector: Inductive detector. MS_inductive_detector = 1000624, /// image current detector (inductive detector): Inductive detector. MS_image_current_detector = MS_inductive_detector, /// chromatogram: The representation of detector response versus time. MS_chromatogram = 1000625, /// chromatogram type: Broad category or type of a chromatogram. MS_chromatogram_type = 1000626, /// selected ion current chromatogram: Chromatogram created by creating an array of the measurements of a specific single ion current at each time point. MS_selected_ion_current_chromatogram = 1000627, /// SIC chromatogram (selected ion current chromatogram): Chromatogram created by creating an array of the measurements of a specific single ion current at each time point. MS_SIC_chromatogram = MS_selected_ion_current_chromatogram, /// basepeak chromatogram: Chromatogram created by creating an array of the most intense peaks at each time point. MS_basepeak_chromatogram = 1000628, /// low intensity threshold: Threshold below which some action is taken. MS_low_intensity_threshold = 1000629, /// data processing parameter: Data processing parameter used in the data processing performed on the data file. MS_data_processing_parameter = 1000630, /// high intensity threshold: Threshold above which some action is taken. MS_high_intensity_threshold = 1000631, /// Q-Tof Premier: Waters oa-ToF based Q-Tof Premier. MS_Q_Tof_Premier = 1000632, /// possible charge state: A possible charge state of the ion in a situation where the charge of an ion is known to be one of several possible values rather than a completely unknown value or determined to be a specific charge with reasonable certainty. MS_possible_charge_state = 1000633, /// DSQ: ThermoFinnigan DSQ GC-MS. MS_DSQ = 1000634, /// ITQ 700: Thermo Scientific ITQ 700 GC-MS. MS_ITQ_700 = 1000635, /// ITQ 900: Thermo Scientific ITQ 900 GC-MS. MS_ITQ_900 = 1000636, /// ITQ 1100: Thermo Scientific ITQ 1100 GC-MS. MS_ITQ_1100 = 1000637, /// LTQ XL ETD: Thermo Scientific LTQ XL MS with ETD. MS_LTQ_XL_ETD = 1000638, /// LTQ Orbitrap XL ETD: Thermo Scientific LTQ Orbitrap XL MS with ETD. MS_LTQ_Orbitrap_XL_ETD = 1000639, /// DFS: Thermo Scientific DFS HR GC-MS. MS_DFS = 1000640, /// DSQ II: Thermo Scientific DSQ II GC-MS. MS_DSQ_II = 1000641, /// MALDI LTQ XL: Thermo Scientific MALDI LTQ XL MS. MS_MALDI_LTQ_XL = 1000642, /// MALDI LTQ Orbitrap: Thermo Scientific MALDI LTQ Orbitrap MS. MS_MALDI_LTQ_Orbitrap = 1000643, /// TSQ Quantum Access: Thermo Scientific TSQ Quantum Access MS. MS_TSQ_Quantum_Access = 1000644, /// Element XR: Thermo Scientific Element XR HR-ICP-MS. MS_Element_XR = 1000645, /// Element 2: Thermo Scientific Element 2 HR-ICP-MS. MS_Element_2 = 1000646, /// Element GD: Thermo Scientific Element GD Glow Discharge MS. MS_Element_GD = 1000647, /// GC IsoLink: Thermo Scientific GC IsoLink Isotope Ratio MS. MS_GC_IsoLink = 1000648, /// Exactive: Thermo Scientific Exactive MS. MS_Exactive = 1000649, /// Proteome Discoverer: Thermo Scientific software for data analysis of peptides and proteins. MS_Proteome_Discoverer = 1000650, /// 3200 QTRAP: SCIEX or Applied Biosystems|MDS SCIEX QTRAP 3200. MS_3200_QTRAP = 1000651, /// 4800 Plus MALDI TOF/TOF: SCIEX or Applied Biosystems|MDS SCIEX 4800 Plus MALDI TOF-TOF Analyzer. MS_4800_Plus_MALDI_TOF_TOF = 1000652, /// API 3200: SCIEX or Applied Biosystems|MDS SCIEX API 3200 MS. MS_API_3200 = 1000653, /// API 5000: SCIEX or Applied Biosystems|MDS SCIEX API 5000 MS. MS_API_5000 = 1000654, /// QSTAR Elite: SCIEX or Applied Biosystems|MDS SCIEX QSTAR Elite. MS_QSTAR_Elite = 1000655, /// QSTAR Pulsar: Applied Biosystems|MDS SCIEX QSTAR Pulsar. MS_QSTAR_Pulsar = 1000656, /// QSTAR XL: Applied Biosystems|MDS SCIEX QSTAR XL. MS_QSTAR_XL = 1000657, /// 4800 Proteomics Analyzer: Applied Biosystems|MDS SCIEX 4800 Proteomics Analyzer. MS_4800_Proteomics_Analyzer = 1000658, /// 4000 Series Explorer Software: SCIEX or Applied Biosystems software for data acquisition and analysis. MS_4000_Series_Explorer_Software = 1000659, /// GPS Explorer: SCIEX or Applied Biosystems software for data acquisition and analysis. MS_GPS_Explorer = 1000661, /// LightSight Software: SCIEX or Applied Biosystems|MDS SCIEX software metabolite identification. MS_LightSight_Software = 1000662, /// ProteinPilot Software: SCIEX or Applied Biosystems|MDS SCIEX software for protein ID and quant. MS_ProteinPilot_Software = 1000663, /// TissueView Software: Applied Biosystems|MDS SCIEX software for tissue imaging. MS_TissueView_Software = 1000664, /// MarkerView Software: Applied Biosystems|MDS SCIEX software for metabolomics and biomarker profiling. MS_MarkerView_Software = 1000665, /// MRMPilot Software: Applied Biosystems|MDS SCIEX software for MRM assay development. MS_MRMPilot_Software = 1000666, /// BioAnalyst: Applied Biosystems|MDS SCIEX software for bio-related data exploration. MS_BioAnalyst = 1000667, /// Pro ID: Applied Biosystems|MDS SCIEX software for protein identification. MS_Pro_ID = 1000668, /// Pro ICAT: Applied Biosystems|MDS SCIEX software for protein ID and quant by ICAT. MS_Pro_ICAT = 1000669, /// Pro Quant: Applied Biosystems|MDS SCIEX software for protein ID and quant by iTRAQ. MS_Pro_Quant = 1000670, /// Pro BLAST: Applied Biosystems|MDS SCIEX software for MS-BLAST identification. MS_Pro_BLAST = 1000671, /// Cliquid: SCIEX Cliquid software for data analysis and quantitation. MS_Cliquid = 1000672, /// MIDAS Workflow Designer: Applied Biosystems|MDS SCIEX software for MRM assay development. MS_MIDAS_Workflow_Designer = 1000673, /// MultiQuant: Applied Biosystems|MDS SCIEX software for MRM-based quantitation. MS_MultiQuant = 1000674, /// 6220 Time-of-Flight LC/MS: The 6220 Time-of-Flight LC/MS is a Agilent liquid chromatography instrument combined with a Agilent time of flight mass spectrometer. This time of flight mass spectrometer has a m/z range of 50-12000, mass accuracy of less than 2 ppm and resolution greater than 13,000 at m/z 2722. It has multiple ion sources and can be used with multimode ion sources. MS_6220_Time_of_Flight_LC_MS = 1000675, /// 6510 Quadrupole Time-of-Flight LC/MS: The 6510 Quadrupole Time-of-Flight LC/MS is a Agilent liquid chromatography instrument combined with a Agilent time of flight mass spectrometer. This time of flight mass spectrometer has a m/z range of 50-12000, mass accuracy of less than 2 ppm and resolution greater than 13,000 at m/z 2722. It has multiple ion sources and can be used with multimode ion sources. MS_6510_Quadrupole_Time_of_Flight_LC_MS = 1000676, /// 6520 Quadrupole Time-of-Flight LC/MS: The 6520 Quadrupole Time-of-Flight LC/MS is a Agilent liquid chromatography instrument combined with a Agilent time of flight mass spectrometer. This time of flight mass spectrometer has a m/z range of 50-12000, mass accuracy of less than 2 ppm and resolution greater than 26,000 at m/z 2722. It has multiple ion sources and can be used with multimode ion sources. MS_6520_Quadrupole_Time_of_Flight_LC_MS = 1000677, /// MassHunter Data Acquisition: Software for data acquisition of 6000 series instruments. MS_MassHunter_Data_Acquisition = 1000678, /// MassHunter Easy Access: Software for open access data acquisition. MS_MassHunter_Easy_Access = 1000679, /// MassHunter Qualitative Analysis: Software for data analysis of data from 6000 series instruments. MS_MassHunter_Qualitative_Analysis = 1000680, /// MassHunter Quantitative Analysis: Software for quantitation of Triple Quadrupole and Quadrupole Time-of-Flight data. MS_MassHunter_Quantitative_Analysis = 1000681, /// MassHunter Metabolite ID: Software for identification of metabolites. MS_MassHunter_Metabolite_ID = 1000682, /// MassHunter BioConfirm: Software for protein characterization. MS_MassHunter_BioConfirm = 1000683, /// Genespring MS: Software for quantitation and statistical analysis of TOF and Q-TOF LC/MS data. MS_Genespring_MS = 1000684, /// MassHunter Mass Profiler: Software for quantitation and statistical analysis of TOF and Q-TOF LC/MS data. MS_MassHunter_Mass_Profiler = 1000685, /// METLIN: Personal Metabolite Database for MassHunter Workstation. Software for identification of human metabolites. MS_METLIN = 1000686, /// Spectrum Mill for MassHunter Workstation: Software for protein identification and characterization of complex protein digest mixtures. MS_Spectrum_Mill_for_MassHunter_Workstation = 1000687, /// 6300 Series Ion Trap Data Analysis Software: Software for data analysis of 6300 series ion trap mass spectrometers. MS_6300_Series_Ion_Trap_Data_Analysis_Software = 1000688, /// Agilent software: Agilent software for data acquisition and analysis. MS_Agilent_software = 1000689, /// SCIEX software: SCIEX or Applied Biosystems software for data acquisition and analysis. MS_SCIEX_software = 1000690, /// Applied Biosystems software: Applied Biosystems|MDS SCIEX software for data acquisition and analysis. MS_Applied_Biosystems_software = 1000691, /// Bruker software: Bruker software for data acquisition and analysis. MS_Bruker_software = 1000692, /// Thermo Finnigan software: Thermo Finnigan software for data acquisition and analysis. MS_Thermo_Finnigan_software = 1000693, /// Waters software: Waters software for data acquisition and analysis. MS_Waters_software = 1000694, /// apex ultra: Bruker Daltonics' apex ultra: ESI, MALDI, Nanospray, APCI, APPI, Qh-FT_ICR. MS_apex_ultra = 1000695, /// autoflex III smartbeam: Bruker Daltonics' autoflex III smartbeam: MALDI TOF. MS_autoflex_III_smartbeam = 1000696, /// Bruker Daltonics HCT Series: Bruker Daltonics' HCT Series. MS_Bruker_Daltonics_HCT_Series = 1000697, /// HCTultra: Bruker Daltonics' HCTultra: ESI TOF, Nanospray, APCI, APPI. MS_HCTultra = 1000698, /// HCTultra PTM: Bruker Daltonics' HCTultra PTM: ESI TOF, Nanospray, APCI, APPI, PTR. MS_HCTultra_PTM = 1000699, /// HCTultra ETD II: Bruker Daltonics' HCTultra ETD II: ESI Q-TOF, Nanospray, APCI, APPI, ETD. MS_HCTultra_ETD_II = 1000700, /// microflex LT: Bruker Daltonics' microflex LT: MALDI TOF. MS_microflex_LT = 1000701, /// micrOTOF: Bruker Daltonics' micrOTOF: ESI TOF, APCI, APPI. MS_micrOTOF = 1000702, /// micrOTOF-Q: Bruker Daltonics' micrOTOF-Q: ESI Q-TOF, Nanospray, APCI, APPI. MS_micrOTOF_Q = 1000703, /// micrOTOF-Q II: Bruker Daltonics' micrOTOF-Q II: ESI Q-TOF, Nanospray, APCI, APPI. MS_micrOTOF_Q_II = 1000704, /// ultraflex III TOF/TOF: Bruker Daltonics' ultraflex III TOF/TOF: MALDI TOF. MS_ultraflex_III_TOF_TOF = 1000705, /// apexControl: Bruker software for data acquisition. MS_apexControl = 1000706, /// BioTools: Bruker software for data analysis. MS_BioTools = 1000707, /// CLINPROT: Bruker CLINPROT software. MS_CLINPROT = 1000708, /// CLINPROT micro: Bruker CLINPROT micro software. MS_CLINPROT_micro = 1000709, /// CLINPROT robot: Bruker CLINPROT robot software. MS_CLINPROT_robot = 1000710, /// ClinProTools: Bruker ClinProTools software. MS_ClinProTools = 1000711, /// Compass: Bruker Compass software. MS_Compass = 1000712, /// Compass for HCT/esquire: Bruker Compass for HCT/esquire software. MS_Compass_for_HCT_esquire = 1000713, /// Compass for micrOTOF: Bruker Compass for micrOTOF software. MS_Compass_for_micrOTOF = 1000714, /// Compass OpenAccess: Bruker compass OpenAccess software. MS_Compass_OpenAccess = 1000715, /// Compass Security Pack: Bruker compass Security Pack software. MS_Compass_Security_Pack = 1000716, /// CompassXport: Bruker stand-alone software for data conversion. MS_CompassXport = 1000717, /// CompassXtract: Bruker software library for data access. MS_CompassXtract = 1000718, /// DataAnalysis: Bruker software for data analysis. MS_DataAnalysis = 1000719, /// dpControl: Bruker software for data acquisition. MS_dpControl = 1000720, /// esquireControl: Bruker software for data acquisition. MS_esquireControl = 1000721, /// flexImaging: Bruker software for data analysis. MS_flexImaging = 1000722, /// GENOLINK: Bruker GENOLINK software. MS_GENOLINK = 1000723, /// GenoTools: Bruker GenoTools software. MS_GenoTools = 1000724, /// HCTcontrol: Bruker software for data acquisition. MS_HCTcontrol = 1000725, /// micrOTOFcontrol: Bruker software for data acquisition. MS_micrOTOFcontrol = 1000726, /// PolyTools: Bruker PolyTools software. MS_PolyTools = 1000727, /// ProfileAnalysis: Bruker software for data analysis. MS_ProfileAnalysis = 1000728, /// PROTEINEER: Bruker PROTEINEER software. MS_PROTEINEER = 1000729, /// PROTEINEER dp: Bruker PROTEINEER dp software. MS_PROTEINEER_dp = 1000730, /// PROTEINEER fc: Bruker PROTEINEER fc software. MS_PROTEINEER_fc = 1000731, /// PROTEINEER spII: Bruker PROTEINEER spII software. MS_PROTEINEER_spII = 1000732, /// PROTEINEER-LC: Bruker PROTEINEER-LC software. MS_PROTEINEER_LC = 1000733, /// ProteinScape: Bruker ProteinScape software. MS_ProteinScape = 1000734, /// PureDisk: BrukerPureDisk software. MS_PureDisk = 1000735, /// QuantAnalysis: Bruker software for data analysis. MS_QuantAnalysis = 1000736, /// spControl: Bruker software for data acquisition. MS_spControl = 1000737, /// TargetAnalysis: Bruker TargetAnalysis software. MS_TargetAnalysis = 1000738, /// WARP-LC: Bruker WARP-LC software. MS_WARP_LC = 1000739, /// parameter file: Parameter file used to configure the acquisition of raw data on the instrument. MS_parameter_file = 1000740, /// Conversion to dta: Conversion to dta format. MS_Conversion_to_dta = 1000741, /// Bioworks SRF format: Thermo Finnigan SRF file format. MS_Bioworks_SRF_format = 1000742, /// TSQ Quantum Ultra AM: Thermo Scientific TSQ Quantum Ultra AM. MS_TSQ_Quantum_Ultra_AM = 1000743, /// selected ion m/z: Mass-to-charge ratio of an selected ion. MS_selected_ion_m_z = 1000744, /// retention time alignment: The correction of the spectrum scan times, as used e.g. in label-free proteomics. MS_retention_time_alignment = 1000745, /// high intensity data point removal: The removal of very high intensity data points. MS_high_intensity_data_point_removal = 1000746, /// completion time: The time that a data processing action was finished. MS_completion_time = 1000747, /// SSQ 7000: ThermoFinnigan SSQ 7000 MS. MS_SSQ_7000 = 1000748, /// TSQ 7000: ThermoFinnigan TSQ 7000 MS. MS_TSQ_7000 = 1000749, /// TSQ: ThermoFinnigan TSQ MS. MS_TSQ = 1000750, /// TSQ Quantum Ultra: Thermo Scientific TSQ Quantum Ultra. MS_TSQ_Quantum_Ultra = 1000751, /// TOPP software: TOPP (The OpenMS proteomics pipeline) software. MS_TOPP_software = 1000752, /// BaselineFilter: Removes the baseline from profile spectra using a top-hat filter. MS_BaselineFilter = 1000753, /// DBExporter: Exports data from an OpenMS database to a file. MS_DBExporter = 1000754, /// DBImporter: Imports data to an OpenMS database. MS_DBImporter = 1000755, /// FileConverter: Converts between different MS file formats. MS_FileConverter = 1000756, /// FileFilter: Extracts or manipulates portions of data from peak, feature or consensus feature files. MS_FileFilter = 1000757, /// FileMerger: Merges several MS files into one file. MS_FileMerger = 1000758, /// InternalCalibration: Applies an internal calibration. MS_InternalCalibration = 1000759, /// MapAligner: Corrects retention time distortions between maps. MS_MapAligner_OBSOLETE = 1000760, /// MapNormalizer: Normalizes peak intensities in an MS run. MS_MapNormalizer = 1000761, /// NoiseFilter: Removes noise from profile spectra by using different smoothing techniques. MS_NoiseFilter_OBSOLETE = 1000762, /// PeakPicker: Finds mass spectrometric peaks in profile mass spectra. MS_PeakPicker_OBSOLETE = 1000763, /// Resampler: Transforms an LC/MS map into a resampled map or a png image. MS_Resampler = 1000764, /// SpectraFilter: Applies a filter to peak spectra. MS_SpectraFilter_OBSOLETE = 1000765, /// TOFCalibration: Applies time of flight calibration. MS_TOFCalibration = 1000766, /// native spectrum identifier format: Describes how the native spectrum identifiers are formated. MS_native_spectrum_identifier_format = 1000767, /// nativeID format (native spectrum identifier format): Describes how the native spectrum identifiers are formated. MS_nativeID_format = MS_native_spectrum_identifier_format, /// Thermo nativeID format: Native format defined by controllerType=xsd:nonNegativeInteger controllerNumber=xsd:positiveInteger scan=xsd:positiveInteger. MS_Thermo_nativeID_format = 1000768, /// Waters nativeID format: Native format defined by function=xsd:positiveInteger process=xsd:nonNegativeInteger scan=xsd:nonNegativeInteger. MS_Waters_nativeID_format = 1000769, /// WIFF nativeID format: Native format defined by sample=xsd:nonNegativeInteger period=xsd:nonNegativeInteger cycle=xsd:nonNegativeInteger experiment=xsd:nonNegativeInteger. MS_WIFF_nativeID_format = 1000770, /// Bruker/Agilent YEP nativeID format: Native format defined by scan=xsd:nonNegativeInteger. MS_Bruker_Agilent_YEP_nativeID_format = 1000771, /// Bruker BAF nativeID format: Native format defined by scan=xsd:nonNegativeInteger. MS_Bruker_BAF_nativeID_format = 1000772, /// Bruker FID nativeID format: Native format defined by file=xsd:IDREF. MS_Bruker_FID_nativeID_format = 1000773, /// multiple peak list nativeID format: Native format defined by index=xsd:nonNegativeInteger. MS_multiple_peak_list_nativeID_format = 1000774, /// single peak list nativeID format: Native format defined by file=xsd:IDREF. MS_single_peak_list_nativeID_format = 1000775, /// scan number only nativeID format: Native format defined by scan=xsd:nonNegativeInteger. MS_scan_number_only_nativeID_format = 1000776, /// spectrum identifier nativeID format: Native format defined by spectrum=xsd:nonNegativeInteger. MS_spectrum_identifier_nativeID_format = 1000777, /// charge state calculation: A process that infers the charge state of an MSn spectrum's precursor(s) by the application of some algorithm. MS_charge_state_calculation = 1000778, /// below precursor intensity dominance charge state calculation: Infers charge state as single or ambiguously multiple by determining the fraction of intensity below the precursor m/z. MS_below_precursor_intensity_dominance_charge_state_calculation = 1000779, /// precursor recalculation: A process that recalculates existing precursor selected ions with one or more algorithmically determined precursor selected ions. MS_precursor_recalculation = 1000780, /// msPrefix precursor recalculation: Recalculates one or more precursor selected ions by peak detection in the isolation windows of high accuracy MS precursor scans. MS_msPrefix_precursor_recalculation = 1000781, /// Savitzky-Golay smoothing: Reduces intensity spikes by applying local polynomial regression (of degree k) on a distribution (of at least k+1 equally spaced points) to determine the smoothed value for each point. It tends to preserve features of the distribution such as relative maxima, minima and width, which are usually 'flattened' by other adjacent averaging techniques. MS_Savitzky_Golay_smoothing = 1000782, /// LOWESS smoothing: Reduces intensity spikes by applying a modelling method known as locally weighted polynomial regression. At each point in the data set a low-degree polynomial is fit to a subset of the data, with explanatory variable values near the point whose response is being estimated. The polynomial is fit using weighted least squares, giving more weight to points near the point whose response is being estimated and less weight to points further away. The value of the regression function for the point is then obtained by evaluating the local polynomial using the explanatory variable values for that data point. The LOESS fit is complete after regression function values have been computed for each of the n data points. Many of the details of this method, such as the degree of the polynomial model and the weights, are flexible. MS_LOWESS_smoothing = 1000783, /// Gaussian smoothing: Reduces intensity spikes by convolving the data with a one-dimensional Gaussian function. MS_Gaussian_smoothing = 1000784, /// binomial smoothing (Gaussian smoothing): Reduces intensity spikes by convolving the data with a one-dimensional Gaussian function. MS_binomial_smoothing = MS_Gaussian_smoothing, /// Weierstrass transform (Gaussian smoothing): Reduces intensity spikes by convolving the data with a one-dimensional Gaussian function. MS_Weierstrass_transform = MS_Gaussian_smoothing, /// moving average smoothing: Reduces intensity spikes by averaging each point with two or more adjacent points. The more adjacent points that used, the stronger the smoothing effect. MS_moving_average_smoothing = 1000785, /// box smoothing (moving average smoothing): Reduces intensity spikes by averaging each point with two or more adjacent points. The more adjacent points that used, the stronger the smoothing effect. MS_box_smoothing = MS_moving_average_smoothing, /// boxcar smoothing (moving average smoothing): Reduces intensity spikes by averaging each point with two or more adjacent points. The more adjacent points that used, the stronger the smoothing effect. MS_boxcar_smoothing = MS_moving_average_smoothing, /// sliding average smoothing (moving average smoothing): Reduces intensity spikes by averaging each point with two or more adjacent points. The more adjacent points that used, the stronger the smoothing effect. MS_sliding_average_smoothing = MS_moving_average_smoothing, /// non-standard data array: A data array that contains data not covered by any other term in this group. Please do not use this term, if the binary data array type might be commonly used - contact the PSI-MS working group in order to have another CV term added. MS_non_standard_data_array = 1000786, /// inclusive low intensity threshold: Threshold at or below which some action is taken. MS_inclusive_low_intensity_threshold = 1000787, /// inclusive high intensity threshold: Threshold at or above which some action is taken. MS_inclusive_high_intensity_threshold = 1000788, /// enhanced multiply charged spectrum: MS1 spectrum that is enriched in multiply-charged ions compared to singly-charged ions. MS_enhanced_multiply_charged_spectrum = 1000789, /// time-delayed fragmentation spectrum: MSn spectrum in which the product ions are collected after a time delay, which allows the observation of lower energy fragmentation processes after precursor ion activation. MS_time_delayed_fragmentation_spectrum = 1000790, /// enhanced resolution scan: Scan with enhanced resolution. MS_enhanced_resolution_scan_OBSOLETE = 1000791, /// isolation window attribute: Isolation window parameter. MS_isolation_window_attribute = 1000792, /// isolation window upper limit: The highest m/z being isolated in an isolation window. MS_isolation_window_upper_limit_OBSOLETE = 1000793, /// isolation window lower limit: The lowest m/z being isolated in an isolation window. MS_isolation_window_lower_limit_OBSOLETE = 1000794, /// no combination: Use this term if only one scan was recorded or there is no information about scans available. MS_no_combination = 1000795, /// spectrum title: A free-form text title describing a spectrum. MS_spectrum_title = 1000796, /// peak list scans: A list of scan numbers and or scan ranges associated with a peak list. If possible the list of scans should be converted to native spectrum identifiers instead of using this term. MS_peak_list_scans = 1000797, /// peak list raw scans: A list of raw scans and or scan ranges used to generate a peak list. If possible the list of scans should be converted to native spectrum identifiers instead of using this term. MS_peak_list_raw_scans = 1000798, /// custom unreleased software tool: A software tool that has not yet been released. The value should describe the software. Please do not use this term for publicly available software - contact the PSI-MS working group in order to have another CV term added. MS_custom_unreleased_software_tool = 1000799, /// mass resolving power: The observed mass divided by the difference between two masses that can be separated: m/dm. The procedure by which dm was obtained and the mass at which the measurement was made should be reported. MS_mass_resolving_power = 1000800, /// area peak picking: Spectral peak processing conducted on the acquired data to convert profile data to centroided data. The area defined by all raw data points that belong to the peak is reported. MS_area_peak_picking = 1000801, /// sum peak picking (area peak picking): Spectral peak processing conducted on the acquired data to convert profile data to centroided data. The area defined by all raw data points that belong to the peak is reported. MS_sum_peak_picking = MS_area_peak_picking, /// height peak picking: Spectral peak processing conducted on the acquired data to convert profile data to centroided data. The maximum intensity of all raw data points that belong to the peak is reported. MS_height_peak_picking = 1000802, /// max peak picking (height peak picking): Spectral peak processing conducted on the acquired data to convert profile data to centroided data. The maximum intensity of all raw data points that belong to the peak is reported. MS_max_peak_picking = MS_height_peak_picking, /// analyzer scan offset: Offset between two analyzers in a constant neutral loss or neutral gain scan. The value corresponds to the neutral loss or neutral gain value. MS_analyzer_scan_offset = 1000803, /// electromagnetic radiation spectrum: A plot of the relative intensity of electromagnetic radiation as a function of the wavelength. MS_electromagnetic_radiation_spectrum = 1000804, /// EMR spectrum (electromagnetic radiation spectrum): A plot of the relative intensity of electromagnetic radiation as a function of the wavelength. MS_EMR_spectrum = MS_electromagnetic_radiation_spectrum, /// emission spectrum: A plot of the relative intensity of electromagnetic radiation emitted by atoms or molecules when excited. MS_emission_spectrum = 1000805, /// absorption spectrum: A plot of the relative intensity of electromagnetic radiation absorbed by atoms or molecules when excited. MS_absorption_spectrum = 1000806, /// Th/s: Unit describing the scan rate of a spectrum in Thomson per second. MS_Th_s = 1000807, /// chromatogram attribute: Chromatogram properties that are associated with a value. MS_chromatogram_attribute = 1000808, /// chromatogram title: A free-form text title describing a chromatogram. MS_chromatogram_title = 1000809, /// mass chromatogram: A plot of the relative abundance of a beam or other collection of ions as a function of the retention time. MS_mass_chromatogram = 1000810, /// electromagnetic radiation chromatogram: The measurement of electromagnetic properties as a function of the retention time. MS_electromagnetic_radiation_chromatogram = 1000811, /// EMR radiation chromatogram (electromagnetic radiation chromatogram): The measurement of electromagnetic properties as a function of the retention time. MS_EMR_radiation_chromatogram = MS_electromagnetic_radiation_chromatogram, /// absorption chromatogram: The measurement of light absorbed by the sample as a function of the retention time. MS_absorption_chromatogram = 1000812, /// emission chromatogram: The measurement of light emitted by the sample as a function of the retention time. MS_emission_chromatogram = 1000813, /// counts per second: The number of counted events observed per second in one or a group of elements of a detector. MS_counts_per_second = 1000814, /// Bruker BAF format: Bruker BAF raw file format. MS_Bruker_BAF_format = 1000815, /// Bruker U2 format: Bruker HyStar U2 file format. MS_Bruker_U2_format = 1000816, /// HyStar: Bruker software for hyphenated experiments. MS_HyStar = 1000817, /// Acquity UPLC PDA: Acquity UPLC Photodiode Array Detector. MS_Acquity_UPLC_PDA = 1000818, /// Acquity UPLC FLR: Acquity UPLC Fluorescence Detector. MS_Acquity_UPLC_FLR = 1000819, /// flow rate array: A data array of flow rate measurements. MS_flow_rate_array = 1000820, /// pressure array: A data array of pressure measurements. MS_pressure_array = 1000821, /// temperature array: A data array of temperature measurements. MS_temperature_array = 1000822, /// Bruker U2 nativeID format: Native format defined by declaration=xsd:nonNegativeInteger collection=xsd:nonNegativeInteger scan=xsd:nonNegativeInteger. MS_Bruker_U2_nativeID_format = 1000823, /// no nativeID format: No nativeID format indicates that the file tagged with this term does not contain spectra that can have a nativeID format. MS_no_nativeID_format = 1000824, /// Bruker FID format: Bruker FID file format. MS_Bruker_FID_format = 1000825, /// elution time: The time of elution from all used chromatographic columns (one or more) in the chromatographic separation step, relative to the start of the chromatography. MS_elution_time = 1000826, /// isolation window target m/z: The primary or reference m/z about which the isolation window is defined. MS_isolation_window_target_m_z = 1000827, /// isolation window lower offset: The extent of the isolation window in m/z below the isolation window target m/z. The lower and upper offsets may be asymmetric about the target m/z. MS_isolation_window_lower_offset = 1000828, /// isolation window upper offset: The extent of the isolation window in m/z above the isolation window target m/z. The lower and upper offsets may be asymmetric about the target m/z. MS_isolation_window_upper_offset = 1000829, /// sample preparation: Properties of the preparation steps which took place before the measurement was performed. MS_sample_preparation = 1000831, /// MALDI matrix application: Attributes to describe the technique how the sample is prepared with the matrix solution. MS_MALDI_matrix_application = 1000832, /// matrix application type: Describes the technique how the matrix is put on the sample target. MS_matrix_application_type = 1000833, /// matrix solution: Describes the chemical solution used as matrix. MS_matrix_solution = 1000834, /// matrix solution concentration: Concentration of the chemical solution used as matrix. MS_matrix_solution_concentration = 1000835, /// dried droplet MALDI matrix preparation: Dried droplet in MALDI matrix preparation. MS_dried_droplet_MALDI_matrix_preparation = 1000836, /// printed MALDI matrix preparation: Printed MALDI matrix preparation. MS_printed_MALDI_matrix_preparation = 1000837, /// sprayed MALDI matrix preparation: Sprayed MALDI matrix preparation. MS_sprayed_MALDI_matrix_preparation = 1000838, /// precoated MALDI sample plate: Precoated MALDI sample plate. MS_precoated_MALDI_sample_plate = 1000839, /// laser: Device that emits light (electromagnetic radiation) through a process called stimulated emission. The term is an acronym for Light Amplification by Stimulated Emission of Radiation. MS_laser = 1000840, /// laser attribute: Laser properties that are associated with a value. MS_laser_attribute = 1000841, /// laser type: Type of laser used used for desorption purpose. MS_laser_type = 1000842, /// wavelength: The distance between two peaks of the emitted laser beam. MS_wavelength_OBSOLETE = 1000843, /// focus diameter x: Describes the diameter of the laser beam in x direction. MS_focus_diameter_x = 1000844, /// focus diameter y: Describes the diameter of the laser beam in y direction. MS_focus_diameter_y = 1000845, /// pulse energy: Describes output energy of the laser system. May be attenuated by filters or other means. MS_pulse_energy = 1000846, /// pulse duration: Describes how long the laser beam was emitted from the laser device. MS_pulse_duration = 1000847, /// attenuation: Describes the reduction of the intensity of the laser beam energy. MS_attenuation = 1000848, /// impact angle: Describes the angle between the laser beam and the sample target. MS_impact_angle = 1000849, /// gas laser: Laser which is powered by a gaseous medium. MS_gas_laser = 1000850, /// solid-state laser: Solid state laser materials are commonly made by doping a crystalline solid host with ions that provide the required energy states. MS_solid_state_laser = 1000851, /// dye-laser: Dye lasers use an organic dye as the gain medium. MS_dye_laser = 1000852, /// free electron laser: Free electron laser uses a relativistic electron beam as the lasing medium which move freely through a magnetic structure, hence the term. MS_free_electron_laser = 1000853, /// LTQ XL: Thermo Scientific LTQ XL MS. MS_LTQ_XL = 1000854, /// LTQ Velos: Thermo Scientific LTQ Velos MS. MS_LTQ_Velos = 1000855, /// LTQ Velos ETD: Thermo Scientific LTQ Velos MS with ETD. MS_LTQ_Velos_ETD = 1000856, /// run attribute: Properties of the described run. MS_run_attribute = 1000857, /// fraction identifier: Identier string that describes the sample fraction. This identifier should contain the fraction number(s) or similar information. MS_fraction_identifier = 1000858, /// molecule: A molecules is a fundamental component of a chemical compound that is the smallest part of the compound that can participate in a chemical reaction. MS_molecule = 1000859, /// peptide: A compound of low molecular weight that is composed of two or more amino acids. MS_peptide = 1000860, /// chemical compound attribute: A describable property of a chemical compound. MS_chemical_compound_attribute = 1000861, /// isoelectric point: The pH of a solution at which a charged molecule does not migrate in an electric field. MS_isoelectric_point = 1000862, /// pI (isoelectric point): The pH of a solution at which a charged molecule does not migrate in an electric field. MS_pI = MS_isoelectric_point, /// predicted isoelectric point: The pH of a solution at which a charged molecule would not migrate in an electric field, as predicted by a software algorithm. MS_predicted_isoelectric_point = 1000863, /// predicted pI (predicted isoelectric point): The pH of a solution at which a charged molecule would not migrate in an electric field, as predicted by a software algorithm. MS_predicted_pI = MS_predicted_isoelectric_point, /// chemical compound formula: A combination of symbols used to express the chemical composition of a compound. MS_chemical_compound_formula = 1000864, /// empirical formula: A chemical formula which expresses the proportions of the elements present in a substance. MS_empirical_formula = 1000865, /// molecular formula: A chemical compound formula expressing the number of atoms of each element present in a compound, without indicating how they are linked. MS_molecular_formula = 1000866, /// structural formula: A chemical formula showing the number of atoms of each element in a molecule, their spatial arrangement, and their linkage to each other. MS_structural_formula = 1000867, /// SMILES string: The simplified molecular input line entry specification or SMILES is a specification for unambiguously describing the structure of a chemical compound using a short ASCII string. MS_SMILES_string = 1000868, /// collision gas pressure: The gas pressure of the collision gas used for collisional excitation. MS_collision_gas_pressure = 1000869, /// 4000 QTRAP: SCIEX or Applied Biosystems|MDS SCIEX QTRAP 4000. MS_4000_QTRAP_OBSOLETE = 1000870, /// SRM software: Software used to predict, select, or optimize transitions or analyze the results of selected reaction monitoring runs. MS_SRM_software = 1000871, /// MaRiMba: Software used to predict transitions for selected reaction monitoring experiments based on observed spectrum libraries developed and distributed by the Institute for Systems Biology. MS_MaRiMba = 1000872, /// peptide attribute calculation software: Software used to predict or calculate numerical attributes of peptides. MS_peptide_attribute_calculation_software = 1000873, /// SSRCalc: Sequence Specific Retention Calculator estimates the retention time of peptides based on their sequence. MS_SSRCalc = 1000874, /// declustering potential: Potential difference between the orifice and the skimmer in volts. MS_declustering_potential = 1000875, /// cone voltage: Potential difference between the sampling cone/orifice in volts. MS_cone_voltage = 1000876, /// tube lens voltage: Potential difference setting of the tube lens in volts. MS_tube_lens_voltage = 1000877, /// external reference identifier: An identifier/accession number to an external reference database. MS_external_reference_identifier = 1000878, /// PubMed identifier: A unique identifier for a publication in the PubMed database (MIR:00000015). MS_PubMed_identifier = 1000879, /// interchannel delay: The duration of intervals between scanning, during which the instrument configuration is switched. MS_interchannel_delay = 1000880, /// chemical compound: A substance formed by chemical union of two or more elements or ingredients in definite proportion by weight. MS_chemical_compound = 1000881, /// protein: A compound composed of one or more chains of amino acids in a specific order determined by the base sequence of nucleotides in the DNA coding for the protein. MS_protein = 1000882, /// protein short name: A short name or symbol of a protein (e.g., HSF 1 or HSF1_HUMAN). MS_protein_short_name = 1000883, /// protein attribute: An nonphysical attribute describing a specific protein. MS_protein_attribute = 1000884, /// protein accession: Accession number for a specific protein in a database. MS_protein_accession = 1000885, /// protein name: A long name describing the function of the protein. MS_protein_name = 1000886, /// peptide attribute: A nonphysical attribute that can be used to describe a peptide. MS_peptide_attribute = 1000887, /// unmodified peptide sequence: A sequence of letter symbols denoting the order of amino acids that compose the peptide, without encoding any amino acid mass modifications that might be present. MS_unmodified_peptide_sequence = 1000888, /// modified peptide sequence: A sequence of letter symbols denoting the order of amino acids that compose the peptide plus the encoding any amino acid modifications that are present. MS_modified_peptide_sequence = 1000889, /// peptide labeling state: A state description of how a peptide might be isotopically or isobarically labelled. MS_peptide_labeling_state = 1000890, /// heavy labeled peptide: A peptide that has been created or labelled with some heavier-than-usual isotopes. MS_heavy_labeled_peptide = 1000891, /// unlabeled peptide: A peptide that has not been labelled with heavier-than-usual isotopes. This is often referred to as \"light\" to distinguish from \"heavy\". MS_unlabeled_peptide = 1000892, /// light labeled peptide (unlabeled peptide): A peptide that has not been labelled with heavier-than-usual isotopes. This is often referred to as \"light\" to distinguish from \"heavy\". MS_light_labeled_peptide = MS_unlabeled_peptide, /// peptide group label: An arbitrary string label used to mark a set of peptides that belong together in a set, whereby the members are differentiated by different isotopic labels. For example, the heavy and light forms of the same peptide will both be assigned the same peptide group label. MS_peptide_group_label = 1000893, /// retention time: A time interval from the start of chromatography when an analyte exits a chromatographic column. MS_retention_time = 1000894, /// local retention time: A time interval from the start of chromatography when an analyte exits an unspecified local chromatographic column and instrumental setup. MS_local_retention_time = 1000895, /// normalized retention time: A time interval from the start of chromatography when an analyte exits a standardized reference chromatographic column and instrumental setup. MS_normalized_retention_time = 1000896, /// predicted retention time: A time interval from the start of chromatography when an analyte exits a chromatographic column as predicted by a referenced software application. MS_predicted_retention_time = 1000897, /// standard: Something, such as a practice or a product, that is widely recognized or employed, especially because of its excellence. MS_standard = 1000898, /// de facto standard: A practice or product that has become a standard not because it has been approved by a standards organization but because it is widely used and recognized by the industry as being standard. MS_de_facto_standard = 1000899, /// minimum information standard: A specification of a minimum amount of information needed to reproduce or fully interpret a scientific result. MS_minimum_information_standard = 1000900, /// retention time normalization standard: A standard providing the retention times at which a set of reference compounds exit the reference chromatographic column. MS_retention_time_normalization_standard = 1000901, /// H-PINS retention time normalization standard: The de facto standard providing the retention times at which a set of halogenated reference peptides exit the reference chromatographic column. MS_H_PINS_retention_time_normalization_standard = 1000902, /// product ion series ordinal: The ordinal of the fragment within a specified ion series. (e.g. 8 for a y8 ion). MS_product_ion_series_ordinal = 1000903, /// product ion m/z delta: The difference in m/z of the predicted m/z based on the assigned product ion minus the actual observed peak m/z. MS_product_ion_m_z_delta = 1000904, /// percent of base peak times 100: The magnitude of a peak expressed in terms of the percentage of the magnitude of the base peak intensity multiplied by 100. The base peak is therefore 10000. This unit is common in normalized spectrum libraries. MS_percent_of_base_peak_times_100 = 1000905, /// peak intensity rank: Ordinal specifying the rank in intensity of a peak in a spectrum. Base peak is 1. The next most intense peak is 2, etc. MS_peak_intensity_rank = 1000906, /// peak targeting suitability rank: Ordinal specifying the rank of a peak in a spectrum in terms of suitability for targeting. The most suitable peak is 1. The next most suitability peak is 2, etc. Suitability is algorithm and context dependant. MS_peak_targeting_suitability_rank = 1000907, /// transition: A set of two m/z values corresponding to the precursor m/z and a fragment m/z that in combination can be used to identify or quantify a specific ion, although not necessarily uniquely. MS_transition = 1000908, /// reaction (transition): A set of two m/z values corresponding to the precursor m/z and a fragment m/z that in combination can be used to identify or quantify a specific ion, although not necessarily uniquely. MS_reaction = MS_transition, /// transition validation method: The strategy used to validate that a transition is effective. MS_transition_validation_method = 1000909, /// transition optimized on specified instrument: The transition has been optimized by direct injection of the peptide into an instrument specified in a separate term, and the optimum voltages and fragmentation energies have been determined. MS_transition_optimized_on_specified_instrument = 1000910, /// transition validated with an MS/MS spectrum on specified instrument: The transition has been validated by obtaining an MS2 spectrum and demonstrating that the peak is detectable on the instrument specified with a separate term. MS_transition_validated_with_an_MS_MS_spectrum_on_specified_instrument = 1000911, /// transition purported from an MS/MS spectrum on a different, specified instrument: The transition has been purported by obtaining an MS2 spectrum and demonstrating that the peak is detectable on the instrument specified with a separate term. However, the detecting instrument is of a different type (e.g. ion trap) than the instrument that the transition will eventually be used on (e.g. triple quad). MS_transition_purported_from_an_MS_MS_spectrum_on_a_different__specified_instrument = 1000912, /// transition predicted by informatic analysis: The transition has been predicted by informatics software without any direct spectral evidence. MS_transition_predicted_by_informatic_analysis = 1000913, /// tab delimited text format: A file format that has two or more columns of tabular data where each column is separated by a TAB character. MS_tab_delimited_text_format = 1000914, /// retention time window attribute: An attribute of a window in time about which a peptide might elute from the column. MS_retention_time_window_attribute = 1000915, /// retention time window lower offset: The extent of the retention time window in time units below the target retention time. The lower and upper offsets may be asymmetric about the target time. MS_retention_time_window_lower_offset = 1000916, /// retention time window upper offset: The extent of the retention time window in time units above the target retention time. The lower and upper offsets may be asymmetric about the target time. MS_retention_time_window_upper_offset = 1000917, /// target list: A list of peptides or compounds and their expected m/z coordinates that can be used to cause a mass spectrometry to obtain spectra of those molecules specifically. MS_target_list = 1000918, /// target inclusion exclusion priority: A priority setting specifying whether included or excluded targets have priority over the other. MS_target_inclusion_exclusion_priority = 1000919, /// includes supersede excludes: A priority setting specifying that included targets have priority over the excluded targets if there is a conflict. MS_includes_supersede_excludes = 1000920, /// excludes supersede includes: A priority setting specifying that excluded targets have priority over the included targets if there is a conflict. MS_excludes_supersede_includes = 1000921, /// Skyline: Software used to predict, select, and optimize transitions as well as analyze the results of selected reaction monitoring runs developed and distributed by the MacCoss lab at the University of Washington. MS_Skyline = 1000922, /// TIQAM: Software used to predict, select, and optimize transitions for selected reaction monitoring experiments developed and distributed by the Institute for Systems Biology. MS_TIQAM = 1000923, /// MaRiMba: Software used to predict transitions for selected reaction monitoring experiments based on observed spectrum libraries developed and distributed by the Institute for Systems Biology. MS_MaRiMba_OBSOLETE = 1000924, /// ATAQS: Software suite used to predict, select, and optimize transitions as well as analyze the results of selected reaction monitoring runs developed and distributed by the Institute for Systems Biology. MS_ATAQS = 1000925, /// product interpretation rank: The integer rank given an interpretation of an observed product ion. For example, if y8 is selected as the most likely interpretation of a peak, then it is assigned a rank of 1. MS_product_interpretation_rank = 1000926, /// ion injection time: The length of time spent filling an ion trapping device. MS_ion_injection_time = 1000927, /// calibration spectrum: A spectrum derived from a special calibration source, rather than from the primary injected sample. A calibration spectrum is typically derived from a substance that can be used to correct systematic shift in m/z for spectra of the primary inject sample. MS_calibration_spectrum = 1000928, /// Shimadzu Biotech nativeID format: Native format defined by source=xsd:string start=xsd:nonNegativeInteger end=xsd:nonNegativeInteger. MS_Shimadzu_Biotech_nativeID_format = 1000929, /// Shimadzu Biotech database entity: Shimadzu Biotech format. MS_Shimadzu_Biotech_database_entity = 1000930, /// QTRAP 5500: Applied Biosystems|MDS SCIEX QTRAP 5500. MS_QTRAP_5500 = 1000931, /// TripleTOF 5600: SCIEX TripleTOF 5600, a quadrupole - quadrupole - time-of-flight mass spectrometer. MS_TripleTOF_5600 = 1000932, /// protein modifications: Encoding of modifications of the protein sequence from the specified accession, written in PEFF notation. MS_protein_modifications = 1000933, /// gene name: Name of the gene from which the protein is translated. MS_gene_name = 1000934, /// spectrum interpretation: Collection of terms from the PSI Proteome Informatics standards describing the interpretation of spectra. MS_spectrum_interpretation = 1001000, /// SEQUEST:CleavesAt: MS_SEQUEST_CleavesAt = 1001005, /// SEQUEST:ViewCV: SEQUEST View Input Parameters. MS_SEQUEST_ViewCV = 1001006, /// SEQUEST:OutputLines: Number of peptide results to show. MS_SEQUEST_OutputLines = 1001007, /// SEQUEST:DescriptionLines: Number of full protein descriptions to show for top N peptides. MS_SEQUEST_DescriptionLines = 1001009, /// de novo search: A de novo sequencing search (without database). MS_de_novo_search = 1001010, /// search database details: Details about the database searched. MS_search_database_details = 1001011, /// database source: The organisation, project or laboratory from where the database is obtained (UniProt, NCBI, EBI, other). MS_database_source = 1001012, /// database name: The name of the search database (nr, SwissProt or est_human). MS_database_name = 1001013, /// database local file path: OBSOLETE: Use attribute in mzIdentML instead. Local file path of the search database from the search engine's point of view. MS_database_local_file_path_OBSOLETE = 1001014, /// database original uri: URI, from where the search database was originally downloaded. MS_database_original_uri = 1001015, /// database version: OBSOLETE: Use attribute in mzIdentML instead. Version of the search database. MS_database_version_OBSOLETE = 1001016, /// database release date: OBSOLETE: Use attribute in mzIdentML instead. Release date of the search database. MS_database_release_date_OBSOLETE = 1001017, /// database type: Database containing amino acid or nucleic acid sequences. MS_database_type = 1001018, /// database filtering: Was there filtering used on the database. MS_database_filtering = 1001019, /// DB filter taxonomy: A taxonomy filter was to the database search. MS_DB_filter_taxonomy = 1001020, /// DB filter on accession numbers: Filtering applied specifically by accession number pattern. MS_DB_filter_on_accession_numbers = 1001021, /// DB MW filter: Filtering applied specifically by protein molecular weight, specified as either a range or above/below a threshold value. MS_DB_MW_filter = 1001022, /// DB PI filter: Filtering applied specifically by predicted protein isoelectric focussing point (pI), specified as either a range or above/below a threshold value. MS_DB_PI_filter = 1001023, /// translation frame: The translated open reading frames from a nucleotide database considered in the search (range: 1-6). MS_translation_frame = 1001024, /// translation table: The translation table used to translate the nucleotides to amino acids. MS_translation_table = 1001025, /// SEQUEST:NormalizeXCorrValues: MS_SEQUEST_NormalizeXCorrValues = 1001026, /// DB filter on sequence pattern: Filtering applied specifically by amino acid sequence pattern. MS_DB_filter_on_sequence_pattern = 1001027, /// SEQUEST:SequenceHeaderFilter: String in the header of a sequence entry for that entry to be searched. MS_SEQUEST_SequenceHeaderFilter = 1001028, /// number of sequences searched: The number of sequences (proteins / nucleotides) from the database search after filtering. MS_number_of_sequences_searched = 1001029, /// number of peptide seqs compared to each spectrum: Number of peptide seqs compared to each spectrum. MS_number_of_peptide_seqs_compared_to_each_spectrum = 1001030, /// spectral library search: A search using a library of spectra. MS_spectral_library_search = 1001031, /// SEQUEST:SequencePartialFilter: MS_SEQUEST_SequencePartialFilter = 1001032, /// date / time search performed: OBSOLETE: use attribute in mzIdentML instead. Date and time of the actual search run. MS_date___time_search_performed_OBSOLETE = 1001035, /// search time taken: The time taken to complete the search in seconds. MS_search_time_taken = 1001036, /// SEQUEST:ShowFragmentIons: Flag indicating that fragment ions should be shown. MS_SEQUEST_ShowFragmentIons = 1001037, /// SEQUEST:Consensus: Specify depth as value of the CVParam. MS_SEQUEST_Consensus = 1001038, /// intermediate analysis format: Type of the source file, the mzIdentML was created from. MS_intermediate_analysis_format = 1001040, /// SEQUEST:sortCV: SEQUEST View / Sort Input Parameters. MS_SEQUEST_sortCV = 1001041, /// SEQUEST:LimitTo: Specify \"number of dtas shown\" as value of the CVParam. MS_SEQUEST_LimitTo = 1001042, /// cleavage agent details: Details of cleavage agent (enzyme). MS_cleavage_agent_details = 1001044, /// cleavage agent name: The name of the cleavage agent. MS_cleavage_agent_name = 1001045, /// SEQUEST:sort by dCn: Sort order of SEQUEST search results by the delta of the normalized correlation score. MS_SEQUEST_sort_by_dCn = 1001046, /// SEQUEST:sort by dM: Sort order of SEQUEST search results by the difference between a theoretically calculated and the corresponding experimentally measured molecular mass M. MS_SEQUEST_sort_by_dM = 1001047, /// SEQUEST:sort by Ions: Sort order of SEQUEST search results given by the ions. MS_SEQUEST_sort_by_Ions = 1001048, /// SEQUEST:sort by MH+: Sort order of SEQUEST search results given by the mass of the protonated ion. MS_SEQUEST_sort_by_MH_ = 1001049, /// SEQUEST:sort by P: Sort order of SEQUEST search results given by the probability. MS_SEQUEST_sort_by_P = 1001050, /// multiple enzyme combination rules: OBSOLETE: use attribute independent in mzIdentML instead. Description of multiple enzyme digestion protocol, if any. MS_multiple_enzyme_combination_rules_OBSOLETE = 1001051, /// SEQUEST:sort by PreviousAminoAcid: Sort order of SEQUEST search results given by the previous amino acid. MS_SEQUEST_sort_by_PreviousAminoAcid = 1001052, /// SEQUEST:sort by Ref: Sort order of SEQUEST search results given by the reference. MS_SEQUEST_sort_by_Ref = 1001053, /// modification parameters: Modification parameters for the search engine run. MS_modification_parameters = 1001055, /// modification specificity rule: The specificity rules for the modifications applied by the search engine. MS_modification_specificity_rule = 1001056, /// tolerance on types: OBSOLETE: Tolerance on types. MS_tolerance_on_types_OBSOLETE = 1001057, /// quality estimation by manual validation: The quality estimation was done manually. MS_quality_estimation_by_manual_validation = 1001058, /// SEQUEST:sort by RSp: Sort order of SEQUEST search results given by the result 'Sp' of 'Rank/Sp' in the out file (peptide). MS_SEQUEST_sort_by_RSp = 1001059, /// quality estimation method details: Method for quality estimation (manually or with decoy database). MS_quality_estimation_method_details = 1001060, /// neutral loss: OBSOLETE: replaced by MS:1000336 (neutral loss): Leave this to PSI-MOD. MS_neutral_loss_OBSOLETE = 1001061, /// Mascot MGF format: Mascot MGF file format. MS_Mascot_MGF_format = 1001062, /// TODOscoring model: OBSOLETE: There is Phenyx:ScoringModel for Phenyx! Scoring model (more detailed granularity). TODO: add some child terms. MS_TODOscoring_model_OBSOLETE = 1001065, /// ions series considered in search: The description of the DEPRECATED ion fragment series (including charges and neutral losses) that are considered by the search engine. MS_ions_series_considered_in_search = 1001066, /// SEQUEST:sort by Sp: Sort order of SEQUEST search results by the Sp score. MS_SEQUEST_sort_by_Sp = 1001068, /// SEQUEST:sort by TIC: Sort order of SEQUEST search results given by the total ion current. MS_SEQUEST_sort_by_TIC = 1001069, /// SEQUEST:sort by Scan: Sort order of SEQUEST search results given by the scan number. MS_SEQUEST_sort_by_Scan = 1001070, /// SEQUEST:sort by Sequence: Sort order of SEQUEST search results given by the sequence. MS_SEQUEST_sort_by_Sequence = 1001071, /// SEQUEST:sort by Sf: Sort order of SEQUEST search results given by the SEQUEST result 'Sf'. MS_SEQUEST_sort_by_Sf = 1001072, /// database type amino acid: Database contains amino acid sequences. MS_database_type_amino_acid = 1001073, /// database type nucleotide: Database contains nucleic acid sequences. MS_database_type_nucleotide = 1001079, /// search type: Enumeration of type of search value (i.e. from PMF, sequence tag, MS2). MS_search_type = 1001080, /// pmf search: A peptide mass fingerprint search. MS_pmf_search = 1001081, /// tag search: A sequence tag search. MS_tag_search = 1001082, /// ms-ms search: An MS2 search (with fragment ions). MS_ms_ms_search = 1001083, /// database nr: Non-redundant GenBank sequence database. MS_database_nr = 1001084, /// protein result details: Protein level information. MS_protein_result_details = 1001085, /// SEQUEST:sort by XCorr: Sort order of SEQUEST search results by the correlation score. MS_SEQUEST_sort_by_XCorr = 1001086, /// SEQUEST:ProcessCV: SEQUEST View / Process Input Parameters. MS_SEQUEST_ProcessCV = 1001087, /// protein description: The protein description line from the sequence entry in the source database FASTA file. MS_protein_description = 1001088, /// molecule taxonomy: The taxonomy of the resultant molecule from the search. MS_molecule_taxonomy = 1001089, /// taxonomy nomenclature: OBSOLETE: The system used to indicate taxonomy. There should be an enumerated list of options: latin name, NCBI TaxID, common name, Swiss-Prot species ID (ex. RABIT from the full protein ID ALBU_RABIT). MS_taxonomy_nomenclature_OBSOLETE = 1001090, /// NoEnzyme: MS_NoEnzyme_OBSOLETE = 1001091, /// peptide identification confidence metric: Identification confidence metric for a peptide. MS_peptide_identification_confidence_metric = 1001092, /// sequence coverage: The percent coverage for the protein based upon the matched peptide sequences (can be calculated). MS_sequence_coverage = 1001093, /// SEQUEST:sort by z: Sort order of SEQUEST search results given by the charge. MS_SEQUEST_sort_by_z = 1001094, /// SEQUEST:ProcessAll: MS_SEQUEST_ProcessAll = 1001095, /// SEQUEST:TopPercentMostIntense: Specify \"percentage\" as value of the CVParam. MS_SEQUEST_TopPercentMostIntense = 1001096, /// distinct peptide sequences: This counts distinct sequences hitting the protein without regard to a minimal confidence threshold. MS_distinct_peptide_sequences = 1001097, /// confident distinct peptide sequences: This counts the number of distinct peptide sequences. Multiple charge states and multiple modification states do NOT count as multiple sequences. The definition of 'confident' must be qualified elsewhere. MS_confident_distinct_peptide_sequences = 1001098, /// confident peptide qualification: The point of this entry is to define what is meant by confident for the term Confident distinct peptide sequence and/or Confident peptides. Example 1 - metric=Paragon:Confidence value=95 sense=greater than Example 2 - metric=Mascot:Eval value=0.05 sense=less than. MS_confident_peptide_qualification = 1001099, /// confident peptide sequence number: This counts the number of peptide sequences without regard to whether they are distinct. Multiple charges states and multiple modification states DO count as multiple peptides. The definition of 'confident' must be qualified elsewhere. MS_confident_peptide_sequence_number = 1001100, /// protein group or subset relationship: Protein group or subset relationships. MS_protein_group_or_subset_relationship = 1001101, /// SEQUEST:Chromatogram: MS_SEQUEST_Chromatogram = 1001102, /// SEQUEST:InfoAndLog: MS_SEQUEST_InfoAndLog = 1001103, /// database UniProtKB/Swiss-Prot: The name of the UniProtKB/Swiss-Prot knowledgebase. MS_database_UniProtKB_Swiss_Prot = 1001104, /// peptide result details: Peptide level information. MS_peptide_result_details = 1001105, /// SEQUEST:TopNumber: Specify \"number\" as value of the CVParam. MS_SEQUEST_TopNumber = 1001106, /// data stored in database: Source file for this mzIdentML was a data set in a database. MS_data_stored_in_database = 1001107, /// param: a ion: Parameter information, type of product: a ion with charge on the N-terminal side. MS_param__a_ion = 1001108, /// SEQUEST:CullTo: Specify cull string as value of the CVParam. MS_SEQUEST_CullTo = 1001109, /// SEQUEST:modeCV: SEQUEST Mode Input Parameters. MS_SEQUEST_modeCV = 1001110, /// SEQUEST:Full: MS_SEQUEST_Full = 1001111, /// n-terminal flanking residue: The residue preceding the first amino acid in the peptide sequence as it occurs in the protein. Use 'N-term' to denote if the peptide starts at the N terminus of the protein. MS_n_terminal_flanking_residue = 1001112, /// c-terminal flanking residue: The residue following the last amino acid in the peptide sequence as it occurs in the protein. Use 'C-term' to denote if the peptide ends at the C terminus of the protein. MS_c_terminal_flanking_residue = 1001113, /// retention time(s): Retention time of the spectrum from the source file. MS_retention_time_s__OBSOLETE = 1001114, /// scan number(s): OBSOLETE: use spectrumID attribute of SpectrumIdentificationResult. Take from mzData. MS_scan_number_s__OBSOLETE = 1001115, /// single protein result details: Results specific for one protein as part of a protein ambiguity group (a result not valid for all the other proteins in the protein ambiguity group). MS_single_protein_result_details = 1001116, /// theoretical mass: The theoretical mass of the molecule (e.g. the peptide sequence and its modifications). MS_theoretical_mass = 1001117, /// param: b ion: Parameter information, type of product: b ion with charge on the N-terminal side. MS_param__b_ion = 1001118, /// param: c ion: Parameter information, type of product: c ion with charge on the N-terminal side. MS_param__c_ion = 1001119, /// SEQUEST:FormatAndLinks: MS_SEQUEST_FormatAndLinks = 1001120, /// number of matched peaks: The number of peaks that were matched as qualified by the ion series considered field. If a peak matches multiple ions then only 1 would be added the count. MS_number_of_matched_peaks = 1001121, /// ions series considered: The ion series that were used during the calculation of the count (e.g. a, b, c, d, v, w, x, y, z, a-H2O, a-NH3, b-H2O, b-NH3, y-H2O, y-NH3, b-H20, b+, z-, z+1, z+2, b-H3PO4, y-H3PO4, immonium, internal ya, internal yb). MS_ions_series_considered = 1001122, /// number of peaks used: The number of peaks from the original peak list that are used to calculate the scores for a particular search engine. All ions that have the opportunity to match or be counted even if they don't. MS_number_of_peaks_used = 1001123, /// number of peaks submitted: The number of peaks from the original peaks listed that were submitted to the search engine. MS_number_of_peaks_submitted = 1001124, /// manual validation: Result of quality estimation: decision of a manual validation. MS_manual_validation = 1001125, /// SEQUEST:Fast: MS_SEQUEST_Fast = 1001126, /// peptide sharing details: Accessions Containing Sequence - Accessions for each protein containing this peptide. MS_peptide_sharing_details = 1001127, /// SEQUEST:selectCV: SEQUEST Select Input Parameters. MS_SEQUEST_selectCV = 1001128, /// quantification information: Quantification information. MS_quantification_information = 1001129, /// peptide raw area: Peptide raw area. MS_peptide_raw_area_OBSOLETE = 1001130, /// error on peptide area: Error on peptide area. MS_error_on_peptide_area = 1001131, /// peptide ratio: Peptide ratio. MS_peptide_ratio = 1001132, /// error on peptide ratio: Error on peptide ratio. MS_error_on_peptide_ratio = 1001133, /// protein ratio: Protein ratio. MS_protein_ratio = 1001134, /// error on protein ratio: Error on protein ratio. MS_error_on_protein_ratio = 1001135, /// p-value (protein diff from 1 randomly): P-value (protein diff from 1 randomly). MS_p_value__protein_diff_from_1_randomly__OBSOLETE = 1001136, /// absolute quantity: Absolute quantity in terms of real concentration or molecule copy number in sample. MS_absolute_quantity = 1001137, /// error on absolute quantity: Error on absolute quantity. MS_error_on_absolute_quantity = 1001138, /// quantitation software name: Quantitation software name. MS_quantitation_software_name = 1001139, /// quantitation software version: Quantitation software version. MS_quantitation_software_version_OBSOLETE = 1001140, /// intensity of precursor ion: The intensity of the precursor ion. MS_intensity_of_precursor_ion = 1001141, /// database IPI_human: International Protein Index database for Homo sapiens sequences. MS_database_IPI_human = 1001142, /// search engine specific score for PSMs: Search engine specific peptide spectrum match scores. MS_search_engine_specific_score_for_PSMs = 1001143, /// SEQUEST:SelectDefault: MS_SEQUEST_SelectDefault = 1001144, /// SEQUEST:SelectAdvancedCV: SEQUEST Select Advanced Input Parameters. MS_SEQUEST_SelectAdvancedCV = 1001145, /// param: a ion-NH3 DEPRECATED: Ion a-NH3 parameter information, type of product: a ion with lost ammonia. MS_param__a_ion_NH3_DEPRECATED = 1001146, /// protein ambiguity group result details: MS_protein_ambiguity_group_result_details = 1001147, /// param: a ion-H2O DEPRECATED: Ion a-H2O if a significant and fragment includes STED. MS_param__a_ion_H2O_DEPRECATED = 1001148, /// param: b ion-NH3 DEPRECATED: Ion b-NH3 parameter information, type of product: b ion with lost ammonia. MS_param__b_ion_NH3_DEPRECATED = 1001149, /// param: b ion-H2O DEPRECATED: Ion b-H2O if b significant and fragment includes STED. MS_param__b_ion_H2O_DEPRECATED = 1001150, /// param: y ion-NH3 DEPRECATED: Ion y-NH3 parameter information, type of product: y ion with lost ammonia. MS_param__y_ion_NH3_DEPRECATED = 1001151, /// param: y ion-H2O DEPRECATED: MS_param__y_ion_H2O_DEPRECATED = 1001152, /// search engine specific score: Search engine specific scores. MS_search_engine_specific_score = 1001153, /// SEQUEST:probability: The SEQUEST result 'Probability'. MS_SEQUEST_probability = 1001154, /// SEQUEST:xcorr: The SEQUEST result 'XCorr'. MS_SEQUEST_xcorr = 1001155, /// SEQUEST:deltacn: The SEQUEST result 'DeltaCn'. MS_SEQUEST_deltacn = 1001156, /// SEQUEST:sp: The SEQUEST result 'Sp' (protein). MS_SEQUEST_sp = 1001157, /// SEQUEST:Uniq: MS_SEQUEST_Uniq = 1001158, /// SEQUEST:expectation value: The SEQUEST result 'Expectation value'. MS_SEQUEST_expectation_value = 1001159, /// SEQUEST:sf: The SEQUEST result 'Sf'. MS_SEQUEST_sf = 1001160, /// SEQUEST:matched ions: The SEQUEST result 'Matched Ions'. MS_SEQUEST_matched_ions = 1001161, /// SEQUEST:total ions: The SEQUEST result 'Total Ions'. MS_SEQUEST_total_ions = 1001162, /// SEQUEST:consensus score: The SEQUEST result 'Consensus Score'. MS_SEQUEST_consensus_score = 1001163, /// Paragon:unused protscore: The Paragon result 'Unused ProtScore'. MS_Paragon_unused_protscore = 1001164, /// Paragon:total protscore: The Paragon result 'Total ProtScore'. MS_Paragon_total_protscore = 1001165, /// Paragon:score: The Paragon result 'Score'. MS_Paragon_score = 1001166, /// Paragon:confidence: The Paragon result 'Confidence'. MS_Paragon_confidence = 1001167, /// Paragon:expression error factor: The Paragon result 'Expression Error Factor'. MS_Paragon_expression_error_factor = 1001168, /// Paragon:expression change p-value: The Paragon result 'Expression change P-value'. MS_Paragon_expression_change_p_value = 1001169, /// Paragon:contrib: The Paragon result 'Contrib'. MS_Paragon_contrib = 1001170, /// Mascot:score: The Mascot result 'Score'. MS_Mascot_score = 1001171, /// Mascot:expectation value: The Mascot result 'expectation value'. MS_Mascot_expectation_value = 1001172, /// Mascot:matched ions: The Mascot result 'Matched ions'. MS_Mascot_matched_ions = 1001173, /// Mascot:total ions: The Mascot result 'Total ions'. MS_Mascot_total_ions = 1001174, /// peptide shared in multiple proteins: A peptide matching multiple proteins. MS_peptide_shared_in_multiple_proteins = 1001175, /// (?<=[KR])(?!P): Regular expression for Trypsin. MS______KR_____P_ = 1001176, /// number of molecular hypothesis considered: Number of Molecular Hypothesis Considered - This is the number of molecules (e.g. peptides for proteomics) considered for a particular search. MS_number_of_molecular_hypothesis_considered = 1001177, /// database EST: Expressed sequence tag nucleotide sequence database. MS_database_EST = 1001178, /// Cleavage agent regular expression: Regular expressions for cleavage enzymes. MS_Cleavage_agent_regular_expression = 1001180, /// search statistics: The details of the actual run of the search. MS_search_statistics = 1001184, /// modification specificity peptide N-term: As parameter for search engine: apply the modification only at the N-terminus of a peptide. MS_modification_specificity_peptide_N_term = 1001189, /// modification specificity peptide C-term: As parameter for search engine: apply the modification only at the C-terminus of a peptide. MS_modification_specificity_peptide_C_term = 1001190, /// p-value: Quality estimation by p-value. MS_p_value_OBSOLETE = 1001191, /// Expect value: Result of quality estimation: Expect value. MS_Expect_value = 1001192, /// confidence score: Result of quality estimation: confidence score. MS_confidence_score = 1001193, /// quality estimation with decoy database: Quality estimation by decoy database. MS_quality_estimation_with_decoy_database = 1001194, /// decoy DB type reverse: Decoy type: Amino acids of protein sequences are used in reverse order. MS_decoy_DB_type_reverse = 1001195, /// decoy DB type randomized: Decoy type: Amino acids of protein sequences are randomized (keeping the original protein mass). MS_decoy_DB_type_randomized = 1001196, /// DB composition target+decoy: Decoy database composition: database contains original (target) and decoy entries. MS_DB_composition_target_decoy = 1001197, /// protein identification confidence metric: Identification confidence metric for a protein. MS_protein_identification_confidence_metric = 1001198, /// Mascot DAT format: Source file for this mzIdentML was in Mascot DAT file format. MS_Mascot_DAT_format = 1001199, /// SEQUEST out file format: Source file for this mzIdentML was in SEQUEST out file format. MS_SEQUEST_out_file_format = 1001200, /// DB MW filter maximum: Maximum value of molecular weight filter. MS_DB_MW_filter_maximum = 1001201, /// DB MW filter minimum: Minimum value of molecular weight filter. MS_DB_MW_filter_minimum = 1001202, /// DB PI filter maximum: Maximum value of isoelectric point filter. MS_DB_PI_filter_maximum = 1001203, /// DB PI filter minimum: Minimum value of isoelectric point filter. MS_DB_PI_filter_minimum = 1001204, /// Mascot: The name of the Mascot search engine. MS_Mascot = 1001207, /// SEQUEST: The name of the SEQUEST search engine. MS_SEQUEST = 1001208, /// Phenyx: The name of the Phenyx search engine. MS_Phenyx = 1001209, /// mass type settings: The type of mass difference value to be considered by the search engine (monoisotopic or average). MS_mass_type_settings = 1001210, /// parent mass type mono: Mass type setting for parent mass was monoisotopic. MS_parent_mass_type_mono = 1001211, /// parent mass type average: Mass type setting for parent mass was average isotopic. MS_parent_mass_type_average = 1001212, /// search result details: OBSOLETE: Scores and global result characteristics. MS_search_result_details_OBSOLETE = 1001213, /// protein-level global FDR: Estimation of the global false discovery rate of proteins. MS_protein_level_global_FDR = 1001214, /// SEQUEST:PeptideSp: The SEQUEST result 'Sp' in out file (peptide). MS_SEQUEST_PeptideSp = 1001215, /// SEQUEST:PeptideRankSp: The SEQUEST result 'Sp' of 'Rank/Sp' in out file (peptide). Also called 'rsp'. MS_SEQUEST_PeptideRankSp = 1001217, /// SEQUEST:PeptideNumber: The SEQUEST result '#' in out file (peptide). MS_SEQUEST_PeptideNumber = 1001218, /// SEQUEST:PeptideIdnumber: The SEQUEST result 'Id#' in out file (peptide). MS_SEQUEST_PeptideIdnumber = 1001219, /// frag: y ion: Fragmentation information, type of product: y ion. MS_frag__y_ion = 1001220, /// fragmentation information: Fragmentation information like ion types. MS_fragmentation_information = 1001221, /// frag: b ion - H2O: Fragmentation information, type of product: b ion without water. MS_frag__b_ion___H2O = 1001222, /// frag: y ion - H2O: Fragmentation information, type of product: y ion without water. MS_frag__y_ion___H2O = 1001223, /// frag: b ion: Fragmentation information, type of product: b ion. MS_frag__b_ion = 1001224, /// product ion m/z: The m/z of the product ion. MS_product_ion_m_z = 1001225, /// fragment ion m/z (product ion m/z): The m/z of the product ion. MS_fragment_ion_m_z = MS_product_ion_m_z, /// product ion intensity: The intensity of a single product ion. MS_product_ion_intensity = 1001226, /// fragment ion intensity (product ion intensity): The intensity of a single product ion. MS_fragment_ion_intensity = MS_product_ion_intensity, /// product ion m/z error: The product ion m/z error. MS_product_ion_m_z_error = 1001227, /// frag: x ion: Fragmentation information, type of product: x ion. MS_frag__x_ion = 1001228, /// frag: a ion: Fragmentation information, type of product: a ion. MS_frag__a_ion = 1001229, /// frag: z ion: Fragmentation information, type of product: z ion. MS_frag__z_ion = 1001230, /// frag: c ion: Fragmentation information, type of product: c ion. MS_frag__c_ion = 1001231, /// frag: b ion - NH3: Ion b-NH3 fragmentation information, type of product: b ion without ammonia. MS_frag__b_ion___NH3 = 1001232, /// frag: y ion - NH3: Ion y-NH3 fragmentation information, type of product: y ion without ammonia. MS_frag__y_ion___NH3 = 1001233, /// frag: a ion - H2O: Fragmentation information, type of product: a ion without water. MS_frag__a_ion___H2O = 1001234, /// frag: a ion - NH3: Ion a-NH3 fragmentation information, type of product: a ion without ammonia. MS_frag__a_ion___NH3 = 1001235, /// frag: d ion: Fragmentation information, type of product: d ion. MS_frag__d_ion = 1001236, /// frag: v ion: Fragmentation information, type of product: v ion. MS_frag__v_ion = 1001237, /// frag: w ion: Fragmentation information, type of product: w ion. MS_frag__w_ion = 1001238, /// frag: immonium ion: Fragmentation information, type of product: immonium ion. MS_frag__immonium_ion = 1001239, /// non-identified ion: Non-identified ion. MS_non_identified_ion = 1001240, /// co-eluting ion: Co-eluting ion. MS_co_eluting_ion = 1001241, /// SEQUEST out folder: Source file for this mzIdentML was a SEQUEST folder with its out files. MS_SEQUEST_out_folder = 1001242, /// SEQUEST summary: Source file for this mzIdentML was a SEQUEST summary page (proteins). MS_SEQUEST_summary = 1001243, /// PerSeptive PKS format: PerSeptive peak list file format. MS_PerSeptive_PKS_format = 1001245, /// SCIEX API III format: PE SCIEX peak list file format. MS_SCIEX_API_III_format = 1001246, /// Bruker XML format: Bruker data exchange XML format. MS_Bruker_XML_format = 1001247, /// search input details: Details describing the search input. MS_search_input_details = 1001249, /// local FDR: Result of quality estimation: the local FDR at the current position of a sorted list. MS_local_FDR = 1001250, /// Trypsin: Enzyme trypsin. MS_Trypsin = 1001251, /// DB source EBI: Database source EBI. MS_DB_source_EBI = 1001252, /// DB source NCBI: Database source NCBI. MS_DB_source_NCBI = 1001253, /// DB source UniProt: Database source UniProt. MS_DB_source_UniProt = 1001254, /// fragment mass type average: Mass type setting for fragment mass was average isotopic. MS_fragment_mass_type_average = 1001255, /// fragment mass type mono: Mass type setting for fragment mass was monoisotopic. MS_fragment_mass_type_mono = 1001256, /// param: v ion: Parameter information, type of product: side chain loss v ion. MS_param__v_ion = 1001257, /// param: d ion: Parameter information, type of product: side chain loss d ion. MS_param__d_ion = 1001258, /// param: immonium ion: Parameter information, type of product: immonium ion. MS_param__immonium_ion = 1001259, /// param: w ion: Parameter information, type of product: side chain loss w ion. MS_param__w_ion = 1001260, /// param: x ion: Parameter information, type of product: x ion with charge on the C-terminal side. MS_param__x_ion = 1001261, /// param: y ion: Parameter information, type of product: y ion with charge on the C-terminal side. MS_param__y_ion = 1001262, /// param: z ion: Parameter information, type of product: z ion with charge on the C-terminal side. MS_param__z_ion = 1001263, /// role type: Role of a Person or Organization. MS_role_type = 1001266, /// software vendor: Software vendor role. MS_software_vendor = 1001267, /// programmer: Programmer role. MS_programmer = 1001268, /// instrument vendor: Instrument vendor role. MS_instrument_vendor = 1001269, /// lab personnel: Lab personnel role. MS_lab_personnel = 1001270, /// researcher: Researcher role. MS_researcher = 1001271, /// (?<=R)(?!P): Regular expression for Arg-C. MS_____R____P_ = 1001272, /// (?=[BD]): Regular expression for Asp-N. MS_____BD__ = 1001273, /// (?=[DE]): Regular expression for Asp-N-ambic. MS_____DE__ = 1001274, /// ProteinScape SearchEvent: Source data for this mzIdentML was a ProteinScape SearchEvent. MS_ProteinScape_SearchEvent = 1001275, /// ProteinScape Gel: Source data for this mzIdentML was a ProteinScape Gel. MS_ProteinScape_Gel = 1001276, /// decoy DB accession regexp: Specify the regular expression for decoy accession numbers. MS_decoy_DB_accession_regexp = 1001283, /// decoy DB derived from: The name of the database, the search database was derived from. MS_decoy_DB_derived_from_OBSOLETE = 1001284, /// database IPI_mouse: International Protein Index database for Mus musculus sequences. MS_database_IPI_mouse = 1001285, /// database IPI_rat: International Protein Index database for Rattus norvegicus sequences. MS_database_IPI_rat = 1001286, /// database IPI_zebrafish: International Protein Index database for Danio rerio sequences. MS_database_IPI_zebrafish = 1001287, /// database IPI_chicken: International Protein Index database for Gallus gallus sequences. MS_database_IPI_chicken = 1001288, /// database IPI_cow: International Protein Index database for Bos taurus sequences. MS_database_IPI_cow = 1001289, /// database IPI_arabidopsis: International Protein Index database for Arabidopsis thaliana sequences. MS_database_IPI_arabidopsis = 1001290, /// decoy DB from nr: Decoy database from a non-redundant GenBank sequence database. MS_decoy_DB_from_nr_OBSOLETE = 1001291, /// decoy DB from IPI_rat: Decoy database from a International Protein Index database for Rattus norvegicus. MS_decoy_DB_from_IPI_rat_OBSOLETE = 1001292, /// decoy DB from IPI_mouse: Decoy database from a International Protein Index database for Mus musculus. MS_decoy_DB_from_IPI_mouse_OBSOLETE = 1001293, /// decoy DB from IPI_arabidopsis: Decoy database from a International Protein Index database for Arabidopsis thaliana. MS_decoy_DB_from_IPI_arabidopsis_OBSOLETE = 1001294, /// decoy DB from EST: Decoy database from an expressed sequence tag nucleotide sequence database. MS_decoy_DB_from_EST_OBSOLETE = 1001295, /// decoy DB from IPI_zebrafish: Decoy database from a International Protein Index database for Danio rerio. MS_decoy_DB_from_IPI_zebrafish_OBSOLETE = 1001296, /// decoy DB from UniProtKB/Swiss-Prot: Decoy database from a Swiss-Prot protein sequence database. MS_decoy_DB_from_UniProtKB_Swiss_Prot_OBSOLETE = 1001297, /// decoy DB from IPI_chicken: Decoy database from a International Protein Index database for Gallus gallus. MS_decoy_DB_from_IPI_chicken_OBSOLETE = 1001298, /// decoy DB from IPI_cow: Decoy database from a International Protein Index database for Bos taurus. MS_decoy_DB_from_IPI_cow_OBSOLETE = 1001299, /// decoy DB from IPI_human: Decoy database from a International Protein Index database for Homo sapiens. MS_decoy_DB_from_IPI_human_OBSOLETE = 1001300, /// protein rank: The rank of the protein in a list sorted by the search engine. MS_protein_rank = 1001301, /// search engine specific input parameter: Search engine specific input parameters. MS_search_engine_specific_input_parameter = 1001302, /// Arg-C: Endoproteinase Arg-C. MS_Arg_C = 1001303, /// Clostripain (Arg-C): Endoproteinase Arg-C. MS_Clostripain = MS_Arg_C, /// Asp-N: Endoproteinase Asp-N. MS_Asp_N = 1001304, /// Asp-N_ambic: Enzyme Asp-N, Ammonium Bicarbonate (AmBic). MS_Asp_N_ambic = 1001305, /// Chymotrypsin: Enzyme chymotrypsin. MS_Chymotrypsin = 1001306, /// CNBr: Cyanogen bromide. MS_CNBr = 1001307, /// Formic_acid: Formic acid. MS_Formic_acid = 1001308, /// Lys-C: Endoproteinase Lys-C. MS_Lys_C = 1001309, /// Lys-C/P: Proteinase Lys-C/P. MS_Lys_C_P = 1001310, /// PepsinA: PepsinA proteinase. MS_PepsinA = 1001311, /// TrypChymo: Cleavage agent TrypChymo. MS_TrypChymo = 1001312, /// Trypsin/P: Cleavage agent Trypsin/P. MS_Trypsin_P = 1001313, /// V8-DE: Cleavage agent V8-DE. MS_V8_DE = 1001314, /// V8-E: Cleavage agent V8-E. MS_V8_E = 1001315, /// Mascot:SigThreshold: Significance threshold below which the p-value of a peptide match must lie to be considered statistically significant (default 0.05). MS_Mascot_SigThreshold = 1001316, /// Mascot:MaxProteinHits: The number of protein hits to display in the report. If 'Auto', all protein hits that have a protein score exceeding the average peptide identity threshold are reported. Otherwise an integer at least 1. MS_Mascot_MaxProteinHits = 1001317, /// Mascot:ProteinScoringMethod: Mascot protein scoring method; either 'Standard' or 'MudPIT'. MS_Mascot_ProteinScoringMethod = 1001318, /// Mascot:MinMSMSThreshold: Mascot peptide match ion score threshold. If between 0 and 1, then peptide matches whose expect value exceeds the thresholds are suppressed; if at least 1, then peptide matches whose ion score is below the threshold are suppressed. MS_Mascot_MinMSMSThreshold = 1001319, /// Mascot:ShowHomologousProteinsWithSamePeptides: If true, show (sequence or spectrum) same-set proteins. Otherwise they are suppressed. MS_Mascot_ShowHomologousProteinsWithSamePeptides = 1001320, /// Mascot:ShowHomologousProteinsWithSubsetOfPeptides: If true, show (sequence or spectrum) sub-set and subsumable proteins. Otherwise they are suppressed. MS_Mascot_ShowHomologousProteinsWithSubsetOfPeptides = 1001321, /// Mascot:RequireBoldRed: Only used in Peptide Summary and Select Summary reports. If true, a peptide match must be 'bold red' to be included in the report; bold red means the peptide is a top ranking match in a query and appears for the first time (in linear order) in the list of protein hits. MS_Mascot_RequireBoldRed = 1001322, /// Mascot:UseUnigeneClustering: If true, then the search results are against a nucleic acid database and Unigene clustering is enabled. Otherwise UniGene clustering is not in use. MS_Mascot_UseUnigeneClustering = 1001323, /// Mascot:IncludeErrorTolerantMatches: If true, then the search results are error tolerant and peptide matches from the second pass are included in search results. Otherwise no error tolerant peptide matches are included. MS_Mascot_IncludeErrorTolerantMatches = 1001324, /// Mascot:ShowDecoyMatches: If true, then the search results are against an automatically generated decoy database and the reported peptide matches and protein hits come from the decoy database. Otherwise peptide matches and protein hits come from the original database. MS_Mascot_ShowDecoyMatches = 1001325, /// add_others: OBSOLETE. MS_add_others_OBSOLETE = 1001326, /// OMSSA:evalue: OMSSA E-value. MS_OMSSA_evalue = 1001328, /// OMSSA:pvalue: OMSSA p-value. MS_OMSSA_pvalue = 1001329, /// X!Tandem:expect: The X!Tandem expectation value. MS_X_Tandem_expect = 1001330, /// X!Tandem:hyperscore: The X!Tandem hyperscore. MS_X_Tandem_hyperscore = 1001331, /// (?<=[FYWL])(?!P): Regular expression for Chymotrypsin. MS______FYWL_____P_ = 1001332, /// (?<=M): Regular expression for CNBr. MS_____M_ = 1001333, /// ((?<=D))|((?=D)): Regular expression for formic acid. MS______D_______D__ = 1001334, /// (?<=K)(?!P): Regular expression for Lys-C. MS_____K____P_ = 1001335, /// (?<=K): Regular expression for Lys-C/P. MS_____K_ = 1001336, /// (?<=[FL]): Regular expression for PepsinA. MS______FL__ = 1001337, /// (?<=[FYWLKR])(?!P): Regular expression for TrypChymo. MS______FYWLKR_____P_ = 1001338, /// (?<=[KR]): Regular expression for Trypsin/P. MS______KR__ = 1001339, /// (?<=[BDEZ])(?!P): Regular expression for V8-DE. MS______BDEZ_____P_ = 1001340, /// (?<=[EZ])(?!P): Regular expression for V8-E. MS______EZ_____P_ = 1001341, /// database sequence details: Details about a single database sequence. MS_database_sequence_details = 1001342, /// NA sequence: The sequence is a nucleic acid sequence. MS_NA_sequence = 1001343, /// AA sequence: The sequence is a amino acid sequence. MS_AA_sequence = 1001344, /// mass table source: Children of this term specify the source of the mass table used. MS_mass_table_source = 1001345, /// AAIndex mass table: The masses used in the mass table are taken from AAIndex. MS_AAIndex_mass_table = 1001346, /// database file formats: The children of this term define file formats of the sequence database used. MS_database_file_formats = 1001347, /// FASTA format: The sequence database was stored in the FASTA format. MS_FASTA_format = 1001348, /// ASN.1: The sequence database was stored in the Abstract Syntax Notation 1 format. MS_ASN_1 = 1001349, /// NCBI *.p*: The sequence database was stored in the NCBI formatdb (*.p*) format. MS_NCBI___p_ = 1001350, /// clustal aln: ClustalW ALN (multiple alignment) format. MS_clustal_aln = 1001351, /// embl em: EMBL entry format. MS_embl_em = 1001352, /// NBRF PIR: The NBRF PIR was used as format. MS_NBRF_PIR = 1001353, /// mass table options: Root node for options for the mass table used. MS_mass_table_options = 1001354, /// peptide descriptions: Descriptions of peptides. MS_peptide_descriptions = 1001355, /// spectrum descriptions: Descriptions of the input spectra. MS_spectrum_descriptions = 1001356, /// spectrum quality descriptions: Description of the quality of the input spectrum. MS_spectrum_quality_descriptions = 1001357, /// msmsEval quality: This term reports the quality of the spectrum assigned by msmsEval. MS_msmsEval_quality = 1001358, /// ambiguous residues: Children of this term describe ambiguous residues. MS_ambiguous_residues = 1001359, /// alternate single letter codes: List of standard residue one letter codes which are used to replace a non-standard. MS_alternate_single_letter_codes = 1001360, /// alternate mass: List of masses a non-standard letter code is replaced with. MS_alternate_mass = 1001361, /// number of unmatched peaks: The number of unmatched peaks. MS_number_of_unmatched_peaks = 1001362, /// peptide unique to one protein: A peptide matching only one. MS_peptide_unique_to_one_protein = 1001363, /// distinct peptide-level global FDR: Estimation of the global false discovery rate for distinct peptides once redundant identifications of the same peptide have been removed (id est multiple PSMs have been collapsed to one entry). MS_distinct_peptide_level_global_FDR = 1001364, /// frag: internal yb ion: Fragmentation information, type of product: internal yb ion. MS_frag__internal_yb_ion = 1001365, /// frag: internal ya ion: Fragmentation information, type of product: internal ya ion. MS_frag__internal_ya_ion = 1001366, /// frag: z+1 ion: Fragmentation information, type of product: z+1 ion. MS_frag__z_1_ion = 1001367, /// frag: z+2 ion: Fragmentation information, type of product: z+2 ion. MS_frag__z_2_ion = 1001368, /// text format: Simple text file format of \"m/z [intensity]\" values for a PMF (or single MS2) search. MS_text_format = 1001369, /// Mascot:homology threshold: The Mascot result 'homology threshold'. MS_Mascot_homology_threshold = 1001370, /// Mascot:identity threshold: The Mascot result 'identity threshold'. MS_Mascot_identity_threshold = 1001371, /// SEQUEST:Sequences: MS_SEQUEST_Sequences = 1001372, /// SEQUEST:TIC: SEQUEST total ion current. MS_SEQUEST_TIC = 1001373, /// SEQUEST:Sum: MS_SEQUEST_Sum = 1001374, /// Phenyx:Instrument Type: The instrument type parameter value in Phenyx. MS_Phenyx_Instrument_Type = 1001375, /// Phenyx:Scoring Model: The selected scoring model in Phenyx. MS_Phenyx_Scoring_Model = 1001376, /// Phenyx:Default Parent Charge: The default parent charge value in Phenyx. MS_Phenyx_Default_Parent_Charge = 1001377, /// Phenyx:Trust Parent Charge: The parameter in Phenyx that specifies if the experimental charge state is to be considered as correct. MS_Phenyx_Trust_Parent_Charge = 1001378, /// Phenyx:Turbo: The turbo mode parameter in Phenyx. MS_Phenyx_Turbo = 1001379, /// Phenyx:Turbo:ErrorTol: The maximal allowed fragment m/z error filter considered in the turbo mode of Phenyx. MS_Phenyx_Turbo_ErrorTol = 1001380, /// Phenyx:Turbo:Coverage: The minimal peptide sequence coverage value, expressed in percent, considered in the turbo mode of Phenyx. MS_Phenyx_Turbo_Coverage = 1001381, /// Phenyx:Turbo:Series: The list of ion series considered in the turbo mode of Phenyx. MS_Phenyx_Turbo_Series = 1001382, /// Phenyx:MinPepLength: The minimal number of residues for a peptide to be considered for a valid identification in Phenyx. MS_Phenyx_MinPepLength = 1001383, /// Phenyx:MinPepzscore: The minimal peptide z-score for a peptide to be considered for a valid identification in Phenyx. MS_Phenyx_MinPepzscore = 1001384, /// Phenyx:MaxPepPvalue: The maximal peptide p-value for a peptide to be considered for a valid identification in Phenyx. MS_Phenyx_MaxPepPvalue = 1001385, /// Phenyx:AC Score: The minimal protein score required for a protein database entry to be displayed in the list of identified proteins in Phenyx. MS_Phenyx_AC_Score = 1001386, /// Phenyx:Conflict Resolution: The parameter in Phenyx that specifies if the conflict resolution algorithm is to be used. MS_Phenyx_Conflict_Resolution = 1001387, /// Phenyx:AC: The primary sequence database identifier of a protein in Phenyx. MS_Phenyx_AC = 1001388, /// Phenyx:ID: A secondary sequence database identifier of a protein in Phenyx. MS_Phenyx_ID = 1001389, /// Phenyx:Score: The protein score of a protein match in Phenyx. MS_Phenyx_Score = 1001390, /// Phenyx:Peptides1: First number of phenyx result \"#Peptides\". MS_Phenyx_Peptides1 = 1001391, /// Phenyx:Peptides2: Second number of phenyx result \"#Peptides\". MS_Phenyx_Peptides2 = 1001392, /// Phenyx:Auto: The value of the automatic peptide acceptance filter in Phenyx. MS_Phenyx_Auto = 1001393, /// Phenyx:User: The value of the user-defined peptide acceptance filter in Phenyx. MS_Phenyx_User = 1001394, /// Phenyx:Pepzscore: The z-score value of a peptide sequence match in Phenyx. MS_Phenyx_Pepzscore = 1001395, /// Phenyx:PepPvalue: The p-value of a peptide sequence match in Phenyx. MS_Phenyx_PepPvalue = 1001396, /// Phenyx:NumberOfMC: The number of missed cleavages of a peptide sequence in Phenyx. MS_Phenyx_NumberOfMC = 1001397, /// Phenyx:Modif: The expression of the nature and position(s) of modified residue(s) on a matched peptide sequence in Phenyx. MS_Phenyx_Modif = 1001398, /// OMSSA csv format: Source file for this mzIdentML was in OMSSA csv file format. MS_OMSSA_csv_format = 1001399, /// OMSSA xml format: Source file for this mzIdentML was in OMSSA xml file format. MS_OMSSA_xml_format = 1001400, /// X!Tandem xml format: Source file for this mzIdentML was in X!Tandem xml file format. MS_X_Tandem_xml_format = 1001401, /// spectrum identification result details: This subsection describes terms which can describe details of spectrum identification results. MS_spectrum_identification_result_details = 1001405, /// param: internal yb ion: Parameter information, type of product: internal yb ion. MS_param__internal_yb_ion = 1001406, /// param: internal ya ion: Parameter information, type of product: internal ya ion. MS_param__internal_ya_ion = 1001407, /// param: z+1 ion: Parameter information, type of product: z+1 ion. MS_param__z_1_ion = 1001408, /// param: z+2 ion: Parameter information, type of product: z+2 ion. MS_param__z_2_ion = 1001409, /// translation start codons: The translation start codons used to translate the nucleotides to amino acids. MS_translation_start_codons = 1001410, /// search tolerance specification: Specification of the search tolerance. MS_search_tolerance_specification = 1001411, /// search tolerance plus value: MS_search_tolerance_plus_value = 1001412, /// search tolerance minus value: MS_search_tolerance_minus_value = 1001413, /// MGF scans: OBSOLETE: replaced by MS:1000797 (peak list scans): This term can hold the scans attribute from an MGF input file. MS_MGF_scans_OBSOLETE = 1001414, /// MGF raw scans: OBSOLETE: replaced by MS:1000798 (peak list raw scans): This term can hold the raw scans attribute from an MGF input file. MS_MGF_raw_scans_OBSOLETE = 1001415, /// spectrum title: OBSOLETE: replaced by MS:1000796 (spectrum title): Holds the spectrum title from different input file formats, e.g. MGF TITLE. MS_spectrum_title_OBSOLETE = 1001416, /// SpectraST:dot: SpectraST dot product of two spectra, measuring spectral similarity. MS_SpectraST_dot = 1001417, /// SpectraST:dot_bias: SpectraST measure of how much of the dot product is dominated by a few peaks. MS_SpectraST_dot_bias = 1001418, /// SpectraST:discriminant score F: SpectraST spectrum score. MS_SpectraST_discriminant_score_F = 1001419, /// SpectraST:delta: SpectraST normalised difference between dot product of top hit and runner-up. MS_SpectraST_delta = 1001420, /// pepXML format: Source file for this mzIdentML was in a pepXML file format. MS_pepXML_format = 1001421, /// protXML format: Source file for this mzIdentML was in protXML file format. MS_protXML_format = 1001422, /// translation table description: A URL that describes the translation table used to translate the nucleotides to amino acids. MS_translation_table_description = 1001423, /// ProteinExtractor:Methodname: Name of the used method in the ProteinExtractor algorithm. MS_ProteinExtractor_Methodname = 1001424, /// ProteinExtractor:GenerateNonRedundant: Flag indicating if a non redundant scoring should be generated. MS_ProteinExtractor_GenerateNonRedundant = 1001425, /// ProteinExtractor:IncludeIdentified: Flag indicating if identified proteins should be included. MS_ProteinExtractor_IncludeIdentified = 1001426, /// ProteinExtractor:MaxNumberOfProteins: The maximum number of proteins to consider. MS_ProteinExtractor_MaxNumberOfProteins = 1001427, /// ProteinExtractor:MaxProteinMass: The maximum considered mass for a protein. MS_ProteinExtractor_MaxProteinMass = 1001428, /// ProteinExtractor:MinNumberOfPeptides: The minimum number of proteins to consider. MS_ProteinExtractor_MinNumberOfPeptides = 1001429, /// ProteinExtractor:UseMascot: Flag indicating to include Mascot scoring for calculation of the ProteinExtractor meta score. MS_ProteinExtractor_UseMascot = 1001430, /// ProteinExtractor:MascotPeptideScoreThreshold: Only peptides with scores higher than that threshold are taken into account in Mascot scoring for calculation of the ProteinExtractor meta score. MS_ProteinExtractor_MascotPeptideScoreThreshold = 1001431, /// ProteinExtractor:MascotUniqueScore: In the final result each protein must have at least one peptide above this Mascot score threshold in ProteinExtractor meta score calculation. MS_ProteinExtractor_MascotUniqueScore = 1001432, /// ProteinExtractor:MascotUseIdentityScore: MS_ProteinExtractor_MascotUseIdentityScore = 1001433, /// ProteinExtractor:MascotWeighting: Influence of Mascot search engine in the process of merging the search engine specific protein lists into the global protein list of ProteinExtractor. MS_ProteinExtractor_MascotWeighting = 1001434, /// ProteinExtractor:UseSequest: Flag indicating to include SEQUEST scoring for calculation of the ProteinExtractor meta score. MS_ProteinExtractor_UseSequest = 1001435, /// ProteinExtractor:SequestPeptideScoreThreshold: Only peptides with scores higher than that threshold are taken into account in SEQUEST scoring for calculation of the ProteinExtractor meta score. MS_ProteinExtractor_SequestPeptideScoreThreshold = 1001436, /// ProteinExtractor:SequestUniqueScore: In the final result each protein must have at least one peptide above this SEQUEST score threshold in ProteinExtractor meta score calculation. MS_ProteinExtractor_SequestUniqueScore = 1001437, /// ProteinExtractor:SequestWeighting: Influence of SEQUEST search engine in the process of merging the search engine specific protein lists into the global protein list of ProteinExtractor. MS_ProteinExtractor_SequestWeighting = 1001438, /// ProteinExtractor:UseProteinSolver: Flag indicating to include ProteinSolver scoring for calculation of the ProteinExtractor meta score. MS_ProteinExtractor_UseProteinSolver = 1001439, /// ProteinExtractor:ProteinSolverPeptideScoreThreshold: Only peptides with scores higher than that threshold are taken into account in ProteinSolver scoring for calculation of the ProteinExtractor meta score. MS_ProteinExtractor_ProteinSolverPeptideScoreThreshold = 1001440, /// ProteinExtractor:ProteinSolverUniqueScore: In the final result each protein must have at least one peptide above this ProteinSolver score threshold in ProteinExtractor meta score calculation. MS_ProteinExtractor_ProteinSolverUniqueScore = 1001441, /// ProteinExtractor:ProteinSolverWeighting: Influence of ProteinSolver search engine in the process of merging the search engine specific protein lists into the global protein list of ProteinExtractor. MS_ProteinExtractor_ProteinSolverWeighting = 1001442, /// ProteinExtractor:UsePhenyx: Flag indicating to include Phenyx scoring for calculation of the ProteinExtractor meta score. MS_ProteinExtractor_UsePhenyx = 1001443, /// ProteinExtractor:PhenyxPeptideScoreThreshold: Only peptides with scores higher than that threshold are taken into account in Phenyx scoring for calculation of the ProteinExtractor meta score. MS_ProteinExtractor_PhenyxPeptideScoreThreshold = 1001444, /// ProteinExtractor:PhenyxUniqueScore: In the final result each protein must have at least one peptide above this Phenyx score threshold in ProteinExtractor meta score calculation. MS_ProteinExtractor_PhenyxUniqueScore = 1001445, /// ProteinExtractor:PhenyxWeighting: Influence of Phenyx search engine in the process of merging the search engine specific protein lists into the global protein list of ProteinExtractor. MS_ProteinExtractor_PhenyxWeighting = 1001446, /// prot:FDR threshold: False-discovery rate threshold for proteins. MS_prot_FDR_threshold = 1001447, /// pep:FDR threshold: False-discovery rate threshold for peptides. MS_pep_FDR_threshold = 1001448, /// OMSSA e-value threshold: Threshold for OMSSA e-value for quality estimation. MS_OMSSA_e_value_threshold = 1001449, /// decoy DB details: Details of decoy generation and database structure. MS_decoy_DB_details = 1001450, /// decoy DB generation algorithm: Name of algorithm used for decoy generation. MS_decoy_DB_generation_algorithm = 1001451, /// decoy DB type shuffle: Decoy type: Amino acids of protein sequences are used in a random order. MS_decoy_DB_type_shuffle = 1001452, /// DB composition only decoy: Decoy database composition: database contains only decoy entries. MS_DB_composition_only_decoy = 1001453, /// quality estimation with implicite decoy sequences: Decoy entries are generated during the search, not explicitly stored in a database (like Mascot Decoy). MS_quality_estimation_with_implicite_decoy_sequences = 1001454, /// acquisition software: Acquisition software. MS_acquisition_software = 1001455, /// analysis software: Analysis software. MS_analysis_software = 1001456, /// data processing software: Data processing software. MS_data_processing_software = 1001457, /// spectrum generation information: Vocabularies describing the spectrum generation information. MS_spectrum_generation_information = 1001458, /// file format: Format of data files. MS_file_format = 1001459, /// unknown modification: This term should be given if the modification was unknown. MS_unknown_modification = 1001460, /// greylag: Greylag identification software. MS_greylag = 1001461, /// PEFF format: The sequence database was stored in the PEFF (PSI enhanced FastA file) format. MS_PEFF_format = 1001462, /// Phenyx XML format: Phenyx open XML file format. MS_Phenyx_XML_format = 1001463, /// DTASelect format: DTASelect file format. MS_DTASelect_format = 1001464, /// MS2 format: MS2 file format for MS2 spectral data. MS_MS2_format = 1001466, /// taxonomy: NCBI TaxID: This term is used if a NCBI TaxID is specified, e.g. 9606 for Homo sapiens. MS_taxonomy__NCBI_TaxID = 1001467, /// taxonomy: common name: This term is used if a common name is specified, e.g. human. Recommend using MS:1001467 (taxonomy: NCBI TaxID) where possible. MS_taxonomy__common_name = 1001468, /// taxonomy: scientific name: This term is used if a scientific name is specified, e.g. Homo sapiens. Recommend using MS:1001467 (taxonomy: NCBI TaxID) where possible. MS_taxonomy__scientific_name = 1001469, /// taxonomy: Swiss-Prot ID: This term is used if a swiss prot taxonomy id is specified, e.g. Human. Recommend using MS:1001467 (taxonomy: NCBI TaxID) where possible. MS_taxonomy__Swiss_Prot_ID = 1001470, /// peptide modification details: The children of this term can be used to describe modifications. MS_peptide_modification_details = 1001471, /// selected ion monitoring chromatogram: Chromatogram created by creating an array of the measurements of a selectively monitored ion at each time point. MS_selected_ion_monitoring_chromatogram = 1001472, /// SIM chromatogram (selected ion monitoring chromatogram): Chromatogram created by creating an array of the measurements of a selectively monitored ion at each time point. MS_SIM_chromatogram = MS_selected_ion_monitoring_chromatogram, /// selected reaction monitoring chromatogram: Chromatogram created by creating an array of the measurements of a selectively monitored reaction at each time point. MS_selected_reaction_monitoring_chromatogram = 1001473, /// SRM chromatogram (selected reaction monitoring chromatogram): Chromatogram created by creating an array of the measurements of a selectively monitored reaction at each time point. MS_SRM_chromatogram = MS_selected_reaction_monitoring_chromatogram, /// consecutive reaction monitoring chromatogram: Chromatogram created by creating an array of the measurements of a series of monitored reactions at each time point. MS_consecutive_reaction_monitoring_chromatogram_OBSOLETE = 1001474, /// CRM chromatogram (consecutive reaction monitoring chromatogram): Chromatogram created by creating an array of the measurements of a series of monitored reactions at each time point. MS_CRM_chromatogram_OBSOLETE = MS_consecutive_reaction_monitoring_chromatogram_OBSOLETE, /// OMSSA: Open Mass Spectrometry Search Algorithm was used to analyze the spectra. MS_OMSSA = 1001475, /// X!Tandem: X!Tandem was used to analyze the spectra. MS_X_Tandem = 1001476, /// SpectraST: SpectraST was used to analyze the spectra. MS_SpectraST = 1001477, /// Mascot Parser: Mascot Parser was used to analyze the spectra. MS_Mascot_Parser = 1001478, /// null-terminated ASCII string: Sequence of zero or more non-zero ASCII characters terminated by a single null (0) byte. MS_null_terminated_ASCII_string = 1001479, /// SCIEX TOF/TOF nativeID format: Native format defined by jobRun=xsd:nonNegativeInteger spotLabel=xsd:string spectrum=xsd:nonNegativeInteger. MS_SCIEX_TOF_TOF_nativeID_format = 1001480, /// SCIEX TOF/TOF database: Applied Biosystems/MDS Analytical Technologies TOF/TOF instrument database. MS_SCIEX_TOF_TOF_database = 1001481, /// 5800 TOF/TOF: SCIEX 5800 TOF-TOF Analyzer. MS_5800_TOF_TOF = 1001482, /// SCIEX TOF/TOF Series Explorer Software: SCIEX or Applied Biosystems software for TOF/TOF data acquisition and analysis. MS_SCIEX_TOF_TOF_Series_Explorer_Software = 1001483, /// intensity normalization: Normalization of data point intensities. MS_intensity_normalization = 1001484, /// m/z calibration: Calibration of data point m/z positions. MS_m_z_calibration = 1001485, /// data filtering: Filtering out part of the data. MS_data_filtering = 1001486, /// ProteinExtractor: An algorithm for protein determination/assembly integrated into Bruker's ProteinScape. MS_ProteinExtractor = 1001487, /// Mascot Distiller: Mascot Distiller. MS_Mascot_Distiller = 1001488, /// Mascot Integra: Mascot Integra. MS_Mascot_Integra = 1001489, /// Percolator: Percolator. MS_Percolator = 1001490, /// percolator:Q value: Percolator:Q value. MS_percolator_Q_value = 1001491, /// percolator:score: Percolator:score. MS_percolator_score = 1001492, /// percolator:PEP: Posterior error probability. MS_percolator_PEP = 1001493, /// no threshold: In case no threshold was used. MS_no_threshold = 1001494, /// ProteinScape:SearchResultId: The SearchResultId of this peptide as SearchResult in the ProteinScape database. MS_ProteinScape_SearchResultId = 1001495, /// ProteinScape:SearchEventId: The SearchEventId of the SearchEvent in the ProteinScape database. MS_ProteinScape_SearchEventId = 1001496, /// ProteinScape:ProfoundProbability: The Profound probability score stored by ProteinScape. MS_ProteinScape_ProfoundProbability = 1001497, /// Profound:z value: The Profound z value. MS_Profound_z_value = 1001498, /// Profound:Cluster: The Profound cluster score. MS_Profound_Cluster = 1001499, /// Profound:ClusterRank: The Profound cluster rank. MS_Profound_ClusterRank = 1001500, /// MSFit:Mowse score: The MSFit Mowse score. MS_MSFit_Mowse_score = 1001501, /// Sonar:Score: The Sonar score. MS_Sonar_Score = 1001502, /// ProteinScape:PFFSolverExp: The ProteinSolver exp value stored by ProteinScape. MS_ProteinScape_PFFSolverExp = 1001503, /// ProteinScape:PFFSolverScore: The ProteinSolver score stored by ProteinScape. MS_ProteinScape_PFFSolverScore = 1001504, /// ProteinScape:IntensityCoverage: The intensity coverage of the identified peaks in the spectrum calculated by ProteinScape. MS_ProteinScape_IntensityCoverage = 1001505, /// ProteinScape:SequestMetaScore: The SEQUEST meta score calculated by ProteinScape from the original SEQUEST scores. MS_ProteinScape_SequestMetaScore = 1001506, /// ProteinExtractor:Score: The score calculated by ProteinExtractor. MS_ProteinExtractor_Score = 1001507, /// Agilent MassHunter nativeID format: Native format defined by scanId=xsd:nonNegativeInteger. MS_Agilent_MassHunter_nativeID_format = 1001508, /// Agilent MassHunter format: A data file format found in an Agilent MassHunter directory which contains raw data acquired by an Agilent mass spectrometer. MS_Agilent_MassHunter_format = 1001509, /// TSQ Vantage: TSQ Vantage. MS_TSQ_Vantage = 1001510, /// Sequence database filter types: Filter types which are used to filter a sequence database. MS_Sequence_database_filter_types = 1001511, /// Sequence database filters: Sequence database filters which actually can contains values, e.g. to limit PI value of the sequences used to search. MS_Sequence_database_filters = 1001512, /// DB sequence filter pattern: DB sequence filter pattern. MS_DB_sequence_filter_pattern = 1001513, /// DB accession filter string: DB accession filter string. MS_DB_accession_filter_string = 1001514, /// frag: c ion - H2O: Fragmentation information, type of product: c ion without water. MS_frag__c_ion___H2O = 1001515, /// frag: c ion - NH3: Fragmentation information, type of product: c ion without ammonia. MS_frag__c_ion___NH3 = 1001516, /// frag: z ion - H2O: Fragmentation information, type of product: z ion without water. MS_frag__z_ion___H2O = 1001517, /// frag: z ion - NH3: Fragmentation information, type of product: z ion without ammonia. MS_frag__z_ion___NH3 = 1001518, /// frag: x ion - H2O: Fragmentation information, type of product: x ion without water. MS_frag__x_ion___H2O = 1001519, /// frag: x ion - NH3: Fragmentation information, type of product: x ion without ammonia. MS_frag__x_ion___NH3 = 1001520, /// frag: precursor ion - H2O: Fragmentation information, type of product: precursor ion without water. MS_frag__precursor_ion___H2O = 1001521, /// frag: precursor ion - NH3: Fragmentation information, type of product: precursor ion without ammonia. MS_frag__precursor_ion___NH3 = 1001522, /// frag: precursor ion: Fragmentation information, type of product: precursor ion. MS_frag__precursor_ion = 1001523, /// fragment neutral loss: This term can describe a neutral loss m/z value that is lost from an ion. MS_fragment_neutral_loss = 1001524, /// precursor neutral loss: This term can describe a neutral loss m/z value that is lost from an ion. MS_precursor_neutral_loss = 1001525, /// spectrum from database integer nativeID format: Native format defined by databasekey=xsd:long. MS_spectrum_from_database_integer_nativeID_format = 1001526, /// Proteinscape spectra: Spectra from Bruker/Protagen Proteinscape database. MS_Proteinscape_spectra = 1001527, /// Mascot query number: Native format defined by query=xsd:nonNegativeInteger. MS_Mascot_query_number = 1001528, /// spectra data details: Child-terms contain information to map the results back to spectra. MS_spectra_data_details = 1001529, /// mzML unique identifier: Native format defined by mzMLid=xsd:IDREF. MS_mzML_unique_identifier = 1001530, /// spectrum from ProteinScape database nativeID format: Native format defined by databasekey=xsd:long. MS_spectrum_from_ProteinScape_database_nativeID_format = 1001531, /// spectrum from database string nativeID format: Native format defined by databasekey=xsd:string. MS_spectrum_from_database_string_nativeID_format = 1001532, /// Bruker Daltonics esquire series: Bruker Daltonics' esquire series. MS_Bruker_Daltonics_esquire_series = 1001533, /// Bruker Daltonics flex series: Bruker Daltonics' flex series. MS_Bruker_Daltonics_flex_series = 1001534, /// Bruker Daltonics BioTOF series: Bruker Daltonics' BioTOF series. MS_Bruker_Daltonics_BioTOF_series = 1001535, /// Bruker Daltonics micrOTOF series: Bruker Daltonics' micrOTOF series. MS_Bruker_Daltonics_micrOTOF_series = 1001536, /// BioTOF: Bruker Daltonics' BioTOF: ESI TOF. MS_BioTOF = 1001537, /// BioTOF III: Bruker Daltonics' BioTOF III: ESI TOF. MS_BioTOF_III = 1001538, /// UltroTOF-Q: Bruker Daltonics' UltroTOF-Q: ESI Q-TOF (MALDI optional). MS_UltroTOF_Q = 1001539, /// micrOTOF II: Bruker Daltonics' micrOTOF II: ESI TOF, Nanospray, APCI, APPI. MS_micrOTOF_II = 1001540, /// maXis: Bruker Daltonics' maXis: ESI Q-TOF, Nanospray, APCI, APPI. MS_maXis = 1001541, /// amaZon ETD: Bruker Daltonics' amaZon ETD: ESI quadrupole ion trap, Nanospray, APCI, APPI, ETD, PTR. MS_amaZon_ETD = 1001542, /// microflex LRF: Bruker Daltonics' microflex LRF: MALDI TOF. MS_microflex_LRF = 1001543, /// ultrafleXtreme: Bruker Daltonics' ultrafleXtreme: MALDI TOF. MS_ultrafleXtreme = 1001544, /// Bruker Daltonics amaZon series: Bruker Daltonics' amaZon series. MS_Bruker_Daltonics_amaZon_series = 1001545, /// amaZon X: Bruker Daltonics' amaZon X: ESI quadrupole ion trap, APCI, APPI, ETD, PTR. MS_amaZon_X = 1001546, /// Bruker Daltonics maXis series: Bruker Daltonics' maXis series. MS_Bruker_Daltonics_maXis_series = 1001547, /// Bruker Daltonics solarix series: Bruker Daltonics' solarix: ESI quadrupole ion trap, APCI, APPI, ETD, PTR. MS_Bruker_Daltonics_solarix_series = 1001548, /// solariX: Bruker Daltonics' solariX: ESI, MALDI, Qh-FT_ICR. MS_solariX = 1001549, /// microflex II: Bruker Daltonics' microflex II: MALDI TOF. MS_microflex_II = 1001550, /// autoflex II TOF/TOF: Bruker Daltonics' autoflex II TOF/TOF: MALDI TOF. MS_autoflex_II_TOF_TOF = 1001553, /// autoflex III TOF/TOF smartbeam: Bruker Daltonics' autoflex III TOF/TOF smartbeam: MALDI TOF. MS_autoflex_III_TOF_TOF_smartbeam = 1001554, /// autoflex: Bruker Daltonics' autoflex: MALDI TOF. MS_autoflex = 1001555, /// Bruker Daltonics apex series: Bruker Daltonics' apex series. MS_Bruker_Daltonics_apex_series = 1001556, /// Shimadzu Corporation software: Shimadzu Corporation software. MS_Shimadzu_Corporation_software = 1001557, /// MALDI Solutions: Shimadzu Biotech software for data acquisition, processing, and analysis. MS_MALDI_Solutions = 1001558, /// SCIEX TOF/TOF T2D nativeID format: Native format defined by file=xsd:IDREF. MS_SCIEX_TOF_TOF_T2D_nativeID_format = 1001559, /// SCIEX TOF/TOF T2D format: Applied Biosystems/MDS Analytical Technologies TOF/TOF instrument export format. MS_SCIEX_TOF_TOF_T2D_format = 1001560, /// Scaffold: Scaffold analysis software. MS_Scaffold = 1001561, /// Scaffold nativeID format: Scaffold native ID format. MS_Scaffold_nativeID_format = 1001562, /// SEQUEST SQT format: Source file for this mzIdentML was in SEQUEST SQT format. MS_SEQUEST_SQT_format = 1001563, /// Discoverer MSF format: Source file for this mzIdentML was in Thermo Scientific Discoverer MSF format. MS_Discoverer_MSF_format = 1001564, /// IdentityE XML format: Source file for this mzIdentML was in Waters IdentityE XML format. MS_IdentityE_XML_format = 1001565, /// ProteinLynx XML format: Source file for this mzIdentML was in Waters ProteinLynx XML format. MS_ProteinLynx_XML_format = 1001566, /// SpectrumMill directories: Source file for this mzIdentML was in Agilent SpectrumMill directory format. MS_SpectrumMill_directories = 1001567, /// Scaffold:Peptide Probability: Scaffold peptide probability score. MS_Scaffold_Peptide_Probability = 1001568, /// IdentityE Score: Waters IdentityE peptide score. MS_IdentityE_Score = 1001569, /// ProteinLynx:Log Likelihood: ProteinLynx log likelihood score. MS_ProteinLynx_Log_Likelihood = 1001570, /// ProteinLynx:Ladder Score: Waters ProteinLynx Ladder score. MS_ProteinLynx_Ladder_Score = 1001571, /// SpectrumMill:Score: Spectrum mill peptide score. MS_SpectrumMill_Score = 1001572, /// SpectrumMill:SPI: SpectrumMill SPI score (%). MS_SpectrumMill_SPI = 1001573, /// report only spectra assigned to identified proteins: Flag indicating to report only the spectra assigned to identified proteins. MS_report_only_spectra_assigned_to_identified_proteins = 1001574, /// Scaffold: Minimum Peptide Count: Minimum number of peptides a protein must have to be accepted. MS_Scaffold__Minimum_Peptide_Count = 1001575, /// Scaffold: Minimum Protein Probability: Minimum protein probability a protein must have to be accepted. MS_Scaffold__Minimum_Protein_Probability = 1001576, /// Scaffold: Minimum Peptide Probability: Minimum probability a peptide must have to be accepted for protein scoring. MS_Scaffold__Minimum_Peptide_Probability = 1001577, /// minimum number of enzymatic termini: Minimum number of enzymatic termini a peptide must have to be accepted. MS_minimum_number_of_enzymatic_termini = 1001578, /// Scaffold:Protein Probability: Scaffold protein probability score. MS_Scaffold_Protein_Probability = 1001579, /// SpectrumMill:Discriminant Score: Discriminant score from Agilent SpectrumMill software. MS_SpectrumMill_Discriminant_Score = 1001580, /// FAIMS compensation voltage: The DC potential applied to the asymmetric waveform in FAIMS that compensates for the difference between high and low field mobility of an ion. MS_FAIMS_compensation_voltage = 1001581, /// FAIMS CV (FAIMS compensation voltage): The DC potential applied to the asymmetric waveform in FAIMS that compensates for the difference between high and low field mobility of an ion. MS_FAIMS_CV = MS_FAIMS_compensation_voltage, /// XCMS: Bioconductor package XCMS for preprocessing high-throughput, untargeted analyte profiling data. MS_XCMS = 1001582, /// MaxQuant: MaxQuant is a quantitative proteomics software package designed for analyzing large mass spectrometric data sets. It is specifically aimed at high resolution MS data. MS_MaxQuant = 1001583, /// combined pmf + ms-ms search: Search that includes data from Peptide Mass Fingerprint (PMF) and MS2 (aka Peptide Fragment Fingerprint - PFF). MS_combined_pmf___ms_ms_search = 1001584, /// MyriMatch: Tabb Lab software for directly comparing peptides in a database to tandem mass spectra. MS_MyriMatch = 1001585, /// DirecTag: Tabb Lab software for generating sequence tags from tandem mass spectra. MS_DirecTag = 1001586, /// TagRecon: Tabb Lab software for reconciling sequence tags to a protein database. MS_TagRecon = 1001587, /// Pepitome: Tabb Lab software for spectral library searches on tandem mass spectra. MS_Pepitome = 1001588, /// MyriMatch:MVH: Using the multivariate hypergeometric distribution and a peak list divided into several intensity classes, this score is the negative natural log probability that the predicted peaks matched to experimental peaks by random chance. MS_MyriMatch_MVH = 1001589, /// Pepitome:MVH (MyriMatch:MVH): Using the multivariate hypergeometric distribution and a peak list divided into several intensity classes, this score is the negative natural log probability that the predicted peaks matched to experimental peaks by random chance. MS_Pepitome_MVH = MS_MyriMatch_MVH, /// TagRecon:MVH (MyriMatch:MVH): Using the multivariate hypergeometric distribution and a peak list divided into several intensity classes, this score is the negative natural log probability that the predicted peaks matched to experimental peaks by random chance. MS_TagRecon_MVH = MS_MyriMatch_MVH, /// MyriMatch:mzFidelity: The negative natural log probability that predicted peaks match to experimental peaks by random chance by scoring the m/z delta of the matches in a multinomial distribution. MS_MyriMatch_mzFidelity = 1001590, /// Pepitome:mzFidelity (MyriMatch:mzFidelity): The negative natural log probability that predicted peaks match to experimental peaks by random chance by scoring the m/z delta of the matches in a multinomial distribution. MS_Pepitome_mzFidelity = MS_MyriMatch_mzFidelity, /// TagRecon:mzFidelity (MyriMatch:mzFidelity): The negative natural log probability that predicted peaks match to experimental peaks by random chance by scoring the m/z delta of the matches in a multinomial distribution. MS_TagRecon_mzFidelity = MS_MyriMatch_mzFidelity, /// anchor protein: A representative protein selected from a set of sequence same-set or spectrum same-set proteins. MS_anchor_protein = 1001591, /// family member protein: A protein with significant homology to another protein, but some distinguishing peptide matches. MS_family_member_protein = 1001592, /// group member with undefined relationship OR ortholog protein: TO ENDETAIL: a really generic relationship OR ortholog protein. MS_group_member_with_undefined_relationship_OR_ortholog_protein = 1001593, /// sequence same-set protein: A protein which is indistinguishable or equivalent to another protein, having matches to an identical set of peptide sequences. MS_sequence_same_set_protein = 1001594, /// spectrum same-set protein: A protein which is indistinguishable or equivalent to another protein, having matches to a set of peptide sequences that cannot be distinguished using the evidence in the mass spectra. MS_spectrum_same_set_protein = 1001595, /// sequence sub-set protein: A protein with a sub-set of the peptide sequence matches for another protein, and no distinguishing peptide matches. MS_sequence_sub_set_protein = 1001596, /// spectrum sub-set protein: A protein with a sub-set of the matched spectra for another protein, where the matches cannot be distinguished using the evidence in the mass spectra, and no distinguishing peptide matches. MS_spectrum_sub_set_protein = 1001597, /// sequence subsumable protein: A sequence same-set or sequence sub-set protein where the matches are distributed across two or more proteins. MS_sequence_subsumable_protein = 1001598, /// spectrum subsumable protein: A spectrum same-set or spectrum sub-set protein where the matches are distributed across two or more proteins. MS_spectrum_subsumable_protein = 1001599, /// protein inference confidence category: Confidence category of inferred protein (conclusive, non conclusive, ambiguous group or indistinguishable). MS_protein_inference_confidence_category = 1001600, /// ProteomeDiscoverer:Spectrum Files:Raw File names: Name and location of the .raw file or files. MS_ProteomeDiscoverer_Spectrum_Files_Raw_File_names_OBSOLETE = 1001601, /// ProteomeDiscoverer:SRF File Selector:SRF File Path: Path and name of the .srf (SEQUEST Result Format) file. MS_ProteomeDiscoverer_SRF_File_Selector_SRF_File_Path_OBSOLETE = 1001602, /// ProteomeDiscoverer:Spectrum Selector:Ionization Source: Ionization source (electro-, nano-, thermospray, electron impact, APCI, MALDI, FAB etc). MS_ProteomeDiscoverer_Spectrum_Selector_Ionization_Source_OBSOLETE = 1001603, /// ProteomeDiscoverer:Activation Type: Fragmentation method used (CID, MPD, ECD, PQD, ETD, HCD, Any). MS_ProteomeDiscoverer_Activation_Type_OBSOLETE = 1001604, /// ProteomeDiscoverer:Spectrum Selector:Lower RT Limit: Lower retention-time limit. MS_ProteomeDiscoverer_Spectrum_Selector_Lower_RT_Limit = 1001605, /// ProteomeDiscoverer:Mass Analyzer: Type of mass spectrometer used (ITMS, FTMS, TOFMS, SQMS, TQMS, SectorMS). MS_ProteomeDiscoverer_Mass_Analyzer_OBSOLETE = 1001606, /// ProteomeDiscoverer:Max Precursor Mass: Maximum mass limit of a singly charged precursor ion. MS_ProteomeDiscoverer_Max_Precursor_Mass = 1001607, /// ProteomeDiscoverer:Min Precursor Mass: Minimum mass limit of a singly charged precursor ion. MS_ProteomeDiscoverer_Min_Precursor_Mass = 1001608, /// ProteomeDiscoverer:Spectrum Selector:Minimum Peak Count: Minimum number of peaks in a tandem mass spectrum that is allowed to pass the filter and to be subjected to further processing in the workflow. MS_ProteomeDiscoverer_Spectrum_Selector_Minimum_Peak_Count = 1001609, /// ProteomeDiscoverer:MS Order: Level of the mass spectrum (MS2 ... MS10). MS_ProteomeDiscoverer_MS_Order_OBSOLETE = 1001610, /// ProteomeDiscoverer:Polarity Mode: Polarity mode (positive or negative). MS_ProteomeDiscoverer_Polarity_Mode_OBSOLETE = 1001611, /// ProteomeDiscoverer:Spectrum Selector:Precursor Selection: Determines which precursor mass to use for a given MSn scan. This option applies only to higher-order MSn scans (n >= 3). MS_ProteomeDiscoverer_Spectrum_Selector_Precursor_Selection = 1001612, /// ProteomeDiscoverer:SN Threshold: Signal-to-Noise ratio below which peaks are removed. MS_ProteomeDiscoverer_SN_Threshold = 1001613, /// ProteomeDiscoverer:Scan Type: Scan type for the precursor ion (full, Single Ion Monitoring (SIM), Single Reaction Monitoring (SRM)). MS_ProteomeDiscoverer_Scan_Type_OBSOLETE = 1001614, /// ProteomeDiscoverer:Spectrum Selector:Total Intensity Threshold: Used to filter out tandem mass spectra that have a total intensity current(sum of the intensities of all peaks in a spectrum) below the specified value. MS_ProteomeDiscoverer_Spectrum_Selector_Total_Intensity_Threshold = 1001615, /// ProteomeDiscoverer:Spectrum Selector:Unrecognized Activation Type Replacements: Specifies the fragmentation method to use in the search algorithm if it is not included in the scan header. MS_ProteomeDiscoverer_Spectrum_Selector_Unrecognized_Activation_Type_Replacements = 1001616, /// ProteomeDiscoverer:Spectrum Selector:Unrecognized Charge Replacements: Specifies the charge state of the precursor ions, if it is not defined in the scan header. MS_ProteomeDiscoverer_Spectrum_Selector_Unrecognized_Charge_Replacements = 1001617, /// ProteomeDiscoverer:Spectrum Selector:Unrecognized Mass Analyzer Replacements: Specifies the mass spectrometer to use to produce the spectra, if it is not included in the scan header. MS_ProteomeDiscoverer_Spectrum_Selector_Unrecognized_Mass_Analyzer_Replacements = 1001618, /// ProteomeDiscoverer:Spectrum Selector:Unrecognized MS Order Replacements: Specifies the MS scan order used to produce the product spectra, if it is not included in the scan header. MS_ProteomeDiscoverer_Spectrum_Selector_Unrecognized_MS_Order_Replacements = 1001619, /// ProteomeDiscoverer:Spectrum Selector:Unrecognized Polarity Replacements: Specifies the polarity of the ions monitored if it is not included in the scan header. MS_ProteomeDiscoverer_Spectrum_Selector_Unrecognized_Polarity_Replacements = 1001620, /// ProteomeDiscoverer:Spectrum Selector:Upper RT Limit: Upper retention-time limit. MS_ProteomeDiscoverer_Spectrum_Selector_Upper_RT_Limit = 1001621, /// ProteomeDiscoverer:Non-Fragment Filter:Mass Window Offset: Specifies the size of the mass-to-charge ratio (m/z) window in daltons used to remove precursors. MS_ProteomeDiscoverer_Non_Fragment_Filter_Mass_Window_Offset = 1001622, /// ProteomeDiscoverer:Non-Fragment Filter:Maximum Neutral Loss Mass: Maximum allowed mass of a neutral loss. MS_ProteomeDiscoverer_Non_Fragment_Filter_Maximum_Neutral_Loss_Mass = 1001623, /// ProteomeDiscoverer:Non-Fragment Filter:Remove Charge Reduced Precursor: Determines whether the charge-reduced precursor peaks found in an ETD or ECD spectrum are removed. MS_ProteomeDiscoverer_Non_Fragment_Filter_Remove_Charge_Reduced_Precursor = 1001624, /// ProteomeDiscoverer:Non-Fragment Filter:Remove Neutral Loss Peaks: Determines whether neutral loss peaks are removed from ETD and ECD spectra. MS_ProteomeDiscoverer_Non_Fragment_Filter_Remove_Neutral_Loss_Peaks = 1001625, /// ProteomeDiscoverer:Non-Fragment Filter:Remove Only Known Masses: Determines whether overtone peaks are removed from LTQ FT or LTQ FT Ultra ECD spectra. MS_ProteomeDiscoverer_Non_Fragment_Filter_Remove_Only_Known_Masses = 1001626, /// ProteomeDiscoverer:Non-Fragment Filter:Remove Precursor Overtones: Determines whether precursor overtone peaks in the spectrum are removed from the input spectrum. MS_ProteomeDiscoverer_Non_Fragment_Filter_Remove_Precursor_Overtones = 1001627, /// ProteomeDiscoverer:Non-Fragment Filter:Remove Precursor Peak: Determines whether precursor artifact peaks from the MS2 input spectra are removed. MS_ProteomeDiscoverer_Non_Fragment_Filter_Remove_Precursor_Peak = 1001628, /// ProteomeDiscoverer:Spectrum Grouper:Allow Mass Analyzer Mismatch: Determines whether the fragment spectrum for scans with the same precursor mass is grouped, regardless of mass analyzer and activation type. MS_ProteomeDiscoverer_Spectrum_Grouper_Allow_Mass_Analyzer_Mismatch = 1001629, /// ProteomeDiscoverer:Spectrum Grouper:Allow MS Order Mismatch: Determines whether spectra from different MS order scans can be grouped together. MS_ProteomeDiscoverer_Spectrum_Grouper_Allow_MS_Order_Mismatch = 1001630, /// ProteomeDiscoverer:Spectrum Grouper:Max RT Difference: Chromatographic window where precursors to be grouped must reside to be considered the same species. MS_ProteomeDiscoverer_Spectrum_Grouper_Max_RT_Difference_OBSOLETE = 1001631, /// ProteomeDiscoverer:Spectrum Grouper:Precursor Mass Criterion: Groups spectra measured within the given mass and retention-time tolerances into a single spectrum for analysis. MS_ProteomeDiscoverer_Spectrum_Grouper_Precursor_Mass_Criterion = 1001632, /// ProteomeDiscoverer:Xtract:Highest Charge: Highest charge state that is allowed for the deconvolution of multiply charged data. MS_ProteomeDiscoverer_Xtract_Highest_Charge = 1001633, /// ProteomeDiscoverer:Xtract:Highest MZ: Highest mass-to-charge (mz) value for spectral peaks in the measured spectrum that are considered for Xtract. MS_ProteomeDiscoverer_Xtract_Highest_MZ_OBSOLETE = 1001634, /// ProteomeDiscoverer:Xtract:Lowest Charge: Lowest charge state that is allowed for the deconvolution of multiply charged data. MS_ProteomeDiscoverer_Xtract_Lowest_Charge = 1001635, /// ProteomeDiscoverer:Xtract:Lowest MZ: Lowest mass-to-charge (mz) value for spectral peaks in the measured spectrum that are considered for Xtract. MS_ProteomeDiscoverer_Xtract_Lowest_MZ_OBSOLETE = 1001636, /// ProteomeDiscoverer:Xtract:Monoisotopic Mass Only: Determines whether the isotopic pattern, i.e. all isotopes of a mass are removed from the spectrum. MS_ProteomeDiscoverer_Xtract_Monoisotopic_Mass_Only = 1001637, /// ProteomeDiscoverer:Xtract:Overlapping Remainder: Fraction of the more abundant peak that an overlapping multiplet must exceed in order to be processed (deconvoluted). MS_ProteomeDiscoverer_Xtract_Overlapping_Remainder = 1001638, /// ProteomeDiscoverer:Xtract:Required Fitting Accuracy: Accuracy required for a pattern fit to be considered valid. MS_ProteomeDiscoverer_Xtract_Required_Fitting_Accuracy = 1001639, /// ProteomeDiscoverer:Xtract:Resolution At 400: Resolution at mass 400. MS_ProteomeDiscoverer_Xtract_Resolution_At_400 = 1001640, /// ProteomeDiscoverer:Lowest Charge State: Minimum charge state below which peptides are filtered out. MS_ProteomeDiscoverer_Lowest_Charge_State = 1001641, /// ProteomeDiscoverer:Highest Charge State: Maximum charge above which peptides are filtered out. MS_ProteomeDiscoverer_Highest_Charge_State = 1001642, /// ProteomeDiscoverer:Spectrum Score Filter:Let Pass Above Scores: Determines whether spectra with scores above the threshold score are retained rather than filtered out. MS_ProteomeDiscoverer_Spectrum_Score_Filter_Let_Pass_Above_Scores = 1001643, /// ProteomeDiscoverer:Dynamic Modification: Determine dynamic post-translational modifications (PTMs). MS_ProteomeDiscoverer_Dynamic_Modification = 1001644, /// ProteomeDiscoverer:Static Modification: Static Modification to all occurrences of a named amino acid. MS_ProteomeDiscoverer_Static_Modification = 1001645, /// ProteomeDiscoverer:Mascot:Decoy Search: Determines whether the Proteome Discoverer application searches an additional decoy database. MS_ProteomeDiscoverer_Mascot_Decoy_Search_OBSOLETE = 1001646, /// ProteomeDiscoverer:Mascot:Error tolerant Search: Determines whether to search error-tolerant. MS_ProteomeDiscoverer_Mascot_Error_tolerant_Search = 1001647, /// ProteomeDiscoverer:Mascot:Max MGF File Size: Maximum size of the .mgf (Mascot Generic Format) file in MByte. MS_ProteomeDiscoverer_Mascot_Max_MGF_File_Size = 1001648, /// ProteomeDiscoverer:Mascot:Mascot Server URL: URL (Uniform resource Locator) of the Mascot server. MS_ProteomeDiscoverer_Mascot_Mascot_Server_URL = 1001649, /// ProteomeDiscoverer:Mascot:Number of attempts to submit the search: Number of attempts to submit the Mascot search. MS_ProteomeDiscoverer_Mascot_Number_of_attempts_to_submit_the_search = 1001650, /// ProteomeDiscoverer:Mascot:X Static Modification: Number of attempts to submit the Mascot search. MS_ProteomeDiscoverer_Mascot_X_Static_Modification = 1001651, /// ProteomeDiscoverer:Mascot:User Name: Name of the user submitting the Mascot search. MS_ProteomeDiscoverer_Mascot_User_Name_OBSOLETE = 1001652, /// ProteomeDiscoverer:Mascot:Time interval between attempts to submit a search: Time interval between attempts to submit a search in seconds. MS_ProteomeDiscoverer_Mascot_Time_interval_between_attempts_to_submit_a_search = 1001653, /// ProteomeDiscoverer:Enzyme Name: Specifies the enzyme reagent used for protein digestion. MS_ProteomeDiscoverer_Enzyme_Name_OBSOLETE = 1001654, /// ProteomeDiscoverer:Fragment Mass Tolerance: Mass tolerance used for matching fragment peaks in Da or mmu. MS_ProteomeDiscoverer_Fragment_Mass_Tolerance_OBSOLETE = 1001655, /// Mascot:Instrument: Type of instrument used to acquire the data in the raw file. MS_Mascot_Instrument = 1001656, /// ProteomeDiscoverer:Maximum Missed Cleavage Sites: Maximum number of missed cleavage sites to consider during the digest. MS_ProteomeDiscoverer_Maximum_Missed_Cleavage_Sites = 1001657, /// ProteomeDiscoverer:Mascot:Peptide CutOff Score: Minimum score in the IonScore column that each peptide must exceed in order to be reported. MS_ProteomeDiscoverer_Mascot_Peptide_CutOff_Score = 1001658, /// ProteomeDiscoverer:Precursor Mass Tolerance: Mass window for which precursor ions are considered to be the same species. MS_ProteomeDiscoverer_Precursor_Mass_Tolerance_OBSOLETE = 1001659, /// ProteomeDiscoverer:Mascot:Protein CutOff Score: Minimum protein score in the IonScore column that each protein must exceed in order to be reported. MS_ProteomeDiscoverer_Mascot_Protein_CutOff_Score = 1001660, /// ProteomeDiscoverer:Protein Database: Database to use in the search (configured on the Mascot server). MS_ProteomeDiscoverer_Protein_Database_OBSOLETE = 1001661, /// ProteomeDiscoverer:Mascot:Protein Relevance Factor: Specifies a factor that is used in calculating a threshold that determines whether a protein appears in the results report. MS_ProteomeDiscoverer_Mascot_Protein_Relevance_Factor = 1001662, /// ProteomeDiscoverer:Target FDR Relaxed: Specifies the relaxed target false discovery rate (FDR, 0.0 - 1.0) for peptide hits with moderate confidence. MS_ProteomeDiscoverer_Target_FDR_Relaxed = 1001663, /// ProteomeDiscoverer:Target FDR Strict: Specifies the strict target false discovery rate (FDR, 0.0 - 1.0) for peptide hits with high confidence. MS_ProteomeDiscoverer_Target_FDR_Strict = 1001664, /// ProteomeDiscoverer:Mascot:Taxonomy: Limits searches to entries from a particular species or group of species. MS_ProteomeDiscoverer_Mascot_Taxonomy_OBSOLETE = 1001665, /// ProteomeDiscoverer:Use Average Precursor Mass: Use average mass for the precursor. MS_ProteomeDiscoverer_Use_Average_Precursor_Mass_OBSOLETE = 1001666, /// Mascot:use MudPIT scoring: Determines whether to use MudPIT or normal scoring. MS_Mascot_use_MudPIT_scoring_OBSOLETE = 1001667, /// ProteomeDiscoverer:Absolute XCorr Threshold: Minimum cross-correlation threshold that determines whether peptides in an .srf file are imported. MS_ProteomeDiscoverer_Absolute_XCorr_Threshold = 1001668, /// ProteomeDiscoverer:SEQUEST:Calculate Probability Score: Determines whether to calculate a probability score for every peptide match. MS_ProteomeDiscoverer_SEQUEST_Calculate_Probability_Score = 1001669, /// ProteomeDiscoverer:SEQUEST:CTerminal Modification: Dynamic C-terminal modification that is used during the search. MS_ProteomeDiscoverer_SEQUEST_CTerminal_Modification = 1001670, /// ProteomeDiscoverer:SEQUEST:Fragment Ion Cutoff Percentage: Percentage of the theoretical ions that must be found in order for a peptide to be scored and retained. MS_ProteomeDiscoverer_SEQUEST_Fragment_Ion_Cutoff_Percentage = 1001671, /// ProteomeDiscoverer:SEQUEST:Max Identical Modifications Per Peptide: Maximum number of identical modifications that a single peptide can have. MS_ProteomeDiscoverer_SEQUEST_Max_Identical_Modifications_Per_Peptide = 1001672, /// ProteomeDiscoverer:Max Modifications Per Peptide: Maximum number of different modifications that a peptide can have, e.g. because of steric hindrance. MS_ProteomeDiscoverer_Max_Modifications_Per_Peptide = 1001673, /// ProteomeDiscoverer:SEQUEST:Maximum Peptides Considered: Maximum number of peptides that are searched and scored per spectrum. MS_ProteomeDiscoverer_SEQUEST_Maximum_Peptides_Considered = 1001674, /// ProteomeDiscoverer:Maximum Peptides Output: Maximum number of peptide matches reported per spectrum. MS_ProteomeDiscoverer_Maximum_Peptides_Output = 1001675, /// ProteomeDiscoverer:Maximum Protein References Per Peptide: Maximum number of proteins that a single identified peptide can be associated with during protein assembly. MS_ProteomeDiscoverer_Maximum_Protein_References_Per_Peptide = 1001676, /// ProteomeDiscoverer:SEQUEST:NTerminal Modification: Dynamic N-terminal modification that is used during the search. MS_ProteomeDiscoverer_SEQUEST_NTerminal_Modification = 1001677, /// ProteomeDiscoverer:Peptide CTerminus: Static modification for the C terminal of the peptide used during the search. MS_ProteomeDiscoverer_Peptide_CTerminus = 1001678, /// ProteomeDiscoverer:Peptide NTerminus: Static modification for the N terminal of the peptide used during the search. MS_ProteomeDiscoverer_Peptide_NTerminus = 1001679, /// ProteomeDiscoverer:SEQUEST:Peptide Relevance Factor: Specifies a factor to apply to the protein score. MS_ProteomeDiscoverer_SEQUEST_Peptide_Relevance_Factor = 1001680, /// ProteomeDiscoverer:Protein Relevance Threshold: Specifies a peptide threshold that determines whether the protein that it is a part of is scored and retained in the report. MS_ProteomeDiscoverer_Protein_Relevance_Threshold = 1001681, /// ProteomeDiscoverer:Search Against Decoy Database: Determines whether the Proteome Discoverer application searches against a decoy database. MS_ProteomeDiscoverer_Search_Against_Decoy_Database_OBSOLETE = 1001682, /// ProteomeDiscoverer:SEQUEST:Use Average Fragment Masses: Use average masses for the fragments. MS_ProteomeDiscoverer_SEQUEST_Use_Average_Fragment_Masses = 1001683, /// ProteomeDiscoverer:Use Neutral Loss a Ions: Determines whether a ions with neutral loss are used for spectrum matching. MS_ProteomeDiscoverer_Use_Neutral_Loss_a_Ions = 1001684, /// ProteomeDiscoverer:Use Neutral Loss b Ions: Determines whether b ions with neutral loss are used for spectrum matching. MS_ProteomeDiscoverer_Use_Neutral_Loss_b_Ions = 1001685, /// ProteomeDiscoverer:Use Neutral Loss y Ions: Determines whether y ions with neutral loss are used for spectrum matching. MS_ProteomeDiscoverer_Use_Neutral_Loss_y_Ions = 1001686, /// ProteomeDiscoverer:Use Neutral Loss z Ions: Determines whether z ions with neutral loss are used for spectrum matching. MS_ProteomeDiscoverer_Use_Neutral_Loss_z_Ions = 1001687, /// ProteomeDiscoverer:SEQUEST:Weight of a Ions: Uses a ions for spectrum matching with this relative factor. MS_ProteomeDiscoverer_SEQUEST_Weight_of_a_Ions = 1001688, /// ProteomeDiscoverer:SEQUEST:Weight of b Ions: Uses b ions for spectrum matching with this relative factor. MS_ProteomeDiscoverer_SEQUEST_Weight_of_b_Ions = 1001689, /// ProteomeDiscoverer:SEQUEST:Weight of c Ions: Uses c ions for spectrum matching with this relative factor. MS_ProteomeDiscoverer_SEQUEST_Weight_of_c_Ions = 1001690, /// ProteomeDiscoverer:SEQUEST:Weight of d Ions: Uses c ions for spectrum matching with this relative factor. MS_ProteomeDiscoverer_SEQUEST_Weight_of_d_Ions = 1001691, /// ProteomeDiscoverer:SEQUEST:Weight of v Ions: Uses c ions for spectrum matching with this relative factor. MS_ProteomeDiscoverer_SEQUEST_Weight_of_v_Ions = 1001692, /// ProteomeDiscoverer:SEQUEST:Weight of w Ions: Uses c ions for spectrum matching with this relative factor. MS_ProteomeDiscoverer_SEQUEST_Weight_of_w_Ions = 1001693, /// ProteomeDiscoverer:SEQUEST:Weight of x Ions: Uses x ions for spectrum matching with this relative factor. MS_ProteomeDiscoverer_SEQUEST_Weight_of_x_Ions = 1001694, /// ProteomeDiscoverer:SEQUEST:Weight of y Ions: Uses y ions for spectrum matching with this relative factor. MS_ProteomeDiscoverer_SEQUEST_Weight_of_y_Ions = 1001695, /// ProteomeDiscoverer:SEQUEST:Weight of z Ions: Uses z ions for spectrum matching with this relative factor. MS_ProteomeDiscoverer_SEQUEST_Weight_of_z_Ions = 1001696, /// ProteomeDiscoverer:ZCore:Protein Score Cutoff: Sets a minimum protein score that each protein must exceed in order to be reported. MS_ProteomeDiscoverer_ZCore_Protein_Score_Cutoff = 1001697, /// ProteomeDiscoverer:Reporter Ions Quantizer:Integration Method: Specifies which peak to select if more than one peak is found inside the integration window. MS_ProteomeDiscoverer_Reporter_Ions_Quantizer_Integration_Method = 1001698, /// ProteomeDiscoverer:Reporter Ions Quantizer:Integration Window Tolerance: Specifies the mass-to-charge window that enables one to look for the reporter peaks. MS_ProteomeDiscoverer_Reporter_Ions_Quantizer_Integration_Window_Tolerance = 1001699, /// ProteomeDiscoverer:Reporter Ions Quantizer:Quantitation Method: Quantitation method for isobarically labeled quantitation. MS_ProteomeDiscoverer_Reporter_Ions_Quantizer_Quantitation_Method = 1001700, /// ProteomeDiscoverer:Spectrum Exporter:Export Format: Format of the exported spectra (dta, mgf or mzData). MS_ProteomeDiscoverer_Spectrum_Exporter_Export_Format_OBSOLETE = 1001701, /// ProteomeDiscoverer:Spectrum Exporter:File name: Name of the output file that contains the exported data. MS_ProteomeDiscoverer_Spectrum_Exporter_File_name = 1001702, /// ProteomeDiscoverer:Search Modifications Only For Identified Proteins: Influences the modifications search. MS_ProteomeDiscoverer_Search_Modifications_Only_For_Identified_Proteins = 1001703, /// ProteomeDiscoverer:SEQUEST:Std High Confidence XCorr Charge1: Standard high confidence XCorr parameter for charge = 1. MS_ProteomeDiscoverer_SEQUEST_Std_High_Confidence_XCorr_Charge1 = 1001704, /// ProteomeDiscoverer:SEQUEST:Std High Confidence XCorr Charge2: Standard high confidence XCorr parameter for charge = 2. MS_ProteomeDiscoverer_SEQUEST_Std_High_Confidence_XCorr_Charge2 = 1001705, /// ProteomeDiscoverer:SEQUEST:Std High Confidence XCorr Charge3: Standard high confidence XCorr parameter for charge = 3. MS_ProteomeDiscoverer_SEQUEST_Std_High_Confidence_XCorr_Charge3 = 1001706, /// ProteomeDiscoverer:SEQUEST:Std High Confidence XCorr Charge4: Standard high confidence XCorr parameter for charge >= 4. MS_ProteomeDiscoverer_SEQUEST_Std_High_Confidence_XCorr_Charge4 = 1001707, /// ProteomeDiscoverer:SEQUEST:Std Medium Confidence XCorr Charge1: Standard medium confidence XCorr parameter for charge = 1. MS_ProteomeDiscoverer_SEQUEST_Std_Medium_Confidence_XCorr_Charge1 = 1001708, /// ProteomeDiscoverer:SEQUEST:Std Medium Confidence XCorr Charge2: Standard medium confidence XCorr parameter for charge = 2. MS_ProteomeDiscoverer_SEQUEST_Std_Medium_Confidence_XCorr_Charge2 = 1001709, /// ProteomeDiscoverer:SEQUEST:Std Medium Confidence XCorr Charge3: Standard medium confidence XCorr parameter for charge = 3. MS_ProteomeDiscoverer_SEQUEST_Std_Medium_Confidence_XCorr_Charge3 = 1001710, /// ProteomeDiscoverer:SEQUEST:Std Medium Confidence XCorr Charge4: Standard medium confidence XCorr parameter for charge >= 4. MS_ProteomeDiscoverer_SEQUEST_Std_Medium_Confidence_XCorr_Charge4 = 1001711, /// ProteomeDiscoverer:SEQUEST:FT High Confidence XCorr Charge1: FT high confidence XCorr parameter for charge = 1. MS_ProteomeDiscoverer_SEQUEST_FT_High_Confidence_XCorr_Charge1 = 1001712, /// ProteomeDiscoverer:SEQUEST:FT High Confidence XCorr Charge2: FT high confidence XCorr parameter for charge = 2. MS_ProteomeDiscoverer_SEQUEST_FT_High_Confidence_XCorr_Charge2 = 1001713, /// ProteomeDiscoverer:SEQUEST:FT High Confidence XCorr Charge3: FT high confidence XCorr parameter for charge = 3. MS_ProteomeDiscoverer_SEQUEST_FT_High_Confidence_XCorr_Charge3 = 1001714, /// ProteomeDiscoverer:SEQUEST:FT High Confidence XCorr Charge4: FT high confidence XCorr parameter for charge >= 4. MS_ProteomeDiscoverer_SEQUEST_FT_High_Confidence_XCorr_Charge4 = 1001715, /// ProteomeDiscoverer:SEQUEST:FT Medium Confidence XCorr Charge1: FT medium confidence XCorr parameter for charge = 1. MS_ProteomeDiscoverer_SEQUEST_FT_Medium_Confidence_XCorr_Charge1 = 1001716, /// ProteomeDiscoverer:SEQUEST:FT Medium Confidence XCorr Charge2: FT medium confidence XCorr parameter for charge = 2. MS_ProteomeDiscoverer_SEQUEST_FT_Medium_Confidence_XCorr_Charge2 = 1001717, /// ProteomeDiscoverer:SEQUEST:FT Medium Confidence XCorr Charge3: FT medium confidence XCorr parameter for charge = 3. MS_ProteomeDiscoverer_SEQUEST_FT_Medium_Confidence_XCorr_Charge3 = 1001718, /// ProteomeDiscoverer:SEQUEST:FT Medium Confidence XCorr Charge4: FT medium confidence XCorr parameter for charge >= 4. MS_ProteomeDiscoverer_SEQUEST_FT_Medium_Confidence_XCorr_Charge4 = 1001719, /// ProteomeDiscoverer:1. Dynamic Modification: ProteomeDiscoverer's 1st dynamic post-translational modification (PTM) input parameter. MS_ProteomeDiscoverer_1__Dynamic_Modification_OBSOLETE = 1001720, /// ProteomeDiscoverer:2. Dynamic Modification: ProteomeDiscoverer's 2nd dynamic post-translational modification (PTM) input parameter. MS_ProteomeDiscoverer_2__Dynamic_Modification_OBSOLETE = 1001721, /// ProteomeDiscoverer:3. Dynamic Modification: ProteomeDiscoverer's 3rd dynamic post-translational modification (PTM) input parameter. MS_ProteomeDiscoverer_3__Dynamic_Modification_OBSOLETE = 1001722, /// ProteomeDiscoverer:4. Dynamic Modification: ProteomeDiscoverer's 4th dynamic post-translational modification (PTM) input parameter. MS_ProteomeDiscoverer_4__Dynamic_Modification_OBSOLETE = 1001723, /// ProteomeDiscoverer:Static Modification for X: Static Modification for X. MS_ProteomeDiscoverer_Static_Modification_for_X = 1001724, /// ProteomeDiscoverer:Initial minimal peptide probability: Minimal initial peptide probability to contribute to analysis. MS_ProteomeDiscoverer_Initial_minimal_peptide_probability = 1001725, /// ProteomeDiscoverer:Minimal peptide probability: Minimum adjusted peptide probability contributing to protein probability. MS_ProteomeDiscoverer_Minimal_peptide_probability = 1001726, /// ProteomeDiscoverer:Minimal peptide weight: Minimum peptide weight contributing to protein probability. MS_ProteomeDiscoverer_Minimal_peptide_weight = 1001727, /// ProteomeDiscoverer:Number of input1 spectra: Number of spectra from 1+ precursor ions. MS_ProteomeDiscoverer_Number_of_input1_spectra = 1001728, /// ProteomeDiscoverer:Number of input2 spectra: Number of spectra from 2+ precursor ions. MS_ProteomeDiscoverer_Number_of_input2_spectra = 1001729, /// ProteomeDiscoverer:Number of input3 spectra: Number of spectra from 3+ precursor ions. MS_ProteomeDiscoverer_Number_of_input3_spectra = 1001730, /// ProteomeDiscoverer:Number of input4 spectra: Number of spectra from 4+ precursor ions. MS_ProteomeDiscoverer_Number_of_input4_spectra = 1001731, /// ProteomeDiscoverer:Number of input5 spectra: Number of spectra from 5+ precursor ions. MS_ProteomeDiscoverer_Number_of_input5_spectra = 1001732, /// ProteomeDiscoverer:Number of predicted correct proteins: Total number of predicted correct protein ids (sum of probabilities). MS_ProteomeDiscoverer_Number_of_predicted_correct_proteins = 1001733, /// ProteomeDiscoverer:Organism: Sample organism (used for annotation purposes). MS_ProteomeDiscoverer_Organism_OBSOLETE = 1001734, /// ProteomeDiscoverer:Reference Database: Full path database name. MS_ProteomeDiscoverer_Reference_Database_OBSOLETE = 1001735, /// ProteomeDiscoverer:Residue substitution list: Residues considered equivalent when comparing peptides. MS_ProteomeDiscoverer_Residue_substitution_list = 1001736, /// ProteomeDiscoverer:Source file extension: File type (if not pepXML). MS_ProteomeDiscoverer_Source_file_extension_OBSOLETE = 1001737, /// ProteomeDiscoverer:Source Files: Input pepXML files. MS_ProteomeDiscoverer_Source_Files_OBSOLETE = 1001738, /// ProteomeDiscoverer:Source Files old: Input pepXML files (old). MS_ProteomeDiscoverer_Source_Files_old_OBSOLETE = 1001739, /// ProteomeDiscoverer:WinCyg reference database: Windows full path for database. MS_ProteomeDiscoverer_WinCyg_reference_database = 1001740, /// ProteomeDiscoverer:WinCyg source files: Windows pepXML file names. MS_ProteomeDiscoverer_WinCyg_source_files = 1001741, /// LTQ Orbitrap Velos: Finnigan LTQ Orbitrap Velos MS. MS_LTQ_Orbitrap_Velos = 1001742, /// ProteomeDiscoverer:Mascot:Weight of A Ions: Determines if to use A ions for spectrum matching. MS_ProteomeDiscoverer_Mascot_Weight_of_A_Ions = 1001743, /// ProteomeDiscoverer:Mascot:Weight of B Ions: Determines if to use B ions for spectrum matching. MS_ProteomeDiscoverer_Mascot_Weight_of_B_Ions = 1001744, /// ProteomeDiscoverer:Mascot:Weight of C Ions: Determines if to use C ions for spectrum matching. MS_ProteomeDiscoverer_Mascot_Weight_of_C_Ions = 1001745, /// ProteomeDiscoverer:Mascot:Weight of D Ions: Determines if to use D ions for spectrum matching. MS_ProteomeDiscoverer_Mascot_Weight_of_D_Ions = 1001746, /// ProteomeDiscoverer:Mascot:Weight of V Ions: Determines if to use V ions for spectrum matching. MS_ProteomeDiscoverer_Mascot_Weight_of_V_Ions = 1001747, /// ProteomeDiscoverer:Mascot:Weight of W Ions: Determines if to use W ions for spectrum matching. MS_ProteomeDiscoverer_Mascot_Weight_of_W_Ions = 1001748, /// ProteomeDiscoverer:Mascot:Weight of X Ions: Determines if to use X ions for spectrum matching. MS_ProteomeDiscoverer_Mascot_Weight_of_X_Ions = 1001749, /// ProteomeDiscoverer:Mascot:Weight of Y Ions: Determines if to use Y ions for spectrum matching. MS_ProteomeDiscoverer_Mascot_Weight_of_Y_Ions = 1001750, /// ProteomeDiscoverer:Mascot:Weight of Z Ions: Determines if to use z ions for spectrum matching. MS_ProteomeDiscoverer_Mascot_Weight_of_Z_Ions = 1001751, /// ProteomeDiscoverer:Spectrum Selector:Use New Precursor Reevaluation: Determines if to use precursor reevaluation. MS_ProteomeDiscoverer_Spectrum_Selector_Use_New_Precursor_Reevaluation = 1001752, /// ProteomeDiscoverer:Spectrum Selector:SN Threshold FTonly: Signal-to-Noise ratio below which peaks are removed (in FT mode only). MS_ProteomeDiscoverer_Spectrum_Selector_SN_Threshold_FTonly = 1001753, /// ProteomeDiscoverer:Mascot:Please Do not Touch this: Unknown Mascot parameter which ProteomeDiscoverer uses for mascot searches. MS_ProteomeDiscoverer_Mascot_Please_Do_not_Touch_this = 1001754, /// contact phone number: Phone number of the contact person or organization. MS_contact_phone_number = 1001755, /// contact fax number: Fax number for the contact person or organization. MS_contact_fax_number = 1001756, /// contact toll-free phone number: Toll-free phone number of the contact person or organization. MS_contact_toll_free_phone_number = 1001757, /// Mascot:SigThresholdType: Significance threshold type used in Mascot reporting (either 'identity' or 'homology'). MS_Mascot_SigThresholdType = 1001758, /// Mascot:ProteinGrouping: Strategy used by Mascot to group proteins with same peptide matches (one of 'none', 'Occam's razor' or 'family clustering'). MS_Mascot_ProteinGrouping = 1001759, /// Percolator:features: List of Percolator features that were used in processing the peptide matches. Typical Percolator features are 'retentionTime', 'dM', 'mScore', 'lgDScore', 'mrCalc', 'charge' and 'dMppm'. MS_Percolator_features = 1001760, /// ACQUITY UPLC: Waters LC-system ACQUITY UPLC. MS_ACQUITY_UPLC = 1001761, /// ACQUITY UPLC H-Class: Waters LC-system ACQUITY UPLC H-Class. MS_ACQUITY_UPLC_H_Class = 1001762, /// ACQUITY UPLC H-Class Bio: Waters LC-system ACQUITY UPLC H-Class Bio. MS_ACQUITY_UPLC_H_Class_Bio = 1001763, /// ACQUITY UPLC I-Class: Waters LC-system ACQUITY UPLC I-Class. MS_ACQUITY_UPLC_I_Class = 1001764, /// ACQUITY UPLC Systems with 2D Technology: Waters LC-system ACQUITY UPLC Systems with 2D Technology. MS_ACQUITY_UPLC_Systems_with_2D_Technology = 1001765, /// nanoACQUITY UPLC: Waters LC-system nanoACQUITY UPLC. MS_nanoACQUITY_UPLC = 1001766, /// nanoACQUITY UPLC System with Technology: Waters LC-system nanoACQUITY UPLC System with Technology. MS_nanoACQUITY_UPLC_System_with_Technology = 1001767, /// nanoACQUITY UPLC with HDX Technology: Waters LC-system nanoACQUITY UPLC with HDX Technology. MS_nanoACQUITY_UPLC_with_HDX_Technology = 1001768, /// TRIZAIC UPLC nanoTile: Waters LC-system TRIZAIC UPLC nanoTile. MS_TRIZAIC_UPLC_nanoTile = 1001769, /// GCT Premier: Waters oa-ToF based GCT Premier. MS_GCT_Premier = 1001770, /// MALDI Synapt G2 HDMS: Waters oa-ToF based MALDI Synapt G2 HDMS. MS_MALDI_Synapt_G2_HDMS = 1001771, /// MALDI Synapt G2 MS: Waters oa-ToF based MALDI Synapt G2 MS. MS_MALDI_Synapt_G2_MS = 1001772, /// MALDI Synapt G2-S HDMS: Waters oa-ToF based MALDI Synapt G2 MS. MS_MALDI_Synapt_G2_S_HDMS = 1001773, /// MALDI Synapt G2-S MS: Waters oa-ToF based MALDI Synapt G2-S MS. MS_MALDI_Synapt_G2_S_MS = 1001774, /// MALDI Synapt HDMS: Waters oa-ToF based MALDI Synapt HDMS. MS_MALDI_Synapt_HDMS = 1001775, /// MALDI Synapt MS: Waters oa-ToF based MALDI Synapt MS. MS_MALDI_Synapt_MS = 1001776, /// Synapt G2 HDMS: Waters oa-ToF based Synapt G2 HDMS. MS_Synapt_G2_HDMS = 1001777, /// Synapt G2 MS: Waters oa-ToF based Synapt G2 MS. MS_Synapt_G2_MS = 1001778, /// Synapt G2-S HDMS: Waters oa-ToF based Synapt G2-S HDMS. MS_Synapt_G2_S_HDMS = 1001779, /// Synapt G2-S MS: Waters oa-ToF based Synapt G2-S MS. MS_Synapt_G2_S_MS = 1001780, /// Synapt HDMS: Waters oa-ToF based Synapt HDMS. MS_Synapt_HDMS = 1001781, /// Synapt MS: Waters oa-ToF based Synapt MS. MS_Synapt_MS = 1001782, /// Xevo G2 Q-Tof: Waters oa-ToF based Xevo G2 Q-Tof. MS_Xevo_G2_Q_Tof = 1001783, /// Xevo G2 Tof: Waters oa-ToF based Xevo G2 Tof. MS_Xevo_G2_Tof = 1001784, /// Xevo Q-Tof: Waters oa-ToF based Xevo Q-Tof. MS_Xevo_Q_Tof = 1001785, /// 3100: Waters quadrupole based 3100. MS_3100 = 1001786, /// Acquity SQD: Waters quadrupole based Acquity SQD. MS_Acquity_SQD = 1001787, /// Acquity TQD: Waters quadrupole based Acquity TQD. MS_Acquity_TQD = 1001788, /// Quattro micro GC: Waters quadrupole based Quattro micro GC. MS_Quattro_micro_GC = 1001789, /// Xevo TQ MS: Waters quadrupole based Xevo TQ MS. MS_Xevo_TQ_MS = 1001790, /// Xevo TQD: Waters quadrupole based Xevo TQD. MS_Xevo_TQD = 1001791, /// Xevo TQ-S: Waters quadrupole based Xevo TQ-S. MS_Xevo_TQ_S = 1001792, /// Mascot:PreferredTaxonomy: NCBI TaxID taxonomy ID to prefer when two or more proteins match the same set of peptides or when protein entry in database represents multiple sequences. MS_Mascot_PreferredTaxonomy = 1001793, /// Empower: Waters Empower software for liquid chromatography and mass spectrometry acquisition. MS_Empower = 1001795, /// Unify: Waters Unify software for liquid chromatography and mass spectrometry acquisition. MS_Unify = 1001796, /// travelling wave ion mobility mass spectrometer: An ion mobility mass spectrometry technique based on the superimposition of travelling voltage waves on a radially-confining RF voltage in a gas-filled, stacked-ring ion guide. MS_travelling_wave_ion_mobility_mass_spectrometer_OBSOLETE = 1001797, /// TWIMS (travelling wave ion mobility mass spectrometer): An ion mobility mass spectrometry technique based on the superimposition of travelling voltage waves on a radially-confining RF voltage in a gas-filled, stacked-ring ion guide. MS_TWIMS_OBSOLETE = MS_travelling_wave_ion_mobility_mass_spectrometer_OBSOLETE, /// LECO software: LECO software for data acquisition and analysis. MS_LECO_software = 1001798, /// ChromaTOF software: Software for acquisition, processing and analysis of data for LECO instruments. MS_ChromaTOF_software = 1001799, /// LECO instrument model: LECO instrument model. MS_LECO_instrument_model = 1001800, /// Pegasus HRT: LECO high resolution time-of-flight GC mass spectrometer. MS_Pegasus_HRT = 1001801, /// Citius HRT: LECO high resolution time-of-flight LC mass spectrometer. MS_Citius_HRT = 1001802, /// Pegasus: LECO GC time-of-flight mass spectrometer. MS_Pegasus = 1001803, /// TruTOF: LECO bench-top GC time-of-flight mass spectrometer. MS_TruTOF = 1001804, /// quantification datatype: The data type of the value reported in a QuantLayer for a feature, peptide, protein, protein group. MS_quantification_datatype = 1001805, /// quantification object attribute: Attributes describing the details of an object relevant for reporting quantification workflows or values. MS_quantification_object_attribute = 1001806, /// study variable attribute: Attribute describing a study variable. MS_study_variable_attribute = 1001807, /// technical replicate: The study variable is 'technical replicate'. The string value denotes the category of technical replicate, e.g. 'run generated from same sample'. MS_technical_replicate = 1001808, /// biological replicate: The study variable is 'biological replicate'. This means, the run was generated from another individual or sample. MS_biological_replicate = 1001809, /// experimental condition 'case': The experimental condition is 'case' in contrast to 'control'. MS_experimental_condition__case_ = 1001810, /// experimental condition 'control': The experimental condition is 'control' in contrast to 'case'. MS_experimental_condition__control_ = 1001811, /// experimental condition 'disease': The experimental condition is 'disease' in contrast to 'healthy'. MS_experimental_condition__disease_ = 1001812, /// experimental condition 'healthy': The experimental condition is 'healthy' in contrast to 'disease'. MS_experimental_condition__healthy_ = 1001813, /// generic experimental condition: The experimental condition is given in the value of this term. MS_generic_experimental_condition = 1001814, /// time series, time point X: The experimental design followed a time series design. The time point of this run is given in the value of this term. MS_time_series__time_point_X = 1001815, /// dilution series, concentration X: The experimental design followed a dilution series design. The concentration of this run is given in the value of this term. MS_dilution_series__concentration_X = 1001816, /// raw file attribute: Attribute describing a raw file. MS_raw_file_attribute = 1001817, /// one sample run: The raw file contains the run of one sample (e.g. spectral counting, LC-MS label-free). MS_one_sample_run = 1001818, /// two sample run: The raw file contains the run of two samples (e.g. SILAC, metabolic labelling). MS_two_sample_run = 1001819, /// three sample run: The raw file contains the run of three samples (e.g. 3-plex SILAC). MS_three_sample_run = 1001820, /// four sample run: The raw file contains the run of four samples (e.g. 4-plex iTraq). MS_four_sample_run = 1001821, /// eight sample run: The raw file contains the run of eight samples (e.g. 8-plex iTraq). MS_eight_sample_run = 1001822, /// raw files group attribute: Attribute describing, how raw files build a raw file group. MS_raw_files_group_attribute = 1001823, /// merge of runs of 1D gel bands: Attribute describing, how raw files build a raw file group. MS_merge_of_runs_of_1D_gel_bands = 1001824, /// feature list attribute: Attribute describing a feature list. MS_feature_list_attribute = 1001825, /// mass trace reporting: rectangles: The mass trace of the features of this feature list specifies rectangles. Each mass trace has the syntax (RT_start,MZ_start,RT_end,MZ_end), i.e. opposite corners are given. MS_mass_trace_reporting__rectangles = 1001826, /// mass trace reporting: polygons: The mass trace of the features of this feature list specifies polygons. Each mass trace has the syntax (RT_1, MZ_1, RT_2, MZ_2, ... , RT_i, MZ_i, ... , RT_n, MZ_n), where the line (RT_n, MZ_n)->(RT_1, MZ_1) is implicit. MS_mass_trace_reporting__polygons = 1001827, /// feature attribute: Attribute describing a feature. MS_feature_attribute = 1001828, /// SRM transition ID: Identifier for an SRM transition in an external document describing additional information about the transition. MS_SRM_transition_ID = 1001829, /// Progenesis LC-MS: Software from Nonlinear Dynamics for LC-MS label-free workflow. MS_Progenesis_LC_MS = 1001830, /// SILACAnalyzer: Software for SILAC workflow. MS_SILACAnalyzer = 1001831, /// quantitation software comment or customizations: Quantitation software comment or any customizations to the default setup of the software. MS_quantitation_software_comment_or_customizations = 1001832, /// quantitation analysis summary: The overall workflow of this quantitation report. MS_quantitation_analysis_summary = 1001833, /// LC-MS label-free quantitation analysis: LC-MS label-free workflow (RT m/z map). MS_LC_MS_label_free_quantitation_analysis = 1001834, /// SILAC quantitation analysis: SILAC workflow (heavy, light, and sometimes medium peak). MS_SILAC_quantitation_analysis = 1001835, /// spectral counting quantitation analysis: Spectral counting workflow (number of identified MS2 spectra as approximation of peptide / protein quant). MS_spectral_counting_quantitation_analysis = 1001836, /// iTRAQ quantitation analysis: Quantification analysis using the SCIEX iTRAQ isobaric labelling workflow, wherein 2-8 reporter ions are measured in MS2 spectra near 114 m/z. MS_iTRAQ_quantitation_analysis = 1001837, /// SRM quantitation analysis: Selected Reaction Monitoring workflow (XIC quantitation of precursor / fragment mass pair). MS_SRM_quantitation_analysis = 1001838, /// metabolic labeling 14N / 15N quantitation analysis: Metabolic labeling workflow (heavy and light versions of peptides, depending on number of nitrogens). MS_metabolic_labeling_14N___15N_quantitation_analysis = 1001839, /// LC-MS feature intensity: Maximum peak intensity of the LC-MS feature. MS_LC_MS_feature_intensity = 1001840, /// LC-MS feature volume: Real (intensity times area) volume of the LC-MS feature. MS_LC_MS_feature_volume = 1001841, /// peptide PSM count: The number of MS2 spectra identified for this peptide in spectral counting. MS_peptide_PSM_count = 1001842, /// MS1 feature maximum intensity: Maximum intensity of MS1 feature. MS_MS1_feature_maximum_intensity = 1001843, /// MS1 feature area: Area of MS1 feature. MS_MS1_feature_area = 1001844, /// peak area: Area of MS1 peak (e.g. SILAC, 15N). MS_peak_area_OBSOLETE = 1001845, /// isotopic pattern area: Area of all peaks belonging to the isotopic pattern of light or heavy peak (e.g. 15N). MS_isotopic_pattern_area = 1001846, /// reporter ion intensity: Intensity of MS2 reporter ion (e.g. iTraq). MS_reporter_ion_intensity = 1001847, /// simple ratio of two values: Simple ratio of two values (enumerator and denominator). MS_simple_ratio_of_two_values = 1001848, /// sum of MatchedFeature values: Peptide quantification value calculated as sum of MatchedFeature quantification values. MS_sum_of_MatchedFeature_values_OBSOLETE = 1001849, /// normalized peptide value: Normalized peptide value. MS_normalized_peptide_value = 1001850, /// protein value: sum of peptide values: Protein quantification value calculated as sum of peptide values. MS_protein_value__sum_of_peptide_values = 1001851, /// normalized protein value: Normalized protein value. MS_normalized_protein_value = 1001852, /// max fold change: Global datatype: Maximum of all pair-wise fold changes of group means (e.g. Progenesis). MS_max_fold_change = 1001853, /// ANOVA p-value: Global datatype: p-value of ANOVA of group means (e.g. Progenesis). MS_ANOVA_p_value = 1001854, /// t-test p-value: P-value of t-Test of two groups. MS_t_test_p_value = 1001855, /// reporter ion raw value: Intensity (or area) of MS2 reporter ion (e.g. iTraq). MS_reporter_ion_raw_value = 1001856, /// reporter ion normalized value: Normalized value of MS2 reporter ion (e.g. iTraq). MS_reporter_ion_normalized_value = 1001857, /// XIC area: Area of the extracted ion chromatogram (e.g. of a transition in SRM). MS_XIC_area = 1001858, /// normalized XIC area: Normalized area of the extracted ion chromatogram (e.g. of a transition in SRM). MS_normalized_XIC_area = 1001859, /// protein value: mean of peptide ratios: Protein quantification value calculated as mean of peptide ratios. MS_protein_value__mean_of_peptide_ratios = 1001860, /// quantification data processing: Terms used to describe types of quantification data processing. MS_quantification_data_processing = 1001861, /// normalization to mean of sum of all proteins: Normalization of protein values to the mean of the sum of all protein PSM counts (e.g. spectral counting). MS_normalization_to_mean_of_sum_of_all_proteins = 1001862, /// quantile normalization, proteins: Normalization of protein values to approach the same distribution. MS_quantile_normalization__proteins = 1001863, /// quantile normalization, peptides: Normalization of peptide values to approach the same distribution. MS_quantile_normalization__peptides = 1001864, /// Progenesis automatic alignment: Automatic RT alignment of Progenesis software. MS_Progenesis_automatic_alignment = 1001865, /// Progenesis manual alignment: RT alignment of Progenesis software using automatic and manual vectors. MS_Progenesis_manual_alignment = 1001866, /// Progenesis normalization: Normalization as performed by Progenesis LC-MS. MS_Progenesis_normalization = 1001867, /// distinct peptide-level q-value: Estimation of the q-value for distinct peptides once redundant identifications of the same peptide have been removed (id est multiple PSMs, possibly with different mass modifications, mapping to the same sequence have been collapsed to one entry). MS_distinct_peptide_level_q_value = 1001868, /// protein-level q-value: Estimation of the q-value for proteins. MS_protein_level_q_value = 1001869, /// distinct peptide-level p-value: Estimation of the p-value for distinct peptides once redundant identifications of the same peptide have been removed (id est multiple PSMs have been collapsed to one entry). MS_distinct_peptide_level_p_value = 1001870, /// protein-level p-value: Estimation of the p-value for proteins. MS_protein_level_p_value = 1001871, /// distinct peptide-level e-value: Estimation of the e-value for distinct peptides once redundant identifications of the same peptide have been removed (id est multiple PSMs have been collapsed to one entry). MS_distinct_peptide_level_e_value = 1001872, /// protein-level e-value: Estimation of the e-value for proteins. MS_protein_level_e_value = 1001873, /// FDRScore: A smoothing of the distribution of q-values calculated for PSMs from individual search engines, such that ordering of result quality is maintained and all FDRScore values are guaranteed to have a value > 0. MS_FDRScore_OBSOLETE = 1001874, /// modification motif: The regular expression describing the sequence motif for a modification. MS_modification_motif = 1001875, /// modification probability: The a priori probability of a modification. MS_modification_probability = 1001876, /// ChromaTOF HRT software: Software for acquisition, processing and analysis of data for LECO instruments. MS_ChromaTOF_HRT_software = 1001877, /// MALDI Solutions Microbial Identification: Shimadzu Biotech software for data acquisition, processing, and analysis. MS_MALDI_Solutions_Microbial_Identification = 1001878, /// offset voltage: The potential difference between two adjacent interface voltages affecting in-source collision induced dissociation. MS_offset_voltage = 1001879, /// in-source collision-induced dissociation: The dissociation of an ion as a result of collisional excitation during ion transfer from an atmospheric pressure ion source and the mass spectrometer vacuum. MS_in_source_collision_induced_dissociation = 1001880, /// mz5 format: mz5 file format, modelled after mzML. MS_mz5_format = 1001881, /// transition validation attribute: Attributes of the quality of a transition that affect its selection as appropriate. MS_transition_validation_attribute = 1001882, /// coefficient of variation: Variation of a set of signal measurements calculated as the standard deviation relative to the mean. MS_coefficient_of_variation = 1001883, /// signal-to-noise ratio: Unitless number providing the ratio of the total measured intensity of a signal relative to the estimated noise level for that signal. MS_signal_to_noise_ratio = 1001884, /// command-line parameters: Parameters string passed to a command-line interface software application, omitting the executable name. MS_command_line_parameters = 1001885, /// SQID: Software for data analysis of peptides and proteins. MS_SQID = 1001886, /// SQID:score: The SQID result 'Score'. MS_SQID_score = 1001887, /// SQID:deltaScore: The SQID result 'deltaScore'. MS_SQID_deltaScore = 1001888, /// SQID:protein score: The SQID result 'protein score'. MS_SQID_protein_score = 1001889, /// Progenesis:protein normalised abundance: The data type normalised abundance for proteins produced by Progenesis LC-MS. MS_Progenesis_protein_normalised_abundance = 1001890, /// Progenesis:peptide normalised abundance: The data type normalised abundance for peptides produced by Progenesis LC-MS. MS_Progenesis_peptide_normalised_abundance = 1001891, /// Progenesis:protein raw abundance: The data type raw abundance for proteins produced by Progenesis LC-MS. MS_Progenesis_protein_raw_abundance = 1001892, /// Progenesis:peptide raw abundance: The data type raw abundance for peptide produced by Progenesis LC-MS. MS_Progenesis_peptide_raw_abundance = 1001893, /// Progenesis:confidence score: The data type confidence score produced by Progenesis LC-MS. MS_Progenesis_confidence_score = 1001894, /// Progenesis:peptide count: The data type peptide count produced by Progenesis LC-MS. MS_Progenesis_peptide_count = 1001895, /// Progenesis:feature intensity: The data type feature intensity produced by Progenesis LC-MS. MS_Progenesis_feature_intensity = 1001896, /// MaxQuant:peptide counts (unique): The data type peptide counts (unique) produced by MaxQuant. MS_MaxQuant_peptide_counts__unique_ = 1001897, /// MaxQuant:peptide counts (all): The data type peptide counts (all) produced by MaxQuant. MS_MaxQuant_peptide_counts__all_ = 1001898, /// MaxQuant:peptide counts (razor+unique): The data type peptide counts (razor+unique) produced by MaxQuant. MS_MaxQuant_peptide_counts__razor_unique_ = 1001899, /// MaxQuant:sequence length: The data type sequence length produced by MaxQuant. MS_MaxQuant_sequence_length = 1001900, /// MaxQuant:PEP: The data type PEP (posterior error probability) produced by MaxQuant. MS_MaxQuant_PEP = 1001901, /// MaxQuant:LFQ intensity: The data type LFQ intensity produced by MaxQuant. MS_MaxQuant_LFQ_intensity = 1001902, /// MaxQuant:feature intensity: The data type feature intensity produced by MaxQuant. MS_MaxQuant_feature_intensity = 1001903, /// MaxQuant:MS/MS count: The data type MS2 count produced by MaxQuant. MS_MaxQuant_MS_MS_count = 1001904, /// emPAI value: The emPAI value of protein abundance, produced from the emPAI algorithm. MS_emPAI_value = 1001905, /// APEX value: The APEX value of protein abundance, produced from the APEX software. MS_APEX_value = 1001906, /// retention time window width: The full width of a retention time window for a chromatographic peak. MS_retention_time_window_width = 1001907, /// ISQ: Thermo Scientific ISQ single quadrupole MS with the ExtractraBrite source. MS_ISQ = 1001908, /// Velos Plus: Thermo Scientific second generation Velos. MS_Velos_Plus = 1001909, /// LTQ Orbitrap Elite: Thermo Scientific second generation Velos and Orbitrap. MS_LTQ_Orbitrap_Elite = 1001910, /// Q Exactive: Thermo Scientific Q Exactive. MS_Q_Exactive = 1001911, /// PinPoint: Thermo Scientific PinPoint SRM analysis software. MS_PinPoint = 1001912, /// S-lens voltage: Potential difference setting of the Thermo Scientific S-lens stacked-ring ion guide in volts. MS_S_lens_voltage = 1001913, /// pymzML: Python module to interface mzML Data. MS_pymzML = 1001914, /// leukocyte elastase: Enzyme leukocyte elastase (EC 3.4.21.37). MS_leukocyte_elastase = 1001915, /// proline endopeptidase: Enzyme proline endopeptidase (EC 3.4.21.26). MS_proline_endopeptidase = 1001916, /// glutamyl endopeptidase: Enzyme glutamyl endopeptidase (EC 3.4.21.19). MS_glutamyl_endopeptidase = 1001917, /// staphylococcal protease (glutamyl endopeptidase): Enzyme glutamyl endopeptidase (EC 3.4.21.19). MS_staphylococcal_protease = MS_glutamyl_endopeptidase, /// Glu-C (glutamyl endopeptidase): Enzyme glutamyl endopeptidase (EC 3.4.21.19). MS_Glu_C = MS_glutamyl_endopeptidase, /// 2-iodobenzoate: Chemical iodobenzoate. Cleaves after W. MS_2_iodobenzoate = 1001918, /// ProteomeXchange accession number: Main identifier of a ProteomeXchange dataset. MS_ProteomeXchange_accession_number = 1001919, /// ProteomeXchange accession number version number: Version number of a ProteomeXchange accession number. MS_ProteomeXchange_accession_number_version_number = 1001921, /// Digital Object Identifier (DOI): DOI unique identifier of a publication. MS_Digital_Object_Identifier__DOI_ = 1001922, /// doi (Digital Object Identifier (DOI)): DOI unique identifier of a publication. MS_doi = MS_Digital_Object_Identifier__DOI_, /// external reference keyword: Free text attribute that can enrich the information about an entity. MS_external_reference_keyword = 1001923, /// journal article keyword: Keyword present in a scientific publication. MS_journal_article_keyword = 1001924, /// submitter keyword: Keyword assigned by the data submitter. MS_submitter_keyword = 1001925, /// curator keyword: Keyword assigned by a data curator. MS_curator_keyword = 1001926, /// Tranche file hash: Hash assigned by the Tranche resource to an individual file. MS_Tranche_file_hash = 1001927, /// Tranche project hash: Hash assigned by the Tranche resource to a whole project. MS_Tranche_project_hash = 1001928, /// PRIDE experiment URI: URI that allows the access to one experiment in the PRIDE database. MS_PRIDE_experiment_URI = 1001929, /// PRIDE project URI: URI that allows the access to one project in the PRIDE database. MS_PRIDE_project_URI = 1001930, /// source interface: The source interface. MS_source_interface = 1001931, /// source interface model: The source interface model. MS_source_interface_model = 1001932, /// source sprayer: The source sprayer. MS_source_sprayer = 1001933, /// source sprayer type: The source sprayer type. MS_source_sprayer_type = 1001934, /// source sprayer manufacturer: The source sprayer manufacturer. MS_source_sprayer_manufacturer = 1001935, /// source sprayer model: The source sprayer model. MS_source_sprayer_model = 1001936, /// sample plate: Plate where the sample solution is spotted in a MALDI or similar instrument. MS_sample_plate = 1001937, /// sample plate type: The sample plate type. MS_sample_plate_type = 1001938, /// stainless steel plate: Stainless steel plate. MS_stainless_steel_plate = 1001939, /// coated glass plate: Coated glass plate. MS_coated_glass_plate = 1001940, /// electrospray supply type: Whether the sprayer is fed or is loaded with sample once. MS_electrospray_supply_type = 1001941, /// static supply electrospray: The sprayer is loaded with sample once. MS_static_supply_electrospray = 1001942, /// fed supply electrospray: The sprayer is continuously fed with sample. MS_fed_supply_electrospray = 1001943, /// Collision cell exit potential: Potential difference between Q2 and Q3 in a triple quadrupole instrument in volts. MS_Collision_cell_exit_potential = 1001944, /// CXP (Collision cell exit potential): Potential difference between Q2 and Q3 in a triple quadrupole instrument in volts. MS_CXP = MS_Collision_cell_exit_potential, /// Pegasus 4D: LECO nominal mass resolution time-of-flight GCxGC mass spectrometer. MS_Pegasus_4D = 1001945, /// PEAKS Studio: PEAKS Studio software for data analysis. MS_PEAKS_Studio = 1001946, /// PEAKS Online: PEAKS Online software for high throughput data analysis. MS_PEAKS_Online = 1001947, /// PEAKS Node: PEAKS Node software for high throughput data analysis. MS_PEAKS_Node = 1001948, /// BSI software: Bioinformatics Solutions Inc. Software for data processing and analysis. MS_BSI_software = 1001949, /// PEAKS:peptideScore: The PEAKS peptide '-10lgP Score'. MS_PEAKS_peptideScore = 1001950, /// PEAKS:proteinScore: The PEAKS protein '-10lgP Score'. MS_PEAKS_proteinScore = 1001951, /// ZCore:probScore: The ZCore probability score. MS_ZCore_probScore = 1001952, /// source interface manufacturer: The source interface manufacturer. MS_source_interface_manufacturer = 1001953, /// acquisition parameter: Parameters used in the mass spectrometry acquisition. MS_acquisition_parameter = 1001954, /// no cleavage: No cleavage. MS_no_cleavage = 1001955, /// unspecific cleavage: Unspecific cleavage. MS_unspecific_cleavage = 1001956, /// (?<=[ALIV])(?!P): Regular expression for leukocyte elastase. MS______ALIV_____P_ = 1001957, /// (?<=[HKR]P)(?!P): Regular expression for proline endopeptidase. MS______HKR_P____P_ = 1001958, /// (?<=[^E]E): Regular expression for glutamyl endopeptidase. MS_______E_E_ = 1001959, /// (?<=W): Regular expression for 2-iodobenzoate. MS_____W_ = 1001960, /// peptide spectrum match scoring algorithm: Algorithm used to score the match between a spectrum and a peptide ion. MS_peptide_spectrum_match_scoring_algorithm = 1001961, /// Mascot:C13 counts: C13 peaks to use in peak detection. MS_Mascot_C13_counts = 1001962, /// ProteinExtractor:Weighting: Weighting factor for protein list compilation by ProteinExtractor. MS_ProteinExtractor_Weighting = 1001963, /// ProteinScape:second round Mascot: Flag indicating a second round search with Mascot. MS_ProteinScape_second_round_Mascot = 1001964, /// ProteinScape:second round Phenyx: Flag indicating a second round search with Phenyx. MS_ProteinScape_second_round_Phenyx = 1001965, /// product ion mobility: The mobility of an MS2 product ion, as measured by ion mobility mass spectrometry. MS_product_ion_mobility = 1001966, /// product ion drift time: The ion drift time of an MS2 product ion. MS_product_ion_drift_time_OBSOLETE = 1001967, /// PSM-level PTM localization score: A score that assign confidence to the localization of an amino acid modification on a peptide sequence at the PSM-level. MS_PSM_level_PTM_localization_score = 1001968, /// phosphoRS score: phosphoRS score for PTM site location at the PSM-level. MS_phosphoRS_score = 1001969, /// phosphoRS sequence probability: Probability that the respective isoform is correct. MS_phosphoRS_sequence_probability = 1001970, /// phosphoRS site probability: Estimate of the probability that the respective site is truly phosphorylated. MS_phosphoRS_site_probability = 1001971, /// PTM scoring algorithm version: Version of the post-translational modification scoring algorithm. MS_PTM_scoring_algorithm_version = 1001972, /// DeBunker: DeBunker software. MS_DeBunker = 1001973, /// DeBunker:score: Score specific to DeBunker. MS_DeBunker_score = 1001974, /// delta m/z: The difference between a theoretically calculated m/z and the corresponding experimentally measured m/z. It can be expressed as absolute or relative value. MS_delta_m_z = 1001975, /// m/z difference (delta m/z): The difference between a theoretically calculated m/z and the corresponding experimentally measured m/z. It can be expressed as absolute or relative value. MS_m_z_difference = MS_delta_m_z, /// delta M: The difference between a theoretically calculated molecular mass M and the corresponding experimentally measured M. It can be expressed as absolute or relative value. MS_delta_M = 1001976, /// mass difference (delta M): The difference between a theoretically calculated molecular mass M and the corresponding experimentally measured M. It can be expressed as absolute or relative value. MS_mass_difference = MS_delta_M, /// MSQuant: MSQuant software. MS_MSQuant = 1001977, /// MSQuant:PTM-score: The PTM score from MSQuant software. MS_MSQuant_PTM_score = 1001978, /// MaxQuant:PTM Score: The PTM score from MaxQuant software. MS_MaxQuant_PTM_Score = 1001979, /// MaxQuant:Phospho (STY) Probabilities: The Phospho (STY) Probabilities from MaxQuant software. MS_MaxQuant_Phospho__STY__Probabilities = 1001980, /// MaxQuant:Phospho (STY) Score Diffs: The Phospho (STY) Score Diffs from MaxQuant software. MS_MaxQuant_Phospho__STY__Score_Diffs = 1001981, /// MaxQuant:P-site localization probability: The P-site localization probability value from MaxQuant software. MS_MaxQuant_P_site_localization_probability = 1001982, /// MaxQuant:PTM Delta Score: The PTM Delta Score value from MaxQuant software (Difference between highest scoring site and second highest). MS_MaxQuant_PTM_Delta_Score = 1001983, /// Ascore: Ascore software. MS_Ascore_1001984 = 1001984, /// Ascore: A-score for PTM site location at the PSM-level. MS_Ascore_1001985 = 1001985, /// H-Score: H-Score for peptide phosphorylation site location. MS_H_Score = 1001986, /// vacuum drying MALDI sample preparation: Vacuum-drying MALDI sample preparation crystallization method. MS_vacuum_drying_MALDI_sample_preparation = 1001987, /// crushed crystal MALDI sample preparation: Crushed-crystal MALDI sample preparation method. MS_crushed_crystal_MALDI_sample_preparation = 1001988, /// fast evaporation MALDI sample preparation: Fast-evaporation MALDI sample preparation method. MS_fast_evaporation_MALDI_sample_preparation = 1001989, /// overlayer MALDI sample preparation: Overlayer method combining features of the crushed-crystal method and the fast-evaporation method. MS_overlayer_MALDI_sample_preparation = 1001990, /// sandwich MALDI sample preparation: Sandwich MALDI sample preparation method. MS_sandwich_MALDI_sample_preparation = 1001991, /// spin coating MALDI sample preparation: Spin coating MALDI sample preparation method. MS_spin_coating_MALDI_sample_preparation = 1001992, /// quick and dirty MALDI sample preparation: Quick & dirty (Q&D) sample preparation separating matrix handling from sample handling. MS_quick_and_dirty_MALDI_sample_preparation = 1001993, /// top hat baseline reduction: Top-hat morphological filter based on the basic morphological operations 'erosion' and 'dilatation'. MS_top_hat_baseline_reduction = 1001994, /// convex hull baseline reduction: Constructs the baseline by fitting multiple parabolas to the spectrum starting with the large scale structures. MS_convex_hull_baseline_reduction = 1001995, /// median baseline reduction: The spectrum that will be baseline subtracted is divided into a number of segments. MS_median_baseline_reduction = 1001996, /// wavelet transformation smoothing: The random noise is removed by using the undecimated wavelet transform. MS_wavelet_transformation_smoothing = 1001997, /// sophisticated numerical annotation procedure: It searches for known patterns in the measured spectrum. MS_sophisticated_numerical_annotation_procedure = 1001998, /// SNAP (sophisticated numerical annotation procedure): It searches for known patterns in the measured spectrum. MS_SNAP = MS_sophisticated_numerical_annotation_procedure, /// area normalization: Normalization of areas below the curves. MS_area_normalization = 1001999, /// LIFT: A Bruker's proprietary technique where molecular ions are initially accelerated at lower energy, then collide with inert gas in a collision cell that is then 'lifted' to high potential. The use of inert gas is optional, as it could lift also fragments provided by LID. MS_LIFT = 1002000, /// MS1 label-based raw feature quantitation: MS1 label-based raw feature quantitation. MS_MS1_label_based_raw_feature_quantitation = 1002001, /// MS1 label-based peptide level quantitation: MS1 label-based peptide level quantitation. MS_MS1_label_based_peptide_level_quantitation = 1002002, /// MS1 label-based protein level quantitation: MS1 label-based protein level quantitation. MS_MS1_label_based_protein_level_quantitation = 1002003, /// MS1 label-based proteingroup level quantitation: MS1 label-based proteingroup level quantitation. MS_MS1_label_based_proteingroup_level_quantitation = 1002004, /// iRT retention time normalization standard: A de facto standard providing the retention times at which a specific set of 10 reference peptides exit the reference chromatographic column. The kit may be obtain from Biognosys. MS_iRT_retention_time_normalization_standard = 1002005, /// SRM transition type: The type of the transitions, e.g. target or decoy. MS_SRM_transition_type = 1002006, /// MRM transition type (SRM transition type): The type of the transitions, e.g. target or decoy. MS_MRM_transition_type = MS_SRM_transition_type, /// target SRM transition: A transition used to target a specific compound that may be in the sample. MS_target_SRM_transition = 1002007, /// target MRM transition (target SRM transition): A transition used to target a specific compound that may be in the sample. MS_target_MRM_transition = MS_target_SRM_transition, /// decoy SRM transition: A transition not expected to be present in the sample and used to calculate statistical confidence of target transition detections in some workflows. MS_decoy_SRM_transition = 1002008, /// decoy MRM transition (decoy SRM transition): A transition not expected to be present in the sample and used to calculate statistical confidence of target transition detections in some workflows. MS_decoy_MRM_transition = MS_decoy_SRM_transition, /// isobaric label quantitation analysis: Quantitation analysis using an isobaric labelling workflow. MS_isobaric_label_quantitation_analysis = 1002009, /// TMT quantitation analysis: Quantitation analysis using the Thermo Fisher tandem mass tag (TMT) labelling workflow. MS_TMT_quantitation_analysis = 1002010, /// desorption electrospray ionization: Combination of electrospray and desorption ionization method that ionizes gases, liquids and solids in open air under atmospheric pressure. MS_desorption_electrospray_ionization = 1002011, /// DESI (desorption electrospray ionization): Combination of electrospray and desorption ionization method that ionizes gases, liquids and solids in open air under atmospheric pressure. MS_DESI = MS_desorption_electrospray_ionization, /// Mascot:PTM site assignment confidence: Relative probability that PTM site assignment is correct, derived from the Mascot score difference between matches to the same spectrum (Mascot Delta Score). MS_Mascot_PTM_site_assignment_confidence = 1002012, /// collision energy ramp start: Collision energy at the start of the collision energy ramp. MS_collision_energy_ramp_start = 1002013, /// collision energy ramp end: Collision energy at the end of the collision energy ramp. MS_collision_energy_ramp_end = 1002014, /// spectral count peptide level quantitation: Spectral count peptide level quantitation. MS_spectral_count_peptide_level_quantitation = 1002015, /// spectral count protein level quantitation: Spectral count protein level quantitation. MS_spectral_count_protein_level_quantitation = 1002016, /// spectral count proteingroup level quantitation: Spectral count proteingroup level quantitation. MS_spectral_count_proteingroup_level_quantitation = 1002017, /// MS1 label-based analysis: MS1 label-based analysis. MS_MS1_label_based_analysis = 1002018, /// label-free raw feature quantitation: Label-free raw feature quantitation. MS_label_free_raw_feature_quantitation = 1002019, /// label-free peptide level quantitation: Label-free peptide level quantitation. MS_label_free_peptide_level_quantitation = 1002020, /// label-free protein level quantitation: Label-free protein level quantitation. MS_label_free_protein_level_quantitation = 1002021, /// label-free proteingroup level quantitation: Label-free proteingroup level quantitation. MS_label_free_proteingroup_level_quantitation = 1002022, /// MS2 tag-based analysis: MS2 tag-based analysis. MS_MS2_tag_based_analysis = 1002023, /// MS2 tag-based feature level quantitation: MS2 tag-based feature level quantitation. MS_MS2_tag_based_feature_level_quantitation = 1002024, /// MS2 tag-based peptide level quantitation: MS2 tag-based peptide level quantitation. MS_MS2_tag_based_peptide_level_quantitation = 1002025, /// MS2 tag-based protein level quantitation: MS2 tag-based protein level quantitation. MS_MS2_tag_based_protein_level_quantitation = 1002026, /// MS2 tag-based proteingroup level quantitation: MS2 tag-based proteingroup level quantitation. MS_MS2_tag_based_proteingroup_level_quantitation = 1002027, /// nucleic acid base modification: Nucleic acid base modification (substitution, insertion or deletion). MS_nucleic_acid_base_modification = 1002028, /// original nucleic acid sequence: Specification of the original nucleic acid sequence, prior to a modification. The value slot should hold the DNA or RNA sequence. MS_original_nucleic_acid_sequence = 1002029, /// modified nucleic acid sequence: Specification of the modified nucleic acid sequence. The value slot should hold the DNA or RNA sequence. MS_modified_nucleic_acid_sequence = 1002030, /// PASSEL transition group browser URI: URI to retrieve transition group data for a PASSEL (PeptideAtlas SRM Experiment Library) experiment. MS_PASSEL_transition_group_browser_URI = 1002031, /// PeptideAtlas dataset URI: URI that allows access to a PeptideAtlas dataset. MS_PeptideAtlas_dataset_URI = 1002032, /// contact role: Role of the contact person. MS_contact_role = 1002033, /// first author: The first of a set of authors associated with a publication or release. There may be more than one first author in cases where several authors share primary attribution. MS_first_author = 1002034, /// senior author: The last of a set of authors associated with a publication or release. There may be more than one senior author in cases where several authors share senior attribution. MS_senior_author = 1002035, /// co-author: One of a set of authors associated with a publication or release. MS_co_author = 1002036, /// dataset submitter: A person who submits a dataset to a repository. MS_dataset_submitter = 1002037, /// unlabeled sample: A sample that has not been labelled or modified. This is often referred to as \"light\" to distinguish from \"heavy\". MS_unlabeled_sample = 1002038, /// light labeled sample (unlabeled sample): A sample that has not been labelled or modified. This is often referred to as \"light\" to distinguish from \"heavy\". MS_light_labeled_sample = MS_unlabeled_sample, /// inlet attribute: Inlet properties that are associated with a value. MS_inlet_attribute = 1002039, /// inlet temperature: The temperature of the inlet of a mass spectrometer. MS_inlet_temperature = 1002040, /// source temperature: The temperature of the source of a mass spectrometer. MS_source_temperature = 1002041, /// modulation time: The duration of a complete cycle of modulation in a comprehensive two-dimensional separation system, equals the length of a second dimension chromatogram, i.e., the time between two successive injections into the second column. MS_modulation_time = 1002042, /// ProteinProspector: ProteinProspector software for data acquisition and analysis. MS_ProteinProspector = 1002043, /// ProteinProspector:score: The ProteinProspector result 'Score'. MS_ProteinProspector_score = 1002044, /// ProteinProspector:expectation value: The ProteinProspector result 'Expectation value'. MS_ProteinProspector_expectation_value = 1002045, /// native source path: The original source path used for directory-based sources. MS_native_source_path = 1002046, /// MS-GF: MS-GF software used to re-score the peptide-spectrum matches. MS_MS_GF = 1002047, /// MS-GF+: MS-GF+ software used to analyze the spectra. MS_MS_GF_ = 1002048, /// MS-GFDB (MS-GF+): MS-GF+ software used to analyze the spectra. MS_MS_GFDB = MS_MS_GF_, /// MS-GF:RawScore: MS-GF raw score. MS_MS_GF_RawScore = 1002049, /// MS-GF:DeNovoScore: MS-GF de novo score. MS_MS_GF_DeNovoScore = 1002050, /// MS-GF:Energy: MS-GF energy score. MS_MS_GF_Energy = 1002051, /// MS-GF:SpecEValue: MS-GF spectral E-value. MS_MS_GF_SpecEValue = 1002052, /// MS-GF:EValue: MS-GF E-value. MS_MS_GF_EValue = 1002053, /// MS-GF:QValue: MS-GF Q-value. MS_MS_GF_QValue = 1002054, /// MS-GF:PepQValue: MS-GF peptide-level Q-value. MS_MS_GF_PepQValue = 1002055, /// MS-GF:PEP: MS-GF posterior error probability. MS_MS_GF_PEP = 1002056, /// modification specificity protein N-term: As parameter for search engine: apply the modification only at the N-terminus of a protein. MS_modification_specificity_protein_N_term = 1002057, /// modification specificity protein C-term: As parameter for search engine: apply the modification only at the C-terminus of a protein. MS_modification_specificity_protein_C_term = 1002058, /// Microsoft Excel: Microsoft Excel (can be used for spectral counting). MS_Microsoft_Excel = 1002059, /// database UniProtKB/TrEMBL: The name of the UniProtKB/TrEMBL database. MS_database_UniProtKB_TrEMBL = 1002060, /// decoy DB from UniProtKB/TrEMBL: Decoy database from a TrEMBL protein sequence database. MS_decoy_DB_from_UniProtKB_TrEMBL_OBSOLETE = 1002061, /// metabolic labelling: natural N (mainly 14N): Metabolic labelling: natural N (mainly 14N). MS_metabolic_labelling__natural_N__mainly_14N_ = 1002062, /// FindPairs: Software e.g. for SILAC and 14N/15N workflow, part of the PeakQuant suite. MS_FindPairs = 1002063, /// peptide consensus RT: Peptide consensus retention time. MS_peptide_consensus_RT = 1002064, /// peptide consensus m/z: Peptide consensus mass/charge ratio. MS_peptide_consensus_m_z = 1002065, /// ratio calculation method: Method used to calculate the ratio. MS_ratio_calculation_method = 1002066, /// protein value: median of peptide ratios: Protein quantification value calculated as median of peptide ratios. MS_protein_value__median_of_peptide_ratios = 1002067, /// metabolic labelling: heavy N (mainly 15N): Metabolic labelling: heavy N (mainly 15N). MS_metabolic_labelling__heavy_N__mainly_15N_ = 1002068, /// metabolic labelling: labelling purity: Metabolic labelling: Description of labelling purity. Usually the purity of feeding material (e.g. 95%), or the inclusion rate derived from isotopic peak pattern shape. MS_metabolic_labelling__labelling_purity = 1002069, /// t-test: Perform a t-test (two groups). Specify in string value, whether paired / unpaired, variance equal / different, one- / two-sided version is performed. MS_t_test = 1002070, /// ANOVA-test: Perform an ANOVA-test (more than two groups). Specify in string value, which version is performed. MS_ANOVA_test = 1002071, /// p-value: P-value as result of one of the processing steps described. Specify in the description, which processing step it was. MS_p_value = 1002072, /// mzIdentML format: The mzIdentML format for peptide and protein identification data from the PSI. File extension '.mzid'. MS_mzIdentML_format = 1002073, /// quantification file format: File format containing quantification results. MS_quantification_file_format = 1002074, /// mzQuantML format: The mzQuantML format for quantification data from the PSI. File extension '.mzq'. MS_mzQuantML_format = 1002075, /// PAnalyzer: PAnalyzer software for getting protein evidence categories. MS_PAnalyzer = 1002076, /// impact: Bruker Daltonics' impact: ESI Q-TOF, Nanospray, APCI, APPI, GC-APCI, CaptiveSpray. MS_impact = 1002077, /// ProteomeDiscoverer:1. Static Modification: ProteomeDiscoverer's 1st static post-translational modification (PTM) input parameter. MS_ProteomeDiscoverer_1__Static_Modification_OBSOLETE = 1002078, /// ProteomeDiscoverer:2. Static Modification: ProteomeDiscoverer's 2nd static post-translational modification (PTM) input parameter. MS_ProteomeDiscoverer_2__Static_Modification_OBSOLETE = 1002079, /// ProteomeDiscoverer:Spectrum Selector:Precursor Clipping Range Before: Precursor clipping range before. MS_ProteomeDiscoverer_Spectrum_Selector_Precursor_Clipping_Range_Before = 1002080, /// ProteomeDiscoverer:Spectrum Selector:Precursor Clipping Range After: Precursor clipping range after. MS_ProteomeDiscoverer_Spectrum_Selector_Precursor_Clipping_Range_After = 1002081, /// first column elution time: The time of elution from the first chromatographic column in the chromatographic separation step, relative to the start of chromatography on the first column. MS_first_column_elution_time = 1002082, /// second column elution time: The time of elution from the second chromatographic column in the chromatographic separation step, relative to the start of the chromatography on the second column. MS_second_column_elution_time = 1002083, /// multidimensional chromatography modulation description: Multidimensional chromatography modulation description. MS_multidimensional_chromatography_modulation_description = 1002084, /// two-dimensional gas chromatography with fixed modulation time: Two-dimensional gas chromatography where a single modulation time is used throughout the acquisition. MS_two_dimensional_gas_chromatography_with_fixed_modulation_time = 1002085, /// two-dimensional gas chromatography with discrete modulation time steps: Two-dimensional gas chromatography where the acquisition is divided into steps, each with a different modulation time. MS_two_dimensional_gas_chromatography_with_discrete_modulation_time_steps = 1002086, /// two-dimensional liquid chromatography with fixed modulation time: Two-dimensional liquid chromatography where a single modulation time is used throughout the acquisition. MS_two_dimensional_liquid_chromatography_with_fixed_modulation_time = 1002087, /// two-dimensional liquid chromatography with discrete modulation time steps: Two-dimensional liquid chromatography where the acquisition is divided into steps, each with a different modulation time. MS_two_dimensional_liquid_chromatography_with_discrete_modulation_time_steps = 1002088, /// ProteomeDiscoverer:Peptide Without Protein XCorr Threshold: XCorr threshold for storing peptides that do not belong to a protein. MS_ProteomeDiscoverer_Peptide_Without_Protein_XCorr_Threshold = 1002089, /// Calculate Probability Scores: Flag indicating that a probability score for the assessment that a reported peptide match is a random occurrence is calculated. MS_Calculate_Probability_Scores = 1002090, /// ProteomeDiscoverer:Maximum Delta Cn: Delta Cn threshold for filtering out PSM's. MS_ProteomeDiscoverer_Maximum_Delta_Cn = 1002091, /// Percolator:Validation based on: Algorithm (e.g. q-value or PEP) used for calculation of the validation score using Percolator. MS_Percolator_Validation_based_on = 1002092, /// search engine input parameter: Search engine input parameter. MS_search_engine_input_parameter = 1002093, /// common search engine input parameter: Search engine input parameter that is shared by more than one search engine. MS_common_search_engine_input_parameter = 1002094, /// Mascot input parameter: Search engine input parameters specific to Mascot. MS_Mascot_input_parameter = 1002095, /// SEQUEST input parameter: Search engine input parameters specific to SEQUEST. MS_SEQUEST_input_parameter = 1002096, /// Phenyx input parameter: Search engine input parameters specific to Phenyx. MS_Phenyx_input_parameter = 1002097, /// ProteinExtractor input parameter: Search engine input parameters specific to ProteinExtractor. MS_ProteinExtractor_input_parameter = 1002098, /// OMSSA input parameter: Search engine input parameters specific to OMSSA. MS_OMSSA_input_parameter = 1002099, /// ProteinScape input parameter: Search engine input parameters specific to ProteinScape. MS_ProteinScape_input_parameter = 1002100, /// ProteomeDiscoverer input parameter: Search engine input parameters specific to ProteomeDiscoverer. MS_ProteomeDiscoverer_input_parameter = 1002101, /// software input parameter: Software input parameters. MS_software_input_parameter = 1002103, /// common software input parameter: Software input parameter that is shared by more than one software. MS_common_software_input_parameter = 1002104, /// software specific input parameter: Software specific input parameter. MS_software_specific_input_parameter = 1002105, /// Scaffold input parameter: Search engine input parameters specific to Scaffold. MS_Scaffold_input_parameter = 1002106, /// Percolator input parameter: Search engine input parameters specific to Percolator. MS_Percolator_input_parameter = 1002107, /// higher score better: Indicates that a higher score is better. MS_higher_score_better = 1002108, /// lower score better: Indicates that a lower score is better. MS_lower_score_better = 1002109, /// assay attribute: Attribute describing an assay. MS_assay_attribute = 1002110, /// assay label attribute: Attribute describing an assay label. MS_assay_label_attribute = 1002111, /// protein group list attribute: Attribute describing a protein group list. MS_protein_group_list_attribute = 1002112, /// protein group attribute: Attribute describing a protein group. MS_protein_group_attribute = 1002113, /// protein list attribute: Attribute describing a protein list. MS_protein_list_attribute = 1002114, /// peptide consensus list attribute: Attribute describing a peptide consensus list. MS_peptide_consensus_list_attribute = 1002115, /// peptide consensus attribute: Attribute describing a peptide consensus. MS_peptide_consensus_attribute = 1002116, /// small molecule list attribute: Attribute describing a small molecule list. MS_small_molecule_list_attribute = 1002117, /// small molecule attribute: Attribute describing a small molecule. MS_small_molecule_attribute = 1002118, /// small molecule modification attribute: Attribute describing a small molecule modification. MS_small_molecule_modification_attribute = 1002119, /// experiment name: The name for identifying an experiment. MS_experiment_name = 1002120, /// spectral count feature: Dummy decribing a spectral count feature. MS_spectral_count_feature = 1002121, /// counts reporting: FeatureList of spectral counts. MS_counts_reporting = 1002122, /// x-Tracker: x-Tracker generic tool for quantitative proteomics. MS_x_Tracker = 1002123, /// ProteoSuite: ProteoSuite software for the analysis of quantitative proteomics data. MS_ProteoSuite = 1002124, /// combined FDRScore: FDRScore values specifically obtained for distinct combinations of single, pairs or triplets of search engines making a given PSM, used for integrating results from these distinct pools. MS_combined_FDRScore_OBSOLETE = 1002125, /// database UniProtKB: The name of the UniProtKB knowledgebase. MS_database_UniProtKB = 1002126, /// identification file attribute: Attribute describing an identification file. MS_identification_file_attribute = 1002127, /// method file format: Attribute describing a method file format. MS_method_file_format = 1002128, /// ITRAQAnalyzer: Software for iTRAQ workflow. Extracts and normalizes iTRAQ information from an MS experiment. MS_ITRAQAnalyzer = 1002129, /// identification file format: Attribute describing an identification file format. MS_identification_file_format = 1002130, /// TOPP noise filter: Noise filter component of the TOPP software. MS_TOPP_noise_filter = 1002131, /// TOPP NoiseFilterGaussian: Removes noise from profile spectra by using a gaussian smoothing. MS_TOPP_NoiseFilterGaussian = 1002132, /// TOPP NoiseFilterSGolay: Removes noise from profile spectra by using a Savitzky-Golay smoothing. MS_TOPP_NoiseFilterSGolay = 1002133, /// TOPP peak picker: Peak picker component of the TOPP software. MS_TOPP_peak_picker = 1002134, /// TOPP PeakPickerHiRes: Finds mass spectrometric peaks in high-resoluted profile mass spectra. MS_TOPP_PeakPickerHiRes = 1002135, /// TOPP PeakPickerWavelet: Finds mass spectrometric peaks with a wavelet algorithm in low-resoluted profile mass spectra. MS_TOPP_PeakPickerWavelet = 1002136, /// TOPP spectra filter: Spectra filter component of the TOPP software. MS_TOPP_spectra_filter = 1002137, /// TOPP SpectraFilterBernNorm: Applies a Bern et al normalization to peak spectra. MS_TOPP_SpectraFilterBernNorm = 1002138, /// TOPP SpectraFilterMarkerMower: Applies a filter to peak spectra for marked peaks. MS_TOPP_SpectraFilterMarkerMower = 1002139, /// TOPP SpectraFilterNLargest: Retains the n largest peaks of a peak spectra. MS_TOPP_SpectraFilterNLargest = 1002140, /// TOPP SpectraFilterNormalizer: Applies a TIC/maximal intensity normalization to peak spectra. MS_TOPP_SpectraFilterNormalizer = 1002141, /// TOPP SpectraFilterParentPeakMower: Filters putative unfragmented precursor ions from tandem spectra. MS_TOPP_SpectraFilterParentPeakMower = 1002142, /// TOPP SpectraFilterScaler: Applies a filter to peak spectra after intensity scaling according to rank. MS_TOPP_SpectraFilterScaler = 1002143, /// TOPP SpectraFilterSqrtMower: Applies a filter to peak spectra after intensity scaling to the square root. MS_TOPP_SpectraFilterSqrtMower = 1002144, /// TOPP SpectraFilterThresholdMower: Applies a filter of peaks below a given threshold to peak spectra. MS_TOPP_SpectraFilterThresholdMower = 1002145, /// TOPP SpectraFilterWindowMower: Applies a filter of the largest peaks in a sliding window over a peak spectrum. MS_TOPP_SpectraFilterWindowMower = 1002146, /// TOPP map aligner: Map aligner component of the TOPP software. MS_TOPP_map_aligner = 1002147, /// TOPP MapAlignerIdentification: Corrects retention time distortions between maps based on common peptide identifications. MS_TOPP_MapAlignerIdentification = 1002148, /// TOPP MapAlignerPoseClustering: Corrects retention time distortions between maps using a pose clustering approach. MS_TOPP_MapAlignerPoseClustering = 1002149, /// TOPP MapAlignerSpectrum: Corrects retention time distortions between maps by spectrum alignment. MS_TOPP_MapAlignerSpectrum = 1002150, /// numerator data type attribute: Attribute describing the data type of the numerator of a ratio. MS_numerator_data_type_attribute = 1002151, /// denominator data type attribute: Attribute describing the data type of the denominator of a ratio. MS_denominator_data_type_attribute = 1002152, /// protein level PSM counts: The number of spectra identified for this protein in spectral counting. MS_protein_level_PSM_counts = 1002153, /// TOPP DTAExtractor: Extracts spectra of an MS run file to several files in DTA format. MS_TOPP_DTAExtractor = 1002154, /// TOPP IDMerger: Merges several protein/peptide identification files into one file. MS_TOPP_IDMerger = 1002155, /// TOPP IDFileConverter: Converts identification engine file formats. MS_TOPP_IDFileConverter = 1002156, /// TOPP SpectraMerger: Merges spectra from an LC/MS map, either by precursor or by RT blocks. MS_TOPP_SpectraMerger = 1002157, /// TOPP MzTabExporter: Exports various XML formats to an mzTab file. MS_TOPP_MzTabExporter = 1002158, /// TOPP MassTraceExtractor: Annotates mass traces in centroided LC/MS maps. MS_TOPP_MassTraceExtractor = 1002159, /// TOPP PrecursorMassCorrector: Correct the precursor entries of tandem MS scans. MS_TOPP_PrecursorMassCorrector = 1002160, /// TOPP HighResPrecursorMassCorrector: Performs precursor mz correction on centroided high resolution data. MS_TOPP_HighResPrecursorMassCorrector = 1002161, /// TOPP AdditiveSeries: Computes an additive series to quantify a peptide in a set of samples. MS_TOPP_AdditiveSeries = 1002162, /// TOPP Decharger: Decharges and merges different feature charge variants of the same chemical entity. MS_TOPP_Decharger = 1002163, /// TOPP EICExtractor: Quantifies signals at given positions in (raw or picked) LC/MS maps. MS_TOPP_EICExtractor = 1002164, /// TOPP feature finder: Feature finder component of the TOPP software. MS_TOPP_feature_finder = 1002165, /// TOPP FeatureFinderCentroided: Detects two-dimensional features in centroided LC-MS data. MS_TOPP_FeatureFinderCentroided = 1002166, /// TOPP FeatureFinderRaw: Detects two-dimensional features in uncentroided LC-MS data. MS_TOPP_FeatureFinderRaw = 1002167, /// TOPP FeatureFinderIsotopeWavelet: Detects two-dimensional features in uncentroided LC-MS data with a wavelet algorithm. MS_TOPP_FeatureFinderIsotopeWavelet = 1002168, /// TOPP FeatureFinderMetabo: Detects two-dimensional features in centroided LC-MS data of metabolites. MS_TOPP_FeatureFinderMetabo = 1002169, /// TOPP FeatureFinderMRM: Quantifies features LC-MS/MS MRM data. MS_TOPP_FeatureFinderMRM = 1002170, /// TOPP ProteinQuantifier: Computes protein abundances from annotated feature/consensus maps. MS_TOPP_ProteinQuantifier = 1002171, /// TOPP ConsensusMapNormalizer: Normalizes maps of one consensus XML file (after linking). MS_TOPP_ConsensusMapNormalizer = 1002172, /// TOPP MapRTTransformer: Applies retention time transformations to maps. MS_TOPP_MapRTTransformer = 1002173, /// TOPP feature linker: Feature linker component of the TOPP software. MS_TOPP_feature_linker = 1002174, /// TOPP FeatureLinkerLabeled: Groups corresponding isotope-labeled features in a feature map. MS_TOPP_FeatureLinkerLabeled = 1002175, /// TOPP FeatureLinkerUnlabeled: Groups corresponding features from multiple maps. MS_TOPP_FeatureLinkerUnlabeled = 1002176, /// TOPP FeatureLinkerUnlabeledQT: Groups corresponding features from multiple maps using a quality threshold clustering approach. MS_TOPP_FeatureLinkerUnlabeledQT = 1002177, /// TOPP CompNovo: Performs a peptide/protein identification with the CompNovo engine. MS_TOPP_CompNovo = 1002178, /// TOPP CompNovoCID: Performs a peptide/protein identification with the CompNovo engine in collision-induced dissociation (CID) mode. MS_TOPP_CompNovoCID = 1002179, /// TOPP software adaptor: Software adaptor to an external program in the TOPP software. MS_TOPP_software_adaptor = 1002180, /// TOPP InspectAdapter: Identifies MS2 spectra using the external program Inspect. MS_TOPP_InspectAdapter = 1002181, /// TOPP MascotAdapter: Identifies MS2 spectra using the external program Mascot. MS_TOPP_MascotAdapter = 1002182, /// TOPP MascotAdapterOnline: Identifies MS2 spectra using the online version of the external program Mascot. MS_TOPP_MascotAdapterOnline = 1002183, /// TOPP OMSSAAdapter: Identifies MS2 spectra using the external program OMSSA. MS_TOPP_OMSSAAdapter = 1002184, /// TOPP PepNovoAdapter: Identifies MS2 spectra using the external program PepNovo. MS_TOPP_PepNovoAdapter = 1002185, /// TOPP XTandemAdapter: Identifies MS2 spectra using the external program XTandem. MS_TOPP_XTandemAdapter = 1002186, /// TOPP SpecLibSearcher: Identifies peptide MS2 spectra by spectral matching with a searchable spectral library. MS_TOPP_SpecLibSearcher = 1002187, /// TOPP ConsensusID: Computes a consensus identification from peptide identifications of several identification engines. MS_TOPP_ConsensusID = 1002188, /// TOPP IDConflictResolver: Resolves ambiguous annotations of features with peptide identifications. MS_TOPP_IDConflictResolver = 1002189, /// TOPP IDFilter: Filters results from protein or peptide identification engines based on different criteria. MS_TOPP_IDFilter = 1002190, /// TOPP IDMapper: Assigns protein/peptide identifications to feature or consensus features. MS_TOPP_IDMapper = 1002191, /// TOPP IDPosteriorErrorProbability: Estimates posterior error probabilities using a mixture model. MS_TOPP_IDPosteriorErrorProbability = 1002192, /// TOPP IDRTCalibration: Calibrate Retention times of peptide hits to standards. MS_TOPP_IDRTCalibration = 1002193, /// TOPP PeptideIndexer: Refreshes the protein references for all peptide hits. MS_TOPP_PeptideIndexer = 1002194, /// TOPP PrecursorIonSelector: A tool for precursor ion selection based on identification results. MS_TOPP_PrecursorIonSelector = 1002195, /// TOPP MRMMapper: MRMMapper maps measured chromatograms (mzML) and the transitions used (TraML). MS_TOPP_MRMMapper = 1002196, /// TOPP OpenSwath component: OpenSwath component of the TOPP software. MS_TOPP_OpenSwath_component = 1002197, /// TOPP OpenSwathAnalyzer: Picks peaks and finds features in an SRM experiment. MS_TOPP_OpenSwathAnalyzer = 1002198, /// TOPP OpenSwathChromatogramExtractor: Extract chromatograms (XIC) from a MS2 map file. MS_TOPP_OpenSwathChromatogramExtractor = 1002199, /// TOPP OpenSwathDecoyGenerator: Generates decoys according to different models for a specific TraML. MS_TOPP_OpenSwathDecoyGenerator = 1002200, /// TOPP OpenSwathFeatureXMLToTSV: Converts a featureXML to a mProphet tsv (tab separated values). MS_TOPP_OpenSwathFeatureXMLToTSV = 1002201, /// TOPP OpenSwathRTNormalizer: Generates a transformation file for retention time space into normalized space. MS_TOPP_OpenSwathRTNormalizer = 1002202, /// TOPP ProteinInference: Infer proteins from a list of (high-confidence) peptides. MS_TOPP_ProteinInference = 1002203, /// TOPP FalseDiscoveryRate: Estimates the false discovery rate on peptide and protein level using decoy searches. MS_TOPP_FalseDiscoveryRate = 1002204, /// ProteoWizard msconvert: Converts, filters, and processes mass spectrometry data in variety of formats. MS_ProteoWizard_msconvert = 1002205, /// ProteoWizard idconvert: Converts, filters, and processes identifications from shotgun proteomics experiments. MS_ProteoWizard_idconvert = 1002206, /// ProteoWizard chainsaw: Filters and processes protein sequence databases. MS_ProteoWizard_chainsaw = 1002207, /// ProteoWizard msaccess: Filters, processes, and displays mass spectrometry data in a variety of ways. MS_ProteoWizard_msaccess = 1002208, /// ProteoWizard SeeMS: An interactive GUI application to view and filter mass spectrometry data in a variety of formats. MS_ProteoWizard_SeeMS = 1002209, /// IsobariQ: A quantitative software package designed for analysis of IPTL, TMT and iTRAQ data. MS_IsobariQ = 1002210, /// Variance stabilizing normalization: The model incorporates data calibration (normalization), a model for the dependence of the variance on the mean intensity, and a variance stabilizing data transformation. MS_Variance_stabilizing_normalization = 1002211, /// IPTL quantitation analysis: Quantification analysis using a labelling strategy where both peptide termini are labelled so that the peptides from different labelling schema are isobaric. MS_IPTL_quantitation_analysis = 1002212, /// PAnalyzer:conclusive protein: A protein identified by at least one unique (distinct, discrete) peptide (peptides are considered different only if they can be distinguished by evidence in mass spectrum). MS_PAnalyzer_conclusive_protein = 1002213, /// PAnalyzer:indistinguishable protein: A member of a group of proteins sharing all peptides that are exclusive to the group (peptides are considered different only if they can be distinguished by evidence in mass spectrum). MS_PAnalyzer_indistinguishable_protein = 1002214, /// PAnalyzer:non-conclusive protein: A protein sharing all its matched peptides with either conclusive or indistinguishable proteins (peptides are considered different only if they can be distinguished by evidence in mass spectrum). MS_PAnalyzer_non_conclusive_protein = 1002215, /// PAnalyzer:ambiguous group member: A protein sharing at least one peptide not matched to either conclusive or indistinguishable proteins (peptides are considered different only if they can be distinguished by evidence in mass spectrum). MS_PAnalyzer_ambiguous_group_member = 1002216, /// decoy peptide: A putative identified peptide issued from a decoy sequence database. MS_decoy_peptide = 1002217, /// percent collision energy ramp start: Collision energy at the start of the collision energy ramp in percent, normalized to the mass of the ion. MS_percent_collision_energy_ramp_start = 1002218, /// percent collision energy ramp end: Collision energy at the end of the collision energy ramp in percent, normalized to the mass of the ion. MS_percent_collision_energy_ramp_end = 1002219, /// MRMaid: A web-based SRM assay design tool whose transitions are generated by mining the millions of identified peptide spectra held in the EBI's PRIDE database. MS_MRMaid = 1002220, /// MRMaid:peptide score: Score in MRMaid to indicate the expected performance of the peptide in SRM. MS_MRMaid_peptide_score = 1002221, /// SRM transition attribute: Attribute associated with a SRM transition. MS_SRM_transition_attribute = 1002222, /// precursor ion detection probability: Probability of detecting precursor when parent protein is present. MS_precursor_ion_detection_probability = 1002223, /// product ion detection probability: Probability of detecting product ion when precursor ion is present. MS_product_ion_detection_probability = 1002224, /// average product ion intensity: Average value of product ion intensity in a collection of identified spectra. MS_average_product_ion_intensity = 1002225, /// product ion intensity standard deviation: Standard deviation of product ion intensity in a collection of identified spectra. MS_product_ion_intensity_standard_deviation = 1002226, /// number of product ion observations: The number of times the specific product ion has been observed in a series of SRM experiments. MS_number_of_product_ion_observations = 1002227, /// number of precursor ion observations: The number of times the specific precursor ion has been observed in a series of SRM experiments. MS_number_of_precursor_ion_observations = 1002228, /// ProteomeDiscoverer:Mascot:Significance Middle: Calculated relaxed significance when performing a decoy search for high-confidence peptides. MS_ProteomeDiscoverer_Mascot_Significance_Middle = 1002229, /// ProteomeDiscoverer:Mascot:Significance High: Calculated relaxed significance when performing a decoy search for medium-confidence peptides. MS_ProteomeDiscoverer_Mascot_Significance_High = 1002230, /// regular expressions for a GUID: ([A-Fa-f0-9]\{8\}-([A-Fa-f0-9]\{4\}-)\{3\}[A-Fa-f0-9]\{12\}). MS_regular_expressions_for_a_GUID = 1002231, /// ProteomeDiscoverer:Default FDR calculator: The default FDR calculator as globally unique identifier (GUID). MS_ProteomeDiscoverer_Default_FDR_calculator = 1002232, /// ProteomeDiscoverer:SEQUEST:Low resolution spectra contained: Flag indicating if low-resolution spectra are taken into consideration. MS_ProteomeDiscoverer_SEQUEST_Low_resolution_spectra_contained = 1002233, /// selected precursor m/z: Mass-to-charge ratio of a precursor ion selected for fragmentation. MS_selected_precursor_m_z = 1002234, /// ProteoGrouper:PDH score: A score assigned to a single protein accession (modelled as ProteinDetectionHypothesis in mzIdentML), based on summed peptide level scores. MS_ProteoGrouper_PDH_score = 1002235, /// ProteoGrouper:PAG score: A score assigned to a protein group (modelled as ProteinAmbiguityGroup in mzIdentML), based on all summed peptide level scores that have been assigned to the group as unique or razor peptides. MS_ProteoGrouper_PAG_score = 1002236, /// mzidLib: A library of Java routines for manipulating mzIdentML files. MS_mzidLib = 1002237, /// mzidLib:Omssa2Mzid: A converter for OMSSA OMX to mzIdentML. MS_mzidLib_Omssa2Mzid = 1002238, /// mzidLib:Tandem2Mzid: A converter for Tandem XML to mzIdentML. MS_mzidLib_Tandem2Mzid = 1002239, /// mzidLib:Csv2Mzid: A converter for CSV files (following OMSSA CSV style) to mzIdentML. MS_mzidLib_Csv2Mzid = 1002240, /// mzidLib:ProteoGrouper: A generic and parameterizable protein inference algorithm for mzIdentML files. MS_mzidLib_ProteoGrouper = 1002241, /// mzidLib:Thresholder: A routine for keeping only identifications passing a given threshold or setting passThreshold to true or false for SpectrumIdentificationItem or ProteinDetectionHypothesis in mzIdentML files. MS_mzidLib_Thresholder = 1002242, /// mzidLib:Perform emPAI on mzid: A routine for adding emPAI quantitative values to an mzIdentML file. MS_mzidLib_Perform_emPAI_on_mzid = 1002243, /// mzidLib:FalseDiscoveryRate: A routine for calculating local FDR, q-value and FDRScore for mzIdentML files, based on a decoy search. MS_mzidLib_FalseDiscoveryRate = 1002244, /// mzidLib:Mzidentml2Csv: A tool for converting mzIdentML files to CSV format. MS_mzidLib_Mzidentml2Csv = 1002245, /// mzidLib:CombineSearchEngines: A tool for combining results analysed in parallel in two or three search engines into a single mzIdentML file. MS_mzidLib_CombineSearchEngines = 1002246, /// mzidLib:InsertMetaDataFromFasta: A tool for adding additional meta data from a FASTA file to DBSequence entries (sequence and description) in mzIdentML files. MS_mzidLib_InsertMetaDataFromFasta = 1002247, /// SEQUEST:spscore: The SEQUEST result 'SpScore'. MS_SEQUEST_spscore = 1002248, /// SEQUEST:sprank: The SEQUEST result 'SpRank'. MS_SEQUEST_sprank = 1002249, /// SEQUEST:deltacnstar: The SEQUEST result 'DeltaCnStar'. MS_SEQUEST_deltacnstar = 1002250, /// Comet: Comet open-source sequence search engine developed at the University of Washington. MS_Comet = 1002251, /// Comet:xcorr: The Comet result 'XCorr'. MS_Comet_xcorr = 1002252, /// Comet:deltacn: The Comet result 'DeltaCn'. MS_Comet_deltacn = 1002253, /// Comet:deltacnstar: The Comet result 'DeltaCnStar'. MS_Comet_deltacnstar = 1002254, /// Comet:spscore: The Comet result 'SpScore'. MS_Comet_spscore = 1002255, /// Comet:sprank: The Comet result 'SpRank'. MS_Comet_sprank = 1002256, /// Comet:expectation value: The Comet result 'Expectation value'. MS_Comet_expectation_value = 1002257, /// Comet:matched ions: The Comet result 'Matched Ions'. MS_Comet_matched_ions = 1002258, /// Comet:total ions: The Comet result 'Total Ions'. MS_Comet_total_ions = 1002259, /// PSM:FDR threshold: False-discovery rate threshold for peptide-spectrum matches. MS_PSM_FDR_threshold = 1002260, /// Byonic: Byonic search engine from Protein Metrics. MS_Byonic = 1002261, /// Byonic:Score: The Byonic score is the primary indicator of PSM correctness. The Byonic score reflects the absolute quality of the peptide-spectrum match, not the relative quality compared to other candidate peptides. Byonic scores range from 0 to about 1000, with 300 a good score, 400 a very good score, and PSMs with scores over 500 almost sure to be correct. MS_Byonic_Score = 1002262, /// Byonic:Delta Score: The drop in Byonic score from the top-scoring peptide to the next peptide with distinct sequence. In this computation, the same peptide with different modifications is not considered distinct. MS_Byonic_Delta_Score = 1002263, /// Byonic:DeltaMod Score: The drop in Byonic score from the top-scoring peptide to the next peptide different in any way, including placement of modifications. DeltaMod gives an indication of whether modifications are confidently localized; DeltaMod over 10.0 means that there is high likelihood that all modification placements are correct. MS_Byonic_DeltaMod_Score = 1002264, /// Byonic:PEP: Byonic posterior error probability. MS_Byonic_PEP = 1002265, /// Byonic:Peptide LogProb: The log p-value of the PSM. This is the log of the probability that the PSM with such a score and delta would arise by chance in a search of this size (size of the protein database, as expanded by the modification rules). A log p-value of -3.0 should happen by chance on only one of a thousand spectra. Caveat: it is very hard to compute a p-value that works for all searches and all spectra, so read Byonic p-values with a certain amount of skepticism. MS_Byonic_Peptide_LogProb = 1002266, /// Byonic:Protein LogProb: The log p-value of the protein. MS_Byonic_Protein_LogProb = 1002267, /// Byonic:Best LogProb: Best (most negative) log p-value of an individual PSM. MS_Byonic_Best_LogProb = 1002268, /// Byonic:Best Score: Best (largest) Byonic score of a PSM. MS_Byonic_Best_Score = 1002269, /// chromatography separation: A technique by which molecules are separated by chemical and physical properties such as hydrophobicity or vapour pressure. MS_chromatography_separation = 1002270, /// liquid chromatography separation: Liquid chromatography (LC) is a separation technique in which the mobile phase is a liquid. MS_liquid_chromatography_separation = 1002271, /// gas chromatography separation: Gas chromatography (GC) is a separation technique in which the mobile phase is a gas. MS_gas_chromatography_separation = 1002272, /// detector potential: Detector potential difference in volts. MS_detector_potential = 1002273, /// SQ Detector 2: Waters quadrupole based SQ Detector 2. MS_SQ_Detector_2 = 1002274, /// Xevo G2-S Tof: Waters oa-ToF based Xevo G2-S Tof. MS_Xevo_G2_S_Tof = 1002275, /// Xevo G2-S QTof: Waters oa-ToF based Xevo G2-S QTof. MS_Xevo_G2_S_QTof = 1002276, /// AutoSpec Premier: Waters AutoSpec Premier. MS_AutoSpec_Premier = 1002277, /// Pegasus III: LECO nominal mass resolution time-of-flight GC mass spectrometer. MS_Pegasus_III = 1002278, /// maXis 4G: Bruker Daltonics' maXis 4G: ESI Q-TOF, Nanospray, APCI, APPI, GC-APCI, CaptiveSpray. MS_maXis_4G = 1002279, /// compact: Bruker Daltonics' compact: ESI Q-TOF, Nanospray, APCI, APPI, GC-APCI, CaptiveSpray. MS_compact = 1002280, /// SRM feature level quantitation: Selected Reaction Monitoring feature level quantitation. MS_SRM_feature_level_quantitation = 1002281, /// SRM peptide level quantitation: Selected Reaction Monitoring peptide level quantitation. MS_SRM_peptide_level_quantitation = 1002282, /// SRM protein level quantitation: Selected Reaction Monitoring protein level quantitation. MS_SRM_protein_level_quantitation = 1002283, /// SRM proteingroup level quantitation: Selected Reaction Monitoring proteingroup level quantitation. MS_SRM_proteingroup_level_quantitation = 1002284, /// Trans-Proteomic Pipeline: A suite of open source tools for the processing of MS2 proteomics data developed by the Seattle Proteome Center at the Institute for Systems Biology. MS_Trans_Proteomic_Pipeline = 1002285, /// TPP (Trans-Proteomic Pipeline): A suite of open source tools for the processing of MS2 proteomics data developed by the Seattle Proteome Center at the Institute for Systems Biology. MS_TPP = MS_Trans_Proteomic_Pipeline, /// Trans-Proteomic Pipeline software: A software program that is a component of the Trans-Proteomic Pipeline. MS_Trans_Proteomic_Pipeline_software = 1002286, /// PeptideProphet: A program in the TPP that calculates PSM probabilities for MS2 proteomics data searched with any of the supported sequence or spectral library search engines via the pepXML format. MS_PeptideProphet = 1002287, /// iProphet: A program in the TPP that calculates distinct peptide probabilities based on several lines of corroborating evidence including search results from multiple search engines via the pepXML format. MS_iProphet = 1002288, /// ProteinProphet: A program in the TPP that calculates protein-level probabilities based on input PSM or peptide-level probabilities from PeptideProphet or iProphet. The output is written in the protXML format. MS_ProteinProphet = 1002289, /// XPRESS: A program in the TPP that calculates PSM-level abundances based on 2-channel isotope-labelled data such as ICAT, SILAC, etc. MS_XPRESS = 1002290, /// Libra: A program in the TPP that calculates PSM, peptide, and protein-level abundances based on N-channel isobaric label peptide data such as iTRAQ, TMT, etc. MS_Libra = 1002291, /// PTMProphet: A program in the TPP that calculates PTM localization probabilities by re-analyzing the peaks that are available to distinguish between possible modification sites. MS_PTMProphet = 1002292, /// Bruker Daltonics SCION series: Bruker Daltonics' SCION series. MS_Bruker_Daltonics_SCION_series = 1002293, /// Bruker Daltonics EVOQ series: Bruker Daltonics' EVOQ series. MS_Bruker_Daltonics_EVOQ_series = 1002294, /// SCION SQ: Bruker Daltonics' SCION SQ: GC-single quadrupole. MS_SCION_SQ = 1002295, /// SCION TQ: Bruker Daltonics' SCION TQ: GC-triple quadrupole. MS_SCION_TQ = 1002296, /// EVOQ Elite: Bruker Daltonics' EVOQ Elite: LC-triple quadrupole. MS_EVOQ_Elite = 1002297, /// EVOQ Qube: Bruker Daltonics' EVOQ Qube: LC-triple quadrupole. MS_EVOQ_Qube = 1002298, /// micrOTOF-Q III: Bruker Daltonics' micrOTOF-Q III: ESI Q-TOF, Nanospray, APCI, APPI, GC-APCI, CaptiveSpray. MS_micrOTOF_Q_III = 1002299, /// amaZon Speed ETD: Bruker Daltonics' amaZon Speed ETD: ESI quadrupole ion trap, Nanospray, APCI, APPI, ETD, PTR, GC-APCI, CaptiveSpray. MS_amaZon_Speed_ETD = 1002300, /// amaZon Speed: Bruker Daltonics' amaZon ETD: ESI quadrupole ion trap, Nanospray, APCI, APPI, GC-APCI, CaptiveSpray. MS_amaZon_Speed = 1002301, /// Bruker Container format: Bruker Container raw file format. MS_Bruker_Container_format = 1002302, /// Bruker Container nativeID format: Native identifier (UUID). MS_Bruker_Container_nativeID_format = 1002303, /// domain range: Domain range of a numerical value. MS_domain_range = 1002304, /// value between 0 and 1 inclusive: Value range for probabilities. MS_value_between_0_and_1_inclusive = 1002305, /// value greater than zero: Positive value range. MS_value_greater_than_zero = 1002306, /// fragmentation ion type: Type of fragment ion based on where the backbone breaks, such as a y ion or a c ion. MS_fragmentation_ion_type = 1002307, /// fluorescence detector: A detector using a fluorescent signal after excitation with light. MS_fluorescence_detector = 1002308, /// Byonic: Peptide AbsLogProb: The absolute value of the log-base10 of the Byonic posterior error probability (PEP) of the PSM. MS_Byonic__Peptide_AbsLogProb = 1002309, /// Byonic: Protein AbsLogProb: The absolute value of the log-base10 of the Byonic posterior error probability (PEP) of the protein. MS_Byonic__Protein_AbsLogProb = 1002310, /// Byonic: Peptide AbsLogProb2D: The absolute value of the log-base10 Byonic two-dimensional posterior error probability (PEP) of the PSM. The two-dimensional PEP takes into account protein ranking information as well as PSM information. MS_Byonic__Peptide_AbsLogProb2D = 1002311, /// MS-Numpress linear prediction compression: Compression using MS-Numpress linear prediction compression. MS_MS_Numpress_linear_prediction_compression = 1002312, /// MS-Numpress positive integer compression: Compression using MS-Numpress positive integer compression. MS_MS_Numpress_positive_integer_compression = 1002313, /// MS-Numpress short logged float compression: Compression using MS-Numpress short logged float compression. MS_MS_Numpress_short_logged_float_compression = 1002314, /// consensus result: Indicates a consensus result from several search engine runs. MS_consensus_result = 1002315, /// ProteomeDiscoverer:Amanda:high confidence threshold: Strict confidence probability score. MS_ProteomeDiscoverer_Amanda_high_confidence_threshold = 1002316, /// ProteomeDiscoverer:Amanda:middle confidence threshold: Relaxed confidence probability score. MS_ProteomeDiscoverer_Amanda_middle_confidence_threshold = 1002317, /// ProteomeDiscoverer:automatic workload: Flag indicating automatic estimation of the workload level. MS_ProteomeDiscoverer_automatic_workload = 1002318, /// Amanda:AmandaScore: The Amanda score of the scoring function for a PSM. MS_Amanda_AmandaScore = 1002319, /// ProteomeDiscoverer:max differential modifications: Maximum dynamic modifications per PSM. MS_ProteomeDiscoverer_max_differential_modifications = 1002320, /// ProteomeDiscoverer:max equal modifications: Maximum equal modifications per PSM. MS_ProteomeDiscoverer_max_equal_modifications = 1002321, /// ProteomeDiscoverer:min peptide length: Minimum peptide length. MS_ProteomeDiscoverer_min_peptide_length = 1002322, /// ProteomeDiscoverer:max peptide length: Maximum peptide length. MS_ProteomeDiscoverer_max_peptide_length = 1002323, /// ProteomeDiscoverer:max number neutral loss: Maximum number of same neutral losses. MS_ProteomeDiscoverer_max_number_neutral_loss = 1002324, /// ProteomeDiscoverer:max number neutral loss modifications: Max number of same neutral losses of modifications. MS_ProteomeDiscoverer_max_number_neutral_loss_modifications = 1002325, /// ProteomeDiscoverer:use flanking ions: Flag for usage of flanking ions. MS_ProteomeDiscoverer_use_flanking_ions = 1002326, /// ProteomeDiscoverer:max number of same modifs: The maximum number of possible equal modifications per PSM. MS_ProteomeDiscoverer_max_number_of_same_modifs = 1002327, /// ProteomeDiscoverer:perform deisotoping: Defines whether a simple deisotoping shall be performed. MS_ProteomeDiscoverer_perform_deisotoping = 1002328, /// ProteomeDiscoverer:ion settings: Specifies the fragment ions and neutral losses that are calculated. MS_ProteomeDiscoverer_ion_settings = 1002329, /// ProteomeDiscoverer:3. Static Modification: ProteomeDiscoverer's 3rd static post-translational modification (PTM) input parameter. MS_ProteomeDiscoverer_3__Static_Modification_OBSOLETE = 1002330, /// ProteomeDiscoverer:5. Dynamic Modification: ProteomeDiscoverer's 5th dynamic post-translational modification (PTM) input parameter. MS_ProteomeDiscoverer_5__Dynamic_Modification_OBSOLETE = 1002331, /// lab head: The scientist responsible for personnel, grants, and instrumentation in a functional laboratory group. MS_lab_head = 1002332, /// conversion software: Computer software primarily designed to convert data represented in one format to another format, sometimes with minor data alterations in the process. MS_conversion_software = 1002333, /// ProCon: Java software designed to convert one of several proteomics identification results formats into mzIdentML or PRIDE XML. MS_ProCon = 1002334, /// PRIDE Converter2: Java software designed to convert one of several proteomics identification results formats into PRIDE XML. MS_PRIDE_Converter2 = 1002335, /// Amanda: Amanda scoring system for PSM identification. MS_Amanda = 1002336, /// Andromeda: Andromeda is a peptide search engine. MS_Andromeda = 1002337, /// Andromeda:score: The probability based score of the Andromeda search engine. MS_Andromeda_score = 1002338, /// site:global FDR: Estimation of global false discovery rate of peptides with a post-translational modification. MS_site_global_FDR = 1002339, /// ProteomeXchange project tag: Tag that can be added to a ProteomeXchange dataset, to enable the grouping of datasets. One tag can be used for indicating that a given dataset is part of a bigger project, like e.g. the Human Proteome Project. MS_ProteomeXchange_project_tag = 1002340, /// second-pass peptide identification: A putative identified peptide found in a second-pass search of protein sequences selected from a first-pass search. MS_second_pass_peptide_identification = 1002341, /// MZmine: A framework for differential analysis of mass spectrometry data. MS_MZmine = 1002342, /// ion stability type: Stability type of the ion. MS_ion_stability_type_OBSOLETE = 1002343, /// Maltcms: Modular Application Toolkit for Chromatography Mass-Spectrometry is an application framework mainly for developers. MS_Maltcms = 1002344, /// PSM-level result details: Peptide spectrum match level information. MS_PSM_level_result_details = 1002345, /// protein group-level result details: Protein group level information. MS_protein_group_level_result_details = 1002346, /// PSM-level identification confidence metric: Identification confidence metric for a peptide spectrum match. MS_PSM_level_identification_confidence_metric = 1002347, /// protein group-level identification confidence metric: Identification confidence metric for a protein group. MS_protein_group_level_identification_confidence_metric = 1002348, /// value greater than zero but less than or equal to one: Positive value range less than or equal to 1. MS_value_greater_than_zero_but_less_than_or_equal_to_one = 1002349, /// PSM-level global FDR: Estimation of the global false discovery rate of peptide spectrum matches. MS_PSM_level_global_FDR = 1002350, /// PSM-level local FDR: Estimation of the local false discovery rate of peptide spectrum matches. MS_PSM_level_local_FDR = 1002351, /// PSM-level p-value: Estimation of the p-value for peptide spectrum matches. MS_PSM_level_p_value = 1002352, /// PSM-level e-value: Estimation of the e-value for peptide spectrum matches. MS_PSM_level_e_value = 1002353, /// PSM-level q-value: Estimation of the q-value for peptide spectrum matches. MS_PSM_level_q_value = 1002354, /// PSM-level FDRScore: FDRScore for peptide spectrum matches. MS_PSM_level_FDRScore = 1002355, /// PSM-level combined FDRScore: Combined FDRScore for peptide spectrum matches specifically obtained for distinct combinations of single, pairs or triplets of search engines making a given PSM, used for integrating results from these distinct pools. MS_PSM_level_combined_FDRScore = 1002356, /// PSM-level probability: Probability that the reported peptide ion is truly responsible for some or all of the components of the specified mass spectrum. MS_PSM_level_probability = 1002357, /// search engine specific score for distinct peptides: Search engine specific distinct peptide score. MS_search_engine_specific_score_for_distinct_peptides = 1002358, /// distinct peptide-level local FDR: Estimation of the local false discovery rate for distinct peptides once redundant identifications of the same peptide have been removed (id est multiple PSMs have been collapsed to one entry). MS_distinct_peptide_level_local_FDR = 1002359, /// distinct peptide-level FDRScore: FDRScore for distinct peptides once redundant identifications of the same peptide have been removed (id est multiple PSMs have been collapsed to one entry). MS_distinct_peptide_level_FDRScore = 1002360, /// distinct peptide-level combined FDRScore: Combined FDRScore for peptides once redundant identifications of the same peptide have been removed (id est multiple PSMs have been collapsed to one entry) specifically obtained for distinct combinations of single, pairs or triplets of search engines making a given peptide, used for integrating results from these distinct pools. MS_distinct_peptide_level_combined_FDRScore = 1002361, /// distinct peptide-level probability: Probability that the reported distinct peptide sequence (irrespective of mass modifications) has been correctly identified via the referenced PSMs. MS_distinct_peptide_level_probability = 1002362, /// search engine specific score for proteins: Search engine specific protein scores. MS_search_engine_specific_score_for_proteins = 1002363, /// protein-level local FDR: Estimation of the local false discovery rate of proteins. MS_protein_level_local_FDR = 1002364, /// FDRScore for proteins: FDRScore for proteins specifically obtained for distinct combinations of single, pairs or triplets of search engines making a given PSM, used for integrating results from these distinct pools. MS_FDRScore_for_proteins = 1002365, /// combined FDRScore for proteins: Combined FDRScore for proteins. MS_combined_FDRScore_for_proteins = 1002366, /// probability for proteins: Probability that a specific protein sequence has been correctly identified from the PSM and distinct peptide evidence, and based on the available protein sequences presented to the analysis software. MS_probability_for_proteins = 1002367, /// search engine specific score for protein groups: Search engine specific protein group scores. MS_search_engine_specific_score_for_protein_groups = 1002368, /// protein group-level global FDR: Estimation of the global false discovery rate of protein groups. MS_protein_group_level_global_FDR = 1002369, /// protein group-level local FDR: Estimation of the local false discovery rate of protein groups. MS_protein_group_level_local_FDR = 1002370, /// protein group-level p-value: Estimation of the p-value for protein groups. MS_protein_group_level_p_value = 1002371, /// protein group-level e-value: Estimation of the e-value for protein groups. MS_protein_group_level_e_value = 1002372, /// protein group-level q-value: Estimation of the q-value for protein groups. MS_protein_group_level_q_value = 1002373, /// protein group-level FDRScore: FDRScore for protein groups. MS_protein_group_level_FDRScore = 1002374, /// protein group-level combined FDRScore: Combined FDRScore for proteins specifically obtained for distinct combinations of single, pairs or triplets of search engines making a given PSM, used for integrating results from these distinct pools. MS_protein_group_level_combined_FDRScore = 1002375, /// protein group-level probability: Probability that at least one of the members of a group of protein sequences has been correctly identified from the PSM and distinct peptide evidence, and based on the available protein sequences presented to the analysis software. MS_protein_group_level_probability = 1002376, /// ProteomeDiscoverer:Relaxed Score Threshold: Specifies the threshold value for relaxed scoring. MS_ProteomeDiscoverer_Relaxed_Score_Threshold = 1002377, /// ProteomeDiscoverer:Strict Score Threshold: Specifies the threshold value for strict scoring. MS_ProteomeDiscoverer_Strict_Score_Threshold = 1002378, /// ProteomeDiscoverer:Peptide Without Protein Cut Off Score: Cut off score for storing peptides that do not belong to a protein. MS_ProteomeDiscoverer_Peptide_Without_Protein_Cut_Off_Score = 1002379, /// false localization rate: Estimation of the false localization rate for modification site assignment. MS_false_localization_rate = 1002380, /// MALDI Solutions LC-MALDI: Software for automated LC-MALDI analysis and reporting. MS_MALDI_Solutions_LC_MALDI = 1002381, /// Shimadzu MALDI-7090: Shimadzu MALDI-7090: MALDI-TOF-TOF. MS_Shimadzu_MALDI_7090 = 1002382, /// SCiLS software: SCiLS software for data acquisition and analysis. MS_SCiLS_software = 1002383, /// SCiLS Lab: SCiLS Lab software. MS_SCiLS_Lab = 1002384, /// SCiLS Lab format: SCiLS Lab file format. MS_SCiLS_Lab_format = 1002385, /// preprocessing software: Preprocessing software. MS_preprocessing_software = 1002386, /// PIA: PIA - Protein Inference Algorithms, a toolbox for protein inference and identification analysis. MS_PIA = 1002387, /// PIA XML format: A compilation of search engine results in the PIA XML format. MS_PIA_XML_format = 1002388, /// PIA workflow parameter: A parameter set for a single PIA analysis. MS_PIA_workflow_parameter = 1002389, /// PIA:FDRScore calculated: Indicates whether the FDR score was calculated for the input file. MS_PIA_FDRScore_calculated = 1002390, /// PIA:Combined FDRScore calculated: Indicates whether the combined FDR score was calculated for the PIA compilation. MS_PIA_Combined_FDRScore_calculated = 1002391, /// PIA:PSM sets created: Indicates whether PSM sets were created. MS_PIA_PSM_sets_created = 1002392, /// PIA:used top identifications for FDR: The number of top identifications per spectrum used for the FDR calculation, 0 means all. MS_PIA_used_top_identifications_for_FDR = 1002393, /// PIA:protein score: The score given to a protein by any protein inference. MS_PIA_protein_score = 1002394, /// PIA:protein inference: The used algorithm for the protein inference using PIA. MS_PIA_protein_inference = 1002395, /// PIA:protein inference filter: A filter used by PIA for the protein inference. MS_PIA_protein_inference_filter = 1002396, /// PIA:protein inference scoring: The used scoring method for the protein inference using PIA. MS_PIA_protein_inference_scoring = 1002397, /// PIA:protein inference used score: The used base score for the protein inference using PIA. MS_PIA_protein_inference_used_score = 1002398, /// PIA:protein inference used PSMs: The method to determine the PSMs used for scoring by the protein inference. MS_PIA_protein_inference_used_PSMs = 1002399, /// PIA:filter: A filter used for the report generation. MS_PIA_filter = 1002400, /// leading protein: At least one protein within each group should be annotated as a leading protein to indicate it has the strongest evidence, or approximately equal evidence as other group members. MS_leading_protein = 1002401, /// non-leading protein: Zero to many proteins within each group should be annotated as non-leading to indicate that other proteins have stronger evidence. MS_non_leading_protein = 1002402, /// group representative: An arbitrary and optional flag applied to exactly one protein per group to indicate it can serve as the representative of the group, amongst leading proteins, in effect serving as a tiebreaker for approaches that require exactly one group representative. MS_group_representative = 1002403, /// count of identified proteins: The number of proteins that have been identified, which must match the number of groups that pass the threshold in the file. MS_count_of_identified_proteins = 1002404, /// protein cluster details: Details describing a protein cluster. MS_protein_cluster_details = 1002405, /// count of identified clusters: The number of protein clusters that have been identified, which must match the number of clusters that pass the threshold in the file. MS_count_of_identified_clusters = 1002406, /// cluster identifier: An identifier applied to protein groups to indicate that they are linked by shared peptides. MS_cluster_identifier = 1002407, /// number of distinct protein sequences: The number of protein clusters that have been identified, which must match the number of clusters that pass the threshold in the file. MS_number_of_distinct_protein_sequences = 1002408, /// marginally distinguished protein: Assigned to a non-leading protein that has some independent evidence to support its presence relative to the leading protein(s), e.g. the protein may have a unique peptide but not sufficient to be promoted as a leading protein of another group. MS_marginally_distinguished_protein = 1002409, /// Anubis: Anubis software for selected reaction monitoring data. MS_Anubis = 1002410, /// TraML format: The TraML format for transitions in SRM from the PSI. File extension '.TraML'. MS_TraML_format = 1002411, /// total XIC area: Summed area of all the extracted ion chromatogram for the peptide (e.g. of all the transitions in SRM). MS_total_XIC_area = 1002412, /// product background: The background area for the quantified transition. MS_product_background = 1002413, /// postprocessing software: Postprocessing software. MS_postprocessing_software = 1002414, /// protein group passes threshold: A Boolean attribute to determine whether the protein group has passed the threshold indicated in the file. MS_protein_group_passes_threshold = 1002415, /// Orbitrap Fusion: Thermo Scientific Orbitrap Fusion. MS_Orbitrap_Fusion = 1002416, /// Orbitrap Fusion ETD: Thermo Scientific Orbitrap Fusion with ETD. MS_Orbitrap_Fusion_ETD = 1002417, /// TSQ Quantiva: Thermo Scientific TSQ Quantiva MS. MS_TSQ_Quantiva = 1002418, /// TSQ Endura: Thermo Scientific TSQ Endura MS. MS_TSQ_Endura = 1002419, /// PASSEL experiment URI: URI that allows access to a PASSEL experiment. MS_PASSEL_experiment_URI = 1002420, /// Paragon input parameter: Search engine input parameters specific to Paragon. MS_Paragon_input_parameter = 1002421, /// Paragon: sample type: The Paragon method setting indicating the type of sample at the high level, generally meaning the type of quantitation labelling or lack thereof. 'Identification' is indicated for samples without any labels for quantitation. MS_Paragon__sample_type = 1002422, /// Paragon: cysteine alkylation: The Paragon method setting indicating the actual cysteine alkylation agent; 'None' is indicated if there was no cysteine alkylation. MS_Paragon__cysteine_alkylation = 1002423, /// Paragon: instrument setting: The Paragon method setting (translating to a large number of lower level settings) indicating the instrument used or a category of instrument. MS_Paragon__instrument_setting = 1002424, /// Paragon: search effort: The Paragon method setting that controls the two major modes of search effort of the Paragon algorithm: the Rapid mode uses a conventional database search, while the Thorough mode uses a hybrid search, starting with the same approach as the Rapid mode but then follows it with a separate tag-based approach enabling a more extensive search. MS_Paragon__search_effort = 1002425, /// Paragon: ID focus: A Paragon method setting that allows the inclusion of large sets of features such as biological modification or substitutions. MS_Paragon__ID_focus = 1002426, /// Paragon: FDR analysis: The Paragon method setting that controls whether FDR analysis is conducted. MS_Paragon__FDR_analysis = 1002427, /// Paragon: quantitation: The Paragon method setting that controls whether quantitation analysis is conducted. MS_Paragon__quantitation = 1002428, /// Paragon: background correction: The Paragon method setting that controls whether the 'Background Correction' analysis is conducted; this processing estimates a correction to the attenuation in extremity ratios that can occur in isobaric quantatitation workflows on complex samples. MS_Paragon__background_correction = 1002429, /// Paragon: bias correction: The Paragon method setting that controls whether 'Bias Correction' is invoked in quantitation analysis; this correction is a normalization to set the central tendency of protein ratios to unity. MS_Paragon__bias_correction = 1002430, /// Paragon: channel to use as denominator in ratios: The Paragon method setting that controls which label channel is used as the denominator in calculating relative expression ratios. MS_Paragon__channel_to_use_as_denominator_in_ratios = 1002431, /// search engine specific input metadata: Search engine specific metadata that are not user-controlled settings. MS_search_engine_specific_input_metadata = 1002432, /// Paragon: modified data dictionary or parameter translation: This metric detects if any changes have been made to the originally installed key control files for the software; if no changes have been made, then the software version and settings are sufficient to enable exact reproduction; if changes have been made, then the modified ParameterTranslation- and ProteinPilot DataDictionary-XML files much also be provided in order to exactly reproduce a result. MS_Paragon__modified_data_dictionary_or_parameter_translation = 1002433, /// number of spectra searched: Number of spectra in a search. MS_number_of_spectra_searched = 1002434, /// data processing start time: The time that a data processing action was started. MS_data_processing_start_time = 1002435, /// Paragon: digestion: The Paragon method setting indicating the actual digestion agent - unlike other search tools, this setting does not include options that control partial specificity like 'semitrypsin'; if trypsin is used, trypsin is set, and partially conforming peptides are found in the Thorough mode of search; 'None' should be indicated only if there was really no digestion done. MS_Paragon__digestion = 1002436, /// number of decoy sequences: The number of decoy sequences, if the concatenated target-decoy approach is used. MS_number_of_decoy_sequences = 1002437, /// spectrum identification list result details: Information about the list of PSMs (SpectrumIdentificationList). MS_spectrum_identification_list_result_details = 1002438, /// final PSM list: A flag on a list of PSMs (SpectrumIdentificationList) to indicate that this is the final set of identifications to be interpreted by consuming software. Amongst the set of SpectrumIdentificationList(s) that are flagged with the term, each spectrum must not be referenced from more than one SpectrumIdentificationResult. MS_final_PSM_list = 1002439, /// intermediate PSM list: A flag on a list of PSMs (SpectrumIdentificationList) to indicate that this is not the final set of identifications to be interpreted by consuming software. This term should be used when results are provided from multiple search engines for the results from each search engine before they are combined to give consensus identifications. Amongst the set of SpectrumIdentificationList(s) that are flagged with the term, each spectrum may be referenced from more than one SpectrumIdentificationResult. MS_intermediate_PSM_list = 1002440, /// Andi-MS format: AIA Analytical Data Interchange file format for mass spectrometry data. MS_Andi_MS_format = 1002441, /// chromatograph file format: The format of the chromatography file being used. This could be a instrument or vendor specific proprietary file format or a converted open file format. MS_chromatograph_file_format = 1002442, /// Andi-CHROM format: AIA Analytical Data Interchange file format for chromatography data. MS_Andi_CHROM_format = 1002443, /// 6420 Triple Quadrupole LC/MS: The 6420 Quadrupole LC/MS system is a Agilent liquid chromatography instrument combined with a Agilent triple quadrupole mass spectrometer. MS_6420_Triple_Quadrupole_LC_MS = 1002444, /// 6460 Triple Quadrupole LC/MS: The 6460 Quadrupole LC/MS system is a Agilent liquid chromatography instrument combined with a Agilent triple quadrupole mass spectrometer. It is similar to the 6420 but adds Agilent Jet Stream (AJS) technology to increase sensitivity. MS_6460_Triple_Quadrupole_LC_MS = 1002445, /// 6490 Triple Quadrupole LC/MS: The 6490 Quadrupole LC/MS system is a Agilent liquid chromatography instrument combined with a Agilent triple quadrupole mass spectrometer. It is similar to the 6420 but adds the Agilent iFunnel technology to increase sensitivity. MS_6490_Triple_Quadrupole_LC_MS = 1002446, /// Paragon:special factor: The Paragon method setting indicating a list of one or more 'special factors', which generally capture secondary effects (relative to other settings) as a set of probabilities of modification features that override the assumed levels. For example the 'gel-based ID' special factor causes an increase probability of oxidation on several resides because of the air exposure impact on a gel, in addition to other effects. MS_Paragon_special_factor = 1002447, /// PEAKS:inChorusPeptideScore: The PEAKS inChorus peptide score. MS_PEAKS_inChorusPeptideScore = 1002448, /// PEAKS:inChorusProteinScore: The PEAKS inChorus protein score. MS_PEAKS_inChorusProteinScore = 1002449, /// param: b ion-H3PO4 DEPRECATED: Ion b-H3PO4: b ion with lost phosphoric acid. MS_param__b_ion_H3PO4_DEPRECATED = 1002450, /// param: y ion-H3PO4 DEPRECATED: Ion y-H3PO4: y ion with lost phosphoric acid. MS_param__y_ion_H3PO4_DEPRECATED = 1002451, /// Maui: The Maltcms Graphical User Interface. MS_Maui = 1002452, /// No fixed modifications searched: No fixed modifications are included as a parameter for the search, and therefore they are not reported. MS_No_fixed_modifications_searched = 1002453, /// No variable modifications searched: No variable modifications are included as a parameter for the search, and therefore they are not reported. MS_No_variable_modifications_searched = 1002454, /// H2O neutral loss: Neutral loss of water. MS_H2O_neutral_loss = 1002455, /// NH3 neutral loss: Neutral loss of ammonia. MS_NH3_neutral_loss = 1002456, /// H3PO4 neutral loss: Neutral loss of phosphoric acid. MS_H3PO4_neutral_loss = 1002457, /// PeptideShaker: PeptideShaker is a software for the interpretation of proteomics identification results. MS_PeptideShaker = 1002458, /// MS Amanda csv format: MS Amanda csv output format. MS_MS_Amanda_csv_format = 1002459, /// protein group-level global FNR: Estimation of the global false negative rate of protein groups. MS_protein_group_level_global_FNR = 1002460, /// protein group-level confidence: Estimation of the global confidence of protein groups. MS_protein_group_level_confidence = 1002461, /// distinct peptide-level global FNR: Estimation of the global false negative rate for distinct peptides once redundant identifications of the same peptide have been removed (id est multiple PSMs have been collapsed to one entry). MS_distinct_peptide_level_global_FNR = 1002462, /// distinct peptide-level global confidence: Estimation of the global confidence for distinct peptides once redundant identifications of the same peptide have been removed (id est multiple PSMs have been collapsed to one entry). MS_distinct_peptide_level_global_confidence = 1002463, /// PSM-level global FNR: Estimation of the global false negative rate of peptide spectrum matches. MS_PSM_level_global_FNR = 1002464, /// PSM-level global confidence: Estimation of the global confidence of peptide spectrum matches. MS_PSM_level_global_confidence = 1002465, /// PeptideShaker PSM score: The probability based PeptideShaker PSM score. MS_PeptideShaker_PSM_score = 1002466, /// PeptideShaker PSM confidence: The probability based PeptideShaker PSM confidence. MS_PeptideShaker_PSM_confidence = 1002467, /// PeptideShaker peptide score: The probability based PeptideShaker peptide score. MS_PeptideShaker_peptide_score = 1002468, /// PeptideShaker peptide confidence: The probability based PeptideShaker peptide confidence. MS_PeptideShaker_peptide_confidence = 1002469, /// PeptideShaker protein group score: The probability based PeptideShaker protein group score. MS_PeptideShaker_protein_group_score = 1002470, /// PeptideShaker protein group confidence: The probability based PeptideShaker protein group confidence. MS_PeptideShaker_protein_group_confidence = 1002471, /// trap-type collision-induced dissociation: A collision-induced dissociation process that occurs in a trap-type collision cell. MS_trap_type_collision_induced_dissociation = 1002472, /// ion series considered in search: The description of the ion fragment series (including charges and neutral losses) that are considered by the search engine. MS_ion_series_considered_in_search = 1002473, /// ProteoAnnotator:non-canonical gene model score: The sum of peptide-level scores for peptides mapped only to non-canonical gene models within the group. MS_ProteoAnnotator_non_canonical_gene_model_score = 1002474, /// ProteoAnnotator:count alternative peptides: The count of the number of peptide sequences mapped to non-canonical gene models only within the group. MS_ProteoAnnotator_count_alternative_peptides = 1002475, /// ion mobility drift time: Drift time of an ion or spectrum of ions as measured in an ion mobility mass spectrometer. This time might refer to the central value of a bin into which all ions within a narrow range of drift time have been aggregated. MS_ion_mobility_drift_time = 1002476, /// mean drift time array: Array of drift times, averaged from a matrix of binned m/z and drift time values, corresponding to spectrum of individual peaks encoded with an m/z array. MS_mean_drift_time_array = 1002477, /// mean charge array: Array of mean charge values where the mean charge is calculated as a weighted mean of the charges of individual peaks that are aggregated into a processed spectrum. MS_mean_charge_array = 1002478, /// regular expression: Regular expression. MS_regular_expression = 1002479, /// regular expression for a digital object identifier (DOI): (10[.][0-9]\{4,\}(?:[.][0-9]+)*/(?:(?![\"&\'<>])[^ \t\\r\n\\v\\f])+). MS_regular_expression_for_a_digital_object_identifier__DOI_ = 1002480, /// higher energy beam-type collision-induced dissociation: A collision-induced dissociation process wherein the projectile ion has the translational energy higher than approximately 1000 eV. MS_higher_energy_beam_type_collision_induced_dissociation = 1002481, /// statistical threshold: Estimated statistical threshold. MS_statistical_threshold = 1002482, /// PSM-level statistical threshold: Estimated statistical threshold at PSM-level. MS_PSM_level_statistical_threshold = 1002483, /// peptide-level statistical threshold: Estimated statistical threshold at peptide-level. MS_peptide_level_statistical_threshold = 1002484, /// protein-level statistical threshold: Estimated statistical threshold at protein-level. MS_protein_level_statistical_threshold = 1002485, /// protein group-level statistical threshold: Estimated statistical threshold at protein group-level. MS_protein_group_level_statistical_threshold = 1002486, /// MassIVE dataset identifier: Dataset identifier issued by the MassIVE repository. A dataset can refer to either a single sample as part of a study, or all samples that are part of the study corresponding to a publication. MS_MassIVE_dataset_identifier = 1002487, /// MassIVE dataset URI: URI that allows the access to one dataset in the MassIVE repository. A dataset can refer to either a single sample as part of a study, or all samples that are part of the study corresponding to a publication. MS_MassIVE_dataset_URI = 1002488, /// special processing: Details describing a special processing. MS_special_processing = 1002489, /// peptide-level scoring: Peptide-level scoring performed. MS_peptide_level_scoring = 1002490, /// modification localization scoring: Modification localization scoring performed. MS_modification_localization_scoring = 1002491, /// consensus scoring: Consensus multiple search engine approach performed. MS_consensus_scoring = 1002492, /// sample pre-fractionation: Sample pre-fractionation performed. MS_sample_pre_fractionation = 1002493, /// cross-linking search: Cross-linking search performed. MS_cross_linking_search = 1002494, /// no special processing: No special processing performed. MS_no_special_processing = 1002495, /// group PSMs by sequence: Group PSMs by distinct peptide sequence ignoring modifications. MS_group_PSMs_by_sequence = 1002496, /// group PSMs by sequence with modifications: Group PSMs by distinct peptide sequence with taking modifications into account. MS_group_PSMs_by_sequence_with_modifications = 1002497, /// group PSMs by sequence with modifications and charge: Group PSMs by distinct peptide sequence with taking modifications and charge into account. MS_group_PSMs_by_sequence_with_modifications_and_charge = 1002498, /// peptide level score: Peptide level score. MS_peptide_level_score = 1002499, /// peptide passes threshold: A Boolean attribute to determine whether the peptide has passed the threshold indicated in the file. MS_peptide_passes_threshold = 1002500, /// no PSM threshold: Indicating that no PSM threshold was used. MS_no_PSM_threshold = 1002501, /// no peptide-level threshold: Indicating that no peptide-level threshold was used. MS_no_peptide_level_threshold = 1002502, /// PSM is used for peptide-level scoring: Flags a PSM that it is used for peptide-level scoring. MS_PSM_is_used_for_peptide_level_scoring = 1002503, /// modification index: The order of modifications to be referenced elsewhere in the document. MS_modification_index = 1002504, /// regular expression for modification localization scoring: ([:digit:]+:[0|1]\{1\}.[:digit:]+:[:digit:]+[|]\{1\}[:digit:]+:(true|false)\{1\}) MS_regular_expression_for_modification_localization_scoring = 1002505, /// modification position score: Modification position score. MS_modification_position_score = 1002506, /// modification rescoring:false localization rate: Mod position score: false localization rate. MS_modification_rescoring_false_localization_rate = 1002507, /// cross-linking attribute: Cross-linking attribute. MS_cross_linking_attribute = 1002508, /// cross-link donor: The Cross-linking donor, assigned according to the following rules: the export software SHOULD use the following rules to choose the cross-link donor as the: longer peptide, then higher peptide neutral mass, then alphabetical order. MS_cross_link_donor = 1002509, /// cross-link receiver: Cross-linking receiver, assigned according to the following rules: the export software SHOULD use the following rules to choose the cross-link donor as the: longer peptide, then higher peptide neutral mass, then alphabetical order. MS_cross_link_receiver = 1002510, /// cross-link spectrum identification item: Cross-linked spectrum identification item. MS_cross_link_spectrum_identification_item = 1002511, /// cross-linking score: Cross-linking scoring value. MS_cross_linking_score = 1002512, /// molecules per cell: The absolute abundance of protein in a cell. MS_molecules_per_cell = 1002513, /// absolute quantitation analysis: Absolute quantitation analysis. MS_absolute_quantitation_analysis = 1002514, /// internal peptide reference used: States whether an internal peptide reference is used or not in absolute quantitation analysis. MS_internal_peptide_reference_used = 1002515, /// internal protein reference used: States whether an internal protein reference is used or not in absolute quantitation analysis. MS_internal_protein_reference_used = 1002516, /// internal reference abundance: The absolute abundance of the spiked in reference peptide or protein used for absolute quantitation analysis. MS_internal_reference_abundance = 1002517, /// Progenesis:protein group normalised abundance: The data type normalised abundance for protein groups produced by Progenesis LC-MS. MS_Progenesis_protein_group_normalised_abundance = 1002518, /// Progenesis:protein group raw abundance: The data type raw abundance for protein groups produced by Progenesis LC-MS. MS_Progenesis_protein_group_raw_abundance = 1002519, /// peptide group ID: Peptide group identifier for peptide-level stats. MS_peptide_group_ID = 1002520, /// mass spectrometry imaging: A technique in which mass spectra are acquired in a spatially resolved manner. This is typically achieved by scanning a laser or primary ion beam over a sample and acquiring a mass spectrum at each position. MS_mass_spectrometry_imaging = 1002521, /// ProteomeDiscoverer:1. Static Terminal Modification: Determine 1st static terminal post-translational modifications (PTMs). MS_ProteomeDiscoverer_1__Static_Terminal_Modification = 1002522, /// Q Exactive HF: Thermo Scientific Q Exactive. MS_Q_Exactive_HF = 1002523, /// PepFinder: Thermo Scientific PepFinder BioPharma analysis software. MS_PepFinder = 1002524, /// TSQ 8000 Evo: Thermo Scientific TSQ 8000 Evo MS. MS_TSQ_8000_Evo = 1002525, /// Exactive Plus: Thermo Scientific Exactive Plus MS. MS_Exactive_Plus = 1002526, /// instrument specific scan attribute: Instrument specific scan properties that are associated with a value. MS_instrument_specific_scan_attribute = 1002527, /// synchronous prefilter selection: Synchronous prefilter selection. MS_synchronous_prefilter_selection = 1002528, /// SPS (synchronous prefilter selection): Synchronous prefilter selection. MS_SPS = MS_synchronous_prefilter_selection, /// resolution array: A data array of resolution values. MS_resolution_array = 1002529, /// baseline array: A data array of signal baseline values (the signal in the absence of analytes). MS_baseline_array = 1002530, /// UIMF format: SQLite-based file format created at Pacific Northwest National Lab. It stores an intermediate analysis of ion-mobility mass spectrometry data. MS_UIMF_format = 1002531, /// UIMF nativeID format: Native format defined by frame=xsd:nonNegativeInteger scan=xsd:nonNegativeInteger frameType=xsd:nonNegativeInteger. MS_UIMF_nativeID_format = 1002532, /// TripleTOF 6600: SCIEX TripleTOF 6600, a quadrupole - quadrupole - time-of-flight mass spectrometer. MS_TripleTOF_6600 = 1002533, /// ProLuCID:xcorr: The ProLuCID result 'XCorr'. MS_ProLuCID_xcorr = 1002534, /// ProLuCID:deltacn: The ProLuCID result 'DeltaCn'. MS_ProLuCID_deltacn = 1002535, /// D-Score: D-Score for PTM site location at the PSM-level. MS_D_Score = 1002536, /// MD-Score: MD-Score for PTM site location at the PSM-level. MS_MD_Score = 1002537, /// PTM localization confidence metric: Localization confidence metric for a post translational modification (PTM). MS_PTM_localization_confidence_metric = 1002538, /// PeptideShaker PTM confidence type: PeptideShaker quality criteria for the confidence of PTM localizations. MS_PeptideShaker_PTM_confidence_type = 1002539, /// PeptideShaker PSM confidence type: PeptideShaker quality criteria for the confidence of PSM's. MS_PeptideShaker_PSM_confidence_type = 1002540, /// PeptideShaker peptide confidence type: PeptideShaker quality criteria for the confidence of peptide identifications. MS_PeptideShaker_peptide_confidence_type = 1002541, /// PeptideShaker protein confidence type: PeptideShaker quality criteria for the confidence of protein identifications. MS_PeptideShaker_protein_confidence_type = 1002542, /// xiFDR: Target/Decoy based FDR estimation for cross-linking peptide-identifications. MS_xiFDR = 1002543, /// xi: Search engine for cross-linked peptides. MS_xi = 1002544, /// xi:score: The xi result 'Score'. MS_xi_score = 1002545, /// Skyline mzQuantML converter: A software package to convert Skyline report to mzQuantML. MS_Skyline_mzQuantML_converter = 1002546, /// normalized spectral abundance factor: A normalized spectral abundance factor (NSAF). MS_normalized_spectral_abundance_factor = 1002547, /// distributed normalized spectral abundance factor: A distributed normalized spectral abundance factor (dNSAF. MS_distributed_normalized_spectral_abundance_factor = 1002548, /// peptide-level PTM localization score: A score that assign confidence to the localization of an amino acid modification on a peptide sequence at the peptide-level. MS_peptide_level_PTM_localization_score = 1002549, /// peptide:phosphoRS score: phosphoRS score for PTM site location at the peptide-level. MS_peptide_phosphoRS_score = 1002550, /// peptide:Ascore: A-score for PTM site location at the peptide-level. MS_peptide_Ascore = 1002551, /// peptide:H-Score: H-Score for peptide phosphorylation site location at the peptide-level. MS_peptide_H_Score = 1002552, /// peptide:D-Score: D-Score for PTM site location at the peptide-level. MS_peptide_D_Score = 1002553, /// peptide:MD-Score: MD-Score for PTM site location at the peptide-level. MS_peptide_MD_Score = 1002554, /// PTM localization score threshold: Threshold for PTM site location score. MS_PTM_localization_score_threshold = 1002555, /// Ascore threshold: Threshold for Ascore PTM site location score. MS_Ascore_threshold = 1002556, /// D-Score threshold: Threshold for D-score PTM site location score. MS_D_Score_threshold = 1002557, /// MD-Score threshold: Threshold for MD-score PTM site location score. MS_MD_Score_threshold = 1002558, /// H-Score threshold: Threshold for H-score PTM site location score. MS_H_Score_threshold = 1002559, /// Mascot:PTM site assignment confidence threshold: Threshold for Mascot PTM site assignment confidence. MS_Mascot_PTM_site_assignment_confidence_threshold = 1002561, /// MSQuant:PTM-score threshold: Threshold for MSQuant:PTM-score. MS_MSQuant_PTM_score_threshold = 1002562, /// MaxQuant:PTM Score threshold: Threshold for MaxQuant:PTM Score. MS_MaxQuant_PTM_Score_threshold = 1002563, /// MaxQuant:P-site localization probability threshold: Threshold for MaxQuant:P-site localization probability. MS_MaxQuant_P_site_localization_probability_threshold = 1002564, /// MaxQuant:PTM Delta Score threshold: Threshold for MaxQuant:PTM Delta Score. MS_MaxQuant_PTM_Delta_Score_threshold = 1002565, /// MaxQuant:Phospho (STY) Probabilities threshold: Threshold for MaxQuant:Phospho (STY) Probabilities. MS_MaxQuant_Phospho__STY__Probabilities_threshold = 1002566, /// phosphoRS score threshold: Threshold for phosphoRS score. MS_phosphoRS_score_threshold = 1002567, /// phosphoRS site probability threshold: Threshold for phosphoRS site probability. MS_phosphoRS_site_probability_threshold = 1002568, /// ProteomeDiscoverer:Number of Spectra Processed At Once: Number of spectra processed at once in a ProteomeDiscoverer search. MS_ProteomeDiscoverer_Number_of_Spectra_Processed_At_Once = 1002569, /// sequence multiply subsumable protein: A protein for which the matched peptide sequences are the same, or a subset of, the matched peptide sequences for two or more other proteins combined. These other proteins need not all be in the same group. MS_sequence_multiply_subsumable_protein = 1002570, /// spectrum multiply subsumable protein: A protein for which the matched spectra are the same, or a subset of, the matched spectra for two or more other proteins combined. These other proteins need not all be in the same group. MS_spectrum_multiply_subsumable_protein = 1002571, /// protein detection statistical threshold: Estimated statistical threshold used for protein detection. MS_protein_detection_statistical_threshold = 1002572, /// spectrum identification statistical threshold: Estimated statistical threshold used for spectrum identification. MS_spectrum_identification_statistical_threshold = 1002573, /// ASAPRatio: A program in the TPP that calculates PSM, peptide, and protein-level abundances based on 2-channel isotope-labelled data such as ICAT, SILAC, etc. MS_ASAPRatio = 1002574, /// Tide: Tide open-source sequence search program developed at the University of Washington. MS_Tide = 1002575, /// Andromeda result file: Andromeda result file output format. MS_Andromeda_result_file = 1002576, /// 2000 QTRAP: SCIEX 2000 QTRAP. MS_2000_QTRAP = 1002577, /// 2500 QTRAP: SCIEX 2500 QTRAP. MS_2500_QTRAP = 1002578, /// 3500 QTRAP: SCIEX 3500 QTRAP. MS_3500_QTRAP = 1002579, /// QTRAP 4500: SCIEX QTRAP 4500. MS_QTRAP_4500 = 1002580, /// QTRAP 6500: SCIEX QTRAP 6500. MS_QTRAP_6500 = 1002581, /// QTRAP 6500+: SCIEX QTRAP 6500+. MS_QTRAP_6500_ = 1002582, /// TripleTOF 4600: SCIEX TripleTOF 4600 time-of-flight mass spectrometer. MS_TripleTOF_4600 = 1002583, /// TripleTOF 5600+: SCIEX TripleTOF 5600+ time-of-flight mass spectrometer. MS_TripleTOF_5600_ = 1002584, /// API 100: Applied Biosystems/MDS SCIEX API 100 MS. MS_API_100 = 1002585, /// API 100LC: Applied Biosystems/MDS SCIEX API 100LC MS. MS_API_100LC = 1002586, /// API 165: Applied Biosystems/MDS SCIEX API 165 MS. MS_API_165 = 1002587, /// API 300: Applied Biosystems/MDS SCIEX API 300 MS. MS_API_300 = 1002588, /// API 350: Applied Biosystems/MDS SCIEX API 350 MS. MS_API_350 = 1002589, /// API 365: Applied Biosystems/MDS SCIEX API 365 MS. MS_API_365 = 1002590, /// Triple Quad 3500: SCIEX Triple Quad 3500. MS_Triple_Quad_3500 = 1002591, /// Triple Quad 4500: SCIEX Triple Quad 4500. MS_Triple_Quad_4500 = 1002592, /// Triple Quad 5500: SCIEX Triple Quad 5500. MS_Triple_Quad_5500 = 1002593, /// Triple Quad 6500: SCIEX Triple Quad 6500. MS_Triple_Quad_6500 = 1002594, /// Triple Quad 6500+: SCIEX Triple Quad 6500+. MS_Triple_Quad_6500_ = 1002595, /// DeBunker:score threshold: Threshold for DeBunker PTM site location score. MS_DeBunker_score_threshold = 10025560, /// unimod root node: The root node of the unimod modifications ontology. UNIMOD_unimod_root_node = 100000000, /// Acetyl: Acetylation. UNIMOD_Acetyl = 100000001, /// Amidated: Amidation. UNIMOD_Amidated = 100000002, /// Biotin: Biotinylation. UNIMOD_Biotin = 100000003, /// Carbamidomethyl: Iodoacetamide derivative. UNIMOD_Carbamidomethyl = 100000004, /// Carbamyl: Carbamylation. UNIMOD_Carbamyl = 100000005, /// Carboxymethyl: Iodoacetic acid derivative. UNIMOD_Carboxymethyl = 100000006, /// Deamidated: Deamidation. UNIMOD_Deamidated = 100000007, /// ICAT-G: Gygi ICAT(TM) d0. UNIMOD_ICAT_G = 100000008, /// ICAT-G:2H(8): Gygi ICAT(TM) d8. UNIMOD_ICAT_G_2H_8_ = 100000009, /// Met->Hse: Homoserine. UNIMOD_Met__Hse = 100000010, /// Met->Hsl: Homoserine lactone. UNIMOD_Met__Hsl = 100000011, /// ICAT-D:2H(8): Applied Biosystems original ICAT(TM) d8. UNIMOD_ICAT_D_2H_8_ = 100000012, /// ICAT-D: Applied Biosystems original ICAT(TM) d0. UNIMOD_ICAT_D = 100000013, /// NIPCAM: N-isopropylcarboxamidomethyl. UNIMOD_NIPCAM = 100000017, /// PEO-Iodoacetyl-LC-Biotin: Biotinyl-iodoacetamidyl-3,6-dioxaoctanediamine. UNIMOD_PEO_Iodoacetyl_LC_Biotin = 100000020, /// Phospho: Phosphorylation. UNIMOD_Phospho = 100000021, /// Dehydrated: Dehydration. UNIMOD_Dehydrated = 100000023, /// Propionamide: Acrylamide adduct. UNIMOD_Propionamide = 100000024, /// Pyridylacetyl: Pyridylacetyl. UNIMOD_Pyridylacetyl = 100000025, /// Pyro-carbamidomethyl: S-carbamoylmethylcysteine cyclization (N-terminus). UNIMOD_Pyro_carbamidomethyl = 100000026, /// Glu->pyro-Glu: Pyro-glu from E. UNIMOD_Glu__pyro_Glu = 100000027, /// Gln->pyro-Glu: Pyro-glu from Q. UNIMOD_Gln__pyro_Glu = 100000028, /// SMA: N-Succinimidyl-2-morpholine acetate. UNIMOD_SMA = 100000029, /// Cation:Na: Sodium adduct. UNIMOD_Cation_Na = 100000030, /// Pyridylethyl: S-pyridylethylation. UNIMOD_Pyridylethyl = 100000031, /// Methyl: Methylation. UNIMOD_Methyl = 100000034, /// Oxidation: Oxidation or Hydroxylation. UNIMOD_Oxidation = 100000035, /// Dimethyl: Di-Methylation. UNIMOD_Dimethyl = 100000036, /// Trimethyl: Tri-Methylation. UNIMOD_Trimethyl = 100000037, /// Methylthio: Beta-methylthiolation. UNIMOD_Methylthio = 100000039, /// Sulfo: O-Sulfonation. UNIMOD_Sulfo = 100000040, /// Hex: Hexose. UNIMOD_Hex = 100000041, /// Lipoyl: Lipoyl. UNIMOD_Lipoyl = 100000042, /// HexNAc: N-Acetylhexosamine. UNIMOD_HexNAc = 100000043, /// Farnesyl: Farnesylation. UNIMOD_Farnesyl = 100000044, /// Myristoyl: Myristoylation. UNIMOD_Myristoyl = 100000045, /// PyridoxalPhosphate: Pyridoxal phosphate. UNIMOD_PyridoxalPhosphate = 100000046, /// Palmitoyl: Palmitoylation. UNIMOD_Palmitoyl = 100000047, /// GeranylGeranyl: Geranyl-geranyl. UNIMOD_GeranylGeranyl = 100000048, /// Phosphopantetheine: Phosphopantetheine. UNIMOD_Phosphopantetheine = 100000049, /// FAD: Flavin adenine dinucleotide. UNIMOD_FAD = 100000050, /// Tripalmitate: N-acyl diglyceride cysteine. UNIMOD_Tripalmitate = 100000051, /// Guanidinyl: Guanidination. UNIMOD_Guanidinyl = 100000052, /// HNE: 4-hydroxynonenal (HNE). UNIMOD_HNE = 100000053, /// Glucuronyl: Hexuronic acid. UNIMOD_Glucuronyl = 100000054, /// Glutathione: Glutathione disulfide. UNIMOD_Glutathione = 100000055, /// Acetyl:2H(3): Acetate labeling reagent (N-term & K) (heavy form, +3amu). UNIMOD_Acetyl_2H_3_ = 100000056, /// Propionyl: Propionate labeling reagent light form (N-term & K). UNIMOD_Propionyl = 100000058, /// Propionyl:13C(3): Propionate labeling reagent heavy form (+3amu), N-term & K. UNIMOD_Propionyl_13C_3_ = 100000059, /// GIST-Quat: Quaternary amine labeling reagent light form (N-term & K). UNIMOD_GIST_Quat = 100000060, /// GIST-Quat:2H(3): Quaternary amine labeling reagent heavy (+3amu) form, N-term & K. UNIMOD_GIST_Quat_2H_3_ = 100000061, /// GIST-Quat:2H(6): Quaternary amine labeling reagent heavy form (+6amu), N-term & K. UNIMOD_GIST_Quat_2H_6_ = 100000062, /// GIST-Quat:2H(9): Quaternary amine labeling reagent heavy form (+9amu), N-term & K. UNIMOD_GIST_Quat_2H_9_ = 100000063, /// Succinyl: Succinic anhydride labeling reagent light form (N-term & K). UNIMOD_Succinyl = 100000064, /// Succinyl:2H(4): Succinic anhydride labeling reagent, heavy form (+4amu, 4H2), N-term & K. UNIMOD_Succinyl_2H_4_ = 100000065, /// Succinyl:13C(4): Succinic anhydride labeling reagent, heavy form (+4amu, 4C13), N-term & K. UNIMOD_Succinyl_13C_4_ = 100000066, /// Iminobiotin: Iminobiotinylation. UNIMOD_Iminobiotin = 100000089, /// ESP: ESP-Tag light d0. UNIMOD_ESP = 100000090, /// ESP:2H(10): ESP-Tag heavy d10. UNIMOD_ESP_2H_10_ = 100000091, /// NHS-LC-Biotin: NHS-LC-Biotin. UNIMOD_NHS_LC_Biotin = 100000092, /// EDT-maleimide-PEO-biotin: EDT-maleimide-PEO-biotin. UNIMOD_EDT_maleimide_PEO_biotin = 100000093, /// IMID: IMID d0. UNIMOD_IMID = 100000094, /// IMID:2H(4): IMID d4. UNIMOD_IMID_2H_4_ = 100000095, /// Propionamide:2H(3): Acrylamide d3. UNIMOD_Propionamide_2H_3_ = 100000097, /// ICAT-C: Applied Biosystems cleavable ICAT(TM) light. UNIMOD_ICAT_C = 100000105, /// ICAT-C:13C(9): Applied Biosystems cleavable ICAT(TM) heavy. UNIMOD_ICAT_C_13C_9_ = 100000106, /// FormylMet: Addition of N-formyl met. UNIMOD_FormylMet = 100000107, /// Nethylmaleimide: N-ethylmaleimide on cysteines. UNIMOD_Nethylmaleimide = 100000108, /// OxLysBiotinRed: Oxidized lysine biotinylated with biotin-LC-hydrazide, reduced. UNIMOD_OxLysBiotinRed = 100000112, /// OxLysBiotin: Oxidized lysine biotinylated with biotin-LC-hydrazide. UNIMOD_OxLysBiotin = 100000113, /// OxProBiotinRed: Oxidized proline biotinylated with biotin-LC-hydrazide, reduced. UNIMOD_OxProBiotinRed = 100000114, /// OxProBiotin: Oxidized Proline biotinylated with biotin-LC-hydrazide. UNIMOD_OxProBiotin = 100000115, /// OxArgBiotin: Oxidized arginine biotinylated with biotin-LC-hydrazide. UNIMOD_OxArgBiotin = 100000116, /// OxArgBiotinRed: Oxidized arginine biotinylated with biotin-LC-hydrazide, reduced. UNIMOD_OxArgBiotinRed = 100000117, /// EDT-iodoacetyl-PEO-biotin: EDT-iodo-PEO-biotin. UNIMOD_EDT_iodoacetyl_PEO_biotin = 100000118, /// IBTP: Thio Ether Formation - BTP Adduct. UNIMOD_IBTP = 100000119, /// GG: Ubiquitinylation residue. UNIMOD_GG = 100000121, /// Formyl: Formylation. UNIMOD_Formyl = 100000122, /// ICAT-H: N-iodoacetyl, p-chlorobenzyl-12C6-glucamine. UNIMOD_ICAT_H = 100000123, /// ICAT-H:13C(6): N-iodoacetyl, p-chlorobenzyl-13C6-glucamine. UNIMOD_ICAT_H_13C_6_ = 100000124, /// Thioacyl: 3-sulfanylpropanoyl. UNIMOD_Thioacyl = 100000126, /// Fluoro: Fluorination. UNIMOD_Fluoro = 100000127, /// Fluorescein: 5-Iodoacetamidofluorescein (Molecular Probe, Eugene, OR). UNIMOD_Fluorescein = 100000128, /// Iodo: Iodination. UNIMOD_Iodo = 100000129, /// Diiodo: Di-Iodination. UNIMOD_Diiodo = 100000130, /// Triiodo: Tri-Iodination. UNIMOD_Triiodo = 100000131, /// Myristoleyl: (cis-delta 5)-tetradecaenoyl. UNIMOD_Myristoleyl = 100000134, /// Myristoyl+Delta:H(-4): (cis,cis-delta 5, delta 8)-tetradecadienoyl. UNIMOD_Myristoyl_Delta_H__4_ = 100000135, /// Benzoyl: Labeling reagent light form (N-term & K). UNIMOD_Benzoyl = 100000136, /// Hex(5)HexNAc(2): N-linked glycan core. UNIMOD_Hex_5_HexNAc_2_ = 100000137, /// Dansyl: 5-dimethylaminonaphthalene-1-sulfonyl. UNIMOD_Dansyl = 100000139, /// a-type-ion: ISD a-series (C-Term). UNIMOD_a_type_ion = 100000140, /// Amidine: Amidination of lysines or N-terminal amines with methyl acetimidate. UNIMOD_Amidine = 100000141, /// HexNAc(1)dHex(1): HexNAc1dHex1. UNIMOD_HexNAc_1_dHex_1_ = 100000142, /// HexNAc(2): HexNAc2. UNIMOD_HexNAc_2_ = 100000143, /// Hex(3): Hex3. UNIMOD_Hex_3_ = 100000144, /// HexNAc(1)dHex(2): HexNAc1dHex2. UNIMOD_HexNAc_1_dHex_2_ = 100000145, /// Hex(1)HexNAc(1)dHex(1): Hex1HexNAc1dHex1. UNIMOD_Hex_1_HexNAc_1_dHex_1_ = 100000146, /// HexNAc(2)dHex(1): HexNAc2dHex1. UNIMOD_HexNAc_2_dHex_1_ = 100000147, /// Hex(1)HexNAc(2): Hex1HexNAc2. UNIMOD_Hex_1_HexNAc_2_ = 100000148, /// Hex(1)HexNAc(1)NeuAc(1): Hex1HexNAc1NeuAc1. UNIMOD_Hex_1_HexNAc_1_NeuAc_1_ = 100000149, /// HexNAc(2)dHex(2): HexNAc2dHex2. UNIMOD_HexNAc_2_dHex_2_ = 100000150, /// Hex(1)HexNAc(2)Pent(1): Hex1HexNAc2Pent1. UNIMOD_Hex_1_HexNAc_2_Pent_1_ = 100000151, /// Hex(1)HexNAc(2)dHex(1): Hex1HexNAc2dHex1. UNIMOD_Hex_1_HexNAc_2_dHex_1_ = 100000152, /// Hex(2)HexNAc(2): Hex2HexNAc2. UNIMOD_Hex_2_HexNAc_2_ = 100000153, /// Hex(3)HexNAc(1)Pent(1): Hex3HexNAc1Pent1. UNIMOD_Hex_3_HexNAc_1_Pent_1_ = 100000154, /// Hex(1)HexNAc(2)dHex(1)Pent(1): Hex1HexNAc2dHex1Pent1. UNIMOD_Hex_1_HexNAc_2_dHex_1_Pent_1_ = 100000155, /// Hex(1)HexNAc(2)dHex(2): Hex1HexNAc2dHex2. UNIMOD_Hex_1_HexNAc_2_dHex_2_ = 100000156, /// Hex(2)HexNAc(2)Pent(1): Hex2HexNAc2Pent1. UNIMOD_Hex_2_HexNAc_2_Pent_1_ = 100000157, /// Hex(2)HexNAc(2)dHex(1): Hex2HexNAc2dHex1. UNIMOD_Hex_2_HexNAc_2_dHex_1_ = 100000158, /// Hex(3)HexNAc(2): Hex3HexNAc2. UNIMOD_Hex_3_HexNAc_2_ = 100000159, /// Hex(1)HexNAc(1)NeuAc(2): Hex1HexNAc1NeuAc2. UNIMOD_Hex_1_HexNAc_1_NeuAc_2_ = 100000160, /// Hex(3)HexNAc(2)Phos(1): Hex(3) HexNAc(2) Phos. UNIMOD_Hex_3_HexNAc_2_Phos_1_ = 100000161, /// Delta:S(-1)Se(1): Selenium replaces sulfur. UNIMOD_Delta_S__1_Se_1_ = 100000162, /// Delta:H(1)N(-1)18O(1): Glycosylated asparagine 18O labeling. UNIMOD_Delta_H_1_N__1_18O_1_ = 100000170, /// NBS:13C(6): Shimadzu NBS-13C. UNIMOD_NBS_13C_6_ = 100000171, /// NBS: Shimadzu NBS-12C. UNIMOD_NBS = 100000172, /// BHT: Michael addition of BHT quinone methide to Cysteine and Lysine. UNIMOD_BHT = 100000176, /// DAET: Phosphorylation to amine thiol. UNIMOD_DAET = 100000178, /// Label:13C(9): 13C(9) Silac label. UNIMOD_Label_13C_9_ = 100000184, /// Label:13C(9)+Phospho: C13 label (Phosphotyrosine). UNIMOD_Label_13C_9__Phospho = 100000185, /// HPG: Hydroxyphenylglyoxal arginine. UNIMOD_HPG = 100000186, /// 2HPG: Bis(hydroxphenylglyoxal) arginine. UNIMOD_2HPG = 100000187, /// Label:13C(6): 13C(6) Silac label. UNIMOD_Label_13C_6_ = 100000188, /// Label:18O(2): O18 label at both C-terminal oxygens. UNIMOD_Label_18O_2_ = 100000193, /// AccQTag: 6-aminoquinolyl-N-hydroxysuccinimidyl carbamate. UNIMOD_AccQTag = 100000194, /// QAT: APTA-d0. UNIMOD_QAT = 100000195, /// QAT:2H(3): APTA d3. UNIMOD_QAT_2H_3_ = 100000196, /// EQAT: EAPTA d0. UNIMOD_EQAT = 100000197, /// EQAT:2H(5): EAPTA d5. UNIMOD_EQAT_2H_5_ = 100000198, /// Dimethyl:2H(4): DiMethyl-CHD2. UNIMOD_Dimethyl_2H_4_ = 100000199, /// Ethanedithiol: EDT. UNIMOD_Ethanedithiol = 100000200, /// Delta:H(6)C(6)O(1): Acrolein addition +94. UNIMOD_Delta_H_6_C_6_O_1_ = 100000205, /// Delta:H(4)C(3)O(1): Acrolein addition +56. UNIMOD_Delta_H_4_C_3_O_1_ = 100000206, /// Delta:H(2)C(3): Acrolein addition +38. UNIMOD_Delta_H_2_C_3_ = 100000207, /// Delta:H(4)C(6): Acrolein addition +76. UNIMOD_Delta_H_4_C_6_ = 100000208, /// Delta:H(8)C(6)O(2): Acrolein addition +112. UNIMOD_Delta_H_8_C_6_O_2_ = 100000209, /// NEIAA: N-ethyl iodoacetamide-d0. UNIMOD_NEIAA = 100000211, /// NEIAA:2H(5): N-ethyl iodoacetamide-d5. UNIMOD_NEIAA_2H_5_ = 100000212, /// ADP-Ribosyl: ADP Ribose addition. UNIMOD_ADP_Ribosyl = 100000213, /// iTRAQ4plex: Representative mass and accurate mass for 116 & 117. UNIMOD_iTRAQ4plex = 100000214, /// IGBP: Light IDBEST tag for quantitation. UNIMOD_IGBP = 100000243, /// Crotonaldehyde: Crotonaldehyde. UNIMOD_Crotonaldehyde = 100000253, /// Delta:H(2)C(2): Acetaldehyde +26. UNIMOD_Delta_H_2_C_2_ = 100000254, /// Delta:H(4)C(2): Acetaldehyde +28. UNIMOD_Delta_H_4_C_2_ = 100000255, /// Delta:H(4)C(3): Propionaldehyde +40. UNIMOD_Delta_H_4_C_3_ = 100000256, /// Label:18O(1): O18 Labeling. UNIMOD_Label_18O_1_ = 100000258, /// Label:13C(6)15N(2): 13C(6) 15N(2) Silac label. UNIMOD_Label_13C_6_15N_2_ = 100000259, /// Thiophospho: Thiophosphorylation. UNIMOD_Thiophospho = 100000260, /// SPITC: 4-sulfophenyl isothiocyanate. UNIMOD_SPITC = 100000261, /// Label:2H(3): Trideuteration. UNIMOD_Label_2H_3_ = 100000262, /// PET: Phosphorylation to pyridyl thiol. UNIMOD_PET = 100000264, /// Label:13C(6)15N(4): 13C(6) 15N(4) Silac label. UNIMOD_Label_13C_6_15N_4_ = 100000267, /// Label:13C(5)15N(1): 13C(5) 15N(1) Silac label. UNIMOD_Label_13C_5_15N_1_ = 100000268, /// Label:13C(9)15N(1): 13C(9) 15N(1) Silac label. UNIMOD_Label_13C_9_15N_1_ = 100000269, /// Cytopiloyne: Nucleophilic addtion to cytopiloyne. UNIMOD_Cytopiloyne = 100000270, /// Cytopiloyne+water: Nucleophilic addition to cytopiloyne+H2O. UNIMOD_Cytopiloyne_water = 100000271, /// CAF: Sulfonation of N-terminus. UNIMOD_CAF = 100000272, /// Xlink:SSD: Covalent modification of lysine by cross-linking reagent. UNIMOD_Xlink_SSD = 100000273, /// Nitrosyl: S-nitrosylation. UNIMOD_Nitrosyl = 100000275, /// AEBS: Aminoethylbenzenesulfonylation. UNIMOD_AEBS = 100000276, /// Ethanolyl: Ethanolation. UNIMOD_Ethanolyl = 100000278, /// Ethyl: Ethylation. UNIMOD_Ethyl = 100000280, /// CoenzymeA: Cysteine modified Coenzyme A. UNIMOD_CoenzymeA = 100000281, /// Methyl:2H(2): Deuterium Methylation of Lysine. UNIMOD_Methyl_2H_2_ = 100000284, /// SulfanilicAcid: Light Sulfanilic Acid (SA) C12. UNIMOD_SulfanilicAcid = 100000285, /// SulfanilicAcid:13C(6): Heavy Sulfanilic Acid (SA) C13. UNIMOD_SulfanilicAcid_13C_6_ = 100000286, /// Trp->Oxolactone: Tryptophan oxidation to oxolactone. UNIMOD_Trp__Oxolactone = 100000288, /// Biotin-PEO-Amine: Biotin polyethyleneoxide amine. UNIMOD_Biotin_PEO_Amine = 100000289, /// Biotin-HPDP: Pierce EZ-Link Biotin-HPDP. UNIMOD_Biotin_HPDP = 100000290, /// Delta:Hg(1): Mercury Mercaptan. UNIMOD_Delta_Hg_1_ = 100000291, /// IodoU-AMP: Cross-link of (Iodo)-uracil MP with W,F,Y. UNIMOD_IodoU_AMP = 100000292, /// CAMthiopropanoyl: 3-(carbamidomethylthio)propanoyl. UNIMOD_CAMthiopropanoyl = 100000293, /// IED-Biotin: Biotinoyl-iodoacetyl-ethylenediamine. UNIMOD_IED_Biotin = 100000294, /// dHex: Fucose. UNIMOD_dHex = 100000295, /// Methyl:2H(3): Deuterated methyl ester. UNIMOD_Methyl_2H_3_ = 100000298, /// Carboxy: Carboxylation. UNIMOD_Carboxy = 100000299, /// Bromobimane: Monobromobimane derivative. UNIMOD_Bromobimane = 100000301, /// Menadione: Menadione quinone derivative. UNIMOD_Menadione = 100000302, /// DeStreak: Cysteine mercaptoethanol. UNIMOD_DeStreak = 100000303, /// dHex(1)Hex(3)HexNAc(4): Fucosylated biantennary (-2 galactose). UNIMOD_dHex_1_Hex_3_HexNAc_4_ = 100000305, /// dHex(1)Hex(4)HexNAc(4): Fucosylated biantennary (-1 galactose). UNIMOD_dHex_1_Hex_4_HexNAc_4_ = 100000307, /// dHex(1)Hex(5)HexNAc(4): Fucosylated biantennary. UNIMOD_dHex_1_Hex_5_HexNAc_4_ = 100000308, /// Hex(3)HexNAc(4): Biantennary (-2 galactose). UNIMOD_Hex_3_HexNAc_4_ = 100000309, /// Hex(4)HexNAc(4): Biantennary (-1 galactose). UNIMOD_Hex_4_HexNAc_4_ = 100000310, /// Hex(5)HexNAc(4): Biantennary. UNIMOD_Hex_5_HexNAc_4_ = 100000311, /// Cysteinyl: Cysteinylation. UNIMOD_Cysteinyl = 100000312, /// Lys-loss: Loss of C-terminal K from Heavy Chain of MAb. UNIMOD_Lys_loss = 100000313, /// Nmethylmaleimide: Nmethylmaleimide. UNIMOD_Nmethylmaleimide = 100000314, /// DimethylpyrroleAdduct: 2,5-dimethypyrrole. UNIMOD_DimethylpyrroleAdduct = 100000316, /// Delta:H(2)C(5): MDA adduct +62. UNIMOD_Delta_H_2_C_5_ = 100000318, /// Delta:H(2)C(3)O(1): MDA adduct +54. UNIMOD_Delta_H_2_C_3_O_1_ = 100000319, /// Nethylmaleimide+water: Nethylmaleimidehydrolysis. UNIMOD_Nethylmaleimide_water = 100000320, /// Xlink:B10621: Bis-N-I-sulfonerahodamine. UNIMOD_Xlink_B10621 = 100000323, /// DTBP: Dimethyl 3,3\'-dithiobispropionimidate. UNIMOD_DTBP = 100000324, /// FP-Biotin: 10-ethoxyphosphinyl-N-(biotinamidopentyl)decanamide. UNIMOD_FP_Biotin = 100000325, /// Delta:H(4)C(2)O(-1)S(1): S-Ethylcystine from Serine. UNIMOD_Delta_H_4_C_2_O__1_S_1_ = 100000327, /// Methyl:2H(3)13C(1): Monomethylation. UNIMOD_Methyl_2H_3_13C_1_ = 100000329, /// Dimethyl:2H(6)13C(2): Dimethylation. UNIMOD_Dimethyl_2H_6_13C_2_ = 100000330, /// Thiophos-S-S-biotin: Thiophosphate labeled with biotin-HPDP. UNIMOD_Thiophos_S_S_biotin = 100000332, /// Can-FP-biotin: 6-N-biotinylaminohexyl isopropyl phosphate. UNIMOD_Can_FP_biotin = 100000333, /// HNE+Delta:H(2): Reduced 4-Hydroxynonenal. UNIMOD_HNE_Delta_H_2_ = 100000335, /// Methylamine: Michael addition with methylamine. UNIMOD_Methylamine = 100000337, /// Bromo: Bromination. UNIMOD_Bromo = 100000340, /// Amino: Tyrosine oxidation to 2-aminotyrosine. UNIMOD_Amino = 100000342, /// Argbiotinhydrazide: Oxidized Arginine biotinylated with biotin hydrazide. UNIMOD_Argbiotinhydrazide = 100000343, /// Arg->GluSA: Arginine oxidation to glutamic semialdehyde. UNIMOD_Arg__GluSA = 100000344, /// Trioxidation: Cysteine oxidation to cysteic acid. UNIMOD_Trioxidation = 100000345, /// His->Asn: His->Asn substitution. UNIMOD_His__Asn = 100000348, /// His->Asp: His->Asp substitution. UNIMOD_His__Asp = 100000349, /// Trp->Hydroxykynurenin: Tryptophan oxidation to hydroxykynurenin. UNIMOD_Trp__Hydroxykynurenin = 100000350, /// Trp->Kynurenin: Tryptophan oxidation to kynurenin. UNIMOD_Trp__Kynurenin = 100000351, /// Lys->Allysine: Lysine oxidation to aminoadipic semialdehyde. UNIMOD_Lys__Allysine = 100000352, /// Lysbiotinhydrazide: Oxidized Lysine biotinylated with biotin hydrazide. UNIMOD_Lysbiotinhydrazide = 100000353, /// Nitro: Oxidation to nitro. UNIMOD_Nitro = 100000354, /// probiotinhydrazide: Oxidized proline biotinylated with biotin hydrazide. UNIMOD_probiotinhydrazide = 100000357, /// Pro->pyro-Glu: Proline oxidation to pyroglutamic acid. UNIMOD_Pro__pyro_Glu = 100000359, /// Pro->Pyrrolidinone: Proline oxidation to pyrrolidinone. UNIMOD_Pro__Pyrrolidinone = 100000360, /// Thrbiotinhydrazide: Oxidized Threonine biotinylated with biotin hydrazide. UNIMOD_Thrbiotinhydrazide = 100000361, /// Diisopropylphosphate: O-Diisopropylphosphorylation. UNIMOD_Diisopropylphosphate = 100000362, /// Isopropylphospho: O-Isopropylphosphorylation. UNIMOD_Isopropylphospho = 100000363, /// ICPL:13C(6): Bruker Daltonics SERVA-ICPL(TM) quantification chemistry, heavy form. UNIMOD_ICPL_13C_6_ = 100000364, /// ICPL: Bruker Daltonics SERVA-ICPL(TM) quantification chemistry, light form. UNIMOD_ICPL = 100000365, /// Deamidated:18O(1): Deamidation in presence of O18. UNIMOD_Deamidated_18O_1_ = 100000366, /// Cys->Dha: Dehydroalanine (from Cysteine). UNIMOD_Cys__Dha = 100000368, /// Pro->Pyrrolidone: Pyrrolidone from Proline. UNIMOD_Pro__Pyrrolidone = 100000369, /// HMVK: Michael addition of hydroxymethylvinyl ketone to cysteine. UNIMOD_HMVK = 100000371, /// Arg->Orn: Ornithine from Arginine. UNIMOD_Arg__Orn = 100000372, /// Dehydro: Half of a disulfide bridge. UNIMOD_Dehydro = 100000374, /// Diphthamide: Diphthamide. UNIMOD_Diphthamide = 100000375, /// Hydroxyfarnesyl: Hydroxyfarnesyl. UNIMOD_Hydroxyfarnesyl = 100000376, /// Diacylglycerol: Diacylglycerol. UNIMOD_Diacylglycerol = 100000377, /// Carboxyethyl: Carboxyethyl. UNIMOD_Carboxyethyl = 100000378, /// Hypusine: Hypusine. UNIMOD_Hypusine = 100000379, /// Retinylidene: Retinal. UNIMOD_Retinylidene = 100000380, /// Lys->AminoadipicAcid: Alpha-amino adipic acid. UNIMOD_Lys__AminoadipicAcid = 100000381, /// Cys->PyruvicAcid: Pyruvic acid from N-term cys. UNIMOD_Cys__PyruvicAcid = 100000382, /// Ammonia-loss: Loss of ammonia. UNIMOD_Ammonia_loss = 100000385, /// Phycocyanobilin: Phycocyanobilin. UNIMOD_Phycocyanobilin = 100000387, /// Phycoerythrobilin: Phycoerythrobilin. UNIMOD_Phycoerythrobilin = 100000388, /// Phytochromobilin: Phytochromobilin. UNIMOD_Phytochromobilin = 100000389, /// Heme: Heme. UNIMOD_Heme = 100000390, /// Molybdopterin: Molybdopterin. UNIMOD_Molybdopterin = 100000391, /// Quinone: Quinone. UNIMOD_Quinone = 100000392, /// Glucosylgalactosyl: Glucosylgalactosyl hydroxylysine. UNIMOD_Glucosylgalactosyl = 100000393, /// GPIanchor: Glycosylphosphatidylinositol. UNIMOD_GPIanchor = 100000394, /// PhosphoribosyldephosphoCoA: Phosphoribosyl dephospho-coenzyme A. UNIMOD_PhosphoribosyldephosphoCoA = 100000395, /// GlycerylPE: Glycerylphosphorylethanolamine. UNIMOD_GlycerylPE = 100000396, /// Triiodothyronine: Triiodo. UNIMOD_Triiodothyronine = 100000397, /// Thyroxine: Tetraiodo. UNIMOD_Thyroxine = 100000398, /// Tyr->Dha: Dehydroalanine (from Tyrosine). UNIMOD_Tyr__Dha = 100000400, /// Didehydro: 2-amino-3-oxo-butanoic_acid. UNIMOD_Didehydro = 100000401, /// Cys->Oxoalanine: Oxoalanine. UNIMOD_Cys__Oxoalanine = 100000402, /// Ser->LacticAcid: Lactic acid from N-term Ser. UNIMOD_Ser__LacticAcid = 100000403, /// Phosphoadenosine: AMP. UNIMOD_Phosphoadenosine = 100000405, /// Hydroxycinnamyl: Hydroxycinnamyl. UNIMOD_Hydroxycinnamyl = 100000407, /// Glycosyl: Glycosyl-L-hydroxyproline. UNIMOD_Glycosyl = 100000408, /// FMNH: Flavin mononucleotide. UNIMOD_FMNH = 100000409, /// Archaeol: S-diphytanylglycerol diether. UNIMOD_Archaeol = 100000410, /// Phenylisocyanate: Phenyl isocyanate. UNIMOD_Phenylisocyanate = 100000411, /// Phenylisocyanate:2H(5): D5-phenyl isocyanate. UNIMOD_Phenylisocyanate_2H_5_ = 100000412, /// Phosphoguanosine: Phospho-guanosine. UNIMOD_Phosphoguanosine = 100000413, /// Hydroxymethyl: Hydroxymethyl. UNIMOD_Hydroxymethyl = 100000414, /// MolybdopterinGD+Delta:S(-1)Se(1): L-selenocysteinyl molybdenum bis(molybdopterin guanine dinucleotide). UNIMOD_MolybdopterinGD_Delta_S__1_Se_1_ = 100000415, /// Dipyrrolylmethanemethyl: Dipyrrolylmethanemethyl. UNIMOD_Dipyrrolylmethanemethyl = 100000416, /// PhosphoUridine: Uridine phosphodiester. UNIMOD_PhosphoUridine = 100000417, /// Glycerophospho: Glycerophospho. UNIMOD_Glycerophospho = 100000419, /// Carboxy->Thiocarboxy: Thiocarboxylic acid. UNIMOD_Carboxy__Thiocarboxy = 100000420, /// Sulfide: Persulfide. UNIMOD_Sulfide = 100000421, /// PyruvicAcidIminyl: N-pyruvic acid 2-iminyl. UNIMOD_PyruvicAcidIminyl = 100000422, /// Delta:Se(1): Selenyl. UNIMOD_Delta_Se_1_ = 100000423, /// MolybdopterinGD: Molybdenum bis(molybdopterin guanine dinucleotide). UNIMOD_MolybdopterinGD = 100000424, /// Dioxidation: Dihydroxy. UNIMOD_Dioxidation = 100000425, /// Octanoyl: Octanoyl. UNIMOD_Octanoyl = 100000426, /// PhosphoHexNAc: N-acetylglucosamine-1-phosphoryl. UNIMOD_PhosphoHexNAc = 100000428, /// PhosphoHex: Phosphoglycosyl-D-mannose-1-phosphoryl. UNIMOD_PhosphoHex = 100000429, /// Palmitoleyl: Palmitoleyl. UNIMOD_Palmitoleyl = 100000431, /// Cholesterol: Cholesterol ester. UNIMOD_Cholesterol = 100000432, /// Didehydroretinylidene: 3,4-didehydroretinylidene. UNIMOD_Didehydroretinylidene = 100000433, /// CHDH: Cis-14-hydroxy-10,13-dioxo-7-heptadecenoic ester. UNIMOD_CHDH = 100000434, /// Methylpyrroline: 4-methyl-delta-1-pyrroline-5-carboxyl. UNIMOD_Methylpyrroline = 100000435, /// Hydroxyheme: Hydroxyheme. UNIMOD_Hydroxyheme = 100000436, /// MicrocinC7: (3-aminopropyl)(L-aspartyl-1-amino)phosphoryl-5-adenosine. UNIMOD_MicrocinC7 = 100000437, /// Cyano: Cyano. UNIMOD_Cyano = 100000438, /// Diironsubcluster: Hydrogenase diiron subcluster. UNIMOD_Diironsubcluster = 100000439, /// Amidino: Amidino. UNIMOD_Amidino = 100000440, /// FMN: O3-(riboflavin phosphoryl). UNIMOD_FMN = 100000442, /// FMNC: S-(4a-FMN). UNIMOD_FMNC = 100000443, /// CuSMo: Copper sulfido molybdopterin cytosine dinuncleotide. UNIMOD_CuSMo = 100000444, /// Hydroxytrimethyl: 5-hydroxy-N6,N6,N6-trimethyl. UNIMOD_Hydroxytrimethyl = 100000445, /// Deoxy: Reduction. UNIMOD_Deoxy = 100000447, /// Microcin: Microcin E492 siderophore ester from serine. UNIMOD_Microcin = 100000448, /// Decanoyl: Lipid. UNIMOD_Decanoyl = 100000449, /// Glu: Monoglutamyl. UNIMOD_Glu = 100000450, /// GluGlu: Diglutamyl. UNIMOD_GluGlu = 100000451, /// GluGluGlu: Triglutamyl. UNIMOD_GluGluGlu = 100000452, /// GluGluGluGlu: Tetraglutamyl. UNIMOD_GluGluGluGlu = 100000453, /// HexN: Hexosamine. UNIMOD_HexN = 100000454, /// Xlink:DMP-s: One end of crosslink attached, one end free. UNIMOD_Xlink_DMP_s = 100000455, /// Xlink:DMP: Both ends of crosslink attached to same peptide. UNIMOD_Xlink_DMP = 100000456, /// NDA: Naphthalene-2,3-dicarboxaldehyde. UNIMOD_NDA = 100000457, /// SPITC:13C(6): 4-sulfophenyl isothiocyanate (Heavy C13). UNIMOD_SPITC_13C_6_ = 100000464, /// AEC-MAEC: Aminoethylcysteine. UNIMOD_AEC_MAEC = 100000472, /// TMAB: 4-trimethyllammoniumbutyryl-. UNIMOD_TMAB = 100000476, /// TMAB:2H(9): D9-4-trimethyllammoniumbutyryl-. UNIMOD_TMAB_2H_9_ = 100000477, /// FTC: Fluorescein-5-thiosemicarbazide. UNIMOD_FTC = 100000478, /// Label:2H(4): 4,4,5,5-D4 Lysine. UNIMOD_Label_2H_4_ = 100000481, /// DHP: Dehydropyrrolizidine alkaloid (dehydroretronecine) on cysteines. UNIMOD_DHP = 100000488, /// Hep: Heptose. UNIMOD_Hep = 100000490, /// BADGE: Bisphenol A diglycidyl ether derivative. UNIMOD_BADGE = 100000493, /// CyDye-Cy3: Cy3 CyDye DIGE Fluor saturation dye. UNIMOD_CyDye_Cy3 = 100000494, /// CyDye-Cy5: Cy5 CyDye DIGE Fluor saturation dye. UNIMOD_CyDye_Cy5 = 100000495, /// BHTOH: Michael addition of t-butyl hydroxylated BHT (BHTOH) to C, H or K. UNIMOD_BHTOH = 100000498, /// IGBP:13C(2): Heavy IDBEST tag for quantitation. UNIMOD_IGBP_13C_2_ = 100000499, /// Nmethylmaleimide+water: Nmethylmaleimidehydrolysis. UNIMOD_Nmethylmaleimide_water = 100000500, /// PyMIC: 3-methyl-2-pyridyl isocyanate. UNIMOD_PyMIC = 100000501, /// LG-lactam-K: Levuglandinyl - lysine lactam adduct. UNIMOD_LG_lactam_K = 100000503, /// LG-Hlactam-K: Levuglandinyl - lysine hydroxylactam adduct. UNIMOD_LG_Hlactam_K = 100000504, /// LG-lactam-R: Levuglandinyl - arginine lactam adduct. UNIMOD_LG_lactam_R = 100000505, /// LG-Hlactam-R: Levuglandinyl - arginine hydroxylactam adduct. UNIMOD_LG_Hlactam_R = 100000506, /// Dimethyl:2H(4)13C(2): DiMethyl-C13HD2. UNIMOD_Dimethyl_2H_4_13C_2_ = 100000510, /// Hex(2): Lactosylation. UNIMOD_Hex_2_ = 100000512, /// C8-QAT: [3-(2,5)-Dioxopyrrolidin-1-yloxycarbonyl)-propyl]dimethyloctylammonium. UNIMOD_C8_QAT = 100000513, /// PropylNAGthiazoline: Propyl-1,2-dideoxy-2\'-methyl-alpha-D-glucopyranoso-[2,1-d]-Delta2\'-thiazoline. UNIMOD_PropylNAGthiazoline = 100000514, /// FNEM: Fluorescein-5-maleimide. UNIMOD_FNEM = 100000515, /// Diethyl: Diethylation, analogous to Dimethylation. UNIMOD_Diethyl = 100000518, /// BisANS: 4,4\'-dianilino-1,1\'-binaphthyl-5,5\'-disulfonic acid. UNIMOD_BisANS = 100000519, /// Piperidine: Piperidination. UNIMOD_Piperidine = 100000520, /// Maleimide-PEO2-Biotin: Maleimide-Biotin. UNIMOD_Maleimide_PEO2_Biotin = 100000522, /// Sulfo-NHS-LC-LC-Biotin: Biot_LC_LC. UNIMOD_Sulfo_NHS_LC_LC_Biotin = 100000523, /// CLIP_TRAQ_2: CLIP_TRAQ_2. UNIMOD_CLIP_TRAQ_2 = 100000525, /// Dethiomethyl: Prompt loss of side chain from oxidised Met. UNIMOD_Dethiomethyl = 100000526, /// Methyl+Deamidated: Deamidation followed by a methylation. UNIMOD_Methyl_Deamidated = 100000528, /// Delta:H(5)C(2): Dimethylation of proline residue. UNIMOD_Delta_H_5_C_2_ = 100000529, /// Cation:K: Replacement of proton by potassium. UNIMOD_Cation_K = 100000530, /// Cation:Cu[I]: Replacement of proton by copper. UNIMOD_Cation_Cu_I_ = 100000531, /// iTRAQ4plex114: Accurate mass for 114. UNIMOD_iTRAQ4plex114 = 100000532, /// iTRAQ4plex115: Accurate mass for 115. UNIMOD_iTRAQ4plex115 = 100000533, /// Dibromo: Dibromo. UNIMOD_Dibromo = 100000534, /// LRGG: Ubiquitination. UNIMOD_LRGG = 100000535, /// CLIP_TRAQ_3: CLIP_TRAQ_3. UNIMOD_CLIP_TRAQ_3 = 100000536, /// CLIP_TRAQ_4: CLIP_TRAQ_4. UNIMOD_CLIP_TRAQ_4 = 100000537, /// Biotin:Cayman-10141: Was 15dB-biotin. UNIMOD_Biotin_Cayman_10141 = 100000538, /// Biotin:Cayman-10013: Was PGA1-biotin. UNIMOD_Biotin_Cayman_10013 = 100000539, /// Ala->Ser: Ala->Ser substitution. UNIMOD_Ala__Ser = 100000540, /// Ala->Thr: Ala->Thr substitution. UNIMOD_Ala__Thr = 100000541, /// Ala->Asp: Ala->Asp substitution. UNIMOD_Ala__Asp = 100000542, /// Ala->Pro: Ala->Pro substitution. UNIMOD_Ala__Pro = 100000543, /// Ala->Gly: Ala->Gly substitution. UNIMOD_Ala__Gly = 100000544, /// Ala->Glu: Ala->Glu substitution. UNIMOD_Ala__Glu = 100000545, /// Ala->Val: Ala->Val substitution. UNIMOD_Ala__Val = 100000546, /// Cys->Phe: Cys->Phe substitution. UNIMOD_Cys__Phe = 100000547, /// Cys->Ser: Cys->Ser substitution. UNIMOD_Cys__Ser = 100000548, /// Cys->Trp: Cys->Trp substitution. UNIMOD_Cys__Trp = 100000549, /// Cys->Tyr: Cys->Tyr substitution. UNIMOD_Cys__Tyr = 100000550, /// Cys->Arg: Cys->Arg substitution. UNIMOD_Cys__Arg = 100000551, /// Cys->Gly: Cys->Gly substitution. UNIMOD_Cys__Gly = 100000552, /// Asp->Ala: Asp->Ala substitution. UNIMOD_Asp__Ala = 100000553, /// Asp->His: Asp->His substitution. UNIMOD_Asp__His = 100000554, /// Asp->Asn: Asp->Asn substitution. UNIMOD_Asp__Asn = 100000555, /// Asp->Gly: Asp->Gly substitution. UNIMOD_Asp__Gly = 100000556, /// Asp->Tyr: Asp->Tyr substitution. UNIMOD_Asp__Tyr = 100000557, /// Asp->Glu: Asp->Glu substitution. UNIMOD_Asp__Glu = 100000558, /// Asp->Val: Asp->Val substitution. UNIMOD_Asp__Val = 100000559, /// Glu->Ala: Glu->Ala substitution. UNIMOD_Glu__Ala = 100000560, /// Glu->Gln: Glu->Gln substitution. UNIMOD_Glu__Gln = 100000561, /// Glu->Asp: Glu->Asp substitution. UNIMOD_Glu__Asp = 100000562, /// Glu->Lys: Glu->Lys substitution. UNIMOD_Glu__Lys = 100000563, /// Glu->Gly: Glu->Gly substitution. UNIMOD_Glu__Gly = 100000564, /// Glu->Val: Glu->Val substitution. UNIMOD_Glu__Val = 100000565, /// Phe->Ser: Phe->Ser substitution. UNIMOD_Phe__Ser = 100000566, /// Phe->Cys: Phe->Cys substitution. UNIMOD_Phe__Cys = 100000567, /// Phe->Xle: Phe->Leu/Ile substitution. UNIMOD_Phe__Xle = 100000568, /// Phe->Tyr: Phe->Tyr substitution. UNIMOD_Phe__Tyr = 100000569, /// Phe->Val: Phe->Val substitution. UNIMOD_Phe__Val = 100000570, /// Gly->Ala: Gly->Ala substitution. UNIMOD_Gly__Ala = 100000571, /// Gly->Ser: Gly->Ser substitution. UNIMOD_Gly__Ser = 100000572, /// Gly->Trp: Gly->Trp substitution. UNIMOD_Gly__Trp = 100000573, /// Gly->Glu: Gly->Glu substitution. UNIMOD_Gly__Glu = 100000574, /// Gly->Val: Gly->Val substitution. UNIMOD_Gly__Val = 100000575, /// Gly->Asp: Gly->Asp substitution. UNIMOD_Gly__Asp = 100000576, /// Gly->Cys: Gly->Cys substitution. UNIMOD_Gly__Cys = 100000577, /// Gly->Arg: Gly->Arg substitution. UNIMOD_Gly__Arg = 100000578, /// His->Pro: His->Pro substitution. UNIMOD_His__Pro = 100000580, /// His->Tyr: His->Tyr substitution. UNIMOD_His__Tyr = 100000581, /// His->Gln: His->Gln substitution. UNIMOD_His__Gln = 100000582, /// His->Arg: His->Arg substitution. UNIMOD_His__Arg = 100000584, /// His->Xle: His->Leu/Ile substitution. UNIMOD_His__Xle = 100000585, /// Xle->Thr: Leu/Ile->Thr substitution. UNIMOD_Xle__Thr = 100000588, /// Xle->Asn: Leu/Ile->Asn substitution. UNIMOD_Xle__Asn = 100000589, /// Xle->Lys: Leu/Ile->Lys substitution. UNIMOD_Xle__Lys = 100000590, /// Lys->Thr: Lys->Thr substitution. UNIMOD_Lys__Thr = 100000594, /// Lys->Asn: Lys->Asn substitution. UNIMOD_Lys__Asn = 100000595, /// Lys->Glu: Lys->Glu substitution. UNIMOD_Lys__Glu = 100000596, /// Lys->Gln: Lys->Gln substitution. UNIMOD_Lys__Gln = 100000597, /// Lys->Met: Lys->Met substitution. UNIMOD_Lys__Met = 100000598, /// Lys->Arg: Lys->Arg substitution. UNIMOD_Lys__Arg = 100000599, /// Lys->Xle: Lys->Leu/Ile substitution. UNIMOD_Lys__Xle = 100000600, /// Xle->Ser: Leu/Ile->Ser substitution. UNIMOD_Xle__Ser = 100000601, /// Xle->Phe: Leu/Ile->Phe substitution. UNIMOD_Xle__Phe = 100000602, /// Xle->Trp: Leu/Ile->Trp substitution. UNIMOD_Xle__Trp = 100000603, /// Xle->Pro: Leu/Ile->Pro substitution. UNIMOD_Xle__Pro = 100000604, /// Xle->Val: Leu/Ile->Val substitution. UNIMOD_Xle__Val = 100000605, /// Xle->His: Leu/Ile->His substitution. UNIMOD_Xle__His = 100000606, /// Xle->Gln: Leu/Ile->Gln substitution. UNIMOD_Xle__Gln = 100000607, /// Xle->Met: Leu/Ile->Met substitution. UNIMOD_Xle__Met = 100000608, /// Xle->Arg: Leu/Ile->Arg substitution. UNIMOD_Xle__Arg = 100000609, /// Met->Thr: Met->Thr substitution. UNIMOD_Met__Thr = 100000610, /// Met->Arg: Met->Arg substitution. UNIMOD_Met__Arg = 100000611, /// Met->Lys: Met->Lys substitution. UNIMOD_Met__Lys = 100000613, /// Met->Xle: Met->Leu/Ile substitution. UNIMOD_Met__Xle = 100000614, /// Met->Val: Met->Val substitution. UNIMOD_Met__Val = 100000615, /// Asn->Ser: Asn->Ser substitution. UNIMOD_Asn__Ser = 100000616, /// Asn->Thr: Asn->Thr substitution. UNIMOD_Asn__Thr = 100000617, /// Asn->Lys: Asn->Lys substitution. UNIMOD_Asn__Lys = 100000618, /// Asn->Tyr: Asn->Tyr substitution. UNIMOD_Asn__Tyr = 100000619, /// Asn->His: Asn->His substitution. UNIMOD_Asn__His = 100000620, /// Asn->Asp: Asn->Asp substitution. UNIMOD_Asn__Asp = 100000621, /// Asn->Xle: Asn->Leu/Ile substitution. UNIMOD_Asn__Xle = 100000622, /// Pro->Ser: Pro->Ser substitution. UNIMOD_Pro__Ser = 100000623, /// Pro->Ala: Pro->Ala substitution. UNIMOD_Pro__Ala = 100000624, /// Pro->His: Pro->His substitution. UNIMOD_Pro__His = 100000625, /// Pro->Gln: Pro->Gln substitution. UNIMOD_Pro__Gln = 100000626, /// Pro->Thr: Pro->Thr substitution. UNIMOD_Pro__Thr = 100000627, /// Pro->Arg: Pro->Arg substitution. UNIMOD_Pro__Arg = 100000628, /// Pro->Xle: Pro->Leu/Ile substitution. UNIMOD_Pro__Xle = 100000629, /// Gln->Pro: Gln->Pro substitution. UNIMOD_Gln__Pro = 100000630, /// Gln->Lys: Gln->Lys substitution. UNIMOD_Gln__Lys = 100000631, /// Gln->Glu: Gln->Glu substitution. UNIMOD_Gln__Glu = 100000632, /// Gln->His: Gln->His substitution. UNIMOD_Gln__His = 100000633, /// Gln->Arg: Gln->Arg substitution. UNIMOD_Gln__Arg = 100000634, /// Gln->Xle: Gln->Leu/Ile substitution. UNIMOD_Gln__Xle = 100000635, /// Arg->Ser: Arg->Ser substitution. UNIMOD_Arg__Ser = 100000636, /// Arg->Trp: Arg->Trp substitution. UNIMOD_Arg__Trp = 100000637, /// Arg->Thr: Arg->Thr substitution. UNIMOD_Arg__Thr = 100000638, /// Arg->Pro: Arg->Pro substitution. UNIMOD_Arg__Pro = 100000639, /// Arg->Lys: Arg->Lys substitution. UNIMOD_Arg__Lys = 100000640, /// Arg->His: Arg->His substitution. UNIMOD_Arg__His = 100000641, /// Arg->Gln: Arg->Gln substitution. UNIMOD_Arg__Gln = 100000642, /// Arg->Met: Arg->Met substitution. UNIMOD_Arg__Met = 100000643, /// Arg->Cys: Arg->Cys substitution. UNIMOD_Arg__Cys = 100000644, /// Arg->Xle: Arg->Leu/Ile substitution. UNIMOD_Arg__Xle = 100000645, /// Arg->Gly: Arg->Gly substitution. UNIMOD_Arg__Gly = 100000646, /// Ser->Phe: Ser->Phe substitution. UNIMOD_Ser__Phe = 100000647, /// Ser->Ala: Ser->Ala substitution. UNIMOD_Ser__Ala = 100000648, /// Ser->Trp: Ser->Trp substitution. UNIMOD_Ser__Trp = 100000649, /// Ser->Thr: Ser->Thr substitution. UNIMOD_Ser__Thr = 100000650, /// Ser->Asn: Ser->Asn substitution. UNIMOD_Ser__Asn = 100000651, /// Ser->Pro: Ser->Pro substitution. UNIMOD_Ser__Pro = 100000652, /// Ser->Tyr: Ser->Tyr substitution. UNIMOD_Ser__Tyr = 100000653, /// Ser->Cys: Ser->Cys substitution. UNIMOD_Ser__Cys = 100000654, /// Ser->Arg: Ser->Arg substitution. UNIMOD_Ser__Arg = 100000655, /// Ser->Xle: Ser->Leu/Ile substitution. UNIMOD_Ser__Xle = 100000656, /// Ser->Gly: Ser->Gly substitution. UNIMOD_Ser__Gly = 100000657, /// Thr->Ser: Thr->Ser substitution. UNIMOD_Thr__Ser = 100000658, /// Thr->Ala: Thr->Ala substitution. UNIMOD_Thr__Ala = 100000659, /// Thr->Asn: Thr->Asn substitution. UNIMOD_Thr__Asn = 100000660, /// Thr->Lys: Thr->Lys substitution. UNIMOD_Thr__Lys = 100000661, /// Thr->Pro: Thr->Pro substitution. UNIMOD_Thr__Pro = 100000662, /// Thr->Met: Thr->Met substitution. UNIMOD_Thr__Met = 100000663, /// Thr->Xle: Thr->Leu/Ile substitution. UNIMOD_Thr__Xle = 100000664, /// Thr->Arg: Thr->Arg substitution. UNIMOD_Thr__Arg = 100000665, /// Val->Phe: Val->Phe substitution. UNIMOD_Val__Phe = 100000666, /// Val->Ala: Val->Ala substitution. UNIMOD_Val__Ala = 100000667, /// Val->Glu: Val->Glu substitution. UNIMOD_Val__Glu = 100000668, /// Val->Met: Val->Met substitution. UNIMOD_Val__Met = 100000669, /// Val->Asp: Val->Asp substitution. UNIMOD_Val__Asp = 100000670, /// Val->Xle: Val->Leu/Ile substitution. UNIMOD_Val__Xle = 100000671, /// Val->Gly: Val->Gly substitution. UNIMOD_Val__Gly = 100000672, /// Trp->Ser: Trp->Ser substitution. UNIMOD_Trp__Ser = 100000673, /// Trp->Cys: Trp->Cys substitution. UNIMOD_Trp__Cys = 100000674, /// Trp->Arg: Trp->Arg substitution. UNIMOD_Trp__Arg = 100000675, /// Trp->Gly: Trp->Gly substitution. UNIMOD_Trp__Gly = 100000676, /// Trp->Xle: Trp->Leu/Ile substitution. UNIMOD_Trp__Xle = 100000677, /// Tyr->Phe: Tyr->Phe substitution. UNIMOD_Tyr__Phe = 100000678, /// Tyr->Ser: Tyr->Ser substitution. UNIMOD_Tyr__Ser = 100000679, /// Tyr->Asn: Tyr->Asn substitution. UNIMOD_Tyr__Asn = 100000680, /// Tyr->His: Tyr->His substitution. UNIMOD_Tyr__His = 100000681, /// Tyr->Asp: Tyr->Asp substitution. UNIMOD_Tyr__Asp = 100000682, /// Tyr->Cys: Tyr->Cys substitution. UNIMOD_Tyr__Cys = 100000683, /// BDMAPP: Mass Defect Tag on lysine e-amino. UNIMOD_BDMAPP = 100000684, /// NA-LNO2: Nitroalkylation by Nitro Linoleic Acid. UNIMOD_NA_LNO2 = 100000685, /// NA-OA-NO2: Nitroalkylation by Nitro Oleic Acid. UNIMOD_NA_OA_NO2 = 100000686, /// ICPL:2H(4): Bruker Daltonics SERVA-ICPL(TM) quantification chemistry, medium form. UNIMOD_ICPL_2H_4_ = 100000687, /// Label:13C(6)15N(1): 13C(6) 15N(1) Silac label. UNIMOD_Label_13C_6_15N_1_ = 100000695, /// Label:2H(9)13C(6)15N(2): 13C(6) 15N(2) (D)9 SILAC label. UNIMOD_Label_2H_9_13C_6_15N_2_ = 100000696, /// NIC: Nicotinic Acid. UNIMOD_NIC = 100000697, /// dNIC: Deuterated Nicotinic Acid. UNIMOD_dNIC = 100000698, /// HNE-Delta:H(2)O: Dehydrated 4-hydroxynonenal. UNIMOD_HNE_Delta_H_2_O = 100000720, /// 4-ONE: 4-Oxononenal (ONE). UNIMOD_4_ONE = 100000721, /// O-Dimethylphosphate: O-Dimethylphosphorylation. UNIMOD_O_Dimethylphosphate = 100000723, /// O-Methylphosphate: O-Methylphosphorylation. UNIMOD_O_Methylphosphate = 100000724, /// Diethylphosphate: O-Diethylphosphorylation. UNIMOD_Diethylphosphate = 100000725, /// Ethylphosphate: O-Ethylphosphorylation. UNIMOD_Ethylphosphate = 100000726, /// O-pinacolylmethylphosphonate: O-pinacolylmethylphosphonylation. UNIMOD_O_pinacolylmethylphosphonate = 100000727, /// Methylphosphonate: Methylphosphonylation. UNIMOD_Methylphosphonate = 100000728, /// O-Isopropylmethylphosphonate: O-Isopropylmethylphosphonylation. UNIMOD_O_Isopropylmethylphosphonate = 100000729, /// iTRAQ8plex: Representative mass and accurate mass for 113, 114, 116 & 117. UNIMOD_iTRAQ8plex = 100000730, /// iTRAQ8plex:13C(6)15N(2): Accurate mass for 115, 118, 119 & 121. UNIMOD_iTRAQ8plex_13C_6_15N_2_ = 100000731, /// Ethanolamine: Carboxyl modification with ethanolamine. UNIMOD_Ethanolamine = 100000734, /// DTT_ST: Dithiothreitol (DTT). UNIMOD_DTT_ST = 100000735, /// DTT_C: Dithiothreitol (DTT) on Cys. UNIMOD_DTT_C = 100000736, /// TMT6plex: Sixplex Tandem Mass Tag®. UNIMOD_TMT6plex = 100000737, /// TMT2plex: Duplex Tandem Mass Tag®. UNIMOD_TMT2plex = 100000738, /// TMT: Native Tandem Mass Tag®. UNIMOD_TMT = 100000739, /// ExacTagThiol: ExacTag Thiol label mass for 2-4-7-10 plex. UNIMOD_ExacTagThiol = 100000740, /// ExacTagAmine: ExacTag Amine label mass for 2-4-7-10 plex. UNIMOD_ExacTagAmine = 100000741, /// 4-ONE+Delta:H(-2)O(-1): Dehydrated 4-Oxononenal Michael adduct. UNIMOD_4_ONE_Delta_H__2_O__1_ = 100000743, /// NO_SMX_SEMD: Nitroso Sulfamethoxazole Sulphenamide thiol adduct. UNIMOD_NO_SMX_SEMD = 100000744, /// NO_SMX_SMCT: Nitroso Sulfamethoxazole semimercaptal thiol adduct. UNIMOD_NO_SMX_SMCT = 100000745, /// NO_SMX_SIMD: Nitroso Sulfamethoxazole Sulfinamide thiol adduct. UNIMOD_NO_SMX_SIMD = 100000746, /// Malonyl: Malonylation of C and S residues. UNIMOD_Malonyl = 100000747, /// 3sulfo: Derivatization by N-term modification using 3-Sulfobenzoic succinimidyl ester. UNIMOD_3sulfo = 100000748, /// trifluoro: Trifluoroleucine replacement of leucine. UNIMOD_trifluoro = 100000750, /// TNBS: Tri nitro benzene. UNIMOD_TNBS = 100000751, /// IDEnT: Isotope Distribution Encoded Tag. UNIMOD_IDEnT = 100000762, /// DTT_ST:2H(6): Isotopically labeled Dithiothreitol (DTT) modification of serines or threonines. UNIMOD_DTT_ST_2H_6_ = 100000763, /// DTT_C:2H(6): Isotopically labeled Dithiothreitol (DTT) modification of cysteines. UNIMOD_DTT_C_2H_6_ = 100000764, /// Met-loss: Removal of initiator methionine from protein N-terminus. UNIMOD_Met_loss = 100000765, /// Met-loss+Acetyl: Removal of initiator methionine from protein N-terminus, then acetylation of the new N-terminus. UNIMOD_Met_loss_Acetyl = 100000766, /// Menadione-HQ: Menadione hydroquinone derivative. UNIMOD_Menadione_HQ = 100000767, /// Methyl+Acetyl:2H(3): Mono-methylated lysine labelled with Acetyl_heavy. UNIMOD_Methyl_Acetyl_2H_3_ = 100000768, /// lapachenole: Lapachenole photochemically added to cysteine. UNIMOD_lapachenole = 100000771, /// Label:13C(5): 13C(5) Silac label. UNIMOD_Label_13C_5_ = 100000772, /// maleimide: Maleimide. UNIMOD_maleimide = 100000773, /// Biotin-phenacyl: Alkylation by biotinylated form of phenacyl bromide. UNIMOD_Biotin_phenacyl = 100000774, /// Carboxymethyl:13C(2): Iodoacetic acid derivative w/ 13C label. UNIMOD_Carboxymethyl_13C_2_ = 100000775, /// NEM:2H(5): D5 N-ethylmaleimide on cysteines. UNIMOD_NEM_2H_5_ = 100000776, /// AEC-MAEC:2H(4): Deuterium cysteamine modification to S or T. UNIMOD_AEC_MAEC_2H_4_ = 100000792, /// Hex(1)HexNAc(1): Hex1HexNAc1. UNIMOD_Hex_1_HexNAc_1_ = 100000793, /// Label:13C(6)+GG: 13C6 labeled ubiquitinylation residue. UNIMOD_Label_13C_6__GG = 100000799, /// Biotin:Thermo-21345: Was PentylamineBiotin. UNIMOD_Biotin_Thermo_21345 = 100000800, /// Pentylamine: Labeling transglutaminase substrate on glutamine side chain. UNIMOD_Pentylamine = 100000801, /// Biotin:Thermo-21360: Was Biotin-PEO4-hydrazide. UNIMOD_Biotin_Thermo_21360 = 100000811, /// Cy3b-maleimide: Fluorescent dye that labels cysteines. UNIMOD_Cy3b_maleimide = 100000821, /// Gly-loss+Amide: Enzymatic glycine removal leaving an amidated C-terminus. UNIMOD_Gly_loss_Amide = 100000822, /// BMOE: Addition of BMOE crosslinker. UNIMOD_BMOE = 100000824, /// DFDNB: Addition of DFDNB crosslinker. UNIMOD_DFDNB = 100000825, /// TMPP-Ac: Tris(2,4,6-trimethoxyphenyl)phosphonium acetic acid N-hydroxysuccinimide ester derivative. UNIMOD_TMPP_Ac = 100000827, /// Dihydroxyimidazolidine: Dihydroxy methylglyoxal adduct. UNIMOD_Dihydroxyimidazolidine = 100000830, /// Label:2H(4)+Acetyl: Acetyl 4,4,5,5-D4 Lysine. UNIMOD_Label_2H_4__Acetyl = 100000834, /// Label:13C(6)+Acetyl: Acetyl 13C(6) Silac label. UNIMOD_Label_13C_6__Acetyl = 100000835, /// Label:13C(6)15N(2)+Acetyl: Acetyl_13C(6) 15N(2) Silac label. UNIMOD_Label_13C_6_15N_2__Acetyl = 100000836, /// Arg->Npo: Arginine replacement by Nitropyrimidyl ornithine. UNIMOD_Arg__Npo = 100000837, /// EQIGG: Sumo mutant Smt3-WT tail following trypsin digestion. UNIMOD_EQIGG = 100000846, /// Arg2PG: Adduct of phenylglyoxal with Arg. UNIMOD_Arg2PG = 100000848, /// cGMP: S-guanylation. UNIMOD_cGMP = 100000849, /// cGMP+RMP-loss: S-guanylation-2. UNIMOD_cGMP_RMP_loss = 100000851, /// Label:2H(4)+GG: Ubiquitination 2H4 lysine. UNIMOD_Label_2H_4__GG = 100000853, /// MG-H1: Methylglyoxal-derived hydroimidazolone. UNIMOD_MG_H1 = 100000859, /// G-H1: Glyoxal-derived hydroimiadazolone. UNIMOD_G_H1 = 100000860, /// ZGB: NHS ester linked Green Fluorescent Bodipy Dye. UNIMOD_ZGB = 100000861, /// Label:13C(1)2H(3): SILAC. UNIMOD_Label_13C_1_2H_3_ = 100000862, /// Label:13C(6)15N(2)+GG: 13C(6) 15N(2) Lysine glygly. UNIMOD_Label_13C_6_15N_2__GG = 100000864, /// ICPL:13C(6)2H(4): Bruker Daltonics SERVA-ICPL(TM) quantification chemistry, +10 Da form. UNIMOD_ICPL_13C_6_2H_4_ = 100000866, /// QEQTGG: SUMOylation by SUMO-1. UNIMOD_QEQTGG = 100000876, /// QQQTGG: SUMOylation by SUMO-2/3. UNIMOD_QQQTGG = 100000877, /// Bodipy: Bodipy modifications onto cysteine. UNIMOD_Bodipy = 100000878, /// Biotin:Thermo-21325: Was ChromoBiotin. UNIMOD_Biotin_Thermo_21325 = 100000884, /// Label:13C(1)2H(3)+Oxidation: Oxidised methionine 13C(1)2H(3) SILAC label. UNIMOD_Label_13C_1_2H_3__Oxidation = 100000885, /// HydroxymethylOP: 2-ammonio-6-[4-(hydroxymethyl)-3-oxidopyridinium-1-yl]- hexanoate. UNIMOD_HydroxymethylOP = 100000886, /// MDCC: Covalent linkage of maleimidyl coumarin probe (Molecular Probes D-10253). UNIMOD_MDCC = 100000887, /// mTRAQ: MTRAQ light. UNIMOD_mTRAQ = 100000888, /// mTRAQ:13C(3)15N(1): MTRAQ medium. UNIMOD_mTRAQ_13C_3_15N_1_ = 100000889, /// DyLight-maleimide: Thiol-reactive dye for fluorescence labelling of proteins. UNIMOD_DyLight_maleimide = 100000890, /// Methyl-PEO12-Maleimide: Methyl-PEO12-Maleimide. UNIMOD_Methyl_PEO12_Maleimide = 100000891, /// CarbamidomethylDTT: Carbamidomethylated DTT modification of cysteine. UNIMOD_CarbamidomethylDTT = 100000893, /// CarboxymethylDTT: Carboxymethylated DTT modification of cysteine. UNIMOD_CarboxymethylDTT = 100000894, /// Biotin-PEG-PRA: Biotin polyethyleneoxide (n=3) alkyne. UNIMOD_Biotin_PEG_PRA = 100000895, /// Met->Aha: Methionine replacement by azido homoalanine. UNIMOD_Met__Aha = 100000896, /// Label:15N(4): SILAC 15N(4). UNIMOD_Label_15N_4_ = 100000897, /// pyrophospho: Pyrophosphorylation of Ser/Thr. UNIMOD_pyrophospho = 100000898, /// Met->Hpg: Methionine replacement by homopropargylglycine. UNIMOD_Met__Hpg = 100000899, /// 4AcAllylGal: 2,3,4,6-tetra-O-Acetyl-1-allyl-alpha-D-galactopyranoside modification of cysteine. UNIMOD_4AcAllylGal = 100000901, /// DimethylArsino: Reaction with dimethylarsinous (AsIII) acid. UNIMOD_DimethylArsino = 100000902, /// Lys->CamCys: Lys->Cys substitution and carbamidomethylation. UNIMOD_Lys__CamCys = 100000903, /// Phe->CamCys: Phe->Cys substitution and carbamidomethylation. UNIMOD_Phe__CamCys = 100000904, /// Leu->MetOx: Leu->Met substitution and sulfoxidation. UNIMOD_Leu__MetOx = 100000905, /// Lys->MetOx: Lys->Met substitution and sulfoxidation. UNIMOD_Lys__MetOx = 100000906, /// Galactosyl: Galactosyl hydroxylysine. UNIMOD_Galactosyl = 100000907, /// SMCC-maleimide: Modified SMCC maleimide with 3-(dimethylamino)-1-propylamine. UNIMOD_SMCC_maleimide = 100000908, /// Bacillosamine: 2,4-diacetamido-2,4,6-trideoxyglucopyranose. UNIMOD_Bacillosamine = 100000910, /// MTSL: Cys modification by (1-oxyl-2,2,5,5-tetramethyl-3-pyrroline-3-methyl)methanesulfonate (MTSL). UNIMOD_MTSL = 100000911, /// HNE-BAHAH: 4-hydroxy-2-nonenal and biotinamidohexanoic acid hydrazide, reduced. UNIMOD_HNE_BAHAH = 100000912, /// Methylmalonylation: Methylmalonylation on Serine. UNIMOD_Methylmalonylation = 100000914, /// Ethoxyformyl: Ethoxyformylation. UNIMOD_Ethoxyformyl = 100000915, /// Label:13C(4)15N(2)+GG: 13C(4) 15N(2) Lysine glygly. UNIMOD_Label_13C_4_15N_2__GG = 100000923, /// ethylamino: Ethyl amino. UNIMOD_ethylamino = 100000926, /// MercaptoEthanol: 2-OH-ethyl thio-Ser. UNIMOD_MercaptoEthanol = 100000928, /// Ethyl+Deamidated: Deamidation followed by esterification with ethanol. UNIMOD_Ethyl_Deamidated = 100000931, /// VFQQQTGG: SUMOylation by SUMO-2/3 (formic acid cleavage). UNIMOD_VFQQQTGG = 100000932, /// VIEVYQEQTGG: SUMOylation by SUMO-1 (formic acid cleavage). UNIMOD_VIEVYQEQTGG = 100000933, /// AMTzHexNAc2: Photocleavable Biotin + GalNAz on O-GlcNAc. UNIMOD_AMTzHexNAc2 = 100000934, /// Atto495Maleimide: High molecular absorption maleimide label for proteins. UNIMOD_Atto495Maleimide = 100000935, /// Chlorination: Chlorination of tyrosine residues. UNIMOD_Chlorination = 100000936, /// dichlorination: Dichlorination. UNIMOD_dichlorination = 100000937, /// AROD: Cysteine modifier. UNIMOD_AROD = 100000938, /// Cys->methylaminoAla: Carbamidomethylated Cys that undergoes beta-elimination and Michael addition of methylamine. UNIMOD_Cys__methylaminoAla = 100000939, /// Cys->ethylaminoAla: Carbamidomethylated Cys that undergoes beta-elimination and Michael addition of ethylamine. UNIMOD_Cys__ethylaminoAla = 100000940, /// DNPS: 2,4-Dinitrobenzenesulfenyl. UNIMOD_DNPS = 100000941, /// SulfoGMBS: High molecular absorption label for proteins. UNIMOD_SulfoGMBS = 100000942, /// DimethylamineGMBS: Modified GMBS X linker for proteins. UNIMOD_DimethylamineGMBS = 100000943, /// Label:15N(2)2H(9): SILAC label. UNIMOD_Label_15N_2_2H_9_ = 100000944, /// LG-anhydrolactam: Levuglandinyl-lysine anhydrolactam adduct. UNIMOD_LG_anhydrolactam = 100000946, /// LG-pyrrole: Levuglandinyl-lysine pyrrole adduct. UNIMOD_LG_pyrrole = 100000947, /// LG-anhyropyrrole: Levuglandinyl-lysine anhyropyrrole adduct. UNIMOD_LG_anhyropyrrole = 100000948, /// 3-deoxyglucosone: Condensation product of 3-deoxyglucosone. UNIMOD_3_deoxyglucosone = 100000949, /// Cation:Li: Replacement of proton by lithium. UNIMOD_Cation_Li = 100000950, /// Cation:Ca[II]: Replacement of 2 protons by calcium. UNIMOD_Cation_Ca_II_ = 100000951, /// Cation:Fe[II]: Replacement of 2 protons by iron. UNIMOD_Cation_Fe_II_ = 100000952, /// Cation:Ni[II]: Replacement of 2 protons by nickel. UNIMOD_Cation_Ni_II_ = 100000953, /// Cation:Zn[II]: Replacement of 2 protons by zinc. UNIMOD_Cation_Zn_II_ = 100000954, /// Cation:Ag: Replacement of proton by silver. UNIMOD_Cation_Ag = 100000955, /// Cation:Mg[II]: Replacement of 2 protons by magnesium. UNIMOD_Cation_Mg_II_ = 100000956, /// 2-succinyl: S-(2-succinyl) cysteine. UNIMOD_2_succinyl = 100000957, /// Propargylamine: Propargylamine. UNIMOD_Propargylamine = 100000958, /// Phosphopropargyl: Phospho-propargylamine. UNIMOD_Phosphopropargyl = 100000959, /// SUMO2135: SUMOylation by SUMO-1 after tryptic cleavage. UNIMOD_SUMO2135 = 100000960, /// SUMO3549: SUMOylation by SUMO-2/3 after tryptic cleavage. UNIMOD_SUMO3549 = 100000961, /// thioacylPA: Membrane protein extraction. UNIMOD_thioacylPA = 100000967, /// maleimide3: Maleimide-3-saccharide. UNIMOD_maleimide3 = 100000971, /// maleimide5: Maleimide-5-saccharide. UNIMOD_maleimide5 = 100000972, /// Puromycin: Puromycin. UNIMOD_Puromycin = 100000973, /// Chlorpyrifos: O,O-diethyl o-3,5,6-trichloro-2-pyridyl phosphorothioate. UNIMOD_Chlorpyrifos = 100000975, /// Carbofuran: 2,3-dihydro-2,2-dimethyl-7-benzofuranol N-methyl carbamate. UNIMOD_Carbofuran = 100000977, /// BITC: Benzyl isothiocyanate. UNIMOD_BITC = 100000978, /// PEITC: Phenethyl isothiocyanate. UNIMOD_PEITC = 100000979, /// glucosone: Condensation product of glucosone. UNIMOD_glucosone = 100000981, /// cysTMT: Native cysteine-reactive Tandem Mass Tag®. UNIMOD_cysTMT = 100000984, /// cysTMT6plex: Cysteine-reactive Sixplex Tandem Mass Tag®. UNIMOD_cysTMT6plex = 100000985, /// Label:13C(6)+Dimethyl: Dimethyl 13C(6) Silac label. UNIMOD_Label_13C_6__Dimethyl = 100000986, /// Label:13C(6)15N(2)+Dimethyl: Dimethyl 13C(6)15N(2) Silac label. UNIMOD_Label_13C_6_15N_2__Dimethyl = 100000987, /// Ammonium: Replacement of proton with ammonium ion. UNIMOD_Ammonium = 100000989, /// ISD_z+2_ion: ISD (z+2)-series. UNIMOD_ISD_z_2_ion = 100000991, /// Biotin:Sigma-B1267: Was Biotin-maleimide. UNIMOD_Biotin_Sigma_B1267 = 100000993, /// Label:15N(1): 15N(1). UNIMOD_Label_15N_1_ = 100000994, /// Label:15N(2): 15N(2). UNIMOD_Label_15N_2_ = 100000995, /// Label:15N(3): 15N(3). UNIMOD_Label_15N_3_ = 100000996, /// sulfo+amino: Aminotyrosine with sulfation. UNIMOD_sulfo_amino = 100000997, /// BHAc: N-biotinyl-6-aminohexanoyl. UNIMOD_BHAc = 100000998, /// AHA-Alkyne: Azidohomoalanine (AHA) bound to propargylglycine-NH2 (alkyne). UNIMOD_AHA_Alkyne = 100001000, /// AHA-Alkyne-KDDDD: Azidohomoalanine (AHA) bound to DDDDK-propargylglycine-NH2 (alkyne). UNIMOD_AHA_Alkyne_KDDDD = 100001001, /// EGCG1: (-)-epigallocatechin-3-gallate. UNIMOD_EGCG1 = 100001002, /// EGCG2: (-)-dehydroepigallocatechin. UNIMOD_EGCG2 = 100001003, /// Label:13C(6)15N(4)+Methyl: Monomethylated Arg13C(6) 15N(4). UNIMOD_Label_13C_6_15N_4__Methyl = 100001004, /// Label:13C(6)15N(4)+Dimethyl: Dimethylated Arg13C(6) 15N(4). UNIMOD_Label_13C_6_15N_4__Dimethyl = 100001005, /// Label:13C(6)15N(4)+Methyl:2H(3)13C(1): 2H(3) 13C(1) monomethylated Arg13C(6) 15N(4). UNIMOD_Label_13C_6_15N_4__Methyl_2H_3_13C_1_ = 100001006, /// Label:13C(6)15N(4)+Dimethyl:2H(6)13C(2): 2H(6) 13C(2) Dimethylated Arg13C(6) 15N(4). UNIMOD_Label_13C_6_15N_4__Dimethyl_2H_6_13C_2_ = 100001007, /// SecCarbamidomethyl: Sec Iodoacetamide derivative. UNIMOD_SecCarbamidomethyl = 100001008, /// Thiazolidine: Addition of Carbon to cysteine. UNIMOD_Thiazolidine = 100001009, /// DEDGFLYMVYASQETFG: Addition of DEDGFLYMVYASQETFG. UNIMOD_DEDGFLYMVYASQETFG = 100001010, /// Biotin:Invitrogen-M1602: Nalpha-(3-maleimidylpropionyl)biocytin. UNIMOD_Biotin_Invitrogen_M1602 = 100001012, /// glycidamide: Glycidamide adduct. UNIMOD_glycidamide = 100001014, /// Ahx2+Hsl: C-terminal homoserine lactone and two aminohexanoic acids. UNIMOD_Ahx2_Hsl = 100001015, /// DMPO: DMPO spin-trap nitrone adduct. UNIMOD_DMPO = 100001017, /// ICDID: Isotope-Coded Dimedone light form. UNIMOD_ICDID = 100001018, /// ICDID:2H(6): Isotope-Coded Dimedone heavy form. UNIMOD_ICDID_2H_6_ = 100001019, /// Xlink:DSS: Monolink of DSS/BS3 crosslinker to Lys or N-terminus. UNIMOD_Xlink_DSS = 100001020, /// Xlink:EGS: Monolink of EGS crosslinker to Lys or N-terminus. UNIMOD_Xlink_EGS = 100001021, /// Xlink:DST: Monolink of DST crosslinker to Lys or N-terminus. UNIMOD_Xlink_DST = 100001022, /// Xlink:DTSSP: Monolink of DSP/DTSSP crosslinker to Lys or N-terminus. UNIMOD_Xlink_DTSSP = 100001023, /// Xlink:SMCC: Monolink of sulfoSMCC/SMCC crosslinker to Cys. UNIMOD_Xlink_SMCC = 100001024, /// Xlink:DMP-de: Monolink of DMP crosslinker to Lys or N-terminus. UNIMOD_Xlink_DMP_de = 100001027, /// Xlink:EGScleaved: EGS crosslinker to Lys or N-terminus following hydroxylamine cleavage. UNIMOD_Xlink_EGScleaved = 100001028, /// Biotin:Thermo-88310: Desthiobiotin modification of lysine. UNIMOD_Biotin_Thermo_88310 = 100001031, /// 2-nitrobenzyl: Tyrosine caged with 2-nitrobenzyl (ONB). UNIMOD_2_nitrobenzyl = 100001032, /// SecNEM: N-ethylmaleimide on selenocysteines. UNIMOD_SecNEM = 100001033, /// SecNEM:2H(5): D5 N-ethylmaleimide on selenocysteines. UNIMOD_SecNEM_2H_5_ = 100001034, /// Thiadiazole: Thiadiazolydation of Cys. UNIMOD_Thiadiazole = 100001035, /// Withaferin: Modification of cystein by withaferin. UNIMOD_Withaferin = 100001036, /// Biotin:Thermo-88317: Desthiobiotin fluorophosphonate. UNIMOD_Biotin_Thermo_88317 = 100001037, /// TAMRA-FP: TAMRA fluorophosphonate modification of serine. UNIMOD_TAMRA_FP = 100001038, /// Biotin:Thermo-21901+H2O: Maleimide-Biotin + Water. UNIMOD_Biotin_Thermo_21901_H2O = 100001039, /// Deoxyhypusine: Deoxyhypusine. UNIMOD_Deoxyhypusine = 100001041, /// Acetyldeoxyhypusine: Acetyldeoxyhypusine. UNIMOD_Acetyldeoxyhypusine = 100001042, /// Acetylhypusine: Acetylhypusine. UNIMOD_Acetylhypusine = 100001043, /// Ala->Cys: Ala->Cys substitution. UNIMOD_Ala__Cys = 100001044, /// Ala->Phe: Ala->Phe substitution. UNIMOD_Ala__Phe = 100001045, /// Ala->His: Ala->His substitution. UNIMOD_Ala__His = 100001046, /// Ala->Xle: Ala->Leu/Ile substitution. UNIMOD_Ala__Xle = 100001047, /// Ala->Lys: Ala->Lys substitution. UNIMOD_Ala__Lys = 100001048, /// Ala->Met: Ala->Met substitution. UNIMOD_Ala__Met = 100001049, /// Ala->Asn: Ala->Asn substitution. UNIMOD_Ala__Asn = 100001050, /// Ala->Gln: Ala->Gln substitution. UNIMOD_Ala__Gln = 100001051, /// Ala->Arg: Ala->Arg substitution. UNIMOD_Ala__Arg = 100001052, /// Ala->Trp: Ala->Trp substitution. UNIMOD_Ala__Trp = 100001053, /// Ala->Tyr: Ala->Tyr substitution. UNIMOD_Ala__Tyr = 100001054, /// Cys->Ala: Cys->Ala substitution. UNIMOD_Cys__Ala = 100001055, /// Cys->Asp: Cys->Asp substitution. UNIMOD_Cys__Asp = 100001056, /// Cys->Glu: Cys->Glu substitution. UNIMOD_Cys__Glu = 100001057, /// Cys->His: Cys->His substitution. UNIMOD_Cys__His = 100001058, /// Cys->Xle: Cys->Leu/Ile substitution. UNIMOD_Cys__Xle = 100001059, /// Cys->Lys: Cys->Lys substitution. UNIMOD_Cys__Lys = 100001060, /// Cys->Met: Cys->Met substitution. UNIMOD_Cys__Met = 100001061, /// Cys->Asn: Cys->Asn substitution. UNIMOD_Cys__Asn = 100001062, /// Cys->Pro: Cys->Pro substitution. UNIMOD_Cys__Pro = 100001063, /// Cys->Gln: Cys->Gln substitution. UNIMOD_Cys__Gln = 100001064, /// Cys->Thr: Cys->Thr substitution. UNIMOD_Cys__Thr = 100001065, /// Cys->Val: Cys->Val substitution. UNIMOD_Cys__Val = 100001066, /// Asp->Cys: Asp->Cys substitution. UNIMOD_Asp__Cys = 100001067, /// Asp->Phe: Asp->Phe substitution. UNIMOD_Asp__Phe = 100001068, /// Asp->Xle: Asp->Leu/Ile substitution. UNIMOD_Asp__Xle = 100001069, /// Asp->Lys: Asp->Lys substitution. UNIMOD_Asp__Lys = 100001070, /// Asp->Met: Asp->Met substitution. UNIMOD_Asp__Met = 100001071, /// Asp->Pro: Asp->Pro substitution. UNIMOD_Asp__Pro = 100001072, /// Asp->Gln: Asp->Gln substitution. UNIMOD_Asp__Gln = 100001073, /// Asp->Arg: Asp->Arg substitution. UNIMOD_Asp__Arg = 100001074, /// Asp->Ser: Asp->Ser substitution. UNIMOD_Asp__Ser = 100001075, /// Asp->Thr: Asp->Thr substitution. UNIMOD_Asp__Thr = 100001076, /// Asp->Trp: Asp->Trp substitution. UNIMOD_Asp__Trp = 100001077, /// Glu->Cys: Glu->Cys substitution. UNIMOD_Glu__Cys = 100001078, /// Glu->Phe: Glu->Phe substitution. UNIMOD_Glu__Phe = 100001079, /// Glu->His: Glu->His substitution. UNIMOD_Glu__His = 100001080, /// Glu->Xle: Glu->Leu/Ile substitution. UNIMOD_Glu__Xle = 100001081, /// Glu->Met: Glu->Met substitution. UNIMOD_Glu__Met = 100001082, /// Glu->Asn: Glu->Asn substitution. UNIMOD_Glu__Asn = 100001083, /// Glu->Pro: Glu->Pro substitution. UNIMOD_Glu__Pro = 100001084, /// Glu->Arg: Glu->Arg substitution. UNIMOD_Glu__Arg = 100001085, /// Glu->Ser: Glu->Ser substitution. UNIMOD_Glu__Ser = 100001086, /// Glu->Thr: Glu->Thr substitution. UNIMOD_Glu__Thr = 100001087, /// Glu->Trp: Glu->Trp substitution. UNIMOD_Glu__Trp = 100001088, /// Glu->Tyr: Glu->Tyr substitution. UNIMOD_Glu__Tyr = 100001089, /// Phe->Ala: Phe->Ala substitution. UNIMOD_Phe__Ala = 100001090, /// Phe->Asp: Phe->Asp substitution. UNIMOD_Phe__Asp = 100001091, /// Phe->Glu: Phe->Glu substitution. UNIMOD_Phe__Glu = 100001092, /// Phe->Gly: Phe->Gly substitution. UNIMOD_Phe__Gly = 100001093, /// Phe->His: Phe->His substitution. UNIMOD_Phe__His = 100001094, /// Phe->Lys: Phe->Lys substitution. UNIMOD_Phe__Lys = 100001095, /// Phe->Met: Phe->Met substitution. UNIMOD_Phe__Met = 100001096, /// Phe->Asn: Phe->Asn substitution. UNIMOD_Phe__Asn = 100001097, /// Phe->Pro: Phe->Pro substitution. UNIMOD_Phe__Pro = 100001098, /// Phe->Gln: Phe->Gln substitution. UNIMOD_Phe__Gln = 100001099, /// Phe->Arg: Phe->Arg substitution. UNIMOD_Phe__Arg = 100001100, /// Phe->Thr: Phe->Thr substitution. UNIMOD_Phe__Thr = 100001101, /// Phe->Trp: Phe->Trp substitution. UNIMOD_Phe__Trp = 100001102, /// Gly->Phe: Gly->Phe substitution. UNIMOD_Gly__Phe = 100001103, /// Gly->His: Gly->His substitution. UNIMOD_Gly__His = 100001104, /// Gly->Xle: Gly->Leu/Ile substitution. UNIMOD_Gly__Xle = 100001105, /// Gly->Lys: Gly->Lys substitution. UNIMOD_Gly__Lys = 100001106, /// Gly->Met: Gly->Met substitution. UNIMOD_Gly__Met = 100001107, /// Gly->Asn: Gly->Asn substitution. UNIMOD_Gly__Asn = 100001108, /// Gly->Pro: Gly->Pro substitution. UNIMOD_Gly__Pro = 100001109, /// Gly->Gln: Gly->Gln substitution. UNIMOD_Gly__Gln = 100001110, /// Gly->Thr: Gly->Thr substitution. UNIMOD_Gly__Thr = 100001111, /// Gly->Tyr: Gly->Tyr substitution. UNIMOD_Gly__Tyr = 100001112, /// His->Ala: His->Ala substitution. UNIMOD_His__Ala = 100001113, /// His->Cys: His->Cys substitution. UNIMOD_His__Cys = 100001114, /// His->Glu: His->Glu substitution. UNIMOD_His__Glu = 100001115, /// His->Phe: His->Phe substitution. UNIMOD_His__Phe = 100001116, /// His->Gly: His->Gly substitution. UNIMOD_His__Gly = 100001117, /// His->Lys: His->Lys substitution. UNIMOD_His__Lys = 100001119, /// His->Met: His->Met substitution. UNIMOD_His__Met = 100001120, /// His->Ser: His->Ser substitution. UNIMOD_His__Ser = 100001121, /// His->Thr: His->Thr substitution. UNIMOD_His__Thr = 100001122, /// His->Val: His->Val substitution. UNIMOD_His__Val = 100001123, /// His->Trp: His->Trp substitution. UNIMOD_His__Trp = 100001124, /// Xle->Ala: Leu/Ile->Ala substitution. UNIMOD_Xle__Ala = 100001125, /// Xle->Cys: Leu/Ile->Cys substitution. UNIMOD_Xle__Cys = 100001126, /// Xle->Asp: Leu/Ile->Asp substitution. UNIMOD_Xle__Asp = 100001127, /// Xle->Glu: Leu/Ile->Glu substitution. UNIMOD_Xle__Glu = 100001128, /// Xle->Gly: Leu/Ile->Gly substitution. UNIMOD_Xle__Gly = 100001129, /// Xle->Tyr: Leu/Ile->Tyr substitution. UNIMOD_Xle__Tyr = 100001130, /// Lys->Ala: Lys->Ala substitution. UNIMOD_Lys__Ala = 100001131, /// Lys->Cys: Lys->Cys substitution. UNIMOD_Lys__Cys = 100001132, /// Lys->Asp: Lys->Asp substitution. UNIMOD_Lys__Asp = 100001133, /// Lys->Phe: Lys->Phe substitution. UNIMOD_Lys__Phe = 100001134, /// Lys->Gly: Lys->Gly substitution. UNIMOD_Lys__Gly = 100001135, /// Lys->His: Lys->His substitution. UNIMOD_Lys__His = 100001136, /// Lys->Pro: Lys->Pro substitution. UNIMOD_Lys__Pro = 100001137, /// Lys->Ser: Lys->Ser substitution. UNIMOD_Lys__Ser = 100001138, /// Lys->Val: Lys->Val substitution. UNIMOD_Lys__Val = 100001139, /// Lys->Trp: Lys->Trp substitution. UNIMOD_Lys__Trp = 100001140, /// Lys->Tyr: Lys->Tyr substitution. UNIMOD_Lys__Tyr = 100001141, /// Met->Ala: Met->Ala substitution. UNIMOD_Met__Ala = 100001142, /// Met->Cys: Met->Cys substitution. UNIMOD_Met__Cys = 100001143, /// Met->Asp: Met->Asp substitution. UNIMOD_Met__Asp = 100001144, /// Met->Glu: Met->Glu substitution. UNIMOD_Met__Glu = 100001145, /// Met->Phe: Met->Phe substitution. UNIMOD_Met__Phe = 100001146, /// Met->Gly: Met->Gly substitution. UNIMOD_Met__Gly = 100001147, /// Met->His: Met->His substitution. UNIMOD_Met__His = 100001148, /// Met->Asn: Met->Asn substitution. UNIMOD_Met__Asn = 100001149, /// Met->Pro: Met->Pro substitution. UNIMOD_Met__Pro = 100001150, /// Met->Gln: Met->Gln substitution. UNIMOD_Met__Gln = 100001151, /// Met->Ser: Met->Ser substitution. UNIMOD_Met__Ser = 100001152, /// Met->Trp: Met->Trp substitution. UNIMOD_Met__Trp = 100001153, /// Met->Tyr: Met->Tyr substitution. UNIMOD_Met__Tyr = 100001154, /// Asn->Ala: Asn->Ala substitution. UNIMOD_Asn__Ala = 100001155, /// Asn->Cys: Asn->Cys substitution. UNIMOD_Asn__Cys = 100001156, /// Asn->Glu: Asn->Glu substitution. UNIMOD_Asn__Glu = 100001157, /// Asn->Phe: Asn->Phe substitution. UNIMOD_Asn__Phe = 100001158, /// Asn->Gly: Asn->Gly substitution. UNIMOD_Asn__Gly = 100001159, /// Asn->Met: Asn->Met substitution. UNIMOD_Asn__Met = 100001160, /// Asn->Pro: Asn->Pro substitution. UNIMOD_Asn__Pro = 100001161, /// Asn->Gln: Asn->Gln substitution. UNIMOD_Asn__Gln = 100001162, /// Asn->Arg: Asn->Arg substitution. UNIMOD_Asn__Arg = 100001163, /// Asn->Val: Asn->Val substitution. UNIMOD_Asn__Val = 100001164, /// Asn->Trp: Asn->Trp substitution. UNIMOD_Asn__Trp = 100001165, /// Pro->Cys: Pro->Cys substitution. UNIMOD_Pro__Cys = 100001166, /// Pro->Asp: Pro->Asp substitution. UNIMOD_Pro__Asp = 100001167, /// Pro->Glu: Pro->Glu substitution. UNIMOD_Pro__Glu = 100001168, /// Pro->Phe: Pro->Phe substitution. UNIMOD_Pro__Phe = 100001169, /// Pro->Gly: Pro->Gly substitution. UNIMOD_Pro__Gly = 100001170, /// Pro->Lys: Pro->Lys substitution. UNIMOD_Pro__Lys = 100001171, /// Pro->Met: Pro->Met substitution. UNIMOD_Pro__Met = 100001172, /// Pro->Asn: Pro->Asn substitution. UNIMOD_Pro__Asn = 100001173, /// Pro->Val: Pro->Val substitution. UNIMOD_Pro__Val = 100001174, /// Pro->Trp: Pro->Trp substitution. UNIMOD_Pro__Trp = 100001175, /// Pro->Tyr: Pro->Tyr substitution. UNIMOD_Pro__Tyr = 100001176, /// Gln->Ala: Gln->Ala substitution. UNIMOD_Gln__Ala = 100001177, /// Gln->Cys: Gln->Cys substitution. UNIMOD_Gln__Cys = 100001178, /// Gln->Asp: Gln->Asp substitution. UNIMOD_Gln__Asp = 100001179, /// Gln->Phe: Gln->Phe substitution. UNIMOD_Gln__Phe = 100001180, /// Gln->Gly: Gln->Gly substitution. UNIMOD_Gln__Gly = 100001181, /// Gln->Met: Gln->Met substitution. UNIMOD_Gln__Met = 100001182, /// Gln->Asn: Gln->Asn substitution. UNIMOD_Gln__Asn = 100001183, /// Gln->Ser: Gln->Ser substitution. UNIMOD_Gln__Ser = 100001184, /// Gln->Thr: Gln->Thr substitution. UNIMOD_Gln__Thr = 100001185, /// Gln->Val: Gln->Val substitution. UNIMOD_Gln__Val = 100001186, /// Gln->Trp: Gln->Trp substitution. UNIMOD_Gln__Trp = 100001187, /// Gln->Tyr: Gln->Tyr substitution. UNIMOD_Gln__Tyr = 100001188, /// Arg->Ala: Arg->Ala substitution. UNIMOD_Arg__Ala = 100001189, /// Arg->Asp: Arg->Asp substitution. UNIMOD_Arg__Asp = 100001190, /// Arg->Glu: Arg->Glu substitution. UNIMOD_Arg__Glu = 100001191, /// Arg->Asn: Arg->Asn substitution. UNIMOD_Arg__Asn = 100001192, /// Arg->Val: Arg->Val substitution. UNIMOD_Arg__Val = 100001193, /// Arg->Tyr: Arg->Tyr substitution. UNIMOD_Arg__Tyr = 100001194, /// Arg->Phe: Arg->Phe substitution. UNIMOD_Arg__Phe = 100001195, /// Ser->Asp: Ser->Asp substitution. UNIMOD_Ser__Asp = 100001196, /// Ser->Glu: Ser->Glu substitution. UNIMOD_Ser__Glu = 100001197, /// Ser->His: Ser->His substitution. UNIMOD_Ser__His = 100001198, /// Ser->Lys: Ser->Lys substitution. UNIMOD_Ser__Lys = 100001199, /// Ser->Met: Ser->Met substitution. UNIMOD_Ser__Met = 100001200, /// Ser->Gln: Ser->Gln substitution. UNIMOD_Ser__Gln = 100001201, /// Ser->Val: Ser->Val substitution. UNIMOD_Ser__Val = 100001202, /// Thr->Cys: Thr->Cys substitution. UNIMOD_Thr__Cys = 100001203, /// Thr->Asp: Thr->Asp substitution. UNIMOD_Thr__Asp = 100001204, /// Thr->Glu: Thr->Glu substitution. UNIMOD_Thr__Glu = 100001205, /// Thr->Phe: Thr->Phe substitution. UNIMOD_Thr__Phe = 100001206, /// Thr->Gly: Thr->Gly substitution. UNIMOD_Thr__Gly = 100001207, /// Thr->His: Thr->His substitution. UNIMOD_Thr__His = 100001208, /// Thr->Gln: Thr->Gln substitution. UNIMOD_Thr__Gln = 100001209, /// Thr->Val: Thr->Val substitution. UNIMOD_Thr__Val = 100001210, /// Thr->Trp: Thr->Trp substitution. UNIMOD_Thr__Trp = 100001211, /// Thr->Tyr: Thr->Tyr substitution. UNIMOD_Thr__Tyr = 100001212, /// Val->Cys: Val->Cys substitution. UNIMOD_Val__Cys = 100001213, /// Val->His: Val->His substitution. UNIMOD_Val__His = 100001214, /// Val->Lys: Val->Lys substitution. UNIMOD_Val__Lys = 100001215, /// Val->Asn: Val->Asn substitution. UNIMOD_Val__Asn = 100001216, /// Val->Pro: Val->Pro substitution. UNIMOD_Val__Pro = 100001217, /// Val->Gln: Val->Gln substitution. UNIMOD_Val__Gln = 100001218, /// Val->Arg: Val->Arg substitution. UNIMOD_Val__Arg = 100001219, /// Val->Ser: Val->Ser substitution. UNIMOD_Val__Ser = 100001220, /// Val->Thr: Val->Thr substitution. UNIMOD_Val__Thr = 100001221, /// Val->Trp: Val->Trp substitution. UNIMOD_Val__Trp = 100001222, /// Val->Tyr: Val->Tyr substitution. UNIMOD_Val__Tyr = 100001223, /// Trp->Ala: Trp->Ala substitution. UNIMOD_Trp__Ala = 100001224, /// Trp->Asp: Trp->Asp substitution. UNIMOD_Trp__Asp = 100001225, /// Trp->Glu: Trp->Glu substitution. UNIMOD_Trp__Glu = 100001226, /// Trp->Phe: Trp->Phe substitution. UNIMOD_Trp__Phe = 100001227, /// Trp->His: Trp->His substitution. UNIMOD_Trp__His = 100001228, /// Trp->Lys: Trp->Lys substitution. UNIMOD_Trp__Lys = 100001229, /// Trp->Met: Trp->Met substitution. UNIMOD_Trp__Met = 100001230, /// Trp->Asn: Trp->Asn substitution. UNIMOD_Trp__Asn = 100001231, /// Trp->Pro: Trp->Pro substitution. UNIMOD_Trp__Pro = 100001232, /// Trp->Gln: Trp->Gln substitution. UNIMOD_Trp__Gln = 100001233, /// Trp->Thr: Trp->Thr substitution. UNIMOD_Trp__Thr = 100001234, /// Trp->Val: Trp->Val substitution. UNIMOD_Trp__Val = 100001235, /// Trp->Tyr: Trp->Tyr substitution. UNIMOD_Trp__Tyr = 100001236, /// Tyr->Ala: Tyr->Ala substitution. UNIMOD_Tyr__Ala = 100001237, /// Tyr->Glu: Tyr->Glu substitution. UNIMOD_Tyr__Glu = 100001238, /// Tyr->Gly: Tyr->Gly substitution. UNIMOD_Tyr__Gly = 100001239, /// Tyr->Lys: Tyr->Lys substitution. UNIMOD_Tyr__Lys = 100001240, /// Tyr->Met: Tyr->Met substitution. UNIMOD_Tyr__Met = 100001241, /// Tyr->Pro: Tyr->Pro substitution. UNIMOD_Tyr__Pro = 100001242, /// Tyr->Gln: Tyr->Gln substitution. UNIMOD_Tyr__Gln = 100001243, /// Tyr->Arg: Tyr->Arg substitution. UNIMOD_Tyr__Arg = 100001244, /// Tyr->Thr: Tyr->Thr substitution. UNIMOD_Tyr__Thr = 100001245, /// Tyr->Val: Tyr->Val substitution. UNIMOD_Tyr__Val = 100001246, /// Tyr->Trp: Tyr->Trp substitution. UNIMOD_Tyr__Trp = 100001247, /// Tyr->Xle: Tyr->Leu/Ile substitution. UNIMOD_Tyr__Xle = 100001248, /// AHA-SS: Azidohomoalanine coupled to reductively cleaved tag. UNIMOD_AHA_SS = 100001249, /// AHA-SS_CAM: Carbamidomethylated form of reductively cleaved tag coupled to azidohomoalanine. UNIMOD_AHA_SS_CAM = 100001250, /// Biotin:Thermo-33033: Sulfo-SBED Label Photoreactive Biotin Crosslinker. UNIMOD_Biotin_Thermo_33033 = 100001251, /// Biotin:Thermo-33033-H: Sulfo-SBED Label Photoreactive Biotin Crosslinker minus Hydrogen. UNIMOD_Biotin_Thermo_33033_H = 100001252, /// 2-monomethylsuccinyl: S-(2-monomethylsuccinyl) cysteine. UNIMOD_2_monomethylsuccinyl = 100001253, /// Saligenin: O-toluene. UNIMOD_Saligenin = 100001254, /// Cresylphosphate: O-toluyl-phosphorylation. UNIMOD_Cresylphosphate = 100001255, /// CresylSaligeninPhosphate: Cresyl-Saligenin-phosphorylation. UNIMOD_CresylSaligeninPhosphate = 100001256, /// Ub-Br2: Ub Bromide probe addition. UNIMOD_Ub_Br2 = 100001257, /// Ub-VME: Ubiquitin vinylmethylester. UNIMOD_Ub_VME = 100001258, /// Ub-amide: Ub amide probe addition. UNIMOD_Ub_amide = 100001260, /// Ub-fluorescein: Ub Fluorescein probe addition. UNIMOD_Ub_fluorescein = 100001261, /// 2-dimethylsuccinyl: S-(2-dimethylsuccinyl) cysteine. UNIMOD_2_dimethylsuccinyl = 100001262, /// Gly: Addition of Glycine. UNIMOD_Gly = 100001263, /// pupylation: Addition of GGE. UNIMOD_pupylation = 100001264, /// Label:13C(4): 13C4 Methionine label. UNIMOD_Label_13C_4_ = 100001266, /// Label:13C(4)+Oxidation: Oxidised 13C4 labelled Methionine. UNIMOD_Label_13C_4__Oxidation = 100001267, /// HCysThiolactone: N-Homocysteine thiolactone. UNIMOD_HCysThiolactone = 100001270, /// HCysteinyl: S-homocysteinylation. UNIMOD_HCysteinyl = 100001271, /// UgiJoullie: Side reaction of HisTag. UNIMOD_UgiJoullie = 100001276, /// Dipyridyl: Cys modified with dipy ligand. UNIMOD_Dipyridyl = 100001277, /// Furan: Chemical modification of the iodinated sites of thyroglobulin by Suzuki reaction. UNIMOD_Furan = 100001278, /// Difuran: Chemical modification of the diiodinated sites of thyroglobulin by Suzuki reaction. UNIMOD_Difuran = 100001279, /// BMP-piperidinol: 1-methyl-3-benzoyl-4-hydroxy-4-phenylpiperidine. UNIMOD_BMP_piperidinol = 100001281, /// UgiJoullieProGly: Side reaction of PG with Side chain of aspartic or glutamic acid. UNIMOD_UgiJoullieProGly = 100001282, /// UgiJoullieProGlyProGly: Side reaction of PGPG with Side chain of aspartic or glutamic acid. UNIMOD_UgiJoullieProGlyProGly = 100001283, /// IMEHex(2)NeuAc(1): Glycosylation with IME linked Hex(2) NeuAc. UNIMOD_IMEHex_2_NeuAc_1_ = 100001286, /// Arg-loss: Loss of arginine due to transpeptidation. UNIMOD_Arg_loss = 100001287, /// Arg: Addition of arginine due to transpeptidation. UNIMOD_Arg = 100001288, /// Butyryl: Butyryl. UNIMOD_Butyryl = 100001289, /// Dicarbamidomethyl: Double Carbamidomethylation. UNIMOD_Dicarbamidomethyl = 100001290, /// Dimethyl:2H(6): Dimethyl-Medium. UNIMOD_Dimethyl_2H_6_ = 100001291, /// GGQ: SUMOylation leaving GlyGlyGln. UNIMOD_GGQ = 100001292, /// QTGG: SUMOylation leaving GlnThrGlyGly. UNIMOD_QTGG = 100001293, /// Label:13C(3): 13C3 label for SILAC. UNIMOD_Label_13C_3_ = 100001296, /// Label:13C(3)15N(1): 13C3 15N1 label for SILAC. UNIMOD_Label_13C_3_15N_1_ = 100001297, /// Label:13C(4)15N(1): 13C4 15N1 label for SILAC. UNIMOD_Label_13C_4_15N_1_ = 100001298, /// Label:2H(10): 2H(10) label. UNIMOD_Label_2H_10_ = 100001299, /// Label:2H(4)13C(1): Label:2H(4)13C(1). UNIMOD_Label_2H_4_13C_1_ = 100001300, /// Lys: Addition of lysine due to transpeptidation. UNIMOD_Lys = 100001301, /// mTRAQ:13C(6)15N(2): MTRAQ heavy. UNIMOD_mTRAQ_13C_6_15N_2_ = 100001302, /// NeuAc: N-acetyl neuraminic acid. UNIMOD_NeuAc = 100001303, /// NeuGc: N-glycoyl neuraminic acid. UNIMOD_NeuGc = 100001304, /// Propyl: Propyl. UNIMOD_Propyl = 100001305, /// Propyl:2H(6): Propyl:2H(6). UNIMOD_Propyl_2H_6_ = 100001306, /// Propiophenone: Propiophenone. UNIMOD_Propiophenone = 100001310, /// Delta:H(6)C(3)O(1): Reduced acrolein addition +58. UNIMOD_Delta_H_6_C_3_O_1_ = 100001312, /// Delta:H(8)C(6)O(1): Reduced acrolein addition +96. UNIMOD_Delta_H_8_C_6_O_1_ = 100001313, /// biotinAcrolein298: Biotin hydrazide labeled acrolein addition +298. UNIMOD_biotinAcrolein298 = 100001314, /// MM-diphenylpentanone: 3-methyl-5-(methylamino)-1,3-diphenylpentan-1-one. UNIMOD_MM_diphenylpentanone = 100001315, /// EHD-diphenylpentanone: 2-ethyl-3-hydroxy-1,3-diphenylpentan-1-one. UNIMOD_EHD_diphenylpentanone = 100001317, /// Biotin:Thermo-21901+2H2O: Maleimide-Biotin + 2Water. UNIMOD_Biotin_Thermo_21901_2H2O = 100001320, /// DiLeu4plex115: Accurate mass for DiLeu 115 isobaric tag. UNIMOD_DiLeu4plex115 = 100001321, /// DiLeu4plex: Accurate mass for DiLeu 116 isobaric tag. UNIMOD_DiLeu4plex = 100001322, /// DiLeu4plex117: Accurate mass for DiLeu 117 isobaric tag. UNIMOD_DiLeu4plex117 = 100001323, /// DiLeu4plex118: Accurate mass for DiLeu 118 isobaric tag. UNIMOD_DiLeu4plex118 = 100001324, /// NEMsulfur: N-ethylmaleimideSulfur. UNIMOD_NEMsulfur = 100001326, /// SulfurDioxide: SulfurDioxide. UNIMOD_SulfurDioxide = 100001327, /// NEMsulfurWater: N-ethylmaleimideSulfurWater. UNIMOD_NEMsulfurWater = 100001328, /// bisANS-sulfonates: BisANS with loss of both sulfonates. UNIMOD_bisANS_sulfonates = 100001330, /// DNCB_hapten: Chemical reaction with 2,4-dinitro-1-chloro benzene (DNCB). UNIMOD_DNCB_hapten = 100001331, /// Biotin:Thermo-21911: Biotin-PEG11-maleimide. UNIMOD_Biotin_Thermo_21911 = 100001340, /// iodoTMT: Native iodoacetyl Tandem Mass Tag®. UNIMOD_iodoTMT = 100001341, /// iodoTMT6plex: Sixplex iodoacetyl Tandem Mass Tag®. UNIMOD_iodoTMT6plex = 100001342, /// Gluconoylation: Gluconoylation. UNIMOD_Gluconoylation = 100001343, /// Phosphogluconoylation: Phosphogluconoylation. UNIMOD_Phosphogluconoylation = 100001344, /// PS_Hapten: Reaction with phenyl salicylate (PS). UNIMOD_PS_Hapten = 100001345, /// Cy3-maleimide: Cy3 Maleimide mono-Reactive dye. UNIMOD_Cy3_maleimide = 100001348, /// benzylguanidine: Modification of the lysine side chain from NH2 to guanidine with a H removed in favor of a benzyl group. UNIMOD_benzylguanidine = 100001349, /// CarboxymethylDMAP: A fixed +1 charge tag attached to the N-terminus of peptides. UNIMOD_CarboxymethylDMAP = 100001350, /// azole: Formation of five membered aromatic heterocycle. UNIMOD_azole = 100001355, /// phosphoRibosyl: Phosphate-ribosylation. UNIMOD_phosphoRibosyl = 100001356, /// NEM:2H(5)+H2O: D5 N-ethylmaleimide+water on cysteines. UNIMOD_NEM_2H_5__H2O = 100001358, /// Crotonyl: Crotonylation. UNIMOD_Crotonyl = 100001363, /// O-Et-N-diMePhospho: O-ethyl, N-dimethyl phosphate. UNIMOD_O_Et_N_diMePhospho = 100001364, /// N-dimethylphosphate: N-dimethylphosphate. UNIMOD_N_dimethylphosphate = 100001365, /// dHex(1)Hex(1): Hex1dHex1. UNIMOD_dHex_1_Hex_1_ = 100001367, /// Methyl:2H(3)+Acetyl:2H(3): 3-fold methylated lysine labelled with Acetyl_heavy. UNIMOD_Methyl_2H_3__Acetyl_2H_3_ = 100001368, /// Label:2H(3)+Oxidation: Oxidised 2H(3) labelled Methionine. UNIMOD_Label_2H_3__Oxidation = 100001370, /// Trimethyl:2H(9): 3-fold methylation with deuterated methyl groups. UNIMOD_Trimethyl_2H_9_ = 100001371, /// Acetyl:13C(2): Heavy acetylation. UNIMOD_Acetyl_13C_2_ = 100001372, /// dHex(1)Hex(2): Hex2dHex1. UNIMOD_dHex_1_Hex_2_ = 100001375, /// dHex(1)Hex(3): Hex3dHex1. UNIMOD_dHex_1_Hex_3_ = 100001376, /// dHex(1)Hex(4): Hex4dHex1. UNIMOD_dHex_1_Hex_4_ = 100001377, /// dHex(1)Hex(5): Hex5dHex1. UNIMOD_dHex_1_Hex_5_ = 100001378, /// dHex(1)Hex(6): Hex6dHex1. UNIMOD_dHex_1_Hex_6_ = 100001379, /// methylsulfonylethyl: Reaction with methyl vinyl sulfone. UNIMOD_methylsulfonylethyl = 100001380, /// ethylsulfonylethyl: Reaction with ethyl vinyl sulfone. UNIMOD_ethylsulfonylethyl = 100001381, /// phenylsulfonylethyl: Reaction with phenyl vinyl sulfone. UNIMOD_phenylsulfonylethyl = 100001382, /// PyridoxalPhosphateH2: PLP bound to lysine reduced by sodium borohydride (NaBH4) to create amine linkage. UNIMOD_PyridoxalPhosphateH2 = 100001383, /// Homocysteic_acid: Methionine oxidation to homocysteic acid. UNIMOD_Homocysteic_acid = 100001384, /// Hydroxamic_acid: Conversion of carboxylic acid to hydroxamic acid. UNIMOD_Hydroxamic_acid = 100001385, /// 3-phosphoglyceryl: 3-phosphoglyceryl. UNIMOD_3_phosphoglyceryl = 100001387, /// HN2_mustard: Modification by hydroxylated mechloroethamine (HN-2). UNIMOD_HN2_mustard = 100001388, /// HN3_mustard: Modification by hydroxylated tris-(2-chloroethyl)amine (HN-3). UNIMOD_HN3_mustard = 100001389, /// Oxidation+NEM: N-ethylmaleimide on cysteine sulfenic acid. UNIMOD_Oxidation_NEM = 100001390, /// NHS-fluorescein: Fluorescein-hexanoate-NHS hydrolysis. UNIMOD_NHS_fluorescein = 100001391, /// DiART6plex: Representative mass and accurate mass for 114. UNIMOD_DiART6plex = 100001392, /// DiART6plex115: Accurate mass for DiART6plex 115. UNIMOD_DiART6plex115 = 100001393, /// DiART6plex116/119: Accurate mass for DiART6plex 116 and 119. UNIMOD_DiART6plex116_119 = 100001394, /// DiART6plex117: Accurate mass for DiART6plex 117. UNIMOD_DiART6plex117 = 100001395, /// DiART6plex118: Accurate mass for DiART6plex 118. UNIMOD_DiART6plex118 = 100001396, /// Iodoacetanilide: Iodoacetanilide derivative. UNIMOD_Iodoacetanilide = 100001397, /// Iodoacetanilide:13C(6): 13C labelled iodoacetanilide derivative. UNIMOD_Iodoacetanilide_13C_6_ = 100001398, /// Dap-DSP: Diaminopimelic acid-DSP monolinked. UNIMOD_Dap_DSP = 100001399, /// MurNAc: N-Acetylmuramic acid. UNIMOD_MurNAc = 100001400, /// Label:2H(7)15N(4): Label:2H(7)15N(4). UNIMOD_Label_2H_7_15N_4_ = 100001402, /// Label:2H(6)15N(1): Label:2H(6)15N(1). UNIMOD_Label_2H_6_15N_1_ = 100001403, /// EEEDVIEVYQEQTGG: Sumoylation by SUMO-1 after Cyanogen bromide (CNBr) cleavage. UNIMOD_EEEDVIEVYQEQTGG = 100001405, /// EDEDTIDVFQQQTGG: Sumoylation by SUMO-2/3 after Cyanogen bromide (CNBr) cleavage. UNIMOD_EDEDTIDVFQQQTGG = 100001406, /// Hex(5)HexNAc(4)NeuAc(2): Hex(5) HexNAc(4) NeuAc(2). UNIMOD_Hex_5_HexNAc_4_NeuAc_2_ = 100001408, /// Hex(5)HexNAc(4)NeuAc(1): Hex(5) HexNAc(4) NeuAc. UNIMOD_Hex_5_HexNAc_4_NeuAc_1_ = 100001409, /// dHex(1)Hex(5)HexNAc(4)NeuAc(1): DHex Hex(5) HexNAc(4) NeuAc. UNIMOD_dHex_1_Hex_5_HexNAc_4_NeuAc_1_ = 100001410, /// dHex(1)Hex(5)HexNAc(4)NeuAc(2): DHex Hex(5) HexNAc(4) NeuAc(2). UNIMOD_dHex_1_Hex_5_HexNAc_4_NeuAc_2_ = 100001411, /// s-GlcNAc: O3S1HexNAc1. UNIMOD_s_GlcNAc = 100001412, /// PhosphoHex(2): H1O3P1Hex2. UNIMOD_PhosphoHex_2_ = 100001413, /// Trimethyl:13C(3)2H(9): 3-fold methylation with fully labelled methyl groups. UNIMOD_Trimethyl_13C_3_2H_9_ = 100001414, /// 15N-oxobutanoic: Loss of ammonia (15N). UNIMOD_15N_oxobutanoic = 100001419, /// spermine: Spermine adduct. UNIMOD_spermine = 100001420, /// spermidine: Spermidine adduct. UNIMOD_spermidine = 100001421, /// Biotin:Thermo-21330: Biotin_PEG4. UNIMOD_Biotin_Thermo_21330 = 100001423, /// Pentose: Pentose. UNIMOD_Pentose = 100001425, /// Hex(1)Pent(1): Hex Pent. UNIMOD_Hex_1_Pent_1_ = 100001426, /// Hex(1)HexA(1): Hex HexA. UNIMOD_Hex_1_HexA_1_ = 100001427, /// Hex(1)Pent(2): Hex Pent(2). UNIMOD_Hex_1_Pent_2_ = 100001428, /// Hex(1)HexNAc(1)Phos(1): Hex HexNAc Phos. UNIMOD_Hex_1_HexNAc_1_Phos_1_ = 100001429, /// Hex(1)HexNAc(1)Sulf(1): Hex HexNAc Sulf. UNIMOD_Hex_1_HexNAc_1_Sulf_1_ = 100001430, /// Hex(1)NeuAc(1): Hex NeuAc. UNIMOD_Hex_1_NeuAc_1_ = 100001431, /// Hex(1)NeuGc(1): Hex NeuGc. UNIMOD_Hex_1_NeuGc_1_ = 100001432, /// HexNAc(3): HexNAc(3). UNIMOD_HexNAc_3_ = 100001433, /// HexNAc(1)NeuAc(1): HexNAc NeuAc. UNIMOD_HexNAc_1_NeuAc_1_ = 100001434, /// HexNAc(1)NeuGc(1): HexNAc NeuGc. UNIMOD_HexNAc_1_NeuGc_1_ = 100001435, /// Hex(1)HexNAc(1)dHex(1)Me(1): Hex HexNAc dHex Me. UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_1_ = 100001436, /// Hex(1)HexNAc(1)dHex(1)Me(2): Hex HexNAc dHex Me(2). UNIMOD_Hex_1_HexNAc_1_dHex_1_Me_2_ = 100001437, /// Hex(2)HexNAc(1): Hex(2) HexNAc. UNIMOD_Hex_2_HexNAc_1_ = 100001438, /// Hex(1)HexA(1)HexNAc(1): Hex HexA HexNAc. UNIMOD_Hex_1_HexA_1_HexNAc_1_ = 100001439, /// Hex(2)HexNAc(1)Me(1): Hex(2) HexNAc Me. UNIMOD_Hex_2_HexNAc_1_Me_1_ = 100001440, /// Hex(3)Phos(1): Hex(3) Phos. UNIMOD_Hex_3_Phos_1_ = 100001441, /// Hex(1)NeuAc(1)Pent(1): Hex NeuAc Pent. UNIMOD_Hex_1_NeuAc_1_Pent_1_ = 100001442, /// Hex(2)HexNAc(1)Sulf(1): Hex(2) HexNAc Sulf. UNIMOD_Hex_2_HexNAc_1_Sulf_1_ = 100001443, /// Hex(2)NeuAc(1): Hex(2) NeuAc. UNIMOD_Hex_2_NeuAc_1_ = 100001444, /// dHex(2)Hex(2): Hex2 dHex2. UNIMOD_dHex_2_Hex_2_ = 100001445, /// dHex(1)Hex(2)HexA(1): DHex Hex(2) HexA. UNIMOD_dHex_1_Hex_2_HexA_1_ = 100001446, /// Hex(1)HexNAc(2)Sulf(1): Hex HexNAc(2) Sulf. UNIMOD_Hex_1_HexNAc_2_Sulf_1_ = 100001447, /// Hex(4): Hex(4). UNIMOD_Hex_4_ = 100001448, /// dHex(1)Hex(2)HexNAc(2)Pent(1): DHex Hex(2) HexNAc(2) Pent. UNIMOD_dHex_1_Hex_2_HexNAc_2_Pent_1_ = 100001449, /// Hex(2)HexNAc(2)NeuAc(1): Hex(2) HexNAc(2) NeuAc. UNIMOD_Hex_2_HexNAc_2_NeuAc_1_ = 100001450, /// Hex(3)HexNAc(2)Pent(1): Hex(3) HexNAc(2) Pent. UNIMOD_Hex_3_HexNAc_2_Pent_1_ = 100001451, /// Hex(4)HexNAc(2): Hex(4) HexNAc(2). UNIMOD_Hex_4_HexNAc_2_ = 100001452, /// dHex(1)Hex(4)HexNAc(1)Pent(1): DHex Hex(4) HexNAc Pent. UNIMOD_dHex_1_Hex_4_HexNAc_1_Pent_1_ = 100001453, /// dHex(1)Hex(3)HexNAc(2)Pent(1): DHex Hex(3) HexNAc(2) Pent. UNIMOD_dHex_1_Hex_3_HexNAc_2_Pent_1_ = 100001454, /// Hex(3)HexNAc(2)NeuAc(1): Hex(3) HexNAc(2) NeuAc. UNIMOD_Hex_3_HexNAc_2_NeuAc_1_ = 100001455, /// Hex(4)HexNAc(2)Pent(1): Hex(4) HexNAc(2) Pent. UNIMOD_Hex_4_HexNAc_2_Pent_1_ = 100001456, /// Hex(3)HexNAc(3)Pent(1): Hex(3) HexNAc(3) Pent. UNIMOD_Hex_3_HexNAc_3_Pent_1_ = 100001457, /// Hex(5)HexNAc(2)Phos(1): Hex(5) HexNAc(2) Phos. UNIMOD_Hex_5_HexNAc_2_Phos_1_ = 100001458, /// dHex(1)Hex(4)HexNAc(2)Pent(1): DHex Hex(4) HexNAc(2) Pent. UNIMOD_dHex_1_Hex_4_HexNAc_2_Pent_1_ = 100001459, /// Hex(7)HexNAc(1): Hex(7) HexNAc. UNIMOD_Hex_7_HexNAc_1_ = 100001460, /// Hex(4)HexNAc(2)NeuAc(1): Hex(4) HexNAc(2) NeuAc. UNIMOD_Hex_4_HexNAc_2_NeuAc_1_ = 100001461, /// dHex(1)Hex(5)HexNAc(2): DHex Hex(5) HexNAc(2). UNIMOD_dHex_1_Hex_5_HexNAc_2_ = 100001462, /// dHex(1)Hex(3)HexNAc(3)Pent(1): DHex Hex(3) HexNAc(3) Pent. UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_1_ = 100001463, /// Hex(3)HexNAc(4)Sulf(1): Hex(3) HexNAc(4) Sulf. UNIMOD_Hex_3_HexNAc_4_Sulf_1_ = 100001464, /// Hex(6)HexNAc(2): Hex(6) HexNAc(2). UNIMOD_Hex_6_HexNAc_2_ = 100001465, /// Hex(4)HexNAc(3)Pent(1): Hex(4) HexNAc(3) Pent. UNIMOD_Hex_4_HexNAc_3_Pent_1_ = 100001466, /// dHex(1)Hex(4)HexNAc(3): DHex Hex(4) HexNAc(3). UNIMOD_dHex_1_Hex_4_HexNAc_3_ = 100001467, /// Hex(5)HexNAc(3): Hex(5) HexNAc(3). UNIMOD_Hex_5_HexNAc_3_ = 100001468, /// Hex(3)HexNAc(4)Pent(1): Hex(3) HexNAc(4) Pent. UNIMOD_Hex_3_HexNAc_4_Pent_1_ = 100001469, /// Hex(6)HexNAc(2)Phos(1): Hex(6) HexNAc(2) Phos. UNIMOD_Hex_6_HexNAc_2_Phos_1_ = 100001470, /// dHex(1)Hex(4)HexNAc(3)Sulf(1): DHex Hex(4) HexNAc(3) Sulf. UNIMOD_dHex_1_Hex_4_HexNAc_3_Sulf_1_ = 100001471, /// dHex(1)Hex(5)HexNAc(2)Pent(1): DHex Hex(5) HexNAc(2) Pent. UNIMOD_dHex_1_Hex_5_HexNAc_2_Pent_1_ = 100001472, /// Hex(8)HexNAc(1): Hex(8) HexNAc. UNIMOD_Hex_8_HexNAc_1_ = 100001473, /// dHex(1)Hex(3)HexNAc(3)Pent(2): DHex Hex(3) HexNAc(3) Pent(2). UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_2_ = 100001474, /// dHex(2)Hex(3)HexNAc(3)Pent(1): DHex(2) Hex(3) HexNAc(3) Pent. UNIMOD_dHex_2_Hex_3_HexNAc_3_Pent_1_ = 100001475, /// dHex(1)Hex(3)HexNAc(4)Sulf(1): DHex Hex(3) HexNAc(4) Sulf. UNIMOD_dHex_1_Hex_3_HexNAc_4_Sulf_1_ = 100001476, /// dHex(1)Hex(6)HexNAc(2): DHex Hex(6) HexNAc(2). UNIMOD_dHex_1_Hex_6_HexNAc_2_ = 100001477, /// dHex(1)Hex(4)HexNAc(3)Pent(1): DHex Hex(4) HexNAc(3) Pent. UNIMOD_dHex_1_Hex_4_HexNAc_3_Pent_1_ = 100001478, /// Hex(4)HexNAc(4)Sulf(1): Hex(4) HexNAc(4) Sulf. UNIMOD_Hex_4_HexNAc_4_Sulf_1_ = 100001479, /// Hex(7)HexNAc(2): Hex(7) HexNAc(2). UNIMOD_Hex_7_HexNAc_2_ = 100001480, /// dHex(2)Hex(4)HexNAc(3): DHex(2) Hex(4) HexNAc(3). UNIMOD_dHex_2_Hex_4_HexNAc_3_ = 100001481, /// Hex(5)HexNAc(3)Pent(1): Hex(5) HexNAc(3) Pent. UNIMOD_Hex_5_HexNAc_3_Pent_1_ = 100001482, /// Hex(4)HexNAc(3)NeuGc(1): Hex(4) HexNAc(3) NeuGc. UNIMOD_Hex_4_HexNAc_3_NeuGc_1_ = 100001483, /// dHex(1)Hex(5)HexNAc(3): DHex Hex(5) HexNAc(3). UNIMOD_dHex_1_Hex_5_HexNAc_3_ = 100001484, /// dHex(1)Hex(3)HexNAc(4)Pent(1): DHex Hex(3) HexNAc(4) Pent. UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_1_ = 100001485, /// Hex(3)HexNAc(5)Sulf(1): Hex(3) HexNAc(5) Sulf. UNIMOD_Hex_3_HexNAc_5_Sulf_1_ = 100001486, /// Hex(6)HexNAc(3): Hex(6) HexNAc(3). UNIMOD_Hex_6_HexNAc_3_ = 100001487, /// Hex(3)HexNAc(4)NeuAc(1): Hex(3) HexNAc(4) NeuAc. UNIMOD_Hex_3_HexNAc_4_NeuAc_1_ = 100001488, /// Hex(4)HexNAc(4)Pent(1): Hex(4) HexNAc(4) Pent. UNIMOD_Hex_4_HexNAc_4_Pent_1_ = 100001489, /// Hex(7)HexNAc(2)Phos(1): Hex(7) HexNAc(2) Phos. UNIMOD_Hex_7_HexNAc_2_Phos_1_ = 100001490, /// Hex(4)HexNAc(4)Me(2)Pent(1): Hex(4) HexNAc(4) Me(2) Pent. UNIMOD_Hex_4_HexNAc_4_Me_2_Pent_1_ = 100001491, /// dHex(1)Hex(3)HexNAc(3)Pent(3): DHex Hex(3) HexNAc(3) Pent(3). UNIMOD_dHex_1_Hex_3_HexNAc_3_Pent_3_ = 100001492, /// dHex(1)Hex(5)HexNAc(3)Sulf(1): DHex Hex(5) HexNAc(3) Sulf. UNIMOD_dHex_1_Hex_5_HexNAc_3_Sulf_1_ = 100001493, /// dHex(2)Hex(3)HexNAc(3)Pent(2): DHex(2) Hex(3) HexNAc(3) Pent(2). UNIMOD_dHex_2_Hex_3_HexNAc_3_Pent_2_ = 100001494, /// Hex(6)HexNAc(3)Phos(1): Hex(6) HexNAc(3) Phos. UNIMOD_Hex_6_HexNAc_3_Phos_1_ = 100001495, /// Hex(4)HexNAc(5): Hex(4) HexNAc(5). UNIMOD_Hex_4_HexNAc_5_ = 100001496, /// dHex(3)Hex(3)HexNAc(3)Pent(1): DHex(3) Hex(3) HexNAc(3) Pent. UNIMOD_dHex_3_Hex_3_HexNAc_3_Pent_1_ = 100001497, /// dHex(2)Hex(4)HexNAc(3)Pent(1): DHex(2) Hex(4) HexNAc(3) Pent. UNIMOD_dHex_2_Hex_4_HexNAc_3_Pent_1_ = 100001498, /// dHex(1)Hex(4)HexNAc(4)Sulf(1): DHex Hex(4) HexNAc(4) Sulf. UNIMOD_dHex_1_Hex_4_HexNAc_4_Sulf_1_ = 100001499, /// dHex(1)Hex(7)HexNAc(2): DHex Hex(7) HexNAc(2). UNIMOD_dHex_1_Hex_7_HexNAc_2_ = 100001500, /// dHex(1)Hex(4)HexNAc(3)NeuAc(1): DHex Hex(4) HexNAc(3) NeuAc. UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuAc_1_ = 100001501, /// Hex(7)HexNAc(2)Phos(2): Hex(7) HexNAc(2) Phos(2). UNIMOD_Hex_7_HexNAc_2_Phos_2_ = 100001502, /// Hex(5)HexNAc(4)Sulf(1): Hex(5) HexNAc(4) Sulf. UNIMOD_Hex_5_HexNAc_4_Sulf_1_ = 100001503, /// Hex(8)HexNAc(2): Hex(8) HexNAc(2). UNIMOD_Hex_8_HexNAc_2_ = 100001504, /// dHex(1)Hex(3)HexNAc(4)Pent(2): DHex Hex(3) HexNAc(4) Pent(2). UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_2_ = 100001505, /// dHex(1)Hex(4)HexNAc(3)NeuGc(1): DHex Hex(4) HexNAc(3) NeuGc. UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuGc_1_ = 100001506, /// dHex(2)Hex(3)HexNAc(4)Pent(1): DHex(2) Hex(3) HexNAc(4) Pent. UNIMOD_dHex_2_Hex_3_HexNAc_4_Pent_1_ = 100001507, /// dHex(1)Hex(3)HexNAc(5)Sulf(1): DHex Hex(3) HexNAc(5) Sulf. UNIMOD_dHex_1_Hex_3_HexNAc_5_Sulf_1_ = 100001508, /// dHex(1)Hex(6)HexNAc(3): DHex Hex(6) HexNAc(3). UNIMOD_dHex_1_Hex_6_HexNAc_3_ = 100001509, /// dHex(1)Hex(3)HexNAc(4)NeuAc(1): DHex Hex(3) HexNAc(4) NeuAc. UNIMOD_dHex_1_Hex_3_HexNAc_4_NeuAc_1_ = 100001510, /// dHex(3)Hex(3)HexNAc(4): DHex(3) Hex(3) HexNAc(4). UNIMOD_dHex_3_Hex_3_HexNAc_4_ = 100001511, /// dHex(1)Hex(4)HexNAc(4)Pent(1): DHex Hex(4) HexNAc(4) Pent. UNIMOD_dHex_1_Hex_4_HexNAc_4_Pent_1_ = 100001512, /// Hex(4)HexNAc(5)Sulf(1): Hex(4) HexNAc(5) Sulf. UNIMOD_Hex_4_HexNAc_5_Sulf_1_ = 100001513, /// Hex(7)HexNAc(3): Hex(7) HexNAc(3). UNIMOD_Hex_7_HexNAc_3_ = 100001514, /// dHex(1)Hex(4)HexNAc(3)NeuAc(1)Sulf(1): DHex Hex(4) HexNAc(3) NeuAc Sulf. UNIMOD_dHex_1_Hex_4_HexNAc_3_NeuAc_1_Sulf_1_ = 100001515, /// Hex(5)HexNAc(4)Me(2)Pent(1): Hex(5) HexNAc(4) Me(2) Pent. UNIMOD_Hex_5_HexNAc_4_Me_2_Pent_1_ = 100001516, /// Hex(3)HexNAc(6)Sulf(1): Hex(3) HexNAc(6) Sulf. UNIMOD_Hex_3_HexNAc_6_Sulf_1_ = 100001517, /// dHex(1)Hex(6)HexNAc(3)Sulf(1): DHex Hex(6) HexNAc(3) Sulf. UNIMOD_dHex_1_Hex_6_HexNAc_3_Sulf_1_ = 100001518, /// dHex(1)Hex(4)HexNAc(5): DHex Hex(4) HexNAc(5). UNIMOD_dHex_1_Hex_4_HexNAc_5_ = 100001519, /// dHex(1)Hex(5)HexA(1)HexNAc(3)Sulf(1): DHex Hex(5) HexA HexNAc(3) Sulf. UNIMOD_dHex_1_Hex_5_HexA_1_HexNAc_3_Sulf_1_ = 100001520, /// Hex(7)HexNAc(3)Phos(1): Hex(7) HexNAc(3) Phos. UNIMOD_Hex_7_HexNAc_3_Phos_1_ = 100001521, /// Hex(6)HexNAc(4)Me(3): Hex(6) HexNAc(4) Me(3). UNIMOD_Hex_6_HexNAc_4_Me_3_ = 100001522, /// dHex(2)Hex(4)HexNAc(4)Sulf(1): DHex(2) Hex(4) HexNAc(4) Sulf. UNIMOD_dHex_2_Hex_4_HexNAc_4_Sulf_1_ = 100001523, /// Hex(4)HexNAc(3)NeuAc(2): Hex(4) HexNAc(3) NeuAc(2). UNIMOD_Hex_4_HexNAc_3_NeuAc_2_ = 100001524, /// dHex(1)Hex(3)HexNAc(4)Pent(3): DHex Hex(3) HexNAc(4) Pent(3). UNIMOD_dHex_1_Hex_3_HexNAc_4_Pent_3_ = 100001525, /// dHex(2)Hex(5)HexNAc(3)Pent(1): DHex(2) Hex(5) HexNAc(3) Pent. UNIMOD_dHex_2_Hex_5_HexNAc_3_Pent_1_ = 100001526, /// dHex(1)Hex(5)HexNAc(4)Sulf(1): DHex Hex(5) HexNAc(4) Sulf. UNIMOD_dHex_1_Hex_5_HexNAc_4_Sulf_1_ = 100001527, /// dHex(2)Hex(3)HexNAc(4)Pent(2): DHex(2) Hex(3) HexNAc(4) Pent(2). UNIMOD_dHex_2_Hex_3_HexNAc_4_Pent_2_ = 100001528, /// dHex(1)Hex(5)HexNAc(3)NeuAc(1): DHex Hex(5) HexNAc(3) NeuAc. UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuAc_1_ = 100001529, /// Hex(3)HexNAc(6)Sulf(2): Hex(3) HexNAc(6) Sulf(2). UNIMOD_Hex_3_HexNAc_6_Sulf_2_ = 100001530, /// Hex(9)HexNAc(2): Hex(9) HexNAc(2). UNIMOD_Hex_9_HexNAc_2_ = 100001531, /// Hex(4)HexNAc(6): Hex(4) HexNAc(6). UNIMOD_Hex_4_HexNAc_6_ = 100001532, /// dHex(3)Hex(3)HexNAc(4)Pent(1): DHex(3) Hex(3) HexNAc(4) Pent. UNIMOD_dHex_3_Hex_3_HexNAc_4_Pent_1_ = 100001533, /// dHex(1)Hex(5)HexNAc(3)NeuGc(1): DHex Hex(5) HexNAc(3) NeuGc. UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuGc_1_ = 100001534, /// dHex(2)Hex(4)HexNAc(4)Pent(1): DHex(2) Hex(4) HexNAc(4) Pent. UNIMOD_dHex_2_Hex_4_HexNAc_4_Pent_1_ = 100001535, /// dHex(1)Hex(4)HexNAc(5)Sulf(1): DHex Hex(4) HexNAc(5) Sulf. UNIMOD_dHex_1_Hex_4_HexNAc_5_Sulf_1_ = 100001536, /// dHex(1)Hex(7)HexNAc(3): DHex Hex(7) HexNAc(3). UNIMOD_dHex_1_Hex_7_HexNAc_3_ = 100001537, /// dHex(1)Hex(5)HexNAc(4)Pent(1): DHex Hex(5) HexNAc(4) Pent. UNIMOD_dHex_1_Hex_5_HexNAc_4_Pent_1_ = 100001538, /// dHex(1)Hex(5)HexA(1)HexNAc(3)Sulf(2): DHex Hex(5) HexA HexNAc(3) Sulf(2). UNIMOD_dHex_1_Hex_5_HexA_1_HexNAc_3_Sulf_2_ = 100001539, /// Hex(3)HexNAc(7): Hex(3) HexNAc(7). UNIMOD_Hex_3_HexNAc_7_ = 100001540, /// dHex(2)Hex(5)HexNAc(4): DHex(2) Hex(5) HexNAc(4). UNIMOD_dHex_2_Hex_5_HexNAc_4_ = 100001541, /// dHex(2)Hex(4)HexNAc(3)NeuAc(1)Sulf(1): DHex(2) Hex(4) HexNAc(3) NeuAc Sulf. UNIMOD_dHex_2_Hex_4_HexNAc_3_NeuAc_1_Sulf_1_ = 100001542, /// dHex(1)Hex(5)HexNAc(4)Sulf(2): DHex Hex(5) HexNAc(4) Sulf(2). UNIMOD_dHex_1_Hex_5_HexNAc_4_Sulf_2_ = 100001543, /// dHex(1)Hex(5)HexNAc(4)Me(2)Pent(1): DHex Hex(5) HexNAc(4) Me(2) Pent. UNIMOD_dHex_1_Hex_5_HexNAc_4_Me_2_Pent_1_ = 100001544, /// Hex(5)HexNAc(4)NeuGc(1): Hex(5) HexNAc(4) NeuGc. UNIMOD_Hex_5_HexNAc_4_NeuGc_1_ = 100001545, /// dHex(1)Hex(3)HexNAc(6)Sulf(1): DHex Hex(3) HexNAc(6) Sulf. UNIMOD_dHex_1_Hex_3_HexNAc_6_Sulf_1_ = 100001546, /// dHex(1)Hex(6)HexNAc(4): DHex Hex(6) HexNAc(4). UNIMOD_dHex_1_Hex_6_HexNAc_4_ = 100001547, /// dHex(1)Hex(5)HexNAc(3)NeuAc(1)Sulf(1): DHex Hex(5) HexNAc(3) NeuAc Sulf. UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuAc_1_Sulf_1_ = 100001548, /// Hex(7)HexNAc(4): Hex(7) HexNAc(4). UNIMOD_Hex_7_HexNAc_4_ = 100001549, /// dHex(1)Hex(5)HexNAc(3)NeuGc(1)Sulf(1): DHex Hex(5) HexNAc(3) NeuGc Sulf. UNIMOD_dHex_1_Hex_5_HexNAc_3_NeuGc_1_Sulf_1_ = 100001550, /// Hex(4)HexNAc(5)NeuAc(1): Hex(4) HexNAc(5) NeuAc. UNIMOD_Hex_4_HexNAc_5_NeuAc_1_ = 100001551, /// Hex(6)HexNAc(4)Me(3)Pent(1): Hex(6) HexNAc(4) Me(3) Pent. UNIMOD_Hex_6_HexNAc_4_Me_3_Pent_1_ = 100001552, /// dHex(1)Hex(7)HexNAc(3)Sulf(1): DHex Hex(7) HexNAc(3) Sulf. UNIMOD_dHex_1_Hex_7_HexNAc_3_Sulf_1_ = 100001553, /// dHex(1)Hex(7)HexNAc(3)Phos(1): DHex Hex(7) HexNAc(3) Phos. UNIMOD_dHex_1_Hex_7_HexNAc_3_Phos_1_ = 100001554, /// dHex(1)Hex(5)HexNAc(5): DHex Hex(5) HexNAc(5). UNIMOD_dHex_1_Hex_5_HexNAc_5_ = 100001555, /// dHex(1)Hex(4)HexNAc(4)NeuAc(1)Sulf(1): DHex Hex(4) HexNAc(4) NeuAc Sulf. UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_Sulf_1_ = 100001556, /// dHex(3)Hex(4)HexNAc(4)Sulf(1): DHex(3) Hex(4) HexNAc(4) Sulf. UNIMOD_dHex_3_Hex_4_HexNAc_4_Sulf_1_ = 100001557, /// Hex(3)HexNAc(7)Sulf(1): Hex(3) HexNAc(7) Sulf. UNIMOD_Hex_3_HexNAc_7_Sulf_1_ = 100001558, /// Hex(6)HexNAc(5): Hex(6) HexNAc(5). UNIMOD_Hex_6_HexNAc_5_ = 100001559, /// Hex(5)HexNAc(4)NeuAc(1)Sulf(1): Hex(5) HexNAc(4) NeuAc Sulf. UNIMOD_Hex_5_HexNAc_4_NeuAc_1_Sulf_1_ = 100001560, /// Hex(3)HexNAc(6)NeuAc(1): Hex(3) HexNAc(6) NeuAc. UNIMOD_Hex_3_HexNAc_6_NeuAc_1_ = 100001561, /// dHex(2)Hex(3)HexNAc(6): DHex(2) Hex(3) HexNAc(6). UNIMOD_dHex_2_Hex_3_HexNAc_6_ = 100001562, /// Hex(1)HexNAc(1)NeuGc(1): Hex HexNAc NeuGc. UNIMOD_Hex_1_HexNAc_1_NeuGc_1_ = 100001563, /// dHex(1)Hex(2)HexNAc(1): DHex Hex(2) HexNAc. UNIMOD_dHex_1_Hex_2_HexNAc_1_ = 100001564, /// HexNAc(3)Sulf(1): HexNAc(3) Sulf. UNIMOD_HexNAc_3_Sulf_1_ = 100001565, /// Hex(3)HexNAc(1): Hex(3) HexNAc. UNIMOD_Hex_3_HexNAc_1_ = 100001566, /// Hex(1)HexNAc(1)Kdn(1)Sulf(1): Hex HexNAc Kdn Sulf. UNIMOD_Hex_1_HexNAc_1_Kdn_1_Sulf_1_ = 100001567, /// HexNAc(2)NeuAc(1): HexNAc(2) NeuAc. UNIMOD_HexNAc_2_NeuAc_1_ = 100001568, /// HexNAc(1)Kdn(2): HexNAc Kdn(2). UNIMOD_HexNAc_1_Kdn_2_ = 100001570, /// Hex(3)HexNAc(1)Me(1): Hex(3) HexNAc Me. UNIMOD_Hex_3_HexNAc_1_Me_1_ = 100001571, /// Hex(2)HexA(1)Pent(1)Sulf(1): Hex(2) HexA Pent Sulf. UNIMOD_Hex_2_HexA_1_Pent_1_Sulf_1_ = 100001572, /// HexNAc(2)NeuGc(1): HexNAc(2) NeuGc. UNIMOD_HexNAc_2_NeuGc_1_ = 100001573, /// Hex(4)Phos(1): Hex(4) Phos. UNIMOD_Hex_4_Phos_1_ = 100001575, /// Hex(1)HexNAc(1)NeuAc(1)Sulf(1): Hex HexNAc NeuAc Sulf. UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Sulf_1_ = 100001577, /// Hex(1)HexA(1)HexNAc(2): Hex HexA HexNAc(2). UNIMOD_Hex_1_HexA_1_HexNAc_2_ = 100001578, /// dHex(1)Hex(2)HexNAc(1)Sulf(1): DHex Hex(2) HexNAc Sulf. UNIMOD_dHex_1_Hex_2_HexNAc_1_Sulf_1_ = 100001579, /// dHex(1)HexNAc(3): DHex HexNAc(3). UNIMOD_dHex_1_HexNAc_3_ = 100001580, /// dHex(1)Hex(1)HexNAc(1)Kdn(1): DHex Hex HexNAc Kdn. UNIMOD_dHex_1_Hex_1_HexNAc_1_Kdn_1_ = 100001581, /// Hex(1)HexNAc(3): Hex HexNAc(3). UNIMOD_Hex_1_HexNAc_3_ = 100001582, /// HexNAc(2)NeuAc(1)Sulf(1): HexNAc(2) NeuAc Sulf. UNIMOD_HexNAc_2_NeuAc_1_Sulf_1_ = 100001583, /// dHex(2)Hex(3): DHex(2) Hex(3). UNIMOD_dHex_2_Hex_3_ = 100001584, /// Hex(2)HexA(1)HexNAc(1)Sulf(1): Hex(2) HexA HexNAc Sulf. UNIMOD_Hex_2_HexA_1_HexNAc_1_Sulf_1_ = 100001585, /// dHex(2)Hex(2)HexA(1): DHex(2) Hex(2) HexA. UNIMOD_dHex_2_Hex_2_HexA_1_ = 100001586, /// dHex(1)Hex(1)HexNAc(2)Sulf(1): DHex Hex HexNAc(2) Sulf. UNIMOD_dHex_1_Hex_1_HexNAc_2_Sulf_1_ = 100001587, /// dHex(1)Hex(1)HexNAc(1)NeuAc(1): DHex Hex HexNAc NeuAc. UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuAc_1_ = 100001588, /// Hex(2)HexNAc(2)Sulf(1): Hex(2) HexNAc(2) Sulf. UNIMOD_Hex_2_HexNAc_2_Sulf_1_ = 100001589, /// Hex(5): Hex(5). UNIMOD_Hex_5_ = 100001590, /// HexNAc(4): HexNAc(4). UNIMOD_HexNAc_4_ = 100001591, /// HexNAc(1)NeuGc(2): HexNAc NeuGc(2). UNIMOD_HexNAc_1_NeuGc_2_ = 100001592, /// dHex(1)Hex(1)HexNAc(1)NeuGc(1): DHex Hex HexNAc NeuGc. UNIMOD_dHex_1_Hex_1_HexNAc_1_NeuGc_1_ = 100001593, /// dHex(2)Hex(2)HexNAc(1): DHex(2) Hex(2) HexNAc. UNIMOD_dHex_2_Hex_2_HexNAc_1_ = 100001594, /// Hex(2)HexNAc(1)NeuGc(1): Hex(2) HexNAc NeuGc. UNIMOD_Hex_2_HexNAc_1_NeuGc_1_ = 100001595, /// dHex(1)Hex(3)HexNAc(1): DHex Hex(3) HexNAc. UNIMOD_dHex_1_Hex_3_HexNAc_1_ = 100001596, /// dHex(1)Hex(2)HexA(1)HexNAc(1): DHex Hex(2) HexA HexNAc. UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_ = 100001597, /// Hex(1)HexNAc(3)Sulf(1): Hex HexNAc(3) Sulf. UNIMOD_Hex_1_HexNAc_3_Sulf_1_ = 100001598, /// Hex(4)HexNAc(1): Hex(4) HexNAc. UNIMOD_Hex_4_HexNAc_1_ = 100001599, /// Hex(1)HexNAc(2)NeuAc(1): Hex HexNAc(2) NeuAc. UNIMOD_Hex_1_HexNAc_2_NeuAc_1_ = 100001600, /// Hex(1)HexNAc(2)NeuGc(1): Hex HexNAc(2) NeuGc. UNIMOD_Hex_1_HexNAc_2_NeuGc_1_ = 100001602, /// Hex(5)Phos(1): Hex(5) Phos. UNIMOD_Hex_5_Phos_1_ = 100001604, /// dHex(2)Hex(1)HexNAc(1)Kdn(1): DHex(2) Hex HexNAc Kdn. UNIMOD_dHex_2_Hex_1_HexNAc_1_Kdn_1_ = 100001606, /// dHex(1)Hex(3)HexNAc(1)Sulf(1): DHex Hex(3) HexNAc Sulf. UNIMOD_dHex_1_Hex_3_HexNAc_1_Sulf_1_ = 100001607, /// dHex(1)Hex(1)HexNAc(3): DHex Hex HexNAc(3). UNIMOD_dHex_1_Hex_1_HexNAc_3_ = 100001608, /// dHex(1)Hex(2)HexA(1)HexNAc(1)Sulf(1): DHex Hex(2) HexA HexNAc Sulf. UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_1_Sulf_1_ = 100001609, /// Hex(2)HexNAc(3): Hex(2) HexNAc(3). UNIMOD_Hex_2_HexNAc_3_ = 100001610, /// Hex(1)HexNAc(2)NeuAc(1)Sulf(1): Hex HexNAc(2) NeuAc Sulf. UNIMOD_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_ = 100001611, /// dHex(2)Hex(4): DHex(2) Hex(4). UNIMOD_dHex_2_Hex_4_ = 100001612, /// dHex(2)HexNAc(2)Kdn(1): DHex(2) HexNAc(2) Kdn. UNIMOD_dHex_2_HexNAc_2_Kdn_1_ = 100001614, /// dHex(1)Hex(2)HexNAc(2)Sulf(1): DHex Hex(2) HexNAc(2) Sulf. UNIMOD_dHex_1_Hex_2_HexNAc_2_Sulf_1_ = 100001615, /// dHex(1)HexNAc(4): DHex HexNAc(4). UNIMOD_dHex_1_HexNAc_4_ = 100001616, /// Hex(1)HexNAc(1)NeuAc(1)NeuGc(1): Hex HexNAc NeuAc NeuGc. UNIMOD_Hex_1_HexNAc_1_NeuAc_1_NeuGc_1_ = 100001617, /// dHex(1)Hex(1)HexNAc(2)Kdn(1): DHex Hex HexNAc(2) Kdn. UNIMOD_dHex_1_Hex_1_HexNAc_2_Kdn_1_ = 100001618, /// Hex(1)HexNAc(1)NeuGc(2): Hex HexNAc NeuGc(2). UNIMOD_Hex_1_HexNAc_1_NeuGc_2_ = 100001619, /// Hex(1)HexNAc(1)NeuAc(2)Ac(1): Ac Hex HexNAc NeuAc(2). UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_1_ = 100001620, /// dHex(2)Hex(2)HexA(1)HexNAc(1): DHex(2) Hex(2) HexA HexNAc. UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_1_ = 100001621, /// dHex(1)Hex(1)HexNAc(3)Sulf(1): DHex Hex HexNAc(3) Sulf. UNIMOD_dHex_1_Hex_1_HexNAc_3_Sulf_1_ = 100001622, /// Hex(2)HexA(1)NeuAc(1)Pent(1)Sulf(1): Hex(2) HexA NeuAc Pent Sulf. UNIMOD_Hex_2_HexA_1_NeuAc_1_Pent_1_Sulf_1_ = 100001623, /// dHex(1)Hex(1)HexNAc(2)NeuAc(1): DHex Hex HexNAc(2) NeuAc. UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_ = 100001624, /// dHex(1)Hex(3)HexA(1)HexNAc(1): DHex Hex(3) HexA HexNAc. UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_ = 100001625, /// Hex(2)HexNAc(3)Sulf(1): Hex(2) HexNAc(3) Sulf. UNIMOD_Hex_2_HexNAc_3_Sulf_1_ = 100001626, /// Hex(5)HexNAc(1): Hex(5) HexNAc. UNIMOD_Hex_5_HexNAc_1_ = 100001627, /// HexNAc(5): HexNAc(5). UNIMOD_HexNAc_5_ = 100001628, /// dHex(1)Hex(1)HexNAc(2)NeuGc(1): DHex Hex HexNAc(2) NeuGc. UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuGc_1_ = 100001629, /// Hex(1)HexNAc(1)NeuAc(2)Ac(2): Ac(2) Hex HexNAc NeuAc(2). UNIMOD_Hex_1_HexNAc_1_NeuAc_2_Ac_2_ = 100001630, /// Hex(2)HexNAc(2)NeuGc(1): Hex(2) HexNAc(2) NeuGc. UNIMOD_Hex_2_HexNAc_2_NeuGc_1_ = 100001631, /// Hex(5)Phos(3): Hex(5) Phos(3). UNIMOD_Hex_5_Phos_3_ = 100001632, /// Hex(6)Phos(1): Hex(6) Phos. UNIMOD_Hex_6_Phos_1_ = 100001633, /// dHex(1)Hex(2)HexA(1)HexNAc(2): DHex Hex(2) HexA HexNAc(2). UNIMOD_dHex_1_Hex_2_HexA_1_HexNAc_2_ = 100001634, /// dHex(2)Hex(3)HexNAc(1)Sulf(1): DHex(2) Hex(3) HexNAc Sulf. UNIMOD_dHex_2_Hex_3_HexNAc_1_Sulf_1_ = 100001635, /// Hex(1)HexNAc(3)NeuAc(1): Hex HexNAc(3) NeuAc. UNIMOD_Hex_1_HexNAc_3_NeuAc_1_ = 100001636, /// dHex(2)Hex(1)HexNAc(3): DHex(2) Hex HexNAc(3). UNIMOD_dHex_2_Hex_1_HexNAc_3_ = 100001637, /// Hex(1)HexNAc(3)NeuGc(1): Hex HexNAc(3) NeuGc. UNIMOD_Hex_1_HexNAc_3_NeuGc_1_ = 100001638, /// dHex(1)Hex(1)HexNAc(2)NeuAc(1)Sulf(1): DHex Hex HexNAc(2) NeuAc Sulf. UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_1_Sulf_1_ = 100001639, /// dHex(1)Hex(3)HexA(1)HexNAc(1)Sulf(1): DHex Hex(3) HexA HexNAc Sulf. UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_1_Sulf_1_ = 100001640, /// dHex(1)Hex(1)HexA(1)HexNAc(3): DHex Hex HexA HexNAc(3). UNIMOD_dHex_1_Hex_1_HexA_1_HexNAc_3_ = 100001641, /// Hex(2)HexNAc(2)NeuAc(1)Sulf(1): Hex(2) HexNAc(2) NeuAc Sulf. UNIMOD_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_ = 100001642, /// dHex(2)Hex(2)HexNAc(2)Sulf(1): DHex(2) Hex(2) HexNAc(2) Sulf. UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_1_ = 100001643, /// dHex(2)Hex(1)HexNAc(2)Kdn(1): DHex(2) Hex HexNAc(2) Kdn. UNIMOD_dHex_2_Hex_1_HexNAc_2_Kdn_1_ = 100001644, /// dHex(1)Hex(1)HexNAc(4): DHex Hex HexNAc(4). UNIMOD_dHex_1_Hex_1_HexNAc_4_ = 100001645, /// Hex(2)HexNAc(4): Hex(2) HexNAc(4). UNIMOD_Hex_2_HexNAc_4_ = 100001646, /// Hex(2)HexNAc(1)NeuGc(2): Hex(2) HexNAc NeuGc(2). UNIMOD_Hex_2_HexNAc_1_NeuGc_2_ = 100001647, /// dHex(2)Hex(4)HexNAc(1): DHex(2) Hex(4) HexNAc. UNIMOD_dHex_2_Hex_4_HexNAc_1_ = 100001648, /// Hex(1)HexNAc(2)NeuAc(2): Hex HexNAc(2) NeuAc(2). UNIMOD_Hex_1_HexNAc_2_NeuAc_2_ = 100001649, /// dHex(2)Hex(1)HexNAc(2)NeuAc(1): DHex(2) Hex HexNAc(2) NeuAc. UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuAc_1_ = 100001650, /// dHex(1)Hex(2)HexNAc(3)Sulf(1): DHex Hex(2) HexNAc(3) Sulf. UNIMOD_dHex_1_Hex_2_HexNAc_3_Sulf_1_ = 100001651, /// dHex(1)HexNAc(5): DHex HexNAc(5). UNIMOD_dHex_1_HexNAc_5_ = 100001652, /// dHex(2)Hex(1)HexNAc(2)NeuGc(1): DHex(2) Hex HexNAc(2) NeuGc. UNIMOD_dHex_2_Hex_1_HexNAc_2_NeuGc_1_ = 100001653, /// dHex(3)Hex(2)HexNAc(2): DHex(3) Hex(2) HexNAc(2). UNIMOD_dHex_3_Hex_2_HexNAc_2_ = 100001654, /// Hex(3)HexNAc(3)Sulf(1): Hex(3) HexNAc(3) Sulf. UNIMOD_Hex_3_HexNAc_3_Sulf_1_ = 100001655, /// dHex(2)Hex(2)HexNAc(2)Sulf(2): DHex(2) Hex(2) HexNAc(2) Sulf(2). UNIMOD_dHex_2_Hex_2_HexNAc_2_Sulf_2_ = 100001656, /// dHex(1)Hex(2)HexNAc(2)NeuGc(1): DHex Hex(2) HexNAc(2) NeuGc. UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_1_ = 100001657, /// dHex(1)Hex(1)HexNAc(3)NeuAc(1): DHex Hex HexNAc(3) NeuAc. UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_ = 100001658, /// Hex(6)Phos(3): Hex(6) Phos(3). UNIMOD_Hex_6_Phos_3_ = 100001659, /// dHex(1)Hex(3)HexA(1)HexNAc(2): DHex Hex(3) HexA HexNAc(2). UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_ = 100001660, /// dHex(1)Hex(1)HexNAc(3)NeuGc(1): DHex Hex HexNAc(3) NeuGc. UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuGc_1_ = 100001661, /// Hex(1)HexNAc(2)NeuAc(2)Sulf(1): Hex HexNAc(2) NeuAc(2) Sulf. UNIMOD_Hex_1_HexNAc_2_NeuAc_2_Sulf_1_ = 100001662, /// dHex(2)Hex(3)HexA(1)HexNAc(1)Sulf(1): DHex(2) Hex(3) HexA HexNAc Sulf. UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_1_Sulf_1_ = 100001663, /// Hex(1)HexNAc(1)NeuAc(3): Hex HexNAc NeuAc(3). UNIMOD_Hex_1_HexNAc_1_NeuAc_3_ = 100001664, /// Hex(2)HexNAc(3)NeuGc(1): Hex(2) HexNAc(3) NeuGc. UNIMOD_Hex_2_HexNAc_3_NeuGc_1_ = 100001665, /// dHex(1)Hex(2)HexNAc(2)NeuAc(1)Sulf(1): DHex Hex(2) HexNAc(2) NeuAc Sulf. UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_ = 100001666, /// dHex(3)Hex(1)HexNAc(2)Kdn(1): DHex(3) Hex HexNAc(2) Kdn. UNIMOD_dHex_3_Hex_1_HexNAc_2_Kdn_1_ = 100001667, /// dHex(2)Hex(3)HexNAc(2)Sulf(1): DHex(2) Hex(3) HexNAc(2) Sulf. UNIMOD_dHex_2_Hex_3_HexNAc_2_Sulf_1_ = 100001668, /// dHex(2)Hex(2)HexNAc(2)Kdn(1): DHex(2) Hex(2) HexNAc(2) Kdn. UNIMOD_dHex_2_Hex_2_HexNAc_2_Kdn_1_ = 100001669, /// dHex(2)Hex(2)HexA(1)HexNAc(2)Sulf(1): DHex(2) Hex(2) HexA HexNAc(2) Sulf. UNIMOD_dHex_2_Hex_2_HexA_1_HexNAc_2_Sulf_1_ = 100001670, /// dHex(1)Hex(2)HexNAc(4): DHex Hex(2) HexNAc(4). UNIMOD_dHex_1_Hex_2_HexNAc_4_ = 100001671, /// Hex(1)HexNAc(1)NeuGc(3): Hex HexNAc NeuGc(3). UNIMOD_Hex_1_HexNAc_1_NeuGc_3_ = 100001672, /// dHex(1)Hex(1)HexNAc(3)NeuAc(1)Sulf(1): DHex Hex HexNAc(3) NeuAc Sulf. UNIMOD_dHex_1_Hex_1_HexNAc_3_NeuAc_1_Sulf_1_ = 100001673, /// dHex(1)Hex(3)HexA(1)HexNAc(2)Sulf(1): DHex Hex(3) HexA HexNAc(2) Sulf. UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_2_Sulf_1_ = 100001674, /// dHex(1)Hex(1)HexNAc(2)NeuAc(2): DHex Hex HexNAc(2) NeuAc(2). UNIMOD_dHex_1_Hex_1_HexNAc_2_NeuAc_2_ = 100001675, /// dHex(3)HexNAc(3)Kdn(1): DHex(3) HexNAc(3) Kdn. UNIMOD_dHex_3_HexNAc_3_Kdn_1_ = 100001676, /// Hex(2)HexNAc(3)NeuAc(1)Sulf(1): Hex(2) HexNAc(3) NeuAc Sulf. UNIMOD_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_ = 100001678, /// dHex(2)Hex(2)HexNAc(3)Sulf(1): DHex(2) Hex(2) HexNAc(3) Sulf. UNIMOD_dHex_2_Hex_2_HexNAc_3_Sulf_1_ = 100001679, /// dHex(2)HexNAc(5): DHex(2) HexNAc(5). UNIMOD_dHex_2_HexNAc_5_ = 100001680, /// Hex(2)HexNAc(2)NeuAc(2): Hex(2) HexNAc(2) NeuAc(2). UNIMOD_Hex_2_HexNAc_2_NeuAc_2_ = 100001681, /// dHex(2)Hex(2)HexNAc(2)NeuAc(1): DHex(2) Hex(2) HexNAc(2) NeuAc. UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_ = 100001682, /// dHex(1)Hex(3)HexNAc(3)Sulf(1): DHex Hex(3) HexNAc(3) Sulf. UNIMOD_dHex_1_Hex_3_HexNAc_3_Sulf_1_ = 100001683, /// dHex(2)Hex(2)HexNAc(2)NeuGc(1): DHex(2) Hex(2) HexNAc(2) NeuGc. UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuGc_1_ = 100001684, /// Hex(2)HexNAc(5): Hex(2) HexNAc(5). UNIMOD_Hex_2_HexNAc_5_ = 100001685, /// dHex(1)Hex(3)HexNAc(2)NeuGc(1): DHex Hex(3) HexNAc(2) NeuGc. UNIMOD_dHex_1_Hex_3_HexNAc_2_NeuGc_1_ = 100001686, /// Hex(1)HexNAc(3)NeuAc(2): Hex HexNAc(3) NeuAc(2). UNIMOD_Hex_1_HexNAc_3_NeuAc_2_ = 100001687, /// dHex(1)Hex(2)HexNAc(3)NeuAc(1): DHex Hex(2) HexNAc(3) NeuAc. UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_ = 100001688, /// dHex(3)Hex(2)HexNAc(3): DHex(3) Hex(2) HexNAc(3). UNIMOD_dHex_3_Hex_2_HexNAc_3_ = 100001689, /// Hex(7)Phos(3): Hex(7) Phos(3). UNIMOD_Hex_7_Phos_3_ = 100001690, /// dHex(1)Hex(4)HexA(1)HexNAc(2): DHex Hex(4) HexA HexNAc(2). UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_2_ = 100001691, /// Hex(3)HexNAc(3)NeuAc(1): Hex(3) HexNAc(3) NeuAc. UNIMOD_Hex_3_HexNAc_3_NeuAc_1_ = 100001692, /// dHex(1)Hex(3)HexA(2)HexNAc(2): DHex Hex(3) HexA(2) HexNAc(2). UNIMOD_dHex_1_Hex_3_HexA_2_HexNAc_2_ = 100001693, /// Hex(2)HexNAc(2)NeuAc(2)Sulf(1): Hex(2) HexNAc(2) NeuAc(2) Sulf. UNIMOD_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_ = 100001694, /// dHex(2)Hex(2)HexNAc(2)NeuAc(1)Sulf(1): DHex(2) Hex(2) HexNAc(2) NeuAc Sulf. UNIMOD_dHex_2_Hex_2_HexNAc_2_NeuAc_1_Sulf_1_ = 100001695, /// Hex(3)HexNAc(3)NeuGc(1): Hex(3) HexNAc(3) NeuGc. UNIMOD_Hex_3_HexNAc_3_NeuGc_1_ = 100001696, /// dHex(4)Hex(1)HexNAc(2)Kdn(1): DHex(4) Hex HexNAc(2) Kdn. UNIMOD_dHex_4_Hex_1_HexNAc_2_Kdn_1_ = 100001697, /// dHex(3)Hex(2)HexNAc(2)Kdn(1): DHex(3) Hex(2) HexNAc(2) Kdn. UNIMOD_dHex_3_Hex_2_HexNAc_2_Kdn_1_ = 100001698, /// dHex(3)Hex(2)HexA(1)HexNAc(2)Sulf(1): DHex(3) Hex(2) HexA HexNAc(2) Sulf. UNIMOD_dHex_3_Hex_2_HexA_1_HexNAc_2_Sulf_1_ = 100001699, /// Hex(2)HexNAc(4)NeuAc(1): Hex(2) HexNAc(4) NeuAc. UNIMOD_Hex_2_HexNAc_4_NeuAc_1_ = 100001700, /// dHex(2)Hex(2)HexNAc(4): DHex(2) Hex(2) HexNAc(4). UNIMOD_dHex_2_Hex_2_HexNAc_4_ = 100001701, /// dHex(2)Hex(3)HexA(1)HexNAc(2)Sulf(1): DHex(2) Hex(3) HexA HexNAc(2) Sulf. UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_2_Sulf_1_ = 100001702, /// dHex(4)HexNAc(3)Kdn(1): DHex(4) HexNAc(3) Kdn. UNIMOD_dHex_4_HexNAc_3_Kdn_1_ = 100001703, /// Hex(2)HexNAc(1)NeuGc(3): Hex(2) HexNAc NeuGc(3). UNIMOD_Hex_2_HexNAc_1_NeuGc_3_ = 100001705, /// dHex(4)Hex(1)HexNAc(1)Kdn(2): DHex(4) Hex HexNAc Kdn(2). UNIMOD_dHex_4_Hex_1_HexNAc_1_Kdn_2_ = 100001706, /// dHex(1)Hex(2)HexNAc(3)NeuAc(1)Sulf(1): DHex Hex(2) HexNAc(3) NeuAc Sulf. UNIMOD_dHex_1_Hex_2_HexNAc_3_NeuAc_1_Sulf_1_ = 100001707, /// dHex(1)Hex(2)HexNAc(2)NeuAc(2): DHex Hex(2) HexNAc(2) NeuAc(2). UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_ = 100001708, /// dHex(3)Hex(1)HexNAc(3)Kdn(1): DHex(3) Hex HexNAc(3) Kdn. UNIMOD_dHex_3_Hex_1_HexNAc_3_Kdn_1_ = 100001709, /// Hex(3)HexNAc(3)NeuAc(1)Sulf(1): Hex(3) HexNAc(3) NeuAc Sulf. UNIMOD_Hex_3_HexNAc_3_NeuAc_1_Sulf_1_ = 100001711, /// Hex(3)HexNAc(2)NeuAc(2): Hex(3) HexNAc(2) NeuAc(2). UNIMOD_Hex_3_HexNAc_2_NeuAc_2_ = 100001712, /// Hex(3)HexNAc(3)NeuGc(1)Sulf(1): Hex(3) HexNAc(3) NeuGc Sulf. UNIMOD_Hex_3_HexNAc_3_NeuGc_1_Sulf_1_ = 100001713, /// dHex(1)Hex(2)HexNAc(2)NeuGc(2): DHex Hex(2) HexNAc(2) NeuGc(2). UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_2_ = 100001714, /// dHex(2)Hex(3)HexNAc(2)NeuGc(1): DHex(2) Hex(3) HexNAc(2) NeuGc. UNIMOD_dHex_2_Hex_3_HexNAc_2_NeuGc_1_ = 100001715, /// dHex(1)Hex(3)HexA(1)HexNAc(3)Sulf(1): DHex Hex(3) HexA HexNAc(3) Sulf. UNIMOD_dHex_1_Hex_3_HexA_1_HexNAc_3_Sulf_1_ = 100001716, /// Hex(2)HexNAc(3)NeuAc(2): Hex(2) HexNAc(3) NeuAc(2). UNIMOD_Hex_2_HexNAc_3_NeuAc_2_ = 100001717, /// dHex(2)Hex(2)HexNAc(3)NeuAc(1): DHex(2) Hex(2) HexNAc(3) NeuAc. UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuAc_1_ = 100001718, /// dHex(4)Hex(2)HexNAc(3): DHex(4) Hex(2) HexNAc(3). UNIMOD_dHex_4_Hex_2_HexNAc_3_ = 100001719, /// Hex(2)HexNAc(3)NeuAc(1)NeuGc(1): Hex(2) HexNAc(3) NeuAc NeuGc. UNIMOD_Hex_2_HexNAc_3_NeuAc_1_NeuGc_1_ = 100001720, /// dHex(2)Hex(2)HexNAc(3)NeuGc(1): DHex(2) Hex(2) HexNAc(3) NeuGc. UNIMOD_dHex_2_Hex_2_HexNAc_3_NeuGc_1_ = 100001721, /// dHex(3)Hex(3)HexNAc(3): DHex(3) Hex(3) HexNAc(3). UNIMOD_dHex_3_Hex_3_HexNAc_3_ = 100001722, /// Hex(8)Phos(3): Hex(8) Phos(3). UNIMOD_Hex_8_Phos_3_ = 100001723, /// dHex(1)Hex(2)HexNAc(2)NeuAc(2)Sulf(1): DHex Hex(2) HexNAc(2) NeuAc(2) Sulf. UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuAc_2_Sulf_1_ = 100001724, /// Hex(2)HexNAc(3)NeuGc(2): Hex(2) HexNAc(3) NeuGc(2). UNIMOD_Hex_2_HexNAc_3_NeuGc_2_ = 100001725, /// dHex(4)Hex(2)HexNAc(2)Kdn(1): DHex(4) Hex(2) HexNAc(2) Kdn. UNIMOD_dHex_4_Hex_2_HexNAc_2_Kdn_1_ = 100001726, /// dHex(1)Hex(2)HexNAc(4)NeuAc(1): DHex Hex(2) HexNAc(4) NeuAc. UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_1_ = 100001727, /// dHex(3)Hex(2)HexNAc(4): DHex(3) Hex(2) HexNAc(4). UNIMOD_dHex_3_Hex_2_HexNAc_4_ = 100001728, /// Hex(1)HexNAc(1)NeuGc(4): Hex HexNAc NeuGc(4). UNIMOD_Hex_1_HexNAc_1_NeuGc_4_ = 100001729, /// dHex(4)Hex(1)HexNAc(3)Kdn(1): DHex(4) Hex HexNAc(3) Kdn. UNIMOD_dHex_4_Hex_1_HexNAc_3_Kdn_1_ = 100001730, /// Hex(4)HexNAc(4)Sulf(2): Hex(4) HexNAc(4) Sulf(2). UNIMOD_Hex_4_HexNAc_4_Sulf_2_ = 100001732, /// dHex(3)Hex(2)HexNAc(3)Kdn(1): DHex(3) Hex(2) HexNAc(3) Kdn. UNIMOD_dHex_3_Hex_2_HexNAc_3_Kdn_1_ = 100001733, /// dHex(2)Hex(2)HexNAc(5): DHex(2) Hex(2) HexNAc(5). UNIMOD_dHex_2_Hex_2_HexNAc_5_ = 100001735, /// dHex(2)Hex(3)HexA(1)HexNAc(3)Sulf(1): DHex(2) Hex(3) HexA HexNAc(3) Sulf. UNIMOD_dHex_2_Hex_3_HexA_1_HexNAc_3_Sulf_1_ = 100001736, /// dHex(1)Hex(4)HexA(1)HexNAc(3)Sulf(1): DHex Hex(4) HexA HexNAc(3) Sulf. UNIMOD_dHex_1_Hex_4_HexA_1_HexNAc_3_Sulf_1_ = 100001737, /// Hex(3)HexNAc(3)NeuAc(2): Hex(3) HexNAc(3) NeuAc(2). UNIMOD_Hex_3_HexNAc_3_NeuAc_2_ = 100001738, /// dHex(2)Hex(3)HexNAc(3)NeuAc(1): DHex(2) Hex(3) HexNAc(3) NeuAc. UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_1_ = 100001739, /// dHex(4)Hex(3)HexNAc(3): DHex(4) Hex(3) HexNAc(3). UNIMOD_dHex_4_Hex_3_HexNAc_3_ = 100001740, /// dHex(2)Hex(3)HexNAc(3)NeuGc(1): DHex(2) Hex(3) HexNAc(3) NeuGc. UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuGc_1_ = 100001741, /// Hex(9)Phos(3): Hex(9) Phos(3). UNIMOD_Hex_9_Phos_3_ = 100001742, /// dHex(2)HexNAc(7): DHex(2) HexNAc(7). UNIMOD_dHex_2_HexNAc_7_ = 100001743, /// Hex(2)HexNAc(1)NeuGc(4): Hex(2) HexNAc NeuGc(4). UNIMOD_Hex_2_HexNAc_1_NeuGc_4_ = 100001744, /// Hex(3)HexNAc(3)NeuAc(2)Sulf(1): Hex(3) HexNAc(3) NeuAc(2) Sulf. UNIMOD_Hex_3_HexNAc_3_NeuAc_2_Sulf_1_ = 100001745, /// dHex(2)Hex(3)HexNAc(5): DHex(2) Hex(3) HexNAc(5). UNIMOD_dHex_2_Hex_3_HexNAc_5_ = 100001746, /// dHex(1)Hex(2)HexNAc(2)NeuGc(3): DHex Hex(2) HexNAc(2) NeuGc(3). UNIMOD_dHex_1_Hex_2_HexNAc_2_NeuGc_3_ = 100001747, /// dHex(2)Hex(4)HexA(1)HexNAc(3)Sulf(1): DHex(2) Hex(4) HexA HexNAc(3) Sulf. UNIMOD_dHex_2_Hex_4_HexA_1_HexNAc_3_Sulf_1_ = 100001748, /// Hex(2)HexNAc(3)NeuAc(3): Hex(2) HexNAc(3) NeuAc(3). UNIMOD_Hex_2_HexNAc_3_NeuAc_3_ = 100001749, /// dHex(1)Hex(3)HexNAc(3)NeuAc(2): DHex Hex(3) HexNAc(3) NeuAc(2). UNIMOD_dHex_1_Hex_3_HexNAc_3_NeuAc_2_ = 100001750, /// dHex(3)Hex(3)HexNAc(3)NeuAc(1): DHex(3) Hex(3) HexNAc(3) NeuAc. UNIMOD_dHex_3_Hex_3_HexNAc_3_NeuAc_1_ = 100001751, /// Hex(2)HexNAc(3)NeuGc(3): Hex(2) HexNAc(3) NeuGc(3). UNIMOD_Hex_2_HexNAc_3_NeuGc_3_ = 100001752, /// Hex(10)Phos(3): Hex(10) Phos(3). UNIMOD_Hex_10_Phos_3_ = 100001753, /// dHex(1)Hex(2)HexNAc(4)NeuAc(2): DHex Hex(2) HexNAc(4) NeuAc(2). UNIMOD_dHex_1_Hex_2_HexNAc_4_NeuAc_2_ = 100001754, /// Hex(1)HexNAc(1)NeuGc(5): Hex HexNAc NeuGc(5). UNIMOD_Hex_1_HexNAc_1_NeuGc_5_ = 100001755, /// Hex(4)HexNAc(4)NeuAc(1)Sulf(2): Hex(4) HexNAc(4) NeuAc Sulf(2). UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_2_ = 100001756, /// Hex(4)HexNAc(4)NeuGc(1)Sulf(2): Hex(4) HexNAc(4) NeuGc Sulf(2). UNIMOD_Hex_4_HexNAc_4_NeuGc_1_Sulf_2_ = 100001757, /// dHex(2)Hex(3)HexNAc(3)NeuAc(2): DHex(2) Hex(3) HexNAc(3) NeuAc(2). UNIMOD_dHex_2_Hex_3_HexNAc_3_NeuAc_2_ = 100001758, /// Hex(4)HexNAc(4)NeuAc(1)Sulf(3): Hex(4) HexNAc(4) NeuAc Sulf(3). UNIMOD_Hex_4_HexNAc_4_NeuAc_1_Sulf_3_ = 100001759, /// dHex(2)Hex(2)HexNAc(2): DHex(2) Hex(2) HexNAc(2). UNIMOD_dHex_2_Hex_2_HexNAc_2_ = 100001760, /// dHex(1)Hex(3)HexNAc(2): DHex Hex(3) HexNAc(2). UNIMOD_dHex_1_Hex_3_HexNAc_2_ = 100001761, /// dHex(1)Hex(2)HexNAc(3): DHex Hex(2) HexNAc(3). UNIMOD_dHex_1_Hex_2_HexNAc_3_ = 100001762, /// Hex(3)HexNAc(3): Hex(3) HexNAc(3). UNIMOD_Hex_3_HexNAc_3_ = 100001763, /// dHex(1)Hex(3)HexNAc(2)Sulf(1): DHex Hex(3) HexNAc(2) Sulf. UNIMOD_dHex_1_Hex_3_HexNAc_2_Sulf_1_ = 100001764, /// dHex(2)Hex(3)HexNAc(2): DHex(2) Hex(3) HexNAc(2). UNIMOD_dHex_2_Hex_3_HexNAc_2_ = 100001765, /// dHex(1)Hex(4)HexNAc(2): DHex Hex(4) HexNAc(2). UNIMOD_dHex_1_Hex_4_HexNAc_2_ = 100001766, /// dHex(2)Hex(2)HexNAc(3): DHex(2) Hex(2) HexNAc(3). UNIMOD_dHex_2_Hex_2_HexNAc_3_ = 100001767, /// dHex(1)Hex(3)HexNAc(3): DHex Hex(3) HexNAc(3). UNIMOD_dHex_1_Hex_3_HexNAc_3_ = 100001768, /// Hex(4)HexNAc(3): Hex(4) HexNAc(3). UNIMOD_Hex_4_HexNAc_3_ = 100001769, /// dHex(2)Hex(4)HexNAc(2): DHex(2) Hex(4) HexNAc(2). UNIMOD_dHex_2_Hex_4_HexNAc_2_ = 100001770, /// dHex(2)Hex(3)HexNAc(3): DHex(2) Hex(3) HexNAc(3). UNIMOD_dHex_2_Hex_3_HexNAc_3_ = 100001771, /// Hex(3)HexNAc(5): Hex(3) HexNAc(5). UNIMOD_Hex_3_HexNAc_5_ = 100001772, /// Hex(4)HexNAc(3)NeuAc(1): Hex(4) HexNAc(3) NeuAc. UNIMOD_Hex_4_HexNAc_3_NeuAc_1_ = 100001773, /// dHex(2)Hex(3)HexNAc(4): DHex(2) Hex(3) HexNAc(4). UNIMOD_dHex_2_Hex_3_HexNAc_4_ = 100001774, /// dHex(1)Hex(3)HexNAc(5): DHex Hex(3) HexNAc(5). UNIMOD_dHex_1_Hex_3_HexNAc_5_ = 100001775, /// Hex(3)HexNAc(6): Hex(3) HexNAc(6). UNIMOD_Hex_3_HexNAc_6_ = 100001776, /// Hex(4)HexNAc(4)NeuAc(1): Hex(4) HexNAc(4) NeuAc. UNIMOD_Hex_4_HexNAc_4_NeuAc_1_ = 100001777, /// dHex(2)Hex(4)HexNAc(4): DHex(2) Hex(4) HexNAc(4). UNIMOD_dHex_2_Hex_4_HexNAc_4_ = 100001778, /// Hex(6)HexNAc(4): Hex(6) HexNAc(4). UNIMOD_Hex_6_HexNAc_4_ = 100001779, /// Hex(5)HexNAc(5): Hex(5) HexNAc(5). UNIMOD_Hex_5_HexNAc_5_ = 100001780, /// dHex(1)Hex(3)HexNAc(6): DHex Hex(3) HexNAc(6). UNIMOD_dHex_1_Hex_3_HexNAc_6_ = 100001781, /// dHex(1)Hex(4)HexNAc(4)NeuAc(1): DHex Hex(4) HexNAc(4) NeuAc. UNIMOD_dHex_1_Hex_4_HexNAc_4_NeuAc_1_ = 100001782, /// dHex(3)Hex(4)HexNAc(4): DHex(3) Hex(4) HexNAc(4). UNIMOD_dHex_3_Hex_4_HexNAc_4_ = 100001783, /// dHex(1)Hex(3)HexNAc(5)NeuAc(1): DHex Hex(3) HexNAc(5) NeuAc. UNIMOD_dHex_1_Hex_3_HexNAc_5_NeuAc_1_ = 100001784, /// dHex(2)Hex(4)HexNAc(5): DHex(2) Hex(4) HexNAc(5). UNIMOD_dHex_2_Hex_4_HexNAc_5_ = 100001785, /// Hex(1)HexNAc(1)NeuAc(1)Ac(1): Ac Hex HexNAc NeuAc. UNIMOD_Hex_1_HexNAc_1_NeuAc_1_Ac_1_ = 100001786, /// unit: A unit of measurement is a standardized quantity of a physical quality. UO_unit = 200000000, /// length unit: A unit which is a standard measure of the distance between two points. UO_length_unit = 200000001, /// mass unit: A unit which is a standard measure of the amount of matter/energy of a physical object. UO_mass_unit = 200000002, /// time unit: A unit which is a standard measure of the dimension in which events occur in sequence. UO_time_unit = 200000003, /// electric current unit: A unit which is a standard measure of the flow of electric charge. UO_electric_current_unit = 200000004, /// temperature unit: A unit which is a standard measure of the average kinetic energy of the particles in a sample of matter. UO_temperature_unit = 200000005, /// substance unit: A unit which is a standardised quantity of an element or compound with uniform composition. UO_substance_unit = 200000006, /// luminous intensity unit: A unit which is a standard measure of the wavelength-weighted power emitted by a light source in a particular direction. UO_luminous_intensity_unit = 200000007, /// meter: A length unit which is equal to the length of the path traveled by light in vacuum during a time interval of 1/299 792 458 of a second. UO_meter = 200000008, /// kilogram: A mass unit which is equal to the mass of the International Prototype Kilogram kept by the BIPM at Svres, France. UO_kilogram = 200000009, /// second: A time unit which is equal to the duration of 9 192 631 770 periods of the radiation corresponding to the transition between the two hyperfine levels of the ground state of the caesium 133 atom. UO_second = 200000010, /// ampere: An electric current unit which is equal to the constant current which, if maintained in two straight parallel conductors of infinite length, of negligible circular cross-section, and placed 1 m apart in vacuum, would produce between these conductors a force equal to 2 x 10^[-7] newton per meter of length. UO_ampere = 200000011, /// kelvin: A thermodynamic temperature unit which is equal to the fraction 1/273.16 of the thermodynamic temperature of the triple point of water. UO_kelvin = 200000012, /// mole: A substance unit which is equal to the amount of substance of a molecular system which contains as many elementary entities as there are atoms in 0.012 kilogram of carbon 12. UO_mole = 200000013, /// candela: A luminous intensity unit which equal to the luminous intensity, in a given direction, of a source that emits monochromatic radiation of frequency 540 x 1012 hertz and that has a radiant intensity in that direction of 1/683 watt per steradian. UO_candela = 200000014, /// centimeter: A length unit which is equal to one hundredth of a meter or 10^[-2] m. UO_centimeter = 200000015, /// millimeter: A length unit which is equal to one thousandth of a meter or 10^[-3] m. UO_millimeter = 200000016, /// micrometer: A length unit which is equal to one millionth of a meter or 10^[-6] m. UO_micrometer = 200000017, /// nanometer: A length unit which is equal to one thousandth of one millionth of a meter or 10^[-9] m. UO_nanometer = 200000018, /// angstrom: A length unit which is equal to 10 [-10] m. UO_angstrom = 200000019, /// picometer: A length unit which is equal to 10^[-12] m. UO_picometer = 200000020, /// gram: A mass unit which is equal to one thousandth of a kilogram or 10^[-3] kg. UO_gram = 200000021, /// milligram: A mass unit which is equal to one thousandth of a gram or 10^[-3] g. UO_milligram = 200000022, /// microgram: A mass unit which is equal to one millionth of a gram or 10^[-6] g. UO_microgram = 200000023, /// nanogram: A mass unit which is equal to one thousandth of one millionth of a gram or 10^[-9] g. UO_nanogram = 200000024, /// picogram: A mass unit which is equal to 10^[-12] g. UO_picogram = 200000025, /// femtogram: A mass unit which is equal to 10^[-15] g. UO_femtogram = 200000026, /// degree celsius: A temperature unit which is equal to one Kelvin degree. However, they have their zeros at different points. The Centigrade scale has its zero at 273.15 K. UO_degree_celsius = 200000027, /// millisecond: A time unit which is equal to one thousandth of a second or 10^[-3] s. UO_millisecond = 200000028, /// microsecond: A time unit which is equal to one millionth of a second or 10^[-6] s. UO_microsecond = 200000029, /// picosecond: A time unit which is equal to 10^[-12] s. UO_picosecond = 200000030, /// minute: A time unit which is equal to 60 seconds. UO_minute = 200000031, /// hour: A time unit which is equal to 3600 seconds or 60 minutes. UO_hour = 200000032, /// day: A time unit which is equal to 24 hours. UO_day = 200000033, /// week: A time unit which is equal to 7 days. UO_week = 200000034, /// month: A time unit which is approximately equal to the length of time of one of cycle of the moon's phases which in science is taken to be equal to 30 days. UO_month = 200000035, /// year: A time unit which is equal to 12 months which is science is taken to be equal to 365.25 days. UO_year = 200000036, /// milliampere: An electric current unit current which is equal to one thousandth of an ampere or 10^[-3] A. UO_milliampere = 200000037, /// microampere: An electric current unit current which is equal to one millionth of an ampere or 10^[-6] A. UO_microampere = 200000038, /// micromole: A substance unit equal to a millionth of a mol or 10^[-6] mol. UO_micromole = 200000039, /// millimole: A substance unit equal to a thousandth of a mol or 10^[-3] mol. UO_millimole = 200000040, /// nanomole: A substance unit equal to one thousandth of one millionth of a mole or 10^[-9] mol. UO_nanomole = 200000041, /// picomole: A substance unit equal to 10^[-12] mol. UO_picomole = 200000042, /// femtomole: A substance unit equal to 10^[-15] mol. UO_femtomole = 200000043, /// attomole: A substance unit equal to 10^[-18] mol. UO_attomole = 200000044, /// base unit: A unit which is one of a particular measure to which all measures of that type can be related. UO_base_unit = 200000045, /// derived unit: A unit which is derived from base units. UO_derived_unit_OBSOLETE = 200000046, /// area unit: A unit which is a standard measure of the amount of a 2-dimensional flat surface. UO_area_unit = 200000047, /// acceleration unit: A unit which is a standard measure of the rate of change of velocity in either speed or direction. UO_acceleration_unit = 200000048, /// angular velocity unit: A unit which is a standard measure of the rate of angular movement about an axis; the angle rotated in a given time. UO_angular_velocity_unit = 200000049, /// angular acceleration unit: A unit which is a standard measure of the rate of change of angular velocity. UO_angular_acceleration_unit = 200000050, /// concentration unit: A unit which represents a standard measurement of how much of a given substance there is mixed with another substance. UO_concentration_unit = 200000051, /// mass density unit: A density unit which is a standard measure of the mass of a substance in a given volume. UO_mass_density_unit = 200000052, /// luminance unit: A unit which is a standard measure of the luminous intensity impinging on a given area. UO_luminance_unit = 200000053, /// area density unit: A density unit which is a standard measure of the mass exerting an influence on a given area. UO_area_density_unit = 200000054, /// molar mass unit: A unit which is a standard measure of the mass of a homogeneous substance containing 6.02 x 1023 atoms or molecules. UO_molar_mass_unit = 200000055, /// molar volume unit: A unit which is a standard measure of the volume of a homogeneous substance containing 6.02 x 1023 atoms or molecules. UO_molar_volume_unit = 200000056, /// momentum unit: A unit which is a standard measure of the quantity of motion measured by the product of mass and velocity. UO_momentum_unit = 200000057, /// rotational frequency unit: A unit which is a standard measure of the number of rotations in a given time. UO_rotational_frequency_unit = 200000058, /// specific volume unit: A unit which is a standard measure of the volume of a given mass of substance (the reciprocal of density). UO_specific_volume_unit = 200000059, /// speed/velocity unit: A unit which is a standard measure of the rate of movement. Speed is measured in the same physical units of measurement as velocity, but does not contain the element of direction that velocity has. Speed is thus the magnitude component of velocity. UO_speed_velocity_unit = 200000060, /// unit of molarity: A concentration unit which is a standard measure of the number of moles of a given substance per liter of solution. UO_unit_of_molarity = 200000061, /// molar: A unit of concentration which expresses a concentration of 1 mole of solute per liter of solution (mol/L). UO_molar = 200000062, /// millimolar: A unit of molarity which is equal to one thousandth of a molar or 10^[-3] M. UO_millimolar = 200000063, /// micromolar: A unit of molarity which is equal to one millionth of a molar or 10^[-6] M. UO_micromolar = 200000064, /// nanomolar: A unit of molarity which is equal to one thousandth of one millionth of a molar or 10^[-9] M. UO_nanomolar = 200000065, /// picomolar: A unit of molarity which is equal to 10^[-12] M. UO_picomolar = 200000066, /// unit of molality: A concentration unit which is a standard measure of the number of moles of a given substance per kilogram of solvent. UO_unit_of_molality = 200000067, /// molal: A unit of concentration which expresses a concentration of a solution of 1 mole per kilogram of solvent (mol/kg). UO_molal = 200000068, /// millimolal: A molality unit which is equal to one thousandth of a molal or 10^[-3] m. UO_millimolal = 200000069, /// micromolal: A molality unit which is equal to one millionth of a molal or 10^[-6] m. UO_micromolal = 200000070, /// nanomolal: A molality unit which is equal to one thousandth of one millionth of a molal or 10^[-9] m. UO_nanomolal = 200000071, /// picomolal: A molality unit which is equal to 10^[-12] m. UO_picomolal = 200000072, /// femtomolar: A unit of molarity which is equal to 10^[-15] M. UO_femtomolar = 200000073, /// unit of normality: A unit of concentration which highlights the chemical nature of salts. UO_unit_of_normality = 200000074, /// normal: A unit of concentration which is one gram equivalent of a solute per liter of solution. A gram equivalent weight or equivalent is a measure of the reactive capacity of a given molecule. UO_normal = 200000075, /// mole fraction: A concentration unit which denotes the number of moles of solute as a proportion of the total number of moles in a solution. UO_mole_fraction = 200000076, /// meter per second per second: An acceleration unit which is equal to the acceleration an object changing its velocity by 1meter/s over a time period that equals one second. UO_meter_per_second_per_second = 200000077, /// radian per second per second: An angular unit acceleration which is equal to the angular acceleration of an object changing its angular velocity by 1rad/s over a time period that equals one second. UO_radian_per_second_per_second = 200000078, /// radian per second: An angular unit velocity which is equal to about 9.54930 rpm (revolutions per minute). UO_radian_per_second = 200000079, /// square meter: An area unit which is equal to an area enclosed by a square with sides each 1 meter long. UO_square_meter = 200000080, /// square centimeter: An area unit which is equal to one thousand of square meter or 10^[-3] m^[2]. UO_square_centimeter = 200000081, /// square millimeter: An area unit which is equal to one millionth of a square meter or 10^[-6] m^[2]. UO_square_millimeter = 200000082, /// kilogram per cubic meter: A mass unit density which is equal to mass of an object in kilograms divided by the volume in cubic meters. UO_kilogram_per_cubic_meter = 200000083, /// gram per cubic centimeter: A mass unit density which is equal to mass of an object in grams divided by the volume in cubic centimeters. UO_gram_per_cubic_centimeter = 200000084, /// candela per square meter: A luminance unit which is equal to a luminous intensity of one candela radiating from a surface whose area is one square meter. UO_candela_per_square_meter = 200000085, /// kilogram per square meter: An area density unit which is equal to the mass of an object in kilograms divided by the surface area in meters squared. UO_kilogram_per_square_meter = 200000086, /// kilogram per mole: A molar mass unit which is equal to one kilogram of mass of one mole of chemical element or chemical compound. UO_kilogram_per_mole = 200000087, /// gram per mole: A molar mass unit which is equal to one gram of mass of one mole of chemical element or chemical compound. UO_gram_per_mole = 200000088, /// cubic meter per mole: A molar volume unit which is equal to 1 cubic meter occupied by one mole of a substance in the form of a solid, liquid, or gas. UO_cubic_meter_per_mole = 200000089, /// cubic centimeter per mole: A molar volume unit which is equal to 1 cubic centimeter occupied by one mole of a substance in the form of a solid, liquid, or gas. UO_cubic_centimeter_per_mole = 200000090, /// kilogram meter per second: A momentum unit which is equal to the momentum of a one kilogram mass object with a speed of one meter per second. UO_kilogram_meter_per_second = 200000091, /// turns per second: A rotational frequency unit which is equal to the number complete turn in a period of time that equals to 1 second. UO_turns_per_second = 200000092, /// cubic meter per kilogram: A specific volume unit which is equal to one cubic meter volume occupied by one kilogram of a particular substance. UO_cubic_meter_per_kilogram = 200000093, /// meter per second: A speed/velocity unit which is equal to the speed of an object traveling 1 meter distance in one second. UO_meter_per_second = 200000094, /// volume unit: A unit which is a standard measure of the amount of space occupied by any substance, whether solid, liquid, or gas. UO_volume_unit = 200000095, /// cubic meter: A volume unit which is equal to the volume of a cube with edges one meter in length. One cubic meter equals to 1000 liters. UO_cubic_meter = 200000096, /// cubic centimeter: A volume unit which is equal to one millionth of a cubic meter or 10^[-9] m^[3], or to 1 ml. UO_cubic_centimeter = 200000097, /// milliliter: A volume unit which is equal to one thousandth of a liter or 10^[-3] L, or to 1 cubic centimeter. UO_milliliter = 200000098, /// liter: A volume unit which is equal to one thousandth of a cubic meter or 10^[-3] m^[3], or to 1 decimeter. UO_liter = 200000099, /// cubic decimeter: A volume unit which is equal to one thousand of a cubic meter or 10^[-3] m^[3], or to 1 L. UO_cubic_decimeter = 200000100, /// microliter: A volume unit which is equal to one millionth of a liter or 10^[-6] L. UO_microliter = 200000101, /// nanoliter: A volume unit which is equal to one thousandth of one millionth of a liter or 10^[-9] L. UO_nanoliter = 200000102, /// picoliter: A volume unit which is equal to 10^[-12] L. UO_picoliter = 200000103, /// femtoliter: A volume unit which is equal to 10^[-15] L. UO_femtoliter = 200000104, /// frequency unit: A unit which is a standard measure of the number of repetitive actions in a particular time. UO_frequency_unit = 200000105, /// hertz: A frequency unit which is equal to 1 complete cycle of a recurring phenomenon in 1 second. UO_hertz = 200000106, /// force unit: A unit which is a standard measure of the force is applied when a mass is accelerated. UO_force_unit = 200000107, /// newton: A force unit which is equal to the force required to cause an acceleration of 1m/s2 of a mass of 1 Kg in the direction of the force. UO_newton = 200000108, /// pressure unit: A unit which is a standard measure of the force applied to a given area. UO_pressure_unit = 200000109, /// pascal: A pressure unit which is equal to the pressure or stress on a surface caused by a force of 1 newton spread over a surface of 1 m^[2]. UO_pascal = 200000110, /// energy unit: A unit which is a standard measure of the work done by a certain force (gravitational, electric, magnetic, force of inertia, etc). UO_energy_unit = 200000111, /// joule: An energy unit which is equal to the energy required when a force of 1 newton moves an object 1 meter in the direction of the force. UO_joule = 200000112, /// power unit: A unit which is a standard measure power or the rate of doing work. UO_power_unit = 200000113, /// watt: A power unit which is equal to the power used when work is done at the rate of 1 joule per second. UO_watt = 200000114, /// illuminance unit: A unit which is a standard measure of the luminous flux incident on a unit area. UO_illuminance_unit = 200000115, /// lux: An illuminance unit which is equal to the illuminance produced by 1 lumen evenly spread over an area 1 m^[2]. UO_lux = 200000116, /// luminous flux unit: A unit which is a standard measure of the flow of radiant energy. UO_luminous_flux_unit = 200000117, /// lumen: A luminous flux unit which is equal to the luminous flux emitted into 1 steradian by a point source of 1 candela. UO_lumen = 200000118, /// catalytic activity unit: A unit which is a standard measure of the amount of the action of a catalyst. UO_catalytic_activity_unit = 200000119, /// katal: A catalytic unit activity which is equal to the activity of a catalyst in moles per second, such as the amount of an enzyme needed to transform one mole of substrate per second. UO_katal = 200000120, /// angle unit: A unit which is a standard measure of the figure or space formed by the junction of two lines or planes. UO_angle_unit = 200000121, /// plane angle unit: A unit which is a standard measure of the angle formed by two straight lines in the same plane. UO_plane_angle_unit = 200000122, /// radian: A plane angle unit which is equal to the angle subtended at the center of a circle by an arc equal in length to the radius of the circle, approximately 57 degrees 17 minutes and 44.6 seconds. UO_radian = 200000123, /// solid angle unit: A unit which is a standard measure of the angle formed by three or more planes intersecting at a common point. UO_solid_angle_unit = 200000124, /// steradian: A solid angle unit which is equal to the solid angle subtended at the center of a sphere by an area on the surface of the sphere that is equal to the radius squared. UO_steradian = 200000125, /// radiation unit: A unit which is a standard measure of the amount of radiation emitted by a given radiation source as well as the amount of radiation absorbed or deposited in a specific material by a radiation source. UO_radiation_unit = 200000127, /// activity (of a radionuclide) unit: A unit which is a standard measure of the transformation (disintegration) rate of a radioactive substance. UO_activity__of_a_radionuclide__unit = 200000128, /// absorbed dose unit: A unit which is a standard measure of the energy imparted by ionizing radiation to unit mass of matter such as tissue. UO_absorbed_dose_unit = 200000129, /// dose equivalent unit: A unit which is a standard measure of the expression of dose in terms of its biological effect. UO_dose_equivalent_unit = 200000130, /// exposure unit: A unit which is a standard measure of the quantity that expresses the ability of radiation to ionize air and thereby create electric charges which can be collected and measured. UO_exposure_unit = 200000131, /// becquerel: An activity (of a radionuclide) unit which is equal to the activity of a quantity of radioactive material in which one nucleus decays per second or there is one atom disintegration per second (dps). UO_becquerel = 200000132, /// curie: An activity (of a radionuclide) unit which is equal to the activity of a quantity of radioactive material in which there are 3.7 x 10^[10] atom disintegration per second (dps). UO_curie = 200000133, /// gray: An absorbed dose unit which is equal to the absorption of one joule of radiation energy by one kilogram of matter. UO_gray = 200000134, /// rad: An absorbed dose unit which is equal to 0.01 gray (Gy). UO_rad = 200000135, /// roentgen: An exposure unit which is equal to the amount of radiation required to liberate positive and negative charges of one electrostatic unit of charge in 1 cm^[3] of air at standard temperature and pressure (STP). This corresponds to the generation of approximately 2.0810^[9] ion pairs. UO_roentgen = 200000136, /// sievert: A dose equivalent unit which is equal to the absorption of one joule of radiation energy by one kilogram of matter. UO_sievert = 200000137, /// millisievert: A dose equivalent unit which is equal to one thousandth of a sievert or 10^[-3] Sv. UO_millisievert = 200000138, /// microsievert: A dose equivalent unit which is equal to one millionth of a sievert or 10^[-6] Sv. UO_microsievert = 200000139, /// Roentgen equivalent man: A dose equivalent unit which when multiplied by hundred is equal to one sievert or 1 Sv. 1 Sv is equal to 100 rem. UO_Roentgen_equivalent_man = 200000140, /// microgray: An absorbed dose unit which is equal to one millionth of a gray or 10^[-6] Gy. UO_microgray = 200000141, /// milligray: An absorbed dose unit which is equal to one thousandth of a gray or 10^[-3] Gy. UO_milligray = 200000142, /// nanogray: An absorbed dose unit which is equal to one thousandth of a millionth of a gray or 10^[-9] Gy. UO_nanogray = 200000143, /// nanosievert: A dose equivalent unit which is equal to one thousandth of a millionth of a sievert or 10^[-9] Sv. UO_nanosievert = 200000144, /// millicurie: An activity (of a radionuclide) unit which is equal to one thousandth of a curie or 10^[-3] Ci. UO_millicurie = 200000145, /// microcurie: An activity (of a radionuclide) unit which is equal to one millionth of a curie or 10^[-6] Ci. UO_microcurie = 200000146, /// disintegrations per minute: An activity (of a radionuclide) unit which is equal to the activity of a quantity of radioactive material in which one nucleus decays per minute or there is one atom disintegration per minute. UO_disintegrations_per_minute = 200000147, /// counts per minute: An activity (of a radionuclide) unit which is equal to the number of light emissions produced by ionizing radiation in one minute. UO_counts_per_minute = 200000148, /// nanosecond: A time unit which is equal to one thousandth of one millionth of a second or 10^[-9] s. UO_nanosecond = 200000150, /// century: A time unit which is equal to 100 years. UO_century = 200000151, /// half life: A time unit which represents the period over which the activity or concentration of a specified chemical or element falls to half its original activity or concentration. UO_half_life = 200000152, /// foot candle: An illuminance unit which is equal to the illuminance produced by 1 lumen evenly spread over an area 1 foot^[2]. One footcandle is equal to 10.76 lux. UO_foot_candle = 200000153, /// irradiance unit: A unit which is a standard measure of the power of electromagnetic radiation at a surface, per unit area. UO_irradiance_unit = 200000154, /// watt per square meter: An irradiance unit which is equal to 1 watt of radiant power incident per one square meter surface area. UO_watt_per_square_meter = 200000155, /// einstein per square meter per second: An irradiance unit which is equal to one einstein per square meter per second. One einstein is one mole of photons, regardless of their frequency. Therefore, the number of photons in an einstein is Avogadro's number. UO_einstein_per_square_meter_per_second = 200000156, /// light unit: A unit which is a standard measure of the intensity of light. UO_light_unit = 200000157, /// watt per steradian per square meter: A radiance unit which is equal to one watt of radiant power incident per steradian solid angle per one square meter projected area of the source, as viewed from the given direction. UO_watt_per_steradian_per_square_meter = 200000158, /// radiant intensity unit: A unit which is a standard measure of the intensity of electromagnetic radiation. UO_radiant_intensity_unit = 200000159, /// microeinstein per square meter per second: An irradiance unit which is equal to one microeinstein per square meter per second or 10^[-6] microeinstein/sm^[2]. UO_microeinstein_per_square_meter_per_second = 200000160, /// radiance unit: A unit which is a standard measure of the power of electromagnetic radiation through space or through a material medium in the form of electromagnetic waves. UO_radiance_unit = 200000161, /// watt per steradian: A radiant intensity unit which is equal to one kilogram meter squared per second cubed per steradian. UO_watt_per_steradian = 200000162, /// mass percentage: A dimensionless concentration unit which denotes the mass of a substance in a mixture as a percentage of the mass of the entire mixture. UO_mass_percentage = 200000163, /// mass volume percentage: A dimensionless concentration unit which denotes the mass of the substance in a mixture as a percentage of the volume of the entire mixture. UO_mass_volume_percentage = 200000164, /// volume percentage: A dimensionless concentration unit which denotes the volume of the solute in mL per 100 mL of the resulting solution. UO_volume_percentage = 200000165, /// parts per notation unit: A dimensionless concentration notation which describes the amount of one substance in another. It is the ratio of the amount of the substance of interest to the amount of that substance plus the amount of the substance. UO_parts_per_notation_unit = 200000166, /// parts per hundred: A dimensionless concentration notation which denotes the amount of a given substance in a total amount of 100 regardless of the units of measure as long as they are the same. UO_parts_per_hundred = 200000167, /// parts per thousand: A dimensionless concentration notation which denotes the amount of a given substance in a total amount of 1000 regardless of the units of measure as long as they are the same. UO_parts_per_thousand = 200000168, /// parts per million: A dimensionless concentration notation which denotes the amount of a given substance in a total amount of 1,000,000 regardless of the units of measure used as long as they are the same or 1 part in 10^[6]. UO_parts_per_million = 200000169, /// parts per billion: A dimensionless concentration notation which denotes the amount of a given substance in a total amount of 1,000,000,000 regardless of the units of measure as long as they are the same or 1 part in 10^[9]. UO_parts_per_billion = 200000170, /// parts per trillion: A dimensionless concentration notation which denotes the amount of a given substance in a total amount of 1,000,000,000 regardless of the units of measure used as long as they are the same or 1 part in 10^[12]. UO_parts_per_trillion = 200000171, /// parts per quadrillion: A dimensionless concentration notation which denotes the amount of a given substance in a total amount of 1,000,000,000,000 regardless of the units of measure used as long as they are the same or 1 part in 10^[15]. UO_parts_per_quadrillion = 200000172, /// gram per milliliter: A mass unit density which is equal to mass of an object in grams divided by the volume in milliliter. UO_gram_per_milliliter = 200000173, /// kilogram per liter: A mass unit density which is equal to mass of an object in kilograms divided by the volume in liters. UO_kilogram_per_liter = 200000174, /// gram per liter: A mass unit density which is equal to mass of an object in grams divided by the volume in liters. UO_gram_per_liter = 200000175, /// milligram per milliliter: A mass unit density which is equal to mass of an object in milligrams divided by the volume in milliliters. UO_milligram_per_milliliter = 200000176, /// unit per volume unit: A concentration unit which is a standard measure of the number of units, as an agreed arbitrary amount, of a given substance per a specific volume of solution. UO_unit_per_volume_unit = 200000177, /// unit per milliliter: A unit per milliliter unit which is equal to one unit of an agreed arbitrary amount per one milliliter. UO_unit_per_milliliter = 200000178, /// unit per liter: A unit per milliliter unit which is equal to one unit of an agreed arbitrary amount per one liter. UO_unit_per_liter = 200000179, /// mass per unit volume: A concentration unit which is a standard measure of the mass of a substance in a given volume (density). UO_mass_per_unit_volume = 200000180, /// enzyme unit: A catalytic unit activity which is equal to the amount of the enzyme that catalyzes the conversion of 1 micro mole of substrate per minute. UO_enzyme_unit = 200000181, /// density unit: A unit which is a standard measure of the influence exerted by some mass. UO_density_unit = 200000182, /// linear density unit: A density unit which is a standard measure of the mass exerting an influence on a one-dimensional object. UO_linear_density_unit = 200000183, /// kilogram per meter: An area density unit which is equal to the mass of an object in kilograms divided by one meter. UO_kilogram_per_meter = 200000184, /// degree: A plane angle unit which is equal to 1/360 of a full rotation or 1.7453310^[-2] rad. UO_degree = 200000185, /// dimensionless unit: A unit which is a standard measure of physical quantity consisting of only a numerical number without any units. UO_dimensionless_unit = 200000186, /// percent: A dimensionless ratio unit which denotes numbers as fractions of 100. UO_percent = 200000187, /// pi: A dimensionless unit which denoted an irrational real number, approximately equal to 3.14159 which is the ratio of a circle's circumference to its diameter in Euclidean geometry. UO_pi = 200000188, /// count unit: A dimensionless unit which denotes a simple count of things. UO_count_unit = 200000189, /// ratio: A dimensionless unit which denotes an amount or magnitude of one quantity relative to another. UO_ratio = 200000190, /// fraction: A dimensionless ratio unit which relates the part (the numerator) to the whole (the denominator). UO_fraction = 200000191, /// molecule count: A dimensionless count unit which denotes the number of molecules. UO_molecule_count = 200000192, /// purity percentage: A dimensionless percent unit which denotes the homogeneity of a biomaterial. UO_purity_percentage = 200000193, /// confluence percentage: A dimensionless percent unit which denotes the density of an attached or monolayer culture (e.g., cell culture). UO_confluence_percentage = 200000194, /// degree fahrenheit: A temperature unit which is equal to 5/9ths of a kelvin. Negative 40 degrees Fahrenheit is equal to negative 40 degrees Celsius. UO_degree_fahrenheit = 200000195, /// pH: A dimensionless concentration notation which denotes the acidity of a solution in terms of activity of hydrogen ions (H+). UO_pH = 200000196, /// liter per kilogram: A specific volume unit which is equal to one liter volume occupied by one kilogram of a particular substance. UO_liter_per_kilogram = 200000197, /// milliliter per kilogram: A specific volume unit which is equal to a thousandth of a liter per kilogram or 10^[-3] l/kg. UO_milliliter_per_kilogram = 200000198, /// microliter per kilogram: A specific volume unit which is equal to one millionth of a liter per kilogram or 10^[-6] l/kg. UO_microliter_per_kilogram = 200000199, /// cell concentration unit: A concentration unit which denotes the average cell number in a given volume. UO_cell_concentration_unit = 200000200, /// cells per milliliter: A unit of cell concentration which is equal to one cell in a volume of 1 milliliter. UO_cells_per_milliliter = 200000201, /// catalytic (activity) concentration unit: A concentration unit which is a standard measure of the amount of the action of a catalyst in a given volume. UO_catalytic__activity__concentration_unit = 200000202, /// katal per cubic meter: A catalytic (activity) concentration unit which is equal to 1 katal activity of a catalyst in a given volume of one cubic meter. UO_katal_per_cubic_meter = 200000203, /// katal per liter: A catalytic (activity) concentration unit which is equal to 1 katal activity of a catalyst in a given volume of one thousandth of a cubic meter. UO_katal_per_liter = 200000204, /// volume per unit volume: A dimensionless concentration unit which denotes the given volume of the solute in the total volume of the resulting solution. UO_volume_per_unit_volume = 200000205, /// milliliter per cubic meter: A volume per unit volume unit which is equal to one millionth of a liter of solute in one cubic meter of solution. UO_milliliter_per_cubic_meter = 200000206, /// milliliter per liter: A volume per unit volume unit which is equal to one millionth of a liter of solute in one liter of solution. UO_milliliter_per_liter = 200000207, /// gram per deciliter: A mass density unit which is equal to mass of an object in grams divided by the volume in deciliters. UO_gram_per_deciliter = 200000208, /// deciliter: A volume unit which is equal to one tenth of a liter or 10^[-1] L. UO_deciliter = 200000209, /// colony forming unit: A dimensionless count unit which a measure of viable bacterial numbers. UO_colony_forming_unit = 200000210, /// plaque forming unit: A dimensionless count unit which a measure of plague forming units in a given volume. UO_plaque_forming_unit = 200000211, /// colony forming unit per volume: A concentration unit which a measure of viable bacterial numbers in a given volume. UO_colony_forming_unit_per_volume = 200000212, /// colony forming unit per milliliter: A colony forming unit which a measure of viable bacterial numbers in one milliliter. UO_colony_forming_unit_per_milliliter = 200000213, /// plaque forming unit per volume: A concentration unit which a measure of plague forming units in a given volume. UO_plaque_forming_unit_per_volume = 200000214, /// plaque forming unit per milliliter: A concentration unit which a measure of plague forming units in one milliliter. UO_plaque_forming_unit_per_milliliter = 200000215, /// disintegrations per second: An activity (of a radionuclide) unit which is equal to the activity of a quantity of radioactive material in which one nucleus decays per second or there is one atom disintegration per second. UO_disintegrations_per_second = 200000216, /// electric potential difference unit: A unit which is a standard measure of the work done per unit charge as a charge is moved between two points in an electric field. UO_electric_potential_difference_unit = 200000217, /// volt: An electric potential difference unit which is equal to the work per unit charge. One volt is the potential difference required to move one coulomb of charge between two points in a circuit while using one joule of energy. UO_volt = 200000218, /// electric charge: A unit which is a standard measure of the quantity of unbalanced electricity in a body (either positive or negative) and construed as an excess or deficiency of electrons. UO_electric_charge = 200000219, /// coulomb: An electrical charge unit which is equal to the amount of charge transferred by a current of 1 ampere in 1 second. UO_coulomb = 200000220, /// dalton: An independently to the base SI units defined mass unit which is equal to one twelfth of the mass of an unbound atom of the carbon-12 nuclide, at rest and in its ground state. UO_dalton = 200000221, /// kilodalton: A mass unit which is equal to one thousand daltons. UO_kilodalton = 200000222, /// watt-hour: An energy unit which is equal to the amount of electrical energy equivalent to a one-watt load drawing power for one hour. UO_watt_hour = 200000223, /// kilowatt-hour: An energy unit which is equal to 1,000 watt-hours. UO_kilowatt_hour = 200000224, /// magnetic flux unit: A unit which is a standard measure of quantity of magnetism, taking account of the strength and the extent of a magnetic field. UO_magnetic_flux_unit = 200000225, /// weber: A magnetic flux unit which is equal to the amount of flux that when linked with a single turn of wire for an interval of one second will induce an electromotive force of one volt. UO_weber = 200000226, /// magnetic flux density unit: A unit which is a standard measure of the strength of a magnetic field. UO_magnetic_flux_density_unit = 200000227, /// tesla: A magnetic flux density unit which is equal to one weber per square meter. UO_tesla = 200000228, /// volt-hour: A magnetic flux unit which is equal to 3600 Wb. UO_volt_hour = 200000229, /// kilovolt-hour: A magnetic flux unit which is equal to one thousand volt-hours. UO_kilovolt_hour = 200000230, /// information unit: A unit which is a standard measure of the amount of information. UO_information_unit = 200000231, /// bit: An information unit which refers to a digit in the binary numeral system, which consists of base 2 digits (ie there are only 2 possible values: 0 or 1). UO_bit = 200000232, /// byte: An information unit which is equal to 8 bits. UO_byte = 200000233, /// kilobyte: An information unit which is equal to 1000 bytes. UO_kilobyte = 200000234, /// megabyte: An information unit which is equal to 1000 kB. UO_megabyte = 200000235, /// image resolution unit: An information unit which is a standard measure of the detail an image holds. UO_image_resolution_unit = 200000236, /// chroma sampling unit: An image resolution unit which is a standard measure of the amount of spatial detail in an image. UO_chroma_sampling_unit = 200000237, /// dynamic range unit: An image resolution unit which is a standard measure of the amount of contrast available in a pixel. UO_dynamic_range_unit = 200000238, /// spatial resolution unit: An image resolution unit which is a standard measure of the way luminance and chrominance may be sampled at different levels. UO_spatial_resolution_unit = 200000239, /// dots per inch: A spatial resolution unit which is a standard measure of the printing resolution, in particular the number of individual dots of ink a printer or toner can produce within a linear one-inch space. UO_dots_per_inch = 200000240, /// micron pixel: A spatial resolution unit which is equal to a pixel size of one micrometer. UO_micron_pixel = 200000241, /// pixels per inch: A spatial resolution unit which is a standard measure of the resolution of a computer display, related to the size of the display in inches and the total number of pixels in the horizontal and vertical directions. UO_pixels_per_inch = 200000242, /// pixels per millimeter: A spatial resolution unit which is a standard measure of the number of pixels in one millimeter length or width of a digital image divided by the physical length or width of a printed image. UO_pixels_per_millimeter = 200000243, /// base pair: A count unit which contains one nucleotide. UO_base_pair = 200000244, /// kibibyte: An information unit which is equal to 1024 B. UO_kibibyte = 200000245, /// mebibyte: An information unit which is equal to 1024 KiB. UO_mebibyte = 200000246, /// millivolt: An electric potential difference unit which is equal to one thousandth of a volt or 10^[-3] V. UO_millivolt = 200000247, /// kilovolt: An electric potential difference unit which is equal to one thousand volts or 10^[3] V. UO_kilovolt = 200000248, /// microvolt: An electric potential difference unit which is equal to one millionth of a volt or 10^[-6] V. UO_microvolt = 200000249, /// nanovolt: An electric potential difference unit which is equal to one billionth of a volt or 10^[-12] V. UO_nanovolt = 200000250, /// picovolt: An electric potential difference unit which is equal to one trillionth of a volt or 10^[-12] V. UO_picovolt = 200000251, /// megavolt: An electric potential difference unit which is equal to one million volts or 10^[6] V. UO_megavolt = 200000252, /// surface tension unit: A unit which is a standard measure of the ability of a liguid to attraction of molecules at its surface as a result of unbalanced molecular cohesive forces. UO_surface_tension_unit = 200000253, /// newton per meter: A surface tension unit which is equal to one newton per meter. UO_newton_per_meter = 200000254, /// dyne per cm: A surface tension unit which is equal to one dyne per centimeter. UO_dyne_per_cm = 200000255, /// viscosity unit: A unit which is a standard measure of the internal resistance of fluids to flow. UO_viscosity_unit = 200000256, /// pascal second: A viscosity unit which is equal to one pascale per second. UO_pascal_second = 200000257, /// poise: A viscosity unit which is equal to one dyne second per square centimeter. UO_poise = 200000258, /// decibel: An ratio unit which is an indicator of sound power per unit area. UO_decibel = 200000259, /// effective dose unit: A unit which is a standard measure of the estimate of the stochastic effect that a non-uniform radiation dose has on a human. UO_effective_dose_unit = 200000260, /// conduction unit: A unit which represents a standard measurement of the transmission of an entity through a medium. UO_conduction_unit = 200000261, /// electrical conduction unit: A unit which represents a standard measurement of the movement of electrically charged particles through a transmission medium (electrical conductor). UO_electrical_conduction_unit = 200000262, /// heat conduction unit: A unit which represents a standard measurement of the spontaneous transfer of thermal energy through matter, from a region of higher temperature to a region of lower temperature. UO_heat_conduction_unit = 200000263, /// siemens: An electrical conduction unit which is equal to A/V. UO_siemens = 200000264, /// watt per meter kelvin: An heat conduction unit which is equal to one watt divided by meter kelvin. UO_watt_per_meter_kelvin = 200000265, /// electronvolt: A non-SI unit of energy (eV) defined as the energy acquired by a single unbound electron when it passes through an electrostatic potential difference of one volt. An electronvolt is equal to 1.602 176 53(14) x 10^-19 J. UO_electronvolt = 200000266, /// electric field strength unit: The electric field strength is a unit which is a measure of the potential difference between two points some distance apart. UO_electric_field_strength_unit = 200000267, /// volt per meter: The volt per meter is a unit of electric field strength equal to the a potential difference of 1 volt existing between two points that are 1 meter apart. UO_volt_per_meter = 200000268, /// absorbance unit: A dimensionless logarithmic unit assigned to a measure of absorbance of light through a partially absorbing substance, defined as -log10(I/I_0) where I = transmitted light and I_0 = incident light. UO_absorbance_unit = 200000269, /// volumetric flow rate unit: A unit which is a standard measure of the volume of fluid which passes through a given surface per unit time . UO_volumetric_flow_rate_unit = 200000270, /// microliters per minute: A volumetric flow rate unit which is equal to one microliter volume through a given surface in one minute. UO_microliters_per_minute = 200000271, /// millimetres of mercury: A unit of pressure equal to the amount of fluid pressure one millimeter deep in mercury at zero degrees centigrade on Earth. UO_millimetres_of_mercury = 200000272, /// milligram per liter: A mass unit density which is equal to mass of an object in milligrams divided by the volume in liters. UO_milligram_per_liter = 200000273, /// microgram per milliliter: A mass unit density which is equal to mass of an object in micrograms divided by the volume in millliters. UO_microgram_per_milliliter = 200000274, /// nanogram per milliliter: A mass unit density which is equal to mass of an object in nanograms divided by the volume in milliliters. UO_nanogram_per_milliliter = 200000275, /// amount per container: A concentration unit which is a standard measure of the amount of a substance in a given container. UO_amount_per_container = 200000276, /// ug/disk: A unit which is equal to one microgram per disk, where a disk is some physical surface/container upon which the substance is deposited. UO_ug_disk = 200000277, /// nmole/disk: A unit which is equal to one nanomole per disk, where a disk is some physical surface/container upon which the substance is deposited. UO_nmole_disk = 200000278, /// milliunits per milliliter: A unit per milliliter unit which is equal to one thousandth of a unit of an agreed arbitrary amount per one milliliter. UO_milliunits_per_milliliter = 200000279, /// rate unit: A unit which represents a standard measurement occurrence of a process per unit time. UO_rate_unit = 200000280, /// count per nanomolar second: A rate unit which is equal to one over one nanomolar second. UO_count_per_nanomolar_second = 200000281, /// count per molar second: A rate unit which is equal to one over one molar second. UO_count_per_molar_second = 200000282, /// kilogram per hectare: An area density unit which is equal to the mass of an object in kilograms divided by the surface area in hectares.. UO_kilogram_per_hectare = 200000283, /// count per nanomolar: A rate unit which is equal to one over one nanomolar. UO_count_per_nanomolar = 200000284, /// count per molar: A rate unit which is equal to one over one molar. UO_count_per_molar = 200000285, /// microgram per liter: A mass unit density which is equal to mass of an object in micrograms divided by the volume in liters. UO_microgram_per_liter = 200000301 }; // enum CVID /// Information about an ontology or CV source and a short 'lookup' tag to refer to. struct PWIZ_API_DECL CV { /// the short label to be used as a reference tag with which to refer to this particular Controlled Vocabulary source description (e.g., from the cvLabel attribute, in CVParamType elements). std::string id; /// the URI for the resource. std::string URI; /// the usual name for the resource (e.g. The PSI-MS Controlled Vocabulary). std::string fullName; /// the version of the CV from which the referred-to terms are drawn. std::string version; /// returns true iff id, URI, fullName, and version are all pairwise equal bool operator==(const CV& that) const; /// returns ture iff id, URI, fullName, and version are all empty bool empty() const; }; /// returns a CV object for the specified namespace (prefix); /// currently supported namespaces are: MS UO PWIZ_API_DECL const CV& cv(const std::string& prefix); /// structure for holding CV term info struct PWIZ_API_DECL CVTermInfo { CVID cvid; std::string id; std::string name; std::string def; bool isObsolete; typedef std::vector id_list; id_list parentsIsA; id_list parentsPartOf; std::multimap otherRelations; std::vector exactSynonyms; std::multimap propertyValues; CVTermInfo() : cvid((CVID)-1) {} const std::string& shortName() const; std::string prefix() const; }; /// returns CV term info for the specified CVID PWIZ_API_DECL const CVTermInfo& cvTermInfo(CVID cvid); /// returns CV term info for the specified id (accession number) PWIZ_API_DECL const CVTermInfo& cvTermInfo(const char* id); PWIZ_API_DECL const CVTermInfo& cvTermInfo(const std::string& id); /// returns true iff child IsA parent in the CV PWIZ_API_DECL bool cvIsA(CVID child, CVID parent); /// returns vector of all valid CVIDs PWIZ_API_DECL const std::vector& cvids(); } // namespace cv } // namespace pwiz #endif // _CV_HPP_ pwiz/libraries/boost_aux/boost/iostreams/arbitrary_positional_facade.hpp0000664000175100017510000002567412664775723031143 0ustar teamcityteamcity00000000000000// arbitrary_positional_facade.hpp: a base class of repositional stream facade // Copyright Takeshi Mouri 2006, 2007. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // See http://hamigaki.sourceforge.jp/libs/iostreams for library home page. #ifndef HAMIGAKI_IOSTREAMS_ARBITRARY_POSITIONAL_FACADE_HPP #define HAMIGAKI_IOSTREAMS_ARBITRARY_POSITIONAL_FACADE_HPP #include #include #include #include #include namespace boost { namespace iostreams { template class arbitrary_positional_facade; class core_access { #if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) public: #else template friend class arbitrary_positional_facade; friend struct device_operations; template friend struct filter_operations; #endif template static std::streamsize read_blocks( RepositionalSource& src, CharT* s, std::streamsize n) { return src.read_blocks(s, n); } template static std::streamsize read_blocks( RepositionalInputFilter& filter, Source& src, typename boost::iostreams::char_type_of::type* s, std::streamsize n) { return filter.read_blocks(src, s, n); } template static std::streamsize write_blocks( RepositionalSink& sink, const CharT* s, std::streamsize n) { return sink.write_blocks(s, n); } template static std::streamsize write_blocks( RepositionalOutputFilter& filter, Sink& sink, const typename boost::iostreams::char_type_of::type* s, std::streamsize n) { return filter.write_blocks(sink, s, n); } template static void close_with_flush( RepositionalSink& sink, const CharT* s, std::streamsize n) { return sink.close_with_flush(s, n); } template static void close_with_flush( RepositionalOutputFilter& filter, Sink& sink, const typename boost::iostreams::char_type_of::type* s, std::streamsize n) { return filter.close_with_flush(sink, s, n); } template static std::streampos seek_blocks( RepositionalDevice& dev, boost::iostreams::stream_offset off, BOOST_IOS::seekdir way) { return dev.seek_blocks(off, way); } struct device_operations { template std::streamsize read_blocks( RepositionalDevice& t, CharT* s, std::streamsize n) const { return core_access::read_blocks(t, s, n); } template std::streamsize write_blocks( RepositionalDevice& t, const CharT* s, std::streamsize n) const { return core_access::write_blocks(t, s, n); } }; template struct filter_operations { typedef typename boost::iostreams:: char_type_of::type char_type; Device* dev_ptr_; explicit filter_operations(Device& dev) : dev_ptr_(&dev) {} template std::streamsize read_blocks( RepositionalInputFilter& t, char_type* s, std::streamsize n) const { return core_access::read_blocks(t, *dev_ptr_, s, n); } template std::streamsize write_blocks( RepositionalOutputFilter& t, const char_type* s, std::streamsize n) const { return core_access::write_blocks(t, *dev_ptr_, s, n); } }; }; template class arbitrary_positional_facade { private: typedef CharT char_type; Derived& derived() { return *static_cast(this); } protected: typedef arbitrary_positional_facade< Derived,CharT,MaxBlockSize> arbitrary_positional_facade_; void block_size(std::streamsize n) { block_size_ = n; } public: arbitrary_positional_facade() : block_size_(MaxBlockSize), count_(0) { } explicit arbitrary_positional_facade(std::streamsize block_size) : block_size_(block_size), count_(0) { BOOST_ASSERT(block_size_ <= MaxBlockSize); } std::streamsize read(char_type* s, std::streamsize n) { return read_impl(core_access::device_operations(), s, n); } template std::streamsize read(Source& src, char_type* s, std::streamsize n) { return read_impl(core_access::filter_operations(src), s, n); } std::streamsize write(const char_type* s, std::streamsize n) { return write_impl(core_access::device_operations(), s, n); } template std::streamsize write(Sink& sink, const char_type* s, std::streamsize n) { return write_impl(core_access::filter_operations(sink), s, n); } void close() { BOOST_ASSERT(count_ < block_size_); core_access::close_with_flush(derived(), buffer_, count_); } template void close(Sink& sink) { BOOST_ASSERT(count_ < block_size_); core_access::close_with_flush(derived(), sink, buffer_, count_); } std::streampos seek( boost::iostreams::stream_offset off, BOOST_IOS::seekdir way) { if (way == BOOST_IOS::beg) { core_access::seek_blocks(derived(), off/block_size_, way); std::streamsize skip = static_cast(off%block_size_); if (skip == 0) count_ = 0; else { std::streamsize res = core_access::read_blocks(derived(), buffer_, 1); if (res != 1) throw BOOST_IOSTREAMS_FAILURE("bad seek"); count_ = block_size_ - skip; } return boost::iostreams::offset_to_position(off); } else if (way == BOOST_IOS::cur) { std::streampos pos = core_access::seek_blocks( derived(), (off-count_)/block_size_, way); std::streamsize skip = static_cast((off-count_)%block_size_); if (skip == 0) { count_ = 0; return boost::iostreams::offset_to_position( boost::iostreams::position_to_offset(pos) * block_size_); } else { std::streamsize res = core_access::read_blocks(derived(), buffer_, 1); if (res != 1) throw BOOST_IOSTREAMS_FAILURE("bad seek"); count_ = block_size_ - skip; return boost::iostreams::offset_to_position( boost::iostreams::position_to_offset(pos) * block_size_ + block_size_-count_); } } else { std::streampos pos = core_access::seek_blocks( derived(), (off-block_size_+1)/block_size_, way); count_ = static_cast((-off)%block_size_); if (count_ == 0) { return boost::iostreams::offset_to_position( boost::iostreams::position_to_offset(pos) * block_size_); } else { std::streamsize res = core_access::read_blocks(derived(), buffer_, 1); if (res != 1) throw BOOST_IOSTREAMS_FAILURE("bad seek"); return boost::iostreams::offset_to_position( boost::iostreams::position_to_offset(pos) * block_size_ + block_size_-count_); } } } private: char_type buffer_[MaxBlockSize]; std::streamsize block_size_; std::streamsize count_; template std::streamsize read_impl(const Op& op, char_type* s, std::streamsize n) { std::streamsize total = 0; if (count_ != 0) { std::streamsize amt = (std::min)(n, count_); char_type* start = buffer_ + (block_size_ - count_); s = std::copy(start, start+amt, s); n -= amt; count_ -= amt; total += amt; } if (n >= block_size_) { BOOST_ASSERT(count_ == 0); std::streamsize request = n/block_size_; std::streamsize res = op.read_blocks(derived(), s, request); if (res != -1) { s += res; n -= res; total += res; } if (res < request*block_size_) return total != 0 ? total : -1; } if (n != 0) { BOOST_ASSERT(n < block_size_); BOOST_ASSERT(count_ == 0); std::streamsize res = op.read_blocks(derived(), buffer_, 1); if (res > 0) { s = std::copy(buffer_, buffer_+n, s); count_ = block_size_ - n; total += n; } } return total != 0 ? total : -1; } template std::streamsize write_impl( const Op& op, const char_type* s, std::streamsize n) { std::streamsize total = 0; if (count_ != 0) { std::streamsize amt = (std::min)(n, block_size_-count_); std::copy(s, s+amt, buffer_+count_); s += amt; n -= amt; count_ += amt; total += amt; if (count_ == block_size_) { op.write_blocks(derived(), buffer_, 1); count_ = 0; } } if (n >= block_size_) { BOOST_ASSERT(count_ == 0); std::streamsize request = n/block_size_; op.write_blocks(derived(), s, request); std::streamsize amt = request*block_size_; s += amt; n -= amt; total += amt; } if (n != 0) { BOOST_ASSERT(n < block_size_); BOOST_ASSERT(count_ == 0); std::copy(s, s+n, buffer_); count_ = n; total += n; } return total != 0 ? total : -1; } }; } } // End namespaces iostreams, boost. #endif // HAMIGAKI_IOSTREAMS_ARBITRARY_POSITIONAL_FACADE_HPP pwiz/pwiz/data/vendor_readers/ABI/Reader_ABI_Detail.hpp0000664000175100017510000000324312664775620024723 0ustar teamcityteamcity00000000000000// // $Id: Reader_ABI_Detail.hpp 8903 2015-09-29 18:17:40Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _READER_ABI_DETAIL_HPP_ #define _READER_ABI_DETAIL_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/MSData.hpp" #include #ifdef PWIZ_READER_ABI #include "pwiz_aux/msrc/utility/vendor_api/ABI/WiffFile.hpp" namespace pwiz { namespace msdata { namespace detail { namespace ABI { using namespace pwiz::vendor_api::ABI; PWIZ_API_DECL InstrumentConfigurationPtr translateAsInstrumentConfiguration(InstrumentModel instrumentModel, IonSourceType ionSource); PWIZ_API_DECL CVID translateAsInstrumentModel(InstrumentModel instrumentModel); PWIZ_API_DECL CVID translateAsIonSource(IonSourceType ionSourceType); PWIZ_API_DECL CVID translateAsSpectrumType(ExperimentType scanType); PWIZ_API_DECL CVID translate(Polarity polarity); } // ABI } // detail } // msdata } // pwiz #endif // PWIZ_READER_ABI #endif // _READER_ABI_DETAIL_HPP_ pwiz/pwiz/data/vendor_readers/ABI/ChromatogramList_ABI.cpp0000664000175100017510000002407712664775620025521 0ustar teamcityteamcity00000000000000// // $Id: ChromatogramList_ABI.cpp 4922 2013-09-05 22:33:08Z pcbrefugee $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "ChromatogramList_ABI.hpp" #ifdef PWIZ_READER_ABI #include "Reader_ABI_Detail.hpp" #include "pwiz/utility/misc/SHA1Calculator.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include namespace pwiz { namespace msdata { namespace detail { PWIZ_API_DECL ChromatogramList_ABI::ChromatogramList_ABI(const MSData& msd, WiffFilePtr wifffile, const ExperimentsMap& experimentsMap, int sample) : msd_(msd), wifffile_(wifffile), experimentsMap_(experimentsMap), sample(sample), size_(0), indexInitialized_(util::init_once_flag_proxy) { } PWIZ_API_DECL size_t ChromatogramList_ABI::size() const { boost::call_once(indexInitialized_.flag, boost::bind(&ChromatogramList_ABI::createIndex, this)); return size_; } PWIZ_API_DECL const ChromatogramIdentity& ChromatogramList_ABI::chromatogramIdentity(size_t index) const { boost::call_once(indexInitialized_.flag, boost::bind(&ChromatogramList_ABI::createIndex, this)); if (index>size_) throw runtime_error(("[ChromatogramList_ABI::chromatogramIdentity()] Bad index: " + lexical_cast(index)).c_str()); return index_[index]; } PWIZ_API_DECL size_t ChromatogramList_ABI::find(const string& id) const { boost::call_once(indexInitialized_.flag, boost::bind(&ChromatogramList_ABI::createIndex, this)); map::const_iterator scanItr = idToIndexMap_.find(id); if (scanItr == idToIndexMap_.end()) return size_; return scanItr->second; } PWIZ_API_DECL ChromatogramPtr ChromatogramList_ABI::chromatogram(size_t index, bool getBinaryData) const { boost::call_once(indexInitialized_.flag, boost::bind(&ChromatogramList_ABI::createIndex, this)); if (index>size_) throw runtime_error(("[ChromatogramList_ABI::chromatogram()] Bad index: " + lexical_cast(index)).c_str()); // allocate a new Chromatogram IndexEntry& ie = index_[index]; ChromatogramPtr result = ChromatogramPtr(new Chromatogram); if (!result.get()) throw std::runtime_error("[ChromatogramList_Thermo::chromatogram()] Allocation error."); result->index = index; result->id = ie.id; result->set(ie.chromatogramType); switch (ie.chromatogramType) { case MS_TIC_chromatogram: { map fullFileTIC; int sampleCount = wifffile_->getSampleCount(); for (int i=1; i <= sampleCount; ++i) { try { int periodCount = wifffile_->getPeriodCount(i); for (int ii=1; ii <= periodCount; ++ii) { //Console::WriteLine("Sample {0}, Period {1}", i, ii); int experimentCount = wifffile_->getExperimentCount(i, ii); for (int iii=1; iii <= experimentCount; ++iii) { ExperimentPtr msExperiment = (i == sample ? experimentsMap_.find(pair(ii, iii))->second : wifffile_->getExperiment(i, ii, iii)); // add current experiment TIC to full file TIC vector times, intensities; msExperiment->getTIC(times, intensities); for (int iiii = 0, end = intensities.size(); iiii < end; ++iiii) fullFileTIC[times[iiii]] += intensities[iiii]; } } } catch (exception&) { // TODO: log warning } } result->setTimeIntensityArrays(std::vector(), std::vector(), UO_minute, MS_number_of_detector_counts); if (getBinaryData) { BinaryDataArrayPtr timeArray = result->getTimeArray(); BinaryDataArrayPtr intensityArray = result->getIntensityArray(); timeArray->data.reserve(fullFileTIC.size()); intensityArray->data.reserve(fullFileTIC.size()); for (map::iterator itr = fullFileTIC.begin(); itr != fullFileTIC.end(); ++itr) { timeArray->data.push_back(itr->first); intensityArray->data.push_back(itr->second); } } result->defaultArrayLength = fullFileTIC.size(); } break; case MS_SRM_chromatogram: { ExperimentPtr experiment = ie.experiment; pwiz::vendor_api::ABI::Target target; experiment->getSRM(ie.transition, target); // TODO: move to global scan settings or leave out entirely? result->userParams.push_back(UserParam("MS_dwell_time", lexical_cast(target.dwellTime /* milliseconds->seconds */ / 1000.0), "xs:float")); result->precursor.isolationWindow.set(MS_isolation_window_target_m_z, ie.q1, MS_m_z); //result->precursor.isolationWindow.set(MS_isolation_window_lower_offset, ie.q1, MS_m_z); //result->precursor.isolationWindow.set(MS_isolation_window_upper_offset, ie.q1, MS_m_z); result->precursor.activation.set(MS_CID); result->precursor.activation.set(MS_collision_energy, target.collisionEnergy, UO_electronvolt); result->precursor.activation.userParams.push_back(UserParam("MS_declustering_potential", lexical_cast(target.declusteringPotential), "xs:float")); result->product.isolationWindow.set(MS_isolation_window_target_m_z, ie.q3, MS_m_z); //result->product.isolationWindow.set(MS_isolation_window_lower_offset, ie.q3, MS_m_z); //result->product.isolationWindow.set(MS_isolation_window_upper_offset, ie.q3, MS_m_z); result->setTimeIntensityArrays(std::vector(), std::vector(), UO_minute, MS_number_of_detector_counts); vector times, intensities; experiment->getSIC(ie.transition, times, intensities); result->defaultArrayLength = times.size(); if (getBinaryData) { BinaryDataArrayPtr timeArray = result->getTimeArray(); BinaryDataArrayPtr intensityArray = result->getIntensityArray(); std::swap(timeArray->data, times); std::swap(intensityArray->data, intensities); } } break; } return result; } PWIZ_API_DECL void ChromatogramList_ABI::createIndex() const { index_.push_back(IndexEntry()); IndexEntry& ie = index_.back(); ie.index = index_.size()-1; ie.id = "TIC"; ie.chromatogramType = MS_TIC_chromatogram; idToIndexMap_[ie.id] = ie.index; pwiz::vendor_api::ABI::Target target; int periodCount = wifffile_->getPeriodCount(sample); for (int ii=1; ii <= periodCount; ++ii) { //Console::WriteLine("Sample {0}, Period {1}", sample, ii); int experimentCount = wifffile_->getExperimentCount(sample, ii); for (int iii=1; iii <= experimentCount; ++iii) { ExperimentPtr msExperiment = experimentsMap_.find(pair(ii, iii))->second; for (int iiii = 0; iiii < (int) msExperiment->getSRMSize(); ++iiii) { msExperiment->getSRM(iiii, target); index_.push_back(IndexEntry()); IndexEntry& ie = index_.back(); ie.chromatogramType = MS_SRM_chromatogram; ie.q1 = target.Q1; ie.q3 = target.Q3; ie.sample = sample; ie.period = ii; ie.experiment = msExperiment; ie.transition = iiii; ie.index = index_.size()-1; std::ostringstream oss; oss << "SRM SIC Q1=" << ie.q1 << " Q3=" << ie.q3 << " sample=" << ie.sample << " period=" << ie.period << " experiment=" << ie.experiment->getExperimentNumber() << " transition=" << ie.transition; ie.id = oss.str(); idToIndexMap_[ie.id] = ie.index; } } } size_ = index_.size(); } } // detail } // msdata } // pwiz #else // PWIZ_READER_ABI // // non-MSVC implementation // namespace pwiz { namespace msdata { namespace detail { namespace {const ChromatogramIdentity emptyIdentity;} size_t ChromatogramList_ABI::size() const {return 0;} const ChromatogramIdentity& ChromatogramList_ABI::chromatogramIdentity(size_t index) const {return emptyIdentity;} size_t ChromatogramList_ABI::find(const std::string& id) const {return 0;} ChromatogramPtr ChromatogramList_ABI::chromatogram(size_t index, bool getBinaryData) const {return ChromatogramPtr();} } // detail } // msdata } // pwiz #endif // PWIZ_READER_ABI pwiz/pwiz/data/vendor_readers/ABI/SpectrumList_ABI.cpp0000664000175100017510000003131212664775620024666 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_ABI.cpp 8693 2015-07-27 22:01:28Z brendanx $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "SpectrumList_ABI.hpp" #ifdef PWIZ_READER_ABI #include "Reader_ABI_Detail.hpp" #include "pwiz/utility/misc/SHA1Calculator.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include #include namespace pwiz { namespace msdata { namespace detail { using namespace ABI; PWIZ_API_DECL SpectrumList_ABI::SpectrumList_ABI(const MSData& msd, WiffFilePtr wifffile, const ExperimentsMap& experimentsMap, int sample, const Reader::Config& config) : msd_(msd), wifffile_(wifffile), config_(config), experimentsMap_(experimentsMap), sample(sample), size_(0), indexInitialized_(util::init_once_flag_proxy), spectrumLastIndex_((size_t)-1) { } PWIZ_API_DECL size_t SpectrumList_ABI::size() const { boost::call_once(indexInitialized_.flag, boost::bind(&SpectrumList_ABI::createIndex, this)); return size_; } PWIZ_API_DECL const SpectrumIdentity& SpectrumList_ABI::spectrumIdentity(size_t index) const { boost::call_once(indexInitialized_.flag, boost::bind(&SpectrumList_ABI::createIndex, this)); if (index >= size_) throw runtime_error("[SpectrumList_ABI::spectrumIdentity()] Bad index: " + lexical_cast(index)); return index_[index]; } PWIZ_API_DECL size_t SpectrumList_ABI::find(const string& id) const { boost::call_once(indexInitialized_.flag, boost::bind(&SpectrumList_ABI::createIndex, this)); map::const_iterator scanItr = idToIndexMap_.find(id); if (scanItr == idToIndexMap_.end()) return size_; return scanItr->second; } PWIZ_API_DECL SpectrumPtr SpectrumList_ABI::spectrum(size_t index, bool getBinaryData) const { return spectrum(index, getBinaryData, pwiz::util::IntegerSet()); } PWIZ_API_DECL SpectrumPtr SpectrumList_ABI::spectrum(size_t index, DetailLevel detailLevel) const { return spectrum(index, detailLevel, pwiz::util::IntegerSet()); } PWIZ_API_DECL SpectrumPtr SpectrumList_ABI::spectrum(size_t index, bool getBinaryData, const pwiz::util::IntegerSet& msLevelsToCentroid) const { return spectrum(index, getBinaryData ? DetailLevel_FullData : DetailLevel_FullMetadata, msLevelsToCentroid); } PWIZ_API_DECL SpectrumPtr SpectrumList_ABI::spectrum(size_t index, DetailLevel detailLevel, const pwiz::util::IntegerSet& msLevelsToCentroid) const { boost::lock_guard lock(readMutex); // lock_guard will unlock mutex when out of scope or when exception thrown (during destruction) boost::call_once(indexInitialized_.flag, boost::bind(&SpectrumList_ABI::createIndex, this)); if (index >= size_) throw runtime_error("[SpectrumList_ABI::spectrum()] Bad index: " + lexical_cast(index)); // allocate a new Spectrum IndexEntry& ie = index_[index]; SpectrumPtr result = SpectrumPtr(new Spectrum); if (!result.get()) throw std::runtime_error("[SpectrumList_ABI::spectrum()] Allocation error."); result->index = index; result->id = ie.id; //Console::WriteLine("spce: {0}.{1}.{2}.{3}", ie.sample, ie.period, ie.cycle, ie.experiment); result->scanList.set(MS_no_combination); result->scanList.scans.push_back(Scan()); Scan& scan = result->scanList.scans[0]; ExperimentPtr msExperiment = ie.experiment; // Synchronize access to cached spectrum for multi-threaded use pwiz::vendor_api::ABI::SpectrumPtr spectrum; { boost::mutex::scoped_lock spectrum_lock(spectrum_mutex); if (spectrumLastIndex_ != index) { spectrumLastIndex_ = index; spectrumLast_ = wifffile_->getSpectrum(msExperiment, ie.cycle); } spectrum = spectrumLast_; } double scanTime = spectrum->getStartTime(); if (scanTime > 0) scan.set(MS_scan_start_time, scanTime, UO_minute); scan.set(MS_preset_scan_configuration, msExperiment->getExperimentNumber()); ExperimentType experimentType = msExperiment->getExperimentType(); int msLevel = spectrum->getMSLevel(); result->set(MS_ms_level, msLevel); result->set(translateAsSpectrumType(experimentType)); result->set(translate(msExperiment->getPolarity())); double startMz, stopMz; msExperiment->getAcquisitionMassRange(startMz, stopMz); scan.scanWindows.push_back(ScanWindow(startMz, stopMz, MS_m_z)); // decide whether to use Points or Peaks to populate data arrays bool doCentroid = msLevelsToCentroid.contains(msLevel); bool continuousData = spectrum->getDataIsContinuous(); if (continuousData && !doCentroid) result->set(MS_profile_spectrum); else { result->set(MS_centroid_spectrum); doCentroid = continuousData; } /*if (experimentType == MRM) { MRMTransitions^ transitions = msExperiment->MRMTransitions; double q1mz = transitions[ie.transition]->Q1Mass;//ie.transition->first; double q3mz = transitions[ie.transition]->Q3Mass; double intensity = points[ie.transition]->Y; result->defaultArrayLength = 1;//ie.transition->second.size(); Precursor precursor; SelectedIon selectedIon; selectedIon.set(MS_selected_ion_m_z, q1mz, MS_m_z); precursor.activation.set(MS_CID); // assume CID precursor.selectedIons.push_back(selectedIon); result->precursors.push_back(precursor); if (getBinaryData) { mzArray.resize(result->defaultArrayLength, q3mz); intensityArray.resize(result->defaultArrayLength, intensity); } } else*/ { if (spectrum->getHasPrecursorInfo()) { double selectedMz, intensity; int charge; spectrum->getPrecursorInfo(selectedMz, intensity, charge); Precursor precursor; if (spectrum->getHasIsolationInfo()) { double centerMz, lowerLimit, upperLimit; spectrum->getIsolationInfo(centerMz, lowerLimit, upperLimit); precursor.isolationWindow.set(MS_isolation_window_target_m_z, centerMz, MS_m_z); precursor.isolationWindow.set(MS_isolation_window_lower_offset, centerMz - lowerLimit, MS_m_z); precursor.isolationWindow.set(MS_isolation_window_upper_offset, upperLimit - centerMz, MS_m_z); selectedMz = centerMz; } SelectedIon selectedIon; selectedIon.set(MS_selected_ion_m_z, selectedMz, MS_m_z); if (charge > 0) selectedIon.set(MS_charge_state, charge); precursor.activation.set(MS_beam_type_collision_induced_dissociation); // assume beam-type CID since all ABI instruments that write WIFFs are either QqTOF or QqLIT precursor.selectedIons.push_back(selectedIon); result->precursors.push_back(precursor); } if (detailLevel == DetailLevel_InstantMetadata) return result; // Revert to previous behavior for getting binary data or not. bool getBinaryData = (detailLevel == DetailLevel_FullData); //result->set(MS_lowest_observed_m_z, spectrum->getMinX(), MS_m_z); //result->set(MS_highest_observed_m_z, spectrum->getMaxX(), MS_m_z); if (!config_.acceptZeroLengthSpectra) { result->set(MS_base_peak_intensity, spectrum->getBasePeakY(), MS_number_of_detector_counts); result->set(MS_base_peak_m_z, spectrum->getBasePeakX(), MS_m_z); } result->set(MS_total_ion_current, spectrum->getSumY(), MS_number_of_detector_counts); if (getBinaryData) { result->setMZIntensityArrays(std::vector(), std::vector(), MS_number_of_detector_counts); BinaryDataArrayPtr mzArray = result->getMZArray(); BinaryDataArrayPtr intensityArray = result->getIntensityArray(); spectrum->getData(doCentroid, mzArray->data, intensityArray->data); if (doCentroid) result->set(MS_profile_spectrum); // let SpectrumList_PeakPicker know this was a profile spectrum } // This forces the WIFF reader to get the data, making full metadata // nearly equivalent in performance to getting binary. result->defaultArrayLength = spectrum->getDataSize(doCentroid); } return result; } PWIZ_API_DECL void SpectrumList_ABI::createIndex() const { using namespace boost::spirit::karma; typedef multimap > ExperimentAndCycleByTime; ExperimentAndCycleByTime experimentAndCycleByTime; vector times, intensities; int periodCount = wifffile_->getPeriodCount(sample); for (int period=1; period <= periodCount; ++period) { int experimentCount = wifffile_->getExperimentCount(sample, period); for (int experiment=1; experiment <= experimentCount; ++experiment) { ExperimentPtr msExperiment = experimentsMap_.find(pair(period, experiment))->second; ExperimentType experimentType = msExperiment->getExperimentType(); if ((experimentType == MRM && !config_.srmAsSpectra) || (experimentType == SIM && !config_.simAsSpectra)) continue; if (config_.acceptZeroLengthSpectra) { msExperiment->getTIC(times, intensities); for (int i = 0, end = (int) times.size(); i < end; ++i) if (intensities[i] > 0) experimentAndCycleByTime.insert(make_pair(times[i], make_pair(msExperiment, i + 1))); } else { msExperiment->getBPC(times, intensities); for (int i = 0, end = (int)times.size(); i < end; ++i) if (intensities[i] > 0 && wifffile_->getSpectrum(msExperiment, i + 1)->getDataSize(false) > 0) experimentAndCycleByTime.insert(make_pair(times[i], make_pair(msExperiment, i + 1))); } } } BOOST_FOREACH(const ExperimentAndCycleByTime::value_type& itr, experimentAndCycleByTime) { index_.push_back(IndexEntry()); IndexEntry& ie = index_.back(); ie.sample = sample; ie.period = 1; // TODO ie.cycle = itr.second.second; ie.experiment = itr.second.first; ie.index = index_.size()-1; std::back_insert_iterator sink(ie.id); generate(sink, "sample=" << int_ << " period=" << int_ << " cycle=" << int_ << " experiment=" << int_, ie.sample, ie.period, ie.cycle, ie.experiment->getExperimentNumber()); idToIndexMap_[ie.id] = ie.index; } size_ = index_.size(); } } // detail } // msdata } // pwiz #else // PWIZ_READER_ABI // // non-MSVC implementation // namespace pwiz { namespace msdata { namespace detail { namespace {const SpectrumIdentity emptyIdentity;} size_t SpectrumList_ABI::size() const {return 0;} const SpectrumIdentity& SpectrumList_ABI::spectrumIdentity(size_t index) const {return emptyIdentity;} size_t SpectrumList_ABI::find(const std::string& id) const {return 0;} SpectrumPtr SpectrumList_ABI::spectrum(size_t index, bool getBinaryData) const {return SpectrumPtr();} SpectrumPtr SpectrumList_ABI::spectrum(size_t index, DetailLevel detailLevel) const {return SpectrumPtr();} SpectrumPtr SpectrumList_ABI::spectrum(size_t index, bool getBinaryData, const pwiz::util::IntegerSet& msLevelsToCentroid) const {return SpectrumPtr();} SpectrumPtr SpectrumList_ABI::spectrum(size_t index, DetailLevel detailLevel, const pwiz::util::IntegerSet& msLevelsToCentroid) const {return SpectrumPtr();} } // detail } // msdata } // pwiz #endif // PWIZ_READER_ABI pwiz/pwiz/data/vendor_readers/ABI/Reader_ABI_Test.cpp0000664000175100017510000000611712664775620024436 0ustar teamcityteamcity00000000000000// // $Id: Reader_ABI_Test.cpp 8903 2015-09-29 18:17:40Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/unit.hpp" #include "Reader_ABI.hpp" #include "pwiz/utility/misc/VendorReaderTestHarness.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #ifdef PWIZ_READER_ABI #include "Reader_ABI_Detail.hpp" #endif struct IsWiffFile : public pwiz::util::TestPathPredicate { bool operator() (const string& rawpath) const { return bal::to_lower_copy(BFS_STRING(bfs::path(rawpath).extension())) == ".wiff"; } }; int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) #ifdef PWIZ_READER_ABI const bool testAcceptOnly = false; #else const bool testAcceptOnly = true; #endif try { #ifdef PWIZ_READER_ABI using namespace pwiz::msdata; using namespace pwiz::msdata::detail; using namespace pwiz::msdata::detail::ABI; using namespace pwiz::util; // test that all instrument types are handled by translation functions (skipping the 'Unknown' type) bool allInstrumentTestsPassed = true; for (int i = 1; i < (int) InstrumentModel_Count; ++i) { InstrumentModel model = (InstrumentModel) i; try { unit_assert(translateAsInstrumentModel(model) != CVID_Unknown); InstrumentConfigurationPtr configuration = translateAsInstrumentConfiguration(model, IonSourceType_Unknown); unit_assert(configuration->componentList.source(0).hasCVParam(MS_ionization_type)); unit_assert(configuration->componentList.analyzer(0).hasCVParam(MS_quadrupole)); unit_assert(configuration->componentList.detector(0).hasCVParam(MS_electron_multiplier)); } catch (runtime_error& e) { cerr << "Unit test failed for instrument model " << lexical_cast(model) << ":\n" << e.what() << endl; allInstrumentTestsPassed = false; } } unit_assert(allInstrumentTestsPassed); #endif bool requireUnicodeSupport = true; pwiz::util::testReader(pwiz::msdata::Reader_ABI(), testArgs, testAcceptOnly, requireUnicodeSupport, IsWiffFile()); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/pwiz/data/vendor_readers/ABI/SpectrumList_ABI.hpp0000664000175100017510000000607612664775620024704 0ustar teamcityteamcity00000000000000// // $Id: SpectrumList_ABI.hpp 6585 2014-08-07 22:49:28Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/SpectrumListBase.hpp" #include "pwiz/utility/misc/IntegerSet.hpp" #include "pwiz/utility/misc/Container.hpp" #include "pwiz/data/msdata/Reader.hpp" #include #include #ifdef PWIZ_READER_ABI #include "pwiz_aux/msrc/utility/vendor_api/ABI/WiffFile.hpp" #include "pwiz/utility/misc/Once.hpp" #include using namespace pwiz::vendor_api::ABI; #endif // PWIZ_READER_ABI namespace pwiz { namespace msdata { namespace detail { class PWIZ_API_DECL SpectrumList_ABI : public SpectrumListBase { public: virtual size_t size() const; virtual const SpectrumIdentity& spectrumIdentity(size_t index) const; virtual size_t find(const std::string& id) const; virtual SpectrumPtr spectrum(size_t index, bool getBinaryData) const; virtual SpectrumPtr spectrum(size_t index, DetailLevel detailLevel) const; virtual SpectrumPtr spectrum(size_t index, bool getBinaryData, const pwiz::util::IntegerSet& msLevelsToCentroid) const; virtual SpectrumPtr spectrum(size_t index, DetailLevel detailLevel, const pwiz::util::IntegerSet& msLevelsToCentroid) const; #ifdef PWIZ_READER_ABI SpectrumList_ABI(const MSData& msd, WiffFilePtr wifffile, const ExperimentsMap& experimentsMap, int sample, const Reader::Config& config); private: const MSData& msd_; WiffFilePtr wifffile_; const Reader::Config config_; ExperimentsMap experimentsMap_; int sample; mutable boost::mutex readMutex; mutable size_t size_; mutable util::once_flag_proxy indexInitialized_; struct IndexEntry : public SpectrumIdentity { int sample; int period; int cycle; ExperimentPtr experiment; int transition; }; mutable std::vector index_; mutable std::map idToIndexMap_; // Cache last accessed spectrum for fast in order access mutable boost::mutex spectrum_mutex; mutable size_t spectrumLastIndex_; mutable pwiz::vendor_api::ABI::SpectrumPtr spectrumLast_; void createIndex() const; #endif // PWIZ_READER_ABI }; } // detail } // msdata } // pwiz pwiz/pwiz/data/vendor_readers/ABI/Reader_ABI_Detail.cpp0000664000175100017510000001676212664775620024730 0ustar teamcityteamcity00000000000000// // $Id: Reader_ABI_Detail.cpp 9220 2015-12-18 20:01:54Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Reader_ABI_Detail.hpp" #include "pwiz/utility/misc/Std.hpp" #ifdef PWIZ_READER_ABI using namespace pwiz::vendor_api::ABI; namespace pwiz { namespace msdata { namespace detail { namespace ABI { PWIZ_API_DECL InstrumentConfigurationPtr translateAsInstrumentConfiguration(InstrumentModel instrumentModel, IonSourceType ionSource) { InstrumentConfigurationPtr icPtr(new InstrumentConfiguration); InstrumentConfiguration& ic = *icPtr; ic.id = "IC1"; ic.set(translateAsInstrumentModel(instrumentModel)); Component source(ComponentType_Source, 1); source.set(translateAsIonSource(ionSource)); switch (instrumentModel) { // QqQ case API150MCA: case API150EX: case API2000: case API3000: case API3200: case API4000: case API5000: case API5500: case API6500: case API100: case API100LC: case API165: case API300: case API350: case API365: ic.componentList.push_back(source); ic.componentList.push_back(Component(MS_quadrupole, 2)); ic.componentList.push_back(Component(MS_quadrupole, 3)); ic.componentList.push_back(Component(MS_quadrupole, 4)); ic.componentList.push_back(Component(MS_electron_multiplier, 5)); break; // QqLIT case API2000QTrap: case API2500QTrap: case API3200QTrap: case API3500QTrap: case API4000QTrap: case API4500QTrap: case API5500QTrap: case API6500QTrap: ic.componentList.push_back(source); ic.componentList.push_back(Component(MS_quadrupole, 2)); ic.componentList.push_back(Component(MS_quadrupole, 3)); ic.componentList.push_back(Component(MS_axial_ejection_linear_ion_trap, 4)); ic.componentList.push_back(Component(MS_electron_multiplier, 5)); break; // QqTOF case QStar: case QStarPulsarI: case QStarXL: case QStarElite: case API4600TripleTOF: case API5600TripleTOF: case API6600TripleTOF: case NlxTof: ic.componentList.push_back(source); ic.componentList.push_back(Component(MS_quadrupole, 2)); ic.componentList.push_back(Component(MS_quadrupole, 3)); ic.componentList.push_back(Component(MS_time_of_flight, 4)); ic.componentList.push_back(Component(MS_electron_multiplier, 5)); break; case InstrumentModel_Unknown: break; default: throw runtime_error("[translateAsInstrumentConfiguration] unhandled instrument model: " + lexical_cast(instrumentModel)); } return icPtr; } PWIZ_API_DECL CVID translateAsInstrumentModel(InstrumentModel instrumentModel) { switch (instrumentModel) { case API100: return MS_API_100; case API100LC: return MS_API_100LC; case API150MCA: return MS_API_150EX; case API150EX: return MS_API_150EX; case API165: return MS_API_165; case API300: return MS_API_300; case API350: return MS_API_350; case API365: return MS_API_365; case API2000: return MS_API_2000; case API3000: return MS_API_3000; case API3200: return MS_API_3200; case API4000: return MS_API_4000; case API5000: return MS_API_5000; case API5500: return MS_Triple_Quad_5500; case API6500: return MS_Triple_Quad_6500; case API2000QTrap: return MS_2000_QTRAP; case API2500QTrap: return MS_2500_QTRAP; case API3200QTrap: return MS_3200_QTRAP; case API3500QTrap: return MS_3500_QTRAP; case API4000QTrap: return MS_4000_QTRAP; case API4500QTrap: return MS_QTRAP_4500; case API5500QTrap: return MS_QTRAP_5500; case API6500QTrap: return MS_QTRAP_6500; case API4600TripleTOF: return MS_TripleTOF_4600; case API5600TripleTOF: return MS_TripleTOF_5600; case API6600TripleTOF: return MS_TripleTOF_6600; case QStar: return MS_QSTAR; case QStarPulsarI: return MS_QSTAR_Pulsar; case QStarXL: return MS_QSTAR_XL; case QStarElite: return MS_QSTAR_Elite; case NlxTof: case InstrumentModel_Unknown: return MS_Applied_Biosystems_instrument_model; default: throw runtime_error("[translateAsInstrumentModel] unhandled instrument model: " + lexical_cast(instrumentModel)); } } PWIZ_API_DECL CVID translateAsIonSource(IonSourceType ionSourceType) { switch (ionSourceType) { case IonSourceType_Unknown: return MS_ionization_type; case FlowNanoSpray: return MS_nanoelectrospray; case HeatedNebulizer: return MS_atmospheric_pressure_chemical_ionization; case TurboSpray: return MS_electrospray_ionization; case IonSpray: return MS_electrospray_ionization; case Maldi: return MS_matrix_assisted_laser_desorption_ionization; case PhotoSpray: return MS_atmospheric_pressure_photoionization; case Medusa: case Duo: case None: return CVID_Unknown; default: throw runtime_error("[translateAsIonSource] unhandled ion source: " + lexical_cast(ionSourceType)); } } PWIZ_API_DECL CVID translateAsSpectrumType(ExperimentType experimentType) { switch (experimentType) { case MS: return MS_MS1_spectrum; case vendor_api::ABI::Product: return MS_MSn_spectrum; case vendor_api::ABI::Precursor: return MS_precursor_ion_spectrum; case NeutralGainOrLoss: return MS_constant_neutral_loss_spectrum; case SIM: return MS_SIM_spectrum; case MRM: return MS_SRM_spectrum; default: return CVID_Unknown; } } PWIZ_API_DECL CVID translate(Polarity polarity) { switch (polarity) { case Positive: return MS_positive_scan; case Negative: return MS_negative_scan; case Undefined: default: return CVID_Unknown; } } } // ABI } // detail } // msdata } // pwiz #endif // PWIZ_READER_ABI pwiz/pwiz/data/vendor_readers/ABI/Reader_ABI.cpp0000664000175100017510000002702712664775620023442 0ustar teamcityteamcity00000000000000// // $Id: Reader_ABI.cpp 9283 2016-01-11 21:31:03Z chambm $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Reader_ABI.hpp" #include "pwiz/utility/misc/SHA1Calculator.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/DateTime.hpp" #include "pwiz/utility/misc/Std.hpp" #include "pwiz/data/msdata/Version.hpp" #include PWIZ_API_DECL std::string pwiz::msdata::Reader_ABI::identify(const std::string& filename, const std::string& head) const { std::string result; // TODO: check header signature? if (bal::iends_with(filename, ".wiff")) result = getType(); return result; } #ifdef PWIZ_READER_ABI #include "pwiz_aux/msrc/utility/vendor_api/ABI/WiffFile.hpp" #include "SpectrumList_ABI.hpp" #include "ChromatogramList_ABI.hpp" #include "Reader_ABI_Detail.hpp" #include // GetModuleFileName namespace pwiz { namespace msdata { using namespace pwiz::util; using namespace pwiz::msdata::detail; using namespace pwiz::msdata::detail::ABI; // // Reader_ABI // namespace { void fillInMetadata(const string& wiffpath, MSData& msd, WiffFilePtr wifffile, const ExperimentsMap& experimentsMap, int sample, const Reader::Config& config) { msd.cvs = defaultCVList(); string sampleName = wifffile->getSampleNames()[sample-1]; BOOST_FOREACH_FIELD((boost::fusion::ignore)(const ExperimentPtr& msExperiment), experimentsMap) { if (msExperiment->getExperimentType() != MRM) msd.fileDescription.fileContent.set(translateAsSpectrumType(msExperiment->getExperimentType())); else msd.fileDescription.fileContent.set(MS_SRM_chromatogram); } SourceFilePtr sourceFile(new SourceFile); bfs::path p(wiffpath); sourceFile->id = "WIFF"; sourceFile->name = BFS_STRING(p.leaf()); string location = BFS_COMPLETE(p.branch_path()).string(); if (location.empty()) location = "."; sourceFile->location = "file://" + location; sourceFile->set(MS_WIFF_nativeID_format); sourceFile->set(MS_ABI_WIFF_format); msd.fileDescription.sourceFilePtrs.push_back(sourceFile); msd.run.defaultSourceFilePtr = sourceFile; // add a SourceFile for the .scan file if it exists bfs::path wiffscan = wiffpath + ".scan"; if (bfs::exists(wiffscan)) { SourceFilePtr sourceFile(new SourceFile); sourceFile->id = "WIFFSCAN"; sourceFile->name = BFS_STRING(wiffscan.leaf()); string location = BFS_COMPLETE(wiffscan.branch_path()).string(); if (location.empty()) location = "."; sourceFile->location = "file://" + location; sourceFile->set(MS_WIFF_nativeID_format); sourceFile->set(MS_ABI_WIFF_format); msd.fileDescription.sourceFilePtrs.push_back(sourceFile); } msd.id = bfs::basename(p); if (!sampleName.empty()) { // if the basename is in the sample name, just use the sample name; // otherwise add the sample name as a suffix if(sampleName.find(msd.id) != string::npos) msd.id = sampleName; else msd.id += "-" + sampleName; } SoftwarePtr acquisitionSoftware(new Software); acquisitionSoftware->id = "Analyst"; acquisitionSoftware->set(MS_Analyst); acquisitionSoftware->version = "unknown"; msd.softwarePtrs.push_back(acquisitionSoftware); SoftwarePtr softwarePwiz(new Software); softwarePwiz->id = "pwiz_Reader_ABI"; softwarePwiz->set(MS_pwiz); softwarePwiz->version = pwiz::msdata::Version::str(); msd.softwarePtrs.push_back(softwarePwiz); DataProcessingPtr dpPwiz(new DataProcessing); dpPwiz->id = "pwiz_Reader_ABI_conversion"; dpPwiz->processingMethods.push_back(ProcessingMethod()); dpPwiz->processingMethods.back().softwarePtr = softwarePwiz; dpPwiz->processingMethods.back().set(MS_Conversion_to_mzML); // give ownership of dpPwiz to the SpectrumList (and ChromatogramList) SpectrumList_ABI* sl = dynamic_cast(msd.run.spectrumListPtr.get()); ChromatogramList_ABI* cl = dynamic_cast(msd.run.chromatogramListPtr.get()); if (sl) sl->setDataProcessingPtr(dpPwiz); if (cl) cl->setDataProcessingPtr(dpPwiz); InstrumentConfigurationPtr ic = translateAsInstrumentConfiguration(wifffile->getInstrumentModel(), IonSpray); ic->softwarePtr = acquisitionSoftware; msd.instrumentConfigurationPtrs.push_back(ic); msd.run.defaultInstrumentConfigurationPtr = ic; msd.run.id = msd.id; msd.run.startTimeStamp = encode_xml_datetime(wifffile->getSampleAcquisitionTime(sample, config.adjustUnknownTimeZonesToHostTimeZone)); } void cacheExperiments(WiffFilePtr wifffile, ExperimentsMap& experimentsMap, int sample) { int periodCount = wifffile->getPeriodCount(sample); for (int ii=1; ii <= periodCount; ++ii) { int experimentCount = wifffile->getExperimentCount(sample, ii); for (int iii=1; iii <= experimentCount; ++iii) experimentsMap[make_pair(ii, iii)] = wifffile->getExperiment(sample, ii, iii); } } } // namespace PWIZ_API_DECL void Reader_ABI::read(const string& filename, const string& head, MSData& result, int runIndex, const Config& config) const { try { runIndex++; // one-based index WiffFilePtr wifffile = WiffFile::create(filename); // Loading the experiments is an expensive operation, so cache them. ExperimentsMap experimentsMap; cacheExperiments(wifffile, experimentsMap, runIndex); SpectrumList_ABI* sl = new SpectrumList_ABI(result, wifffile, experimentsMap, runIndex, config); ChromatogramList_ABI* cl = new ChromatogramList_ABI(result, wifffile, experimentsMap, runIndex); result.run.spectrumListPtr = SpectrumListPtr(sl); result.run.chromatogramListPtr = ChromatogramListPtr(cl); fillInMetadata(filename, result, wifffile, experimentsMap, runIndex, config); } catch (std::exception& e) { throw std::runtime_error(e.what()); } catch (...) { throw runtime_error("[Reader_ABI::read()] unhandled exception"); } } PWIZ_API_DECL void Reader_ABI::read(const string& filename, const string& head, vector& results, const Config& config) const { try { WiffFilePtr wifffile = WiffFile::create(filename); int sampleCount = wifffile->getSampleCount(); for (int i=1; i <= sampleCount; ++i) { try { MSDataPtr msDataPtr = MSDataPtr(new MSData); MSData& result = *msDataPtr; // Loading the experiments is an expensive operation, so cache them. ExperimentsMap experimentsMap; cacheExperiments(wifffile, experimentsMap, i); SpectrumList_ABI* sl = new SpectrumList_ABI(result, wifffile, experimentsMap, i, config); ChromatogramList_ABI* cl = new ChromatogramList_ABI(result, wifffile, experimentsMap, i); result.run.spectrumListPtr = SpectrumListPtr(sl); result.run.chromatogramListPtr = ChromatogramListPtr(cl); fillInMetadata(filename, result, wifffile, experimentsMap, i, config); results.push_back(msDataPtr); } catch (exception& e) { // TODO: make this a critical logged warning cerr << "[Reader_ABI::read] Error opening run " << i << " in " << bfs::path(filename).leaf() << ":\n" << e.what() << endl; } } } catch (std::exception& e) { throw std::runtime_error(e.what()); } catch (...) { throw runtime_error("[Reader_ABI::read()] unhandled exception"); } } PWIZ_API_DECL void Reader_ABI::readIds(const string& filename, const string& head, vector& results, const Config& config) const { try { WiffFilePtr wifffile = WiffFile::create(filename); vector sampleNames = wifffile->getSampleNames(); for (vector::iterator it = sampleNames.begin(); it != sampleNames.end(); it++) results.push_back(*it); } catch (std::exception& e) { throw std::runtime_error(e.what()); } catch (...) { throw runtime_error("[Reader_ABI::readIds()] unhandled exception"); } } } // namespace msdata } // namespace pwiz #else // PWIZ_READER_ABI // // non-MSVC implementation // #include "Reader_ABI.hpp" #include "pwiz/utility/misc/String.hpp" namespace pwiz { namespace msdata { PWIZ_API_DECL void Reader_ABI::read(const string& filename, const string& head, MSData& result, int runIndex, const Config& config) const { throw ReaderFail("[Reader_ABI::read()] ABSciex WIFF reader not implemented: " #ifdef _MSC_VER // should be possible, apparently somebody decided to skip it "support was explicitly disabled when program was built" #elif defined(WIN32) // wrong compiler "program was built without COM support and cannot access ABSciex DLLs - try building with MSVC instead of GCC" #else // wrong platform "requires ABSciex DLLs which only work on Windows" #endif ); } PWIZ_API_DECL void Reader_ABI::read(const string& filename, const string& head, vector& results, const Config& config) const { throw ReaderFail("[Reader_ABI::read()] ABSciex WIFF reader not implemented: " #ifdef _MSC_VER // should be possible, apparently somebody decided to skip it "support was explicitly disabled when program was built" #elif defined(WIN32) // wrong compiler "program was built without COM support and cannot access ABSciex DLLs - try building with MSVC instead of GCC" #else // wrong platform "requires ABSciex DLLs which only work on Windows" #endif ); } PWIZ_API_DECL void Reader_ABI::readIds(const std::string& filename, const std::string& head, std::vector& results, const Config& config) const { throw ReaderFail("[Reader_ABI::readIds()] ABSciex WIFF reader not implemented: " #ifdef _MSC_VER // should be possible, apparently somebody decided to skip it "support was explicitly disabled when program was built" #elif defined(WIN32) // wrong compiler "program was built without COM support and cannot access ABSciex DLLs - try building with MSVC instead of GCC" #else // wrong platform "requires ABSciex DLLs which only work on Windows" #endif ); } } // namespace msdata } // namespace pwiz #endif // PWIZ_READER_ABI pwiz/pwiz/data/vendor_readers/ABI/Reader_ABI.hpp0000664000175100017510000000421112664775620023435 0ustar teamcityteamcity00000000000000// // $Id: Reader_ABI.hpp 3808 2012-07-24 20:31:10Z donmarsh $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _READER_ABI_HPP_ #define _READER_ABI_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/Reader.hpp" #include // WIFF usage is msvc only - mingw doesn't provide com support #if (!defined(_MSC_VER) && defined(PWIZ_READER_ABI)) #undef PWIZ_READER_ABI #endif namespace pwiz { namespace msdata { class PWIZ_API_DECL Reader_ABI : public Reader { public: virtual std::string identify(const std::string& filename, const std::string& head) const; virtual void read(const std::string& filename, const std::string& head, MSData& result, int sampleIndex = 0, const Config& config = Config()) const; virtual void read(const std::string& filename, const std::string& head, std::vector& results, const Config& config = Config()) const; virtual void readIds(const std::string& filename, const std::string& head, std::vector& results, const Config& config = Config()) const; virtual const char * getType() const {return "ABSciex WIFF";} }; } // namespace msdata } // namespace pwiz #endif // _READER_ABI_HPP_ pwiz/pwiz/data/vendor_readers/ABI/ChromatogramList_ABI.hpp0000664000175100017510000000436712664775620025526 0ustar teamcityteamcity00000000000000// // $Id: ChromatogramList_ABI.hpp 2735 2011-05-29 05:53:40Z brendanx $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/ChromatogramListBase.hpp" #ifdef PWIZ_READER_ABI #include "pwiz_aux/msrc/utility/vendor_api/ABI/WiffFile.hpp" #include "pwiz/utility/misc/Once.hpp" using namespace pwiz::vendor_api::ABI; #endif // PWIZ_READER_ABI namespace pwiz { namespace msdata { namespace detail { class PWIZ_API_DECL ChromatogramList_ABI : public ChromatogramListBase { public: virtual size_t size() const; virtual const ChromatogramIdentity& chromatogramIdentity(size_t index) const; virtual size_t find(const std::string& id) const; virtual ChromatogramPtr chromatogram(size_t index, bool getBinaryData) const; #ifdef PWIZ_READER_ABI ChromatogramList_ABI(const MSData& msd, WiffFilePtr wifffile, const ExperimentsMap& experimentsMap, int sample); private: const MSData& msd_; WiffFilePtr wifffile_; ExperimentsMap experimentsMap_; int sample; mutable size_t size_; mutable util::once_flag_proxy indexInitialized_; struct IndexEntry : public ChromatogramIdentity { CVID chromatogramType; int sample; int period; ExperimentPtr experiment; int transition; double q1, q3; }; mutable std::vector index_; mutable std::map idToIndexMap_; void createIndex() const; #endif // PWIZ_READER_ABI }; } // detail } // msdata } // pwiz pwiz/pwiz/data/vendor_readers/Shimadzu/ChromatogramList_Shimadzu.cpp0000664000175100017510000001601112664775617030076 0ustar teamcityteamcity00000000000000// // $Id: ChromatogramList_Shimadzu.cpp 8738 2015-08-06 22:19:25Z kaipot $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "ChromatogramList_Shimadzu.hpp" #ifdef PWIZ_READER_SHIMADZU #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/Std.hpp" #include namespace pwiz { namespace msdata { namespace detail { ChromatogramList_Shimadzu::ChromatogramList_Shimadzu(ShimadzuReaderPtr rawfile) : rawfile_(rawfile), indexInitialized_(util::init_once_flag_proxy) { } PWIZ_API_DECL size_t ChromatogramList_Shimadzu::size() const { boost::call_once(indexInitialized_.flag, boost::bind(&ChromatogramList_Shimadzu::createIndex, this)); return index_.size(); } PWIZ_API_DECL const ChromatogramIdentity& ChromatogramList_Shimadzu::chromatogramIdentity(size_t index) const { boost::call_once(indexInitialized_.flag, boost::bind(&ChromatogramList_Shimadzu::createIndex, this)); if (index>size()) throw runtime_error(("[ChromatogramList_Shimadzu::chromatogramIdentity()] Bad index: " + lexical_cast(index)).c_str()); return reinterpret_cast(index_[index]); } PWIZ_API_DECL size_t ChromatogramList_Shimadzu::find(const string& id) const { boost::call_once(indexInitialized_.flag, boost::bind(&ChromatogramList_Shimadzu::createIndex, this)); map::const_iterator itr = idMap_.find(id); if (itr != idMap_.end()) return itr->second; return size(); } PWIZ_API_DECL ChromatogramPtr ChromatogramList_Shimadzu::chromatogram(size_t index, bool getBinaryData) const { boost::call_once(indexInitialized_.flag, boost::bind(&ChromatogramList_Shimadzu::createIndex, this)); if (index>size()) throw runtime_error(("[ChromatogramList_Shimadzu::chromatogram()] Bad index: " + lexical_cast(index)).c_str()); const IndexEntry& ci = index_[index]; ChromatogramPtr result(new Chromatogram); result->index = ci.index; result->id = ci.id; result->set(MS_SRM_chromatogram); switch (MS_SRM_chromatogram) { default: break; /*case MS_TIC_chromatogram: { if (getBinaryData) { result->setTimeIntensityArrays(vector(), vector(), UO_minute, MS_number_of_detector_counts); result->getTimeArray()->data.assign(rawfile_->getTicTimes().begin(), rawfile_->getTicTimes().end()); result->getIntensityArray()->data.assign(rawfile_->getTicIntensities().begin(), rawfile_->getTicIntensities().end()); result->defaultArrayLength = result->getTimeArray()->data.size(); } else result->defaultArrayLength = rawfile_->getTicTimes().size(); } break;*/ case MS_SRM_chromatogram: { pwiz::vendor_api::Shimadzu::ChromatogramPtr chromatogramPtr(rawfile_->getChromatogram(ci.transition)); result->precursor.isolationWindow.set(MS_isolation_window_target_m_z, ci.transition.Q1, MS_m_z); result->precursor.activation.set(MS_CID); result->precursor.activation.set(MS_collision_energy, ci.transition.collisionEnergy, UO_electronvolt); result->set(ci.transition.polarity != 1 ? MS_positive_scan : MS_negative_scan); result->product.isolationWindow.set(MS_isolation_window_target_m_z, ci.transition.Q3, MS_m_z); //result->product.isolationWindow.set(MS_isolation_window_lower_offset, ci.q3Offset, MS_m_z); //result->product.isolationWindow.set(MS_isolation_window_upper_offset, ci.q3Offset, MS_m_z); if (getBinaryData) { result->setTimeIntensityArrays(vector(), vector(), UO_minute, MS_number_of_detector_counts); vector xArray; chromatogramPtr->getXArray(xArray); result->getTimeArray()->data.assign(xArray.begin(), xArray.end()); vector yArray; chromatogramPtr->getYArray(yArray); result->getIntensityArray()->data.assign(yArray.begin(), yArray.end()); result->defaultArrayLength = xArray.size(); } else result->defaultArrayLength = chromatogramPtr->getTotalDataPoints(); } break; } return result; } PWIZ_API_DECL void ChromatogramList_Shimadzu::createIndex() const { // support file-level TIC for all file types /*index_.push_back(IndexEntry()); IndexEntry& ci = index_.back(); ci.index = index_.size()-1; ci.chromatogramType = MS_TIC_chromatogram; ci.id = "TIC"; idMap_[ci.id] = ci.index;*/ const set& transitions = rawfile_->getTransitions(); BOOST_FOREACH(const SRMTransition& transition, transitions) { index_.push_back(IndexEntry()); IndexEntry& ci = index_.back(); ci.index = index_.size()-1; ci.transition = transition; ci.id = (format("SRM SIC Q1=%.10g Q3=%.10g Channel=%d Event=%d Segment=%d CE=%.10g"/* start=%.10g end=%.10g"*/) % transition.Q1 % transition.Q3 % transition.channel % transition.event % transition.segment % transition.collisionEnergy /*% transition.acquiredTimeRange.start % transition.acquiredTimeRange.end*/ ).str(); idMap_[ci.id] = ci.index; } } } // detail } // msdata } // pwiz #else // PWIZ_READER_SHIMADZU // // non-MSVC implementation // namespace pwiz { namespace msdata { namespace detail { namespace {const ChromatogramIdentity emptyIdentity;} size_t ChromatogramList_Shimadzu::size() const {return 0;} const ChromatogramIdentity& ChromatogramList_Shimadzu::chromatogramIdentity(size_t index) const {return emptyIdentity;} size_t ChromatogramList_Shimadzu::find(const string& id) const {return 0;} ChromatogramPtr ChromatogramList_Shimadzu::chromatogram(size_t index, bool getBinaryData) const {return ChromatogramPtr();} } // detail } // msdata } // pwiz #endif // PWIZ_READER_SHIMADZU pwiz/pwiz/data/vendor_readers/Shimadzu/Reader_Shimadzu.cpp0000664000175100017510000001527712664775617026036 0ustar teamcityteamcity00000000000000// // $Id: Reader_Shimadzu.cpp 6314 2014-06-04 18:04:36Z chambm $ // // // Original author: Matt Chambers // // Copyright 2014 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "Reader_Shimadzu.hpp" #include "pwiz/utility/misc/Filesystem.hpp" #include "pwiz/utility/misc/String.hpp" #include PWIZ_API_DECL std::string pwiz::msdata::Reader_Shimadzu::identify(const std::string& filename, const std::string& head) const { if (bal::iends_with(filename, ".lcd")) return getType(); return ""; } #ifdef PWIZ_READER_SHIMADZU #include "pwiz/utility/misc/SHA1Calculator.hpp" #include "pwiz/data/msdata/Version.hpp" #include "pwiz/utility/misc/DateTime.hpp" #include "pwiz_aux/msrc/utility/vendor_api/Shimadzu/ShimadzuReader.hpp" //#include "SpectrumList_Shimadzu.hpp" #include "ChromatogramList_Shimadzu.hpp" #include "pwiz/utility/misc/Std.hpp" namespace pwiz { namespace msdata { using namespace pwiz::util; using namespace pwiz::msdata::detail; namespace Shimadzu = pwiz::vendor_api::Shimadzu; // // Reader_Shimadzu // namespace { void initializeInstrumentConfigurationPtrs(MSData& msd, Shimadzu::ShimadzuReaderPtr rawfile, const SoftwarePtr& instrumentSoftware) { // create instrument configuration templates based on the instrument model vector configurations(1, InstrumentConfigurationPtr(new InstrumentConfiguration)); for (size_t i=0; i < configurations.size(); ++i) { InstrumentConfigurationPtr ic = InstrumentConfigurationPtr(new InstrumentConfiguration); ic->id = (format("IC%d") % (i+1)).str(); ic->softwarePtr = instrumentSoftware; ic->set(MS_Shimadzu_instrument_model); msd.instrumentConfigurationPtrs.push_back(ic); } } void fillInMetadata(const string& rawpath, Shimadzu::ShimadzuReaderPtr rawfile, MSData& msd) { msd.cvs = defaultCVList(); msd.fileDescription.fileContent.set(MS_SRM_chromatogram); boost::filesystem::detail::utf8_codecvt_facet utf8; bfs::path p(rawpath, utf8); SourceFilePtr sourceFile(new SourceFile); sourceFile->id = p.filename().string(utf8); sourceFile->name = p.filename().string(utf8); sourceFile->location = "file:///" + bfs::system_complete(p.branch_path()).string(utf8); sourceFile->set(MS_Shimadzu_Biotech_nativeID_format); sourceFile->set(MS_mass_spectrometer_file_format); msd.fileDescription.sourceFilePtrs.push_back(sourceFile); msd.run.defaultSourceFilePtr = sourceFile; msd.id = p.filename().replace_extension("").string(utf8); SoftwarePtr softwareShimadzu(new Software); softwareShimadzu->id = "Shimadzu software"; softwareShimadzu->set(MS_Shimadzu_Corporation_software); softwareShimadzu->version = "4.0"; msd.softwarePtrs.push_back(softwareShimadzu); SoftwarePtr softwarePwiz(new Software); softwarePwiz->id = "pwiz"; softwarePwiz->set(MS_pwiz); softwarePwiz->version = pwiz::msdata::Version::str(); msd.softwarePtrs.push_back(softwarePwiz); DataProcessingPtr dpPwiz(new DataProcessing); dpPwiz->id = "pwiz_Reader_Shimadzu_conversion"; dpPwiz->processingMethods.push_back(ProcessingMethod()); dpPwiz->processingMethods.back().softwarePtr = softwarePwiz; dpPwiz->processingMethods.back().set(MS_Conversion_to_mzML); // give ownership of dpPwiz to the SpectrumList (and ChromatogramList) //SpectrumList_Shimadzu* sl = dynamic_cast(msd.run.spectrumListPtr.get()); ChromatogramList_Shimadzu* cl = dynamic_cast(msd.run.chromatogramListPtr.get()); //if (sl) sl->setDataProcessingPtr(dpPwiz); if (cl) cl->setDataProcessingPtr(dpPwiz); initializeInstrumentConfigurationPtrs(msd, rawfile, softwareShimadzu); if (!msd.instrumentConfigurationPtrs.empty()) msd.run.defaultInstrumentConfigurationPtr = msd.instrumentConfigurationPtrs[0]; msd.run.id = msd.id; //msd.run.startTimeStamp = encode_xml_datetime(rawfile->getAcquisitionTime()); } } // namespace PWIZ_API_DECL void Reader_Shimadzu::read(const string& filename, const string& head, MSData& result, int runIndex /* = 0 */, const Config& config) const { if (runIndex != 0) throw ReaderFail("[Reader_Shimadzu::read] multiple runs not supported"); // instantiate RawFile, share ownership with SpectrumList_Shimadzu Shimadzu::ShimadzuReaderPtr dataReader(Shimadzu::ShimadzuReader::create(filename)); //shared_ptr sl(new SpectrumList_Shimadzu(result, dataReader)); shared_ptr cl(new ChromatogramList_Shimadzu(dataReader)); //result.run.spectrumListPtr = sl; result.run.chromatogramListPtr = cl; fillInMetadata(filename, dataReader, result); } } // namespace msdata } // namespace pwiz #else // PWIZ_READER_SHIMADZU ///////////////////////////////////////////////////////////////////////////// // // non-MSVC implementation // #include "pwiz/utility/misc/String.hpp" namespace pwiz { namespace msdata { PWIZ_API_DECL void Reader_Shimadzu::read(const string& filename, const string& head, MSData& result, int sampleIndex /* = 0 */, const Config& config) const { throw ReaderFail("[Reader_Shimadzu::read()] Shimadzu reader not implemented: " #ifdef _MSC_VER // should be possible, apparently somebody decided to skip it "support was explicitly disabled when program was built" #elif defined(WIN32) // wrong compiler "program was built without COM support and cannot access Shimadzu DLLs - try building with MSVC instead of GCC" #else // wrong platform "Shimadzu DLLs only work on Windows" #endif ); } } // namespace msdata } // namespace pwiz #endif // PWIZ_READER_SHIMADZU ///////////////////////////////////////////////////////////////////////////// pwiz/pwiz/data/vendor_readers/Shimadzu/Reader_Shimadzu.hpp0000664000175100017510000000360112664775617026027 0ustar teamcityteamcity00000000000000// // $Id: Reader_Shimadzu.hpp 6234 2014-05-23 21:19:09Z nickshulman $ // // // Original author: Matt Chambers // // Copyright 2014 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _READER_SHIMADZU_HPP_ #define _READER_SHIMADZU_HPP_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/Reader.hpp" namespace pwiz { namespace msdata { class PWIZ_API_DECL Reader_Shimadzu : public Reader { public: virtual std::string identify(const std::string& filename, const std::string& head) const; virtual void read(const std::string& filename, const std::string& head, MSData& result, int runIndex = 0, const Config& config = Config()) const; virtual void read(const std::string& filename, const std::string& head, std::vector& results, const Config& config = Config()) const { results.push_back(MSDataPtr(new MSData)); read(filename, head, *results.back(), 0, config); } virtual const char *getType() const {return "Shimadzu LCD";} }; } // namespace msdata } // namespace pwiz #endif // _READER_SHIMADZU_HPP_ pwiz/pwiz/data/vendor_readers/Shimadzu/ChromatogramList_Shimadzu.hpp0000664000175100017510000000421112664775617030102 0ustar teamcityteamcity00000000000000// // $Id: ChromatogramList_Shimadzu.hpp 6234 2014-05-23 21:19:09Z nickshulman $ // // // Original author: Matt Chambers // // Copyright 2009 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _CHROMATOGRAMLIST_SHIMADZU_ #define _CHROMATOGRAMLIST_SHIMADZU_ #include "pwiz/utility/misc/Export.hpp" #include "pwiz/data/msdata/ChromatogramListBase.hpp" #include "pwiz/utility/misc/Std.hpp" #ifdef PWIZ_READER_SHIMADZU #include "pwiz_aux/msrc/utility/vendor_api/Shimadzu/ShimadzuReader.hpp" #include "pwiz/utility/misc/Once.hpp" using namespace pwiz::vendor_api::Shimadzu; #endif // PWIZ_READER_SHIMADZU namespace pwiz { namespace msdata { namespace detail { class PWIZ_API_DECL ChromatogramList_Shimadzu : public ChromatogramListBase { public: virtual size_t size() const; virtual const ChromatogramIdentity& chromatogramIdentity(size_t index) const; virtual size_t find(const string& id) const; virtual ChromatogramPtr chromatogram(size_t index, bool getBinaryData) const; #ifdef PWIZ_READER_SHIMADZU ChromatogramList_Shimadzu(ShimadzuReaderPtr reader); private: ShimadzuReaderPtr rawfile_; mutable util::once_flag_proxy indexInitialized_; struct IndexEntry : public ChromatogramIdentity { SRMTransition transition; }; mutable vector index_; mutable map idMap_; void createIndex() const; #endif // PWIZ_READER_SHIMADZU }; } // detail } // msdata } // pwiz #endif // _CHROMATOGRAMLIST_SHIMADZU_ pwiz/pwiz/Version.hpp0000664000175100017510000000223712664775621016706 0ustar teamcityteamcity00000000000000// // $Id: Version.hpp 1195 2009-08-14 22:12:04Z chambm $ // // // Original author: Darren Kessner // // Copyright 2008 Spielberg Family Center for Applied Proteomics // Cedars-Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _PWIZ_VERSION_HPP_ #define _PWIZ_VERSION_HPP_ #include "utility/misc/Export.hpp" #include namespace pwiz { struct PWIZ_API_DECL Version { static int Major(); static int Minor(); static int Revision(); static std::string str(); static std::string LastModified(); }; } // namespace pwiz #endif // _PWIZ_VERSION_HPP_ pwiz/pwiz/Version.cpp0000664000175100017510000000261112664776103016671 0ustar teamcityteamcity00000000000000// This file was generated by the "svnrev" utility // You should not modify it manually, as it may be re-generated. // // $Revision: 9393 $ // $Date: 2016-2-10 $ // // Licensed under the Apache License, Version 2.0 (the License); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an AS IS BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "Version.hpp" #include #ifdef PWIZ_USER_VERSION_INFO_H // in case you need to add any info version of your own #include PWIZ_USER_VERSION_INFO_H // must define PWIZ_USER_VERSION_INFO_H_STR for use below #endif namespace pwiz { int Version::Major() {return 3;} int Version::Minor() {return 0;} int Version::Revision() {return 9393;} std::string Version::LastModified() {return "2016-2-10";} std::string Version::str() { std::ostringstream v; v << Major() << '.' << Minor() << '.' << Revision(); #ifdef PWIZ_USER_VERSION_INFO_H v << " (" << PWIZ_USER_VERSION_INFO_H_STR << ")"; #endif return v.str(); } } // namespace pwiz pwiz/pwiz/utility/proteome/IPIFASTADatabase.hpp0000664000175100017510000000414312664775616023445 0ustar teamcityteamcity00000000000000// // $Id: IPIFASTADatabase.hpp 1407 2009-10-10 17:07:39Z paragmallick $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef _IPIFASTADATABASE_HPP_ #define _IPIFASTADATABASE_HPP_ #include "pwiz/utility/misc/Export.hpp" #include #include #include #include namespace pwiz { namespace proteome { /// class for accessing data in ipi.*.fasta files class PWIZ_API_DECL IPIFASTADatabase { public: /// constructor reads in entire file IPIFASTADatabase(const std::string& filename); ~IPIFASTADatabase(); /// structure for holding peptide info struct PWIZ_API_DECL Record { int id; std::string faID; std::string fullSeqDescription; std::string sequence; Record(int _id=0) : id(_id) {} }; /// access to the data in memory const std::vector& records() const; /// typedef to simplify declaration of Record iterator typedef std::vector::const_iterator const_iterator; // begin() and end() const_iterator begin(); const_iterator end(); private: class Impl; std::auto_ptr impl_; }; PWIZ_API_DECL std::ostream& operator<<(std::ostream& os, const IPIFASTADatabase::Record& record); } // namespace proteome } // namespace pwiz #endif // _IPIFASTADATABASE_HPP_ pwiz/pwiz/utility/proteome/IPIFASTADatabase.cpp0000664000175100017510000001151412664775616023440 0ustar teamcityteamcity00000000000000// // $Id: IPIFASTADatabase.cpp 2051 2010-06-15 18:39:13Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define PWIZ_SOURCE #include "IPIFASTADatabase.hpp" #include "pwiz/utility/misc/Std.hpp" #include #include namespace pwiz { namespace proteome { IPIFASTADatabase::const_iterator IPIFASTADatabase::begin() { return records().begin(); } IPIFASTADatabase::const_iterator IPIFASTADatabase::end() { return records().end(); } class IPIFASTADatabase::Impl { public: Impl(const string& filename); const vector& records() const {return records_;} private: vector records_; void readRecords(istream& is); }; IPIFASTADatabase::Impl::Impl(const string& filename) { ifstream is(filename.c_str()); if (!is) throw runtime_error(("[IPIFASTADatabase::Impl::Impl()] Unable to open file " + filename).c_str()); //cout << "Reading records from " << filename << "..." << flush; readRecords(is); //cout << "done.\n"; } void IPIFASTADatabase::Impl::readRecords(istream& is) { Record* current = 0; for (string buffer; getline(is, buffer); ) { // std::cout<<"||||"<IPI:IPI") == 0) { // start a new record, and set current pointer records_.push_back(Record(atoi(buffer.c_str()+8))); current = &records_.back(); current->fullSeqDescription = buffer; // get protein ID (e.g. IPI number, or whatever precedes first pipe) // TODO: Increase flexibility (e.g. what if no pipe, get all ids between pipes as different // variables, etc ... const char* pipe = "|"; if (buffer.find(pipe) != string::npos) { const size_t& pipeLocation = buffer.find(pipe); char protein[30]; memset(protein, '\0', 30); buffer.copy(protein, pipeLocation - 1, 1); // skip initial '>' current->faID = protein; } else current->faID ="unknown"; } else if(buffer.find(">") == 0){ //there is likely a better way to handle these cases. // start a new record, and set current pointer records_.push_back(Record(atoi(buffer.c_str()))); current = &records_.back(); current->fullSeqDescription = buffer; // get protein ID (e.g. IPI number, or whatever precedes first space) // TODO: Increase flexibility (e.g. what if no pipe, get all ids between pipes as different // variables, etc ... const char* space = " "; if (buffer.find(space) != string::npos) { const size_t& spaceLocation = buffer.find(space); char protein[50]; memset(protein, '\0', 50); buffer.copy(protein, spaceLocation - 1, 1); // skip initial '>' current->faID = protein; } else current->faID ="unknown"; } else if (current) { // update current record with next line of the sequence if(buffer.find("*") != string::npos){ const size_t& stringLocation = buffer.find("*"); buffer.erase(stringLocation); } current->sequence += buffer; } } } PWIZ_API_DECL IPIFASTADatabase::IPIFASTADatabase(const string& filename) : impl_(new Impl(filename)) {} PWIZ_API_DECL IPIFASTADatabase::~IPIFASTADatabase(){} // auto-destruction of impl_ PWIZ_API_DECL const vector& IPIFASTADatabase::records() const {return impl_->records();} PWIZ_API_DECL ostream& operator<<(ostream& os, const IPIFASTADatabase::Record& record) { os << ">IPI:IPI" << setfill('0') << setw(8) << record.id << endl; for (unsigned int i=0; i // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "PeptideDatabase.hpp" #include "proteome/Peptide.hpp" #include "proteome/Ion.hpp" #include "proteome/Chemistry.hpp" #include "peptideSieve/fasta.h" // interface to fasta file handling using bioinfo::fasta; #include "peptideSieve/digest.hpp"// interface for doing trivial tryptic digests #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::proteome; void header(const vector& args) { if (args.size() != 1) throw runtime_error("[header] Wrong number of arguments."); const string& filename = args[0]; auto_ptr pdb = PeptideDatabase::create(filename); cout << "PeptideDatabase " << filename << endl; cout << pdb->size() << " records.\n"; } bool parseRange(const string& range, double& low, double& high) { string::size_type dash = range.find('-'); if (dash == string::npos) return false; if (dash > 0) low = atof(range.substr(0,dash).c_str()); if (dash < range.size()-1) high = atof(range.substr(dash+1).c_str()); return true; } void cat(const vector& args) { if (args.size() < 1) throw runtime_error("[cat] Wrong number of arguments."); const string& filename = args[0]; double massLow = 0; double massHigh = numeric_limits::max(); enum Format {Default, MassSequence, WeightMassSequence}; Format format = Default; for (unsigned int i=1; i pdb = PeptideDatabase::create(filename); PeptideDatabase::iterator begin = pdb->mass_lower_bound(massLow); PeptideDatabase::iterator end = pdb->mass_upper_bound(massHigh); cout.precision(10); switch (format) { case MassSequence: for (PeptideDatabase::iterator it=begin; it!=end; ++it) cout << it->mass << " " << pdb->sequence(*it) << endl; break; case WeightMassSequence: for (PeptideDatabase::iterator it=begin; it!=end; ++it) cout << setw(7) << it->abundance << " " << it->mass << " " << pdb->sequence(*it) << endl; break; case Default: default: for (PeptideDatabase::iterator it=begin; it!=end; ++it) cout << *it << " " << pdb->sequence(*it) << endl; break; } } void hist(const vector& args) { if (args.size() != 4) throw runtime_error("[hist] Wrong number of arguments."); const string& filename = args[0]; double massLow = atof(args[1].c_str()); double massHigh = atof(args[2].c_str()); double binSize = atof(args[3].c_str()); cout.precision(10); auto_ptr pdb = PeptideDatabase::create(filename); int binCount = int((massHigh-massLow)/binSize)+1; cerr << "binCount: " << binCount << endl; vector bins(binCount); PeptideDatabase::iterator begin = pdb->mass_lower_bound(massLow); PeptideDatabase::iterator end = pdb->mass_upper_bound(massHigh); for (PeptideDatabase::iterator it=begin; it!=end; ++it) { int bin = int((it->mass - massLow)/binSize); bins[bin] += it->abundance; } for (int i=0; i& args) { if (args.size() != 2) throw runtime_error("[convert_2] Wrong number of arguments."); const string& in = args[0]; const string& out = args[1]; ifstream is(in.c_str()); if (!is) throw runtime_error("[convert_2] Unable to open input file " + in); auto_ptr pdb = PeptideDatabase::create(); while (is) { PeptideDatabaseRecord record; string sequence; is >> record.mass >> sequence; if (!is) break; pdb->append(record, sequence); } pdb->write(out); } void convert_3(const vector& args) { if (args.size() != 2) throw runtime_error("[convert_3] Wrong number of arguments."); const string& in = args[0]; const string& out = args[1]; ifstream is(in.c_str()); if (!is) throw runtime_error("[convert_3] Unable to open input file " + in); auto_ptr pdb = PeptideDatabase::create(); while (is) { PeptideDatabaseRecord record; string sequence; is >> record.abundance >> record.mass >> sequence; if (!is) break; pdb->append(record, sequence); } pdb->write(out); } void convert_ipi(const vector& args) { cout << "convert_ipi not implemented yet.\n"; } inline int cmp_record_by_mass (const PeptideDatabaseRecord & a, const PeptideDatabaseRecord & b) { return (a.mass < b.mass); } void convert_fasta(const vector& args) { if (args.size() != 2) throw runtime_error("[convert_fasta] Wrong number of arguments."); const string& in = args[0]; const string& out = args[1]; auto_ptr pdb = PeptideDatabase::create(); fasta mf(in); vector pdb_tmp; vector sequences; int stringId = 0; for(fasta::const_iterator seqIter = mf.begin();seqIter != mf.end();seqIter++){ const fasta_seq* fseq = *seqIter; const string& str = fseq->get_seq(); // std::cout<append(record, peptide); peptides.next(); } } sort(pdb_tmp.begin(),pdb_tmp.end(),cmp_record_by_mass); for(vector::iterator i=pdb_tmp.begin();i!=pdb_tmp.end();i++){ string seq = sequences[i->sequenceKey]; i->sequenceKey = 0; pdb->append(*i, seq); } pdb->write(out); } void test(const vector& args) { auto_ptr pdb = PeptideDatabase::create(); for (int i=0; i<20; i++) { PeptideDatabaseRecord record; record.abundance = record.mass = i; record.formula = PeptideDatabaseFormula(i, i, i, i, i); pdb->append(record, "test"); } pdb->write("test.pdb"); } typedef void (*command_type)(const vector& args); struct CommandInfo { const char* name; command_type function; const char* usage; }; CommandInfo commandInfo_[] = { // register commands here {"header", header, "header filename.pdb (output header info)"}, {"cat", cat, "cat filename.pdb [2col|3col] [[low]-[high]] (output records)"}, {"hist", hist, "hist filename.pdb mzLow mzHigh binSize (output histogram)"}, {"convert_2", convert_2, "convert_2 filename.txt filename.pdb (convert mass-sequence text database)"}, {"convert_3", convert_3, "convert_3 filename.txt filename.pdb (convert weight-mass-sequence text database)"}, {"convert_ipi", convert_ipi, "convert_ipi filename.fasta filename.pdb (convert ipi fasta database)"}, {"convert_fasta", convert_fasta, "convert_fasta filename.fasta filename.pdb (convert fasta database)"}, {"test", test, "test (creates test database test.pdb)"}, }; int commandCount_ = sizeof(commandInfo_)/sizeof(CommandInfo); map commandTable_; void execute(const string& command, const vector& args) { command_type f = commandTable_[command]; if (!f) throw runtime_error("Invalid command: " + command); f(args); } void registerCommand(const CommandInfo& info) { commandTable_[info.name] = info.function; } void initializeCommandTable() { for_each(commandInfo_, commandInfo_+commandCount_, registerCommand); } int main(int argc, char* argv[]) { if (argc < 2) { cout << "Usage: pepdb command [args]" << endl; cout << "Commands:\n"; for (int i=0; i args; copy(argv+2, argv+argc, back_inserter(args)); initializeCommandTable(); try { execute(command, args); return 0; } catch (exception& e) { cerr << e.what() << endl; return 1; } } pwiz/pwiz/utility/proteome/IPIFASTADatabaseTest.cpp0000664000175100017510000000730612664775616024304 0ustar teamcityteamcity00000000000000// // $Id: IPIFASTADatabaseTest.cpp 4129 2012-11-20 00:05:37Z chambm $ // // // Original author: Darren Kessner // // Copyright 2006 Louis Warschaw Prostate Cancer Center // Cedars Sinai Medical Center, Los Angeles, California 90048 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "IPIFASTADatabase.hpp" #include "pwiz/utility/misc/unit.hpp" #include #include "pwiz/utility/misc/Std.hpp" #include using namespace pwiz::util; using namespace pwiz::proteome; ostream* os_ = 0; void writeTestEntries(ostream& os) { os << ">IPI:IPI00000001.2|SWISS-PROT:O95793-1|..." << endl; os << "MSQVQVQVQNPSAALSGSQILNKNQSLLSQPLMSIPSTTSSLPSENAGRPIQNSALPSAS" << endl; os << "ITSTSAAAESITPTVELNALCMKLGKKPMYKPVDPYSRMQSTYNYNMRGGAYPPRYFYPF" << endl; os << "PVPPLLYQVELSVGGQQFNGKGKTRQAAKHDAAAKALRILQNEPLPERLEVNGRESEEEN" << endl; os << "LNKSEISQVFEIALKRNLPVNFEVARESGPPHMKNFVTKVSVGEFVGEGEGKSKKISKKN" << endl; os << "AAIAVLEELKKLPPLPAVERVKPRIKKKTKPIVKPQTSPEYGQGINPISRLAQIQQAKKE" << endl; os << "KEPEYTLLTERGLPRRREFVMQVKVGNHTAEGTGTNKKVAKRNAAENMLEILGFKVPQAQ" << endl; os << "PTKPALKSEEKTPIKKPGDGRKVTFFEPGSGDENGTSNKEDEFRMPYLSHQQLPAGILPM" << endl; os << "VPEVAQAVGVSQGHHTKDFTRAAPNPAKATVTAMIARELLYGGTSPTAETILKNNISSGH" << endl; os << "VPHGPLTRPSEQLDYLSRVQGFQVEYKDFPKNNKNEFVSLINCSSQPPLISHGIGKDVES" << endl; os << "CHDMAALNILKLLSELDQQSTEMPRTGNGPMSVCGRC" << endl; os << ">IPI:IPI00000005.1|SWISS-PROT:P01111|..." << endl; os << "MTEYKLVVVGAGGVGKSALTIQLIQNHFVDEYDPTIEDSYRKQVVIDGETCLLDILDTAG" << endl; os << "QEEYSAMRDQYMRTGEGFLCVFAINNSKSFADINLYREQIKRVKDSDDVPMVLVGNKCDL" << endl; os << "PTRTVDTKQAHELAKSYGIPFIETSAKTRQGVEDAFYTLVREIRQYRMKKLNSSDDGTQG" << endl; os << "CMGLPCVVM" << endl; } void test() { string filename = "IPIFASTADatabaseTest.test.txt"; ofstream os(filename.c_str()); writeTestEntries(os); os.close(); IPIFASTADatabase db(filename); unit_assert(db.records().size() == 2); IPIFASTADatabase::const_iterator it = db.records().begin(); unit_assert(it->id == 1); unit_assert(it->faID == "IPI:IPI00000001.2"); unit_assert(it->sequence.size() == 577); unit_assert(it->sequence.find("PVPPLL") == 120); if (os_) *os_ << *it << endl; ++it; unit_assert(it->id == 5); unit_assert(it->faID == "IPI:IPI00000005.1"); unit_assert(it->sequence.size() == 189); unit_assert(it->sequence.find("PTRTVD") == 120); if (os_) *os_ << *it << endl; boost::filesystem::remove(filename); } void testRealDatabase() { IPIFASTADatabase db("ipi.HUMAN.fasta"); cout << "record count: " << db.records().size() << endl; if (!db.records().empty()) { const IPIFASTADatabase::Record* record = &db.records().back(); cout << *record << endl; } } int main(int argc, char* argv[]) { TEST_PROLOG(argc, argv) try { if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout; if (os_) *os_ << "IPIFASTADatabaseTest\n"; test(); //testRealDatabase(); } catch (exception& e) { TEST_FAILED(e.what()) } catch (...) { TEST_FAILED("Caught unknown exception.") } TEST_EPILOG } pwiz/libraries/libsvm-3.0/svm-model2code.cpp0000664000175100017510000001320312664775725022651 0ustar teamcityteamcity00000000000000// // $Id: svm-model2code.cpp 2382 2010-11-22 23:01:20Z chambm $ // // // Original author: Matt Chambers vanderbilt.edu> // // Copyright 2010 Vanderbilt University - Nashville, TN 37232 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "svm.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using boost::format; using boost::lexical_cast; namespace bio = boost::iostreams; namespace boost { namespace serialization { template void serialize(Archive& a, svm_parameter& param, const unsigned int version) { a & param.svm_type & param.kernel_type & param.degree & param.gamma & param.coef0; } template void serialize(Archive& a, svm_node& node, const unsigned int version) { a & node.index & node.value; } template void load(Archive& a, svm_model& model, const unsigned int version) { a & model.param & model.nr_class & model.l; model.SV = (svm_node**) malloc(model.l * sizeof(svm_node*)); for (int i=0; i < model.l; ++i) { vector nodes; for (int j=0;;++j) { nodes.push_back(svm_node()); a & nodes.back(); if (nodes.back().index == -1) break; } model.SV[i] = (svm_node*) malloc(nodes.size() * sizeof(svm_node)); copy(nodes.begin(), nodes.end(), model.SV[i]); } model.sv_coef = (double**) malloc((model.nr_class-1) * sizeof(double*)); for (int i=0; i < model.nr_class-1; ++i) { model.sv_coef[i] = (double*) malloc(model.l * sizeof(double)); for (int j=0; j < model.l; ++j) a & model.sv_coef[i][j]; } int numRho = model.nr_class*(model.nr_class-1)/2; model.rho = (double*) malloc(numRho * sizeof(double)); model.probA = (double*) malloc(numRho * sizeof(double)); model.probB = (double*) malloc(numRho * sizeof(double)); for (int i=0; i < numRho; ++i) a & model.rho[i] & model.probA[i] & model.probB[i]; model.label = (int*) malloc(model.nr_class * sizeof(int)); model.nSV = (int*) malloc(model.nr_class * sizeof(int)); for (int i=0; i < model.nr_class; ++i) a & model.label[i] & model.nSV[i]; a & model.free_sv; } template void save(Archive& a, const svm_model& model, const unsigned int version) { a & model.param & model.nr_class & model.l; for (int i=0; i < model.l; ++i) for (int j=0;;++j) { a & model.SV[i][j]; if (model.SV[i][j].index == -1) break; } for (int i=0; i < model.nr_class-1; ++i) for (int j=0; j < model.l; ++j) a & model.sv_coef[i][j]; for (int i=0, end=model.nr_class*(model.nr_class-1)/2; i < end; ++i) a & model.rho[i] & model.probA[i] & model.probB[i]; for (int i=0; i < model.nr_class; ++i) a & model.label[i] & model.nSV[i]; a & model.free_sv; } }} BOOST_SERIALIZATION_SPLIT_FREE(svm_model) int main(int argc, char* argv[]) { if (argc != 2) { cerr << "Usage: svm-model2code " << endl; return 1; } boost::filesystem::path filepath(argv[1]); // load the model from disk svm_model* model = svm_load_model(filepath.string().c_str()); // serialize the model stringstream decoded; boost::archive::text_oarchive a(decoded); a & *model; svm_free_and_destroy_model(&model); // compress and base64 encode the serialized model stringstream encoded; bio::copy(decoded, bio::compose(bio::zlib_compressor(bio::zlib_params::zlib_params(bio::zlib::best_compression)), bio::compose(bio::base64_encoder(), encoded))); string encodedString = encoded.str(); // write a dummy header file for the model, limit each line to 4000 characters ofstream code((filepath.string() + ".hpp").c_str()); code << "const std::string model =\nstd::string(\""; copy(encodedString.begin(), min(encodedString.end(), encodedString.begin()+4000), ostream_iterator(code)); code << "\") +\n"; for (size_t i=4000; i < encodedString.length(); i += 4090) { code << "\""; copy(encodedString.begin()+i, min(encodedString.end(), encodedString.begin()+i+4090), ostream_iterator(code)); code << "\"" << (encodedString.end() > encodedString.begin()+i+4090 ? " +\n" : ";\n"); } return 0; }pwiz/libraries/libsvm-3.0/COPYRIGHT0000664000175100017510000000273112664775725020624 0ustar teamcityteamcity00000000000000 Copyright (c) 2000-2010 Chih-Chung Chang and Chih-Jen Lin All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. Neither name of copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 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 THE REGENTS OR CONTRIBUTORS 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. pwiz/libraries/libsvm-3.0/README0000664000175100017510000006364112664775725020220 0ustar teamcityteamcity00000000000000Libsvm is a simple, easy-to-use, and efficient software for SVM classification and regression. It solves C-SVM classification, nu-SVM classification, one-class-SVM, epsilon-SVM regression, and nu-SVM regression. It also provides an automatic model selection tool for C-SVM classification. This document explains the use of libsvm. Libsvm is available at http://www.csie.ntu.edu.tw/~cjlin/libsvm Please read the COPYRIGHT file before using libsvm. Table of Contents ================= - Quick Start - Installation and Data Format - `svm-train' Usage - `svm-predict' Usage - `svm-scale' Usage - Tips on Practical Use - Examples - Precomputed Kernels - Library Usage - Java Version - Building Windows Binaries - Additional Tools: Sub-sampling, Parameter Selection, Format checking, etc. - Python Interface - Additional Information Quick Start =========== If you are new to SVM and if the data is not large, please go to `tools' directory and use easy.py after installation. It does everything automatic -- from data scaling to parameter selection. Usage: easy.py training_file [testing_file] More information about parameter selection can be found in `tools/README.' Installation and Data Format ============================ On Unix systems, type `make' to build the `svm-train' and `svm-predict' programs. Run them without arguments to show the usages of them. On other systems, consult `Makefile' to build them (e.g., see 'Building Windows binaries' in this file) or use the pre-built binaries (Windows binaries are in the directory `windows'). The format of training and testing data file is: