amsmercury/0000755000717200071640000000000010775367460013555 5ustar mkirchnerMultBildamsmercury/R/0000755000717200071640000000000010446067334013746 5ustar mkirchnerMultBildamsmercury/R/zzz.R0000644000717200071640000000046210446066613014727 0ustar mkirchnerMultBild.packageName <- "amsmercury"; .First.lib <- function(libname, pkgname) { #cat("ams.mercury - Copyright (c) 2006 Marc Kirchner\nBased on 'emass' (Haimi P and Rockwood AL, 2006)\n"); library.dynam("amsmercury", pkgname, libname); } .Last.lib <- function(libpath) { library.dynam.unload("amsmercury"); } amsmercury/R/ams.mercury.mercury.R0000644000717200071640000000046010446066613020022 0ustar mkirchnerMultBild"ams.mercury.mercury" <- function(composition, charge, limit) { # currently. we expect H-C-N-O-S stopifnot(length(composition)==5); tmp <- .Call("Rmercury", as.numeric(composition), as.integer(charge), as.numeric(limit), PACKAGE="amsmercury" ); return(cbind(tmp$mz, tmp$abundance)); } amsmercury/src/0000755000717200071640000000000010775371220014331 5ustar mkirchnerMultBildamsmercury/src/libmercury++.cpp0000644000717200071640000001026610446066614017350 0ustar mkirchnerMultBild#include "libmercury++.h" // declare private stuff namespace mercury { void convolve(std::vector& result_mz, std::vector& result_ab, const std::vector& mz1, const std::vector& ab1, const std::vector& mz2, const std::vector& ab2); void prune(std::vector& mz, std::vector& ab, const double limit); } void mercury::convolve(std::vector& result_mz, std::vector& result_ab, const std::vector& mz1, const std::vector& ab1, const std::vector& mz2, const std::vector& ab2) { size_t n1 = mz1.size(); size_t n2 = mz2.size(); if ((n1+n2) == 0) return; result_mz.clear(); result_ab.clear(); // the following two lines speed up calculations by a factor of 3 (!) result_mz.resize(n1+n2); result_ab.resize(n1+n2); // for each isotope peak in the compound... double totalAbundance, massExpectation, ithMass, ithAbundance; for (size_t k = 0; k < n1 + n2 - 1; k++) { totalAbundance = 0; massExpectation = 0; size_t start = k < (n2 - 1) ? 0 : k - n2 + 1; // start=max(0, k-n2+1) size_t end = k < (n1 - 1) ? k : n1 - 1; // end=min(n1 - 1, k) // ... calculate the mass expectation value and the abundance for (size_t i = start; i <= end; i++) { ithAbundance = ab1[i] * ab2[k - i]; if (ithAbundance > 0) { totalAbundance += ithAbundance; ithMass = mz1[i] + mz2[k - i]; massExpectation += ithAbundance * ithMass; } } // do NOT throw away isotopes with zero probability, this would // screw up the isotope count k !! result_mz[k] = totalAbundance > 0 ? massExpectation / totalAbundance : 0; result_ab[k] = totalAbundance; } } void mercury::prune(std::vector& mz, std::vector& ab, const double limit) { size_t i; for (i = 0; i < ab.size(); i++) { if(ab[i] > limit) break; } mz.erase(mz.begin(), mz.begin()+i); ab.erase(ab.begin(), ab.begin()+i); // prune the end for (i = ab.size()-1; i >= 0; i--) { if(ab[i] > limit) break; } mz.resize(i+1); ab.resize(i+1); //mz.erase(mz.begin()+i+1, mz.end()); //ab.erase(ab.begin()+i+1, ab.end()); } int mercury::mercury(std::vector& msa_mz, std::vector& msa_abundance, const std::vector& composition, const int charge, const double limit) { if (composition.size() != MAX_ELEMENTS) { return(-1); } unsigned int n; std::vector tmp_mz, tmp_abundance, esa_mz, esa_abundance ; bool msa_initialized = false; // walk through the elements for (unsigned int e = 0; e < MAX_ELEMENTS; e++) { // if the element is present in the composition, // then calculate ESA and update MSA // std::cout << "e=" << e << std::endl; n = composition[e]; if (n) { // initialize ESA esa_mz.assign(elemMasses[e], elemMasses[e]+nIsotopes[e]); esa_abundance.assign(elemAbundances[e], elemAbundances[e]+nIsotopes[e]); // esa_mz.resize(n*nIsotopes[e]); // esa_abundance.resize(n*nIsotopes[e]); //while (n > 0) { while (1) { // std::cout << "n=" << n << std::endl; // check if we need to do the MSA update if (n & 1) { // MSA update if (msa_initialized) { // normal update convolve(tmp_mz, tmp_abundance, msa_mz, msa_abundance, esa_mz, esa_abundance); msa_mz = tmp_mz; msa_abundance = tmp_abundance; } else { // for the first assignment MSA=ESA msa_mz = esa_mz; msa_abundance = esa_abundance; msa_initialized = true; } prune(msa_mz, msa_abundance, limit); } // the ESA update is always carried out (with the exception of // the last time, i.e. when n==1) if (n==1) { break; } convolve(tmp_mz, tmp_abundance, esa_mz, esa_abundance, esa_mz, esa_abundance); esa_mz = tmp_mz; esa_abundance = tmp_abundance; prune(esa_mz, esa_abundance, limit); n = n >> 1; } } } // take charge into account (placing the if around two loops is faster // than vice versa if (charge > 0) { for (std::vector::iterator i = msa_mz.begin(); i != msa_mz.end(); i++) { *i = *i / abs(charge) - electronMass; } } if (charge < 0) { for (std::vector::iterator i = msa_mz.begin(); i != msa_mz.end(); i++) { *i = *i / abs(charge) + electronMass; } } return(0); } amsmercury/src/amsmercury.cpp0000644000717200071640000000414310446066614017231 0ustar mkirchnerMultBild/* * amsmercury.cpp * $Id$ * * Copyright (c) 2006 * Marc Kirchner * * This code may be freely distributed under the terms of the * Lesser GNU Public License (LGPL) version 2 or any later version. * */ #include #include #include #include #include #include "libmercury++.h" extern "C" { SEXP Rmercury(SEXP composition, SEXP charge, SEXP limit); } SEXP Rmercury(SEXP composition, SEXP charge, SEXP limit) { int ncharge, nlimit, ncomposition; int *pcharge, *pcomposition; double *plimit; PROTECT(charge = AS_INTEGER(charge)); PROTECT(limit = AS_NUMERIC(limit)); ncharge = LENGTH(charge); nlimit = LENGTH(limit); if ((ncharge!=1) || (nlimit!=1)) { error("mercury: charge and limit must have length==1"); } PROTECT(composition = AS_INTEGER(composition)); ncomposition = LENGTH(composition); pcharge = INTEGER_POINTER(charge); plimit = NUMERIC_POINTER(limit); pcomposition = INTEGER_POINTER(composition); // build std::vector to call mercury::mercury() std::vector comp(ncomposition); for (int i = 0; i < ncomposition; i++) { comp[i] = pcomposition[i]; } // other: comp(pcomposition[0], pcomposition[0]+ncomposition); std::vector mz, ab; mercury::mercury(mz, ab, comp, pcharge[0], plimit[0]); // build R expression: a list with two vectors SEXP result, mzcol, abcol; PROTECT(result = NEW_LIST(2)); PROTECT(mzcol = NEW_NUMERIC(mz.size())); double* pmzcol = NUMERIC_POINTER(mzcol); // write mz values to vector and save to list for (unsigned int j=0; j * * Based on the emass implementation of Perttu Haimi * (see Copyright notice below). * * This code may be distributed under the terms of the * Lesser GNU Public License (LGPL) version 2 or any later version. */ /* * * Based on an algorithm developed by Alan L. Rockwood. * * Published in * Rockwood, A.L. and Haimi, P.: "Efficent calculation of * Accurate Masses of Isotopic Peaks", * Journal of The American Society for Mass Spectrometry * JASMS 03-2263, 2006 * * Copyright (c) 2005 Perttu Haimi and Alan L. Rockwood * * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the * above copyright notice, this list of conditions * and the following disclaimer. * * Redistributions in binary form must reproduce * the above copyright notice, this list of conditions * and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the author nor the names of any 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 COPYRIGHT OWNER 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. */ #include #include #include namespace mercury { const unsigned int MAX_ELEMENTS = 5; const unsigned int MAX_ISOTOPES = 5; const double electronMass = 0.00054858; const unsigned int nIsotopes[MAX_ELEMENTS] = { 2, 2, 2, 3, 5 }; const double elemMasses[MAX_ELEMENTS][MAX_ISOTOPES] = { {1.0078246, 2.0141021, 0, 0, 0}, // H {12.0000000, 13.0033554, 0, 0, 0}, // C {14.0030732, 15.0001088, 0, 0, 0}, // N {15.9949141, 16.9991322, 17.9991616, 0, 0}, // O {31.972070, 32.971456, 33.967866, 34, 35.967080} // S }; const double elemAbundances[MAX_ELEMENTS][MAX_ISOTOPES] = { {0.99985, 0.00015, 0, 0, 0}, // H {0.988930, 0.011070, 0, 0, 0}, // C {0.996337, 0.003663, 0, 0, 0}, // N {0.997590, 0.000374, 0.002036, 0, 0}, // O {0.9502, 0.0075, 0.0421, 0, 0.0002} // S }; /* mercury: calculates the expected isotpic distribution for a given composition parameters: msa_mz returned mass list msa_abundance returned abundance list composition a vector of length MAX_ELEMENTS giving the the number for occurences of each element charge the charge state for which the isotopic pattern is to be calculated limit a pruning limit, (Rockwood et al. 2006) suggest a value between 10e-25 and 10e-30 */ int mercury(std::vector& msa_mz, std::vector& msa_abundance, const std::vector& composition, const int charge, const double limit); } #endif amsmercury/man/0000755000717200071640000000000010446067334014320 5ustar mkirchnerMultBildamsmercury/man/ams.mercury.mercury.Rd0000644000717200071640000000215610446066614020545 0ustar mkirchnerMultBild\name{ams.mercury.mercury} \alias{ams.mercury.mercury} \title{ calculate accurate isotopic masses and abundances } \description{ \code{ams.mercury.mercury} uses the mercury7 algortihm for the quick and accurate calculation of isotopic masses and abundances } \usage{ ams.mercury.mercury(composition, charge, limit) } \arguments{ \item{composition}{ a vector of integers; needs to have \code{length==MAXLENGTH} of the libmercury++ library. This is a current shortcoming that is going to be resolvedin the near future. } \item{charge}{ a single integer giving the desired charge } \item{limit}{ a pruning limit, recommended values are between 1e-25 and 1e-30 } } \details{ See the C++ source } \value{ Returns a two-column matrix. The first columns holds the m/z values, the second the corrsponding abundances. } \references{ Rockwood AL, Haimi P, Efficient calculation of accurate masses of isotopic peaks, J Am Soc Mass Spectrom, 17, 415-419, (2006). } \author{ Marc Kirchner \email{marc.kirchner@iwr.uni-heidelberg.de} } \examples{ # CH4 x <- ams.mercury.mercury(c(4,4,0,0,0), 1, 0); } \keyword{ datagen } amsmercury/DESCRIPTION0000644000717200071640000000047610775371220015257 0ustar mkirchnerMultBildTitle: Mercury Maintainer: Marc Kirchner Priority: optional Version: 1.3.0 Author: Marc Kirchner SaveImage: Yes License: LGPL Package: amsmercury Description: Efficient calculation of accurate masses and abundances of isotopic peaks Packaged: Fri Apr 4 11:19:12 2008; mkirchner