1 //
2 // metrosichel.cpp
3 // Mothur
4 //
5 // Created by Sarah Westcott on 5/3/19.
6 // Copyright © 2019 Schloss Lab. All rights reserved.
7 //
8
9 #include "metrosichel.hpp"
10
11 /***********************************************************************/
MetroSichel(int af,double siga,double sigb,double sigg,double sigS,int n,string st)12 MetroSichel::MetroSichel(int af, double siga, double sigb, double sigg, double sigS, int n, string st) : sigmaA(siga), sigmaB(sigb), sigmaG(sigg), sigmaS(sigS), nIters(n), outFileStub(st), fitIters(af), DiversityCalculator(false) {}
13 /***********************************************************************/
14
15
16
17 #ifdef USE_GSL
18 /***********************************************************************/
nLogLikelihood3(const gsl_vector * x,void * params)19 double nLogLikelihood3(const gsl_vector * x, void * params)
20 {
21 double dAlpha = gsl_vector_get(x,0), dBeta = gsl_vector_get(x,1);
22 double dGamma = gsl_vector_get(x,2);
23 int nS = (int) floor(gsl_vector_get(x, 3));
24 t_Data *ptData = (t_Data *) params;
25 int i = 0;
26 double dLogL = 0.0;
27 double dLog0 = 0.0, dLog1 = 0.0, dLog2 = 0.0, dLog3 = 0.0;
28
29 if(dAlpha <= 0.0 || dBeta <= 0.0){
30 return PENALTY;
31 }
32
33 DiversityUtils dutils("metrosichel");
34
35 for(i = 0; i < ptData->nNA; i++){
36
37 if (dutils.m->getControl_pressed()) { break; }
38
39 double dLogP = 0.0;
40 int nA = ptData->aanAbund[i][0];
41
42 dLogP = dutils.logLikelihood(nA, dAlpha, dBeta, dGamma);
43
44 dLogL += ((double) ptData->aanAbund[i][1])*dLogP;
45
46 dLogL -= gsl_sf_lnfact(ptData->aanAbund[i][1]);
47
48 }
49
50 dLog0 = dutils.logLikelihood(0, dAlpha, dBeta, dGamma);
51
52 dLog1 = (nS - ptData->nL)*dLog0;
53
54 dLog2 = - gsl_sf_lnfact(nS - ptData->nL);
55
56 dLog3 = gsl_sf_lnfact(nS);
57
58 dLogL += dLog1 + dLog2 + dLog3;
59
60 /*return*/
61 return -dLogL;
62 }
63 /***********************************************************************/
negLogLikelihood3(double dAlpha,double dBeta,double dGamma,int nS,void * params)64 double negLogLikelihood3(double dAlpha, double dBeta, double dGamma, int nS, void * params)
65 {
66 t_Data *ptData = (t_Data *) params;
67 int i = 0;
68 double dLogL = 0.0;
69 double dLog0 = 0.0, dLog1 = 0.0, dLog2 = 0.0, dLog3 = 0.0;
70
71 if(dAlpha <= 0.0 || dBeta <= 0.0){
72 return PENALTY;
73 }
74
75 DiversityUtils dutils("metrosichel");
76
77 for(i = 0; i < ptData->nNA; i++){
78
79 if (dutils.m->getControl_pressed()) { break; }
80
81 double dLogP = 0.0;
82 int nA = ptData->aanAbund[i][0];
83
84 dLogP = dutils.logLikelihood(nA, dAlpha, dBeta, dGamma);
85
86 dLogL += ((double) ptData->aanAbund[i][1])*dLogP;
87
88 dLogL -= gsl_sf_lnfact(ptData->aanAbund[i][1]);
89
90 }
91
92 dLog0 = dutils.logLikelihood(0, dAlpha, dBeta, dGamma);
93
94 dLog1 = (nS - ptData->nL)*dLog0;
95
96 dLog2 = - gsl_sf_lnfact(nS - ptData->nL);
97
98 dLog3 = gsl_sf_lnfact(nS);
99
100 dLogL += dLog1 + dLog2 + dLog3;
101
102 /*return*/
103 return -dLogL;
104 }
105 /***********************************************************************/
metropolis3(void * pvInitMetro)106 void* metropolis3 (void * pvInitMetro)
107 {
108 t_MetroInit *ptMetroInit = (t_MetroInit *) pvInitMetro;
109 gsl_vector *ptX = ptMetroInit->ptX;
110 t_Data *ptData = ptMetroInit->ptData;
111 t_Params *ptParams = ptMetroInit->ptParams;
112 gsl_vector *ptXDash = gsl_vector_alloc(4); /*proposal*/
113 char *szSampleFile = (char *) malloc(1024*sizeof(char));
114 const gsl_rng_type *T;
115 gsl_rng *ptGSLRNG;
116 int nS = 0, nSDash = 0, nIter = 0;
117 double dRand = 0.0, dNLL = 0.0;
118 void *pvRet = NULL;
119
120 /*set up random number generator*/
121 T = gsl_rng_default;
122 ptGSLRNG = gsl_rng_alloc (T);
123
124 nS = (int) floor(gsl_vector_get(ptX,3));
125
126 dNLL = negLogLikelihood3(gsl_vector_get(ptX,0), gsl_vector_get(ptX,1), gsl_vector_get(ptX,2), nS,(void*) ptData);
127
128 string filename = ptParams->szOutFileStub + "_" + toString(ptMetroInit->nThread) + ".sample";
129
130 ofstream out; Utils util; util.openOutputFile(filename, out);
131 out.setf(ios::fixed, ios::floatfield); out.setf(ios::showpoint);
132
133 /*seed random number generator*/
134 gsl_rng_set(ptGSLRNG, ptMetroInit->lSeed);
135
136 DiversityUtils dutils("metrosichel");
137
138 /*now perform simple Metropolis algorithm*/
139 while(nIter < ptParams->nIter){
140 double dA = 0.0, dNLLDash = 0.0;
141
142 if (dutils.m->getControl_pressed()) { break; }
143
144 dutils.getProposal(ptGSLRNG, ptXDash, ptX, &nSDash, nS, ptParams);
145
146 dNLLDash = negLogLikelihood3(gsl_vector_get(ptXDash,0), gsl_vector_get(ptXDash,1), gsl_vector_get(ptXDash,2), nSDash, (void*) ptData);
147
148 dA = exp(dNLL - dNLLDash);
149 if(dA > 1.0){
150 dA = 1.0;
151 }
152
153 dRand = gsl_rng_uniform(ptGSLRNG);
154
155 if(dRand < dA){
156 gsl_vector_memcpy(ptX, ptXDash);
157 nS = nSDash;
158 dNLL = dNLLDash;
159 ptMetroInit->nAccepted++;
160 }
161
162 if(nIter % 10 == 0){
163 out << nIter << "," << gsl_vector_get(ptX, 0) << "," << gsl_vector_get(ptX, 1) << "," << gsl_vector_get(ptX, 2) << "," << nS << "," << dNLL << endl;
164 }
165
166 nIter++;
167 }
168
169 out.close();
170
171 /*free up allocated memory*/
172 gsl_vector_free(ptXDash);
173 free(szSampleFile);
174 gsl_rng_free(ptGSLRNG);
175
176 return pvRet;
177 }
178 #endif
179 /***********************************************************************/
getValues(SAbundVector * rank)180 vector<string> MetroSichel::getValues(SAbundVector* rank){
181 try {
182
183 t_Params tParams; tParams.nIter = nIters; tParams.dSigmaX = sigmaA; tParams.dSigmaY = sigmaB; tParams.dSigmaN = sigmaG; tParams.dSigmaS = sigmaS; tParams.szOutFileStub = outFileStub; tParams.lSeed = m->getRandomSeed();
184 t_Data tData;
185
186 int bestSample = 0;
187
188 #ifdef USE_GSL
189
190 DiversityUtils dutils("metrosichel");
191
192 dutils.loadAbundance(&tData, rank);
193
194 int sampled = rank->getNumSeqs(); //nj
195 int numOTUs = rank->getNumBins(); //nl
196
197 gsl_vector* ptX = gsl_vector_alloc(4); /*parameter estimates*/
198
199 gsl_rng_env_setup();
200 gsl_set_error_handler_off();
201
202 /*set initial estimates for parameters*/
203 gsl_vector_set(ptX, 0, 0.1); //INIT_A
204 gsl_vector_set(ptX, 1, 1.0); //INIT_B
205 gsl_vector_set(ptX, 2, -0.5); //INIT_G
206 gsl_vector_set(ptX, 3, numOTUs*2);
207
208 double chaoResult = dutils.chao(&tData);
209 m->mothurOut("\nMetroSichel - D = " + toString(numOTUs) + " L = " + toString(sampled) + " Chao = " + toString(chaoResult) + "\n");
210
211 dutils.minimiseSimplex(ptX, 4, (void*) &tData, &nLogLikelihood3, 0.1, 1.0e-5, 100000);
212 vector<double> parameterResults = dutils.outputResults(ptX, &tData, &nLogLikelihood3);
213
214
215 if(tParams.nIter > 0){
216
217 vector<double> acceptanceRates = dutils.mcmc(&tParams, &tData, ptX, &metropolis3);
218
219 if (fitIters != 0) { bestSample = dutils.fitSigma(acceptanceRates, parameterResults, fitIters, &tParams, &tData, ptX, &metropolis3); }
220 }
221
222
223 /*free up allocated memory*/
224 gsl_vector_free(ptX);
225
226 dutils.freeAbundance(&tData);
227
228 #endif
229
230 outputs.push_back(outFileStub + "_" + toString(bestSample) + ".sample");
231 if (bestSample == 0) { outputs.push_back(outFileStub + "_1.sample"); outputs.push_back(outFileStub + "_2.sample"); }
232 else if (bestSample == 1) { outputs.push_back(outFileStub + "_0.sample"); outputs.push_back(outFileStub + "_2.sample"); }
233 else if (bestSample == 2) { outputs.push_back(outFileStub + "_0.sample"); outputs.push_back(outFileStub + "_1.sample"); }
234
235 return outputs;
236 }
237 catch(exception& e) {
238 m->errorOut(e, "MetroSichel", "getValues");
239 exit(1);
240 }
241 }
242 /***********************************************************************/
243