SHORE API
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
mtc.hpp
Go to the documentation of this file.
1 
2 /*
3  * Copyright 2008,2009,2010,2011,2012 Stephan Ossowski, Korbinian Schneeberger,
4  * Felix Ott, Joerg Hagmann, Alf Scotland, Sebastian Bender
5  *
6  * This file is part of SHORE.
7  *
8  * SHORE is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * SHORE is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with SHORE. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
26 
27 #ifndef SHORE_STATISTICS_MTC_HPP__
28 #define SHORE_STATISTICS_MTC_HPP__
29 
30 #include <algorithm>
31 #include <cmath>
32 #include <iterator>
33 #include <vector>
34 
35 #include "shore/base/stringops.hpp"
36 
37 namespace shore {
38 
40 class mtc
41 {
42 
43  public:
44 
46  enum mtcmethod
47  {
48  FDR_BH=0,
49  FWER_BONFERRONI=1,
50  FWER_HOLM=2,
51  FWER_HOCHBERG=3,
52  FWER_SIDAK_SS=4,
53  FWER_SIDAK_SD=5,
54  FDR_BY=6
55  };
56 
57  private:
58 
60  std::vector<double> m_rawp;
62  std::vector<size_t> m_rawp_ord;
63 
64  template<class Iter>
65  void runBhCorrection(Iter res)
66  {
67  ensureOrdering();
68 
69  res[*m_rawp_ord.rbegin()]=m_rawp[*m_rawp_ord.rbegin()];
70  for(int i=m_rawp_ord.size()-2;i>=0;--i)
71  {
72  const size_t j=m_rawp_ord[i+1];
73  const size_t k=m_rawp_ord[i];
74 
75  const double c=static_cast<double>(m_rawp_ord.size())/(i+1);
76  const double d=std::min(c*m_rawp[k],1.0);
77 
78  res[k]=std::min(res[j],d);
79  }
80  }
81 
82  template<class Iter>
83  void runBonferroniCorrection(Iter res)
84  {
85  for(size_t i=0;i<m_rawp.size();++i)
86  {
87  res[i]=std::min(m_rawp[i]*m_rawp.size(),1.0);
88  }
89  }
90 
91  template<class Iter>
92  void runHolmCorrection(Iter res)
93  {
94  ensureOrdering();
95 
96  const size_t m=m_rawp_ord.size();
97  res[m_rawp_ord[0]]=std::min(m_rawp[m_rawp_ord[0]]*m,1.0);
98  for(size_t i=1;i<m;++i)
99  {
100  const double scaled=
101  std::min(m_rawp[m_rawp_ord[i]]*(m-i),1.0);
102 
103  res[m_rawp_ord[i]]=
104  std::max(scaled,res[m_rawp_ord[i-1]]);
105  }
106  }
107 
108  template<class Iter>
109  void runHochbergCorrection(Iter res)
110  {
111  ensureOrdering();
112 
113  const size_t m=m_rawp_ord.size();
114  res[*m_rawp_ord.rbegin()]=m_rawp[*m_rawp_ord.rbegin()];
115 
116  for(int i=m-2;i>=0;--i)
117  {
118  const double sc=std::min(m_rawp[m_rawp_ord[i]]*(m-i),1.0);
119  res[m_rawp_ord[i]]=
120  std::min(sc,res[m_rawp_ord[i+1]]);
121  }
122  }
123 
124  template<class Iter>
125  void runSidakSsCorrection(Iter res)
126  {
127  const int m=m_rawp.size();
128 
129  for(size_t i=0;i<m_rawp.size();++i)
130  {
131  res[i]=1.0-std::pow(1.0-m_rawp[i],m);
132  }
133  }
134 
135  template<class Iter>
136  void runSidakSdCorrection(Iter res)
137  {
138  ensureOrdering();
139 
140  const int m=m_rawp_ord.size();
141  res[m_rawp_ord[0]]=
142  1.0-std::pow(1.0-m_rawp[m_rawp_ord[0]],m);
143 
144  for(int i=1;i<m;++i)
145  {
146  res[m_rawp_ord[i]]=
147  std::max(res[m_rawp_ord[i-1]],
148  1.0-std::pow(1.0-m_rawp[m_rawp_ord[i]],m-i));
149  }
150  }
151 
152  template<class Iter>
153  void runByCorrection(Iter res)
154  {
155  ensureOrdering();
156 
157  const size_t m=m_rawp_ord.size();
158 
159  double a=1.5;
160  for(size_t i=3;i<=m;++i) a+=1.0/i;
161 
162  res[*m_rawp_ord.rbegin()]=
163  std::min(a*m_rawp[*m_rawp_ord.rbegin()],1.0);
164 
165  for(int i=m-2;i>=0;--i)
166  {
167  const double sc=std::min(m*a*m_rawp[m_rawp_ord[i]]/(i+1),1.0);
168  res[m_rawp_ord[i]]=
169  std::min(res[m_rawp_ord[i+1]],sc);
170  }
171  }
172 
175  void ensureOrdering();
176 
177  public:
178 
179  mtc();
180 
181  template<class Iter>
182  mtc(Iter rawp_start,Iter rawp_end)
183  {
184  std::copy(rawp_start,rawp_end,std::back_inserter(m_rawp));
185  }
186 
187  void addRawValue(const double val);
188 
189  template<class Iter>
190  void correctPvalues(const mtcmethod m,Iter result)
191  {
192  if(m_rawp.size()<=1)
193  {
194  if(!m_rawp.empty()) *result=m_rawp[0];
195  }
196  else switch(m)
197  {
198  case FDR_BH:
199  runBhCorrection(result);
200  break;
201 
202  case FWER_BONFERRONI:
203  runBonferroniCorrection(result);
204  break;
205 
206  case FWER_HOLM:
207  runHolmCorrection(result);
208  break;
209 
210  case FWER_HOCHBERG:
211  runHochbergCorrection(result);
212  break;
213 
214  case FWER_SIDAK_SS:
215  runSidakSsCorrection(result);
216  break;
217 
218  case FWER_SIDAK_SD:
219  runSidakSdCorrection(result);
220  break;
221 
222  case FDR_BY:
223  runByCorrection(result);
224  break;
225 
226  default:
227  throw "unhandled p-value correction method";
228  }
229  }
230 
231  size_t size() const;
232 };
233 
234 S_MAKE_ENUM_TRAITS(mtc::mtcmethod)
235 
236 } // namespace
237 
238 #endif // SHORE_STATISTICS_MTC_HPP__
239