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

StatisticFunctions.h

Go to the documentation of this file.
00001 // --------------------------------------------------------------------------
00002 //                   OpenMS -- Open-Source Mass Spectrometry
00003 // --------------------------------------------------------------------------
00004 // Copyright The OpenMS Team -- Eberhard Karls University Tuebingen,
00005 // ETH Zurich, and Freie Universitaet Berlin 2002-2012.
00006 //
00007 // This software is released under a three-clause BSD license:
00008 //  * Redistributions of source code must retain the above copyright
00009 //    notice, this list of conditions and the following disclaimer.
00010 //  * Redistributions in binary form must reproduce the above copyright
00011 //    notice, this list of conditions and the following disclaimer in the
00012 //    documentation and/or other materials provided with the distribution.
00013 //  * Neither the name of any author or any participating institution
00014 //    may be used to endorse or promote products derived from this software
00015 //    without specific prior written permission.
00016 // For a full list of authors, refer to the file AUTHORS.
00017 // --------------------------------------------------------------------------
00018 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 // ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING
00022 // INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00023 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00024 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
00025 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00026 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00027 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00028 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 //
00030 // --------------------------------------------------------------------------
00031 // $Maintainer: Clemens Groepl $
00032 // $Authors: Clemens Groepl, Johannes Junker, Mathias Walzer$
00033 // --------------------------------------------------------------------------
00034 
00035 #include <numeric>
00036 #include <algorithm>
00037 #include <OpenMS/CONCEPT/Types.h>
00038 #include <boost/lambda/lambda.hpp>
00039 #include <boost/lambda/casts.hpp>
00040 #include <boost/function/function_base.hpp>
00041 
00042 #ifndef OPENMS_MATH_STATISTICS_STATISTICFUNCTIONS_H
00043 #define OPENMS_MATH_STATISTICS_STATISTICFUNCTIONS_H
00044 
00045 namespace OpenMS
00046 {
00047 
00048   namespace Math
00049   {
00055     template <typename IteratorType>
00056     static DoubleReal sum(IteratorType begin, IteratorType end)
00057     {
00058       return std::accumulate(begin, end, 0.0);
00059     }
00060 
00068     template <typename IteratorType>
00069     static DoubleReal mean(IteratorType begin, IteratorType end)
00070     {
00071       SignedSize size = std::distance(begin, end);
00072       if (size <= 0)
00073       {
00074         throw Exception::InvalidRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00075       }
00076       return sum(begin, end) / size;
00077     }
00078 
00090     template <typename IteratorType>
00091     static DoubleReal median(IteratorType begin, IteratorType end, bool sorted = FALSE)
00092     {
00093       Size size = std::distance(begin, end);
00094 
00095       if (size == 0)
00096       {
00097         throw Exception::InvalidRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00098       }
00099 
00100       if (!sorted)
00101       {
00102         std::sort(begin, end);
00103       }
00104 
00105       if (size % 2 == 0)        // even size => average two middle values
00106       {
00107         IteratorType it1 = begin;
00108         std::advance(it1, size / 2 - 1);
00109         IteratorType it2 = it1;
00110         std::advance(it2, 1);
00111         return (*it1 + *it2) / 2.0;
00112       }
00113       else
00114       {
00115         IteratorType it = begin;
00116         std::advance(it, (size - 1) / 2);
00117         return *it;
00118       }
00119     }
00120 
00132     template <typename IteratorType>
00133     static DoubleReal quantile(IteratorType begin, IteratorType end, UInt quantile, bool sorted = FALSE)
00134     {
00135       Size size = std::distance(begin, end);
00136 
00137       if (size == 0)
00138       {
00139         throw Exception::InvalidRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00140       }
00141       if (quantile > 100 || quantile < 1) //TODO is 0 quantile a valid request?
00142       {
00143         throw Exception::InvalidRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00144       }
00145 
00146       int l = floor( (double(quantile) * (double(size) / 100)) + 0.5); // will not be negative, so this is round nearest
00147 
00148       if (!sorted)
00149       {
00150         std::sort(begin, end);
00151       }
00152 
00153       IteratorType it = begin;
00154       std::advance(it, l - 1);
00155       return *it;
00156 
00157     }
00158 
00168     template <typename IteratorType1, typename IteratorType2>
00169     static DoubleReal meanSquareError(IteratorType1 begin_a, IteratorType1 end_a, IteratorType2 begin_b, IteratorType2 end_b)
00170     {
00171       //no data or different lengths
00172       SignedSize dist = std::distance(begin_a, end_a);
00173       if (dist == 0 || dist != std::distance(begin_b, end_b))
00174       {
00175         throw Exception::InvalidRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00176       }
00177 
00178       DoubleReal error = 0;
00179       while (begin_a != end_a)
00180       {
00181         DoubleReal tmp(*begin_a - *begin_b);
00182         error += tmp * tmp;
00183         ++begin_a;
00184         ++begin_b;
00185       }
00186 
00187       return error / dist;
00188     }
00189 
00199     template <typename IteratorType1, typename IteratorType2>
00200     static DoubleReal classificationRate(IteratorType1 begin_a, IteratorType1 end_a, IteratorType2 begin_b, IteratorType2 end_b)
00201     {
00202       //no data or different lengths
00203       SignedSize dist = std::distance(begin_a, end_a);
00204       if (dist == 0 || dist != std::distance(begin_b, end_b))
00205       {
00206         throw Exception::InvalidRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00207       }
00208 
00209       DoubleReal correct = (DoubleReal) dist;
00210       while (begin_a != end_a)
00211       {
00212         if ((*begin_a < 0 && *begin_b >= 0) || (*begin_a >= 0 && *begin_b < 0))
00213         {
00214           --correct;
00215         }
00216         ++begin_a;
00217         ++begin_b;
00218       }
00219 
00220       return correct / dist;
00221     }
00222 
00232     template <typename IteratorType1, typename IteratorType2>
00233     static DoubleReal matthewsCorrelationCoefficient(IteratorType1 begin_a, IteratorType1 end_a, IteratorType2 begin_b, IteratorType2 end_b)
00234     {
00235       //no data or different lengths
00236       Int dist = std::distance(begin_a, end_a);
00237       if (dist == 0 || dist != std::distance(begin_b, end_b))
00238       {
00239         throw Exception::InvalidRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00240       }
00241 
00242       DoubleReal tp = 0;
00243       DoubleReal fp = 0;
00244       DoubleReal tn = 0;
00245       DoubleReal fn = 0;
00246 
00247       while (begin_a != end_a)
00248       {
00249         if (*begin_a < 0 && *begin_b >= 0)
00250         {
00251           ++fn;
00252         }
00253         else if (*begin_a < 0 && *begin_b < 0)
00254         {
00255           ++tn;
00256         }
00257         else if (*begin_a >= 0 && *begin_b >= 0)
00258         {
00259           ++tp;
00260         }
00261         else if (*begin_a >= 0 && *begin_b < 0)
00262         {
00263           ++fp;
00264         }
00265 
00266         ++begin_a;
00267         ++begin_b;
00268       }
00269 
00270       return (tp * tn - fp * fn) / sqrt((tp + fp) * (tp + fn) * (tn + fp) * (tn + fn));
00271     }
00272 
00284     template <typename IteratorType1, typename IteratorType2>
00285     static DoubleReal pearsonCorrelationCoefficient(IteratorType1 begin_a, IteratorType1 end_a, IteratorType2 begin_b, IteratorType2 end_b)
00286     {
00287       //no data or different lengths
00288       SignedSize dist = std::distance(begin_a, end_a);
00289       if (dist == 0 || dist != std::distance(begin_b, end_b))
00290       {
00291         throw Exception::InvalidRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00292       }
00293 
00294       //calculate average
00295       DoubleReal avg_a = std::accumulate(begin_a, end_a, 0.0) / dist;
00296       DoubleReal avg_b = std::accumulate(begin_b, end_b, 0.0) / dist;
00297 
00298       DoubleReal numerator = 0;
00299       DoubleReal denominator_a = 0;
00300       DoubleReal denominator_b = 0;
00301       while (begin_a != end_a)
00302       {
00303         DoubleReal temp_a = *begin_a - avg_a;
00304         DoubleReal temp_b = *begin_b - avg_b;
00305         numerator += (temp_a * temp_b);
00306         denominator_a += (temp_a * temp_a);
00307         denominator_b += (temp_b * temp_b);
00308         ++begin_a;
00309         ++begin_b;
00310       }
00311 
00312       return numerator / sqrt(denominator_a * denominator_b);
00313     }
00314 
00316     template <typename Value>
00317     static void computeRank(std::vector<Value> & w)
00318     {
00319       using namespace boost::lambda;
00320       Size i = 0; // main index
00321       Size z  = 0;  // "secondary" index
00322       Value rank = 0;
00323       Size n = (w.size() - 1);
00324       //store original indices for later
00325       std::vector<std::pair<Size, Value> > w_idx;
00326       for (Size j = 0; j < w.size(); ++j)
00327       {
00328         w_idx.push_back(std::make_pair(j, w[j]));
00329       }
00330       //sort
00331       std::sort(w_idx.begin(), w_idx.end(),
00332                 ret<bool>((&_1->*& std::pair<Size, Value>::second) < (&_2->*& std::pair<Size, Value>::second)));
00333       //replace pairs <orig_index, value> in w_idx by pairs <orig_index, rank>
00334       while (i < n)
00335       {
00336         // test for equality with tolerance:
00337         if (fabs(w_idx[i + 1].second - w_idx[i].second) > 0.0000001 * fabs(w_idx[i + 1].second)) // no tie
00338         {
00339           w_idx[i].second = Value(i + 1);
00340           ++i;
00341         }
00342         else // tie, replace by mean rank
00343         {
00344           // count number of ties
00345           for (z = i + 1; (z <= n) && fabs(w_idx[z].second - w_idx[i].second) <= 0.0000001 * fabs(w_idx[z].second); ++z)
00346           {
00347           }
00348           // compute mean rank of tie
00349           rank = 0.5 * (i + z + 1);
00350           // replace intensities by rank
00351           for (Size v = i; v <= z - 1; ++v)
00352           {
00353             w_idx[v].second = rank;
00354           }
00355           i = z;
00356         }
00357       }
00358       if (i == n)
00359         w_idx[n].second = Value(n + 1);
00360       //restore original order and replace elements of w with their ranks
00361       for (Size j = 0; j < w.size(); ++j)
00362       {
00363         w[w_idx[j].first] = w_idx[j].second;
00364       }
00365     }
00366 
00378     template <typename IteratorType1, typename IteratorType2>
00379     static DoubleReal rankCorrelationCoefficient(IteratorType1 begin_a, IteratorType1 end_a, IteratorType2 begin_b, IteratorType2 end_b)
00380     {
00381       //no data or different lengths
00382       SignedSize dist = std::distance(begin_a, end_a);
00383       if (dist == 0 || dist != std::distance(begin_b, end_b))
00384       {
00385         throw Exception::InvalidRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00386       }
00387 
00388       // store and sort intensities of model and data
00389       std::vector<DoubleReal> ranks_data;
00390       ranks_data.reserve(dist);
00391       std::vector<DoubleReal> ranks_model;
00392       ranks_model.reserve(dist);
00393 
00394       while (begin_a != end_a)
00395       {
00396         ranks_model.push_back(*begin_a);
00397         ranks_data.push_back(*begin_b);
00398         ++begin_a;
00399         ++begin_b;
00400       }
00401 
00402       // replace entries by their ranks
00403       computeRank(ranks_data);
00404       computeRank(ranks_model);
00405 
00406       DoubleReal mu = DoubleReal(ranks_data.size() + 1) / 2.; // mean of ranks
00407       // Was the following, but I think the above is more correct ... (Clemens)
00408       // DoubleReal mu = (ranks_data.size() + 1) / 2;
00409 
00410       DoubleReal sum_model_data = 0;
00411       DoubleReal sqsum_data = 0;
00412       DoubleReal sqsum_model = 0;
00413 
00414       for (Int i = 0; i < dist; ++i)
00415       {
00416         sum_model_data += (ranks_data[i] - mu) * (ranks_model[i] - mu);
00417         sqsum_data += (ranks_data[i] - mu) * (ranks_data[i] - mu);
00418         sqsum_model += (ranks_model[i] - mu) * (ranks_model[i] - mu);
00419       }
00420 
00421       // check for division by zero
00422       if (!sqsum_data || !sqsum_model)
00423         return 0;
00424 
00425       return sum_model_data / (sqrt(sqsum_data) * sqrt(sqsum_model));
00426     }
00427 
00428   }   // namespace Math
00429 } // namespace OpenMS
00430 
00431 #endif // OPENMS_MATH_STATISTICS_STATISTICFUNCTIONS_H

OpenMS / TOPP release 1.10.0 Documentation generated on Thu Mar 7 2013 09:42:45 using doxygen 1.7.1