/*
Copyright 2009-2012 Andreas Biegert, Christof Angermueller
This file is part of the CS-BLAST package.
The CS-BLAST package is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
The CS-BLAST package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#ifndef CS_PSEUDOCOUNTS_INL_H_
#define CS_PSEUDOCOUNTS_INL_H_
#include "pseudocounts.h"
namespace cs {
// Adds pseudocounts to sequence using admixture and returns normalized profile.
template
Profile Pseudocounts::AddTo(const Sequence& seq, Admix& admix) const {
Profile p(seq.length());
AddToSequence(seq, p);
if (target_neff_ >= 1.0) {
AdmixToTargetNeff(seq, p, admix);
} else {
AdmixTo(seq, p, admix);
}
for(size_t i = 0; i < seq.length(); ++i) p[i][Abc::kAny] = 0.0;
Normalize(p, 1.0);
return p;
}
// Adds pseudocounts to sequence using admixture and returns normalized profile.
template
Profile Pseudocounts::AddTo(const CountProfile& cp, Admix& admix) const {
Profile p(cp.counts.length());
AddToProfile(cp, p);
if (target_neff_ >= 1.0) {
AdmixToTargetNeff(cp, p, admix);
} else {
AdmixTo(cp, p, admix);
}
for(size_t i = 0; i < cp.counts.length(); ++i)
p[i][Abc::kAny] = 0.0;
Normalize(p, 1.0);
return p;
}
template
void Pseudocounts::AdmixTo(const Sequence& q, Profile& p, const Admix& admix) const {
double tau = admix(1.0);
double t = 1 - tau;
for (size_t i = 0; i < p.length(); ++i) {
for (size_t a = 0; a < Abc::kSize; ++a)
p[i][a] *= tau;
p[i][q[i]] += t;
}
}
template
void Pseudocounts::AdmixTo(const CountProfile& q, Profile& p, const Admix& admix) const {
for (size_t i = 0; i < p.length(); ++i) {
double tau = admix(q.neff[i]);
double t = 1 - tau;
for (size_t a = 0; a < Abc::kSize; ++a)
p[i][a] = tau * p[i][a] + t * q.counts[i][a] / q.neff[i];
}
}
// Adjusts the Neff in 'p' to 'neff' by admixing q and returns tau.
template
template
double Pseudocounts::AdmixToTargetNeff(const T& q, Profile& p, Admix& admix) const {
double l = kTargetNeffParamMin;
double r = kTargetNeffParamMax;
admix.SetTargetNeffParam(kTargetNeffParamInit);
Profile pp;
while (l < kTargetNeffParamMax - kTargetNeffEps && r > kTargetNeffParamMin + kTargetNeffEps) {
pp = p;
AdmixTo(q, pp, admix);
double ne = Neff(pp);
if (fabs(ne - target_neff_) <= target_neff_delta_) {
break;
} else {
if (ne < target_neff_) l = admix.GetTargetNeffParam();
else r = admix.GetTargetNeffParam();
}
admix.SetTargetNeffParam(0.5 * (l + r));
}
if (l > kTargetNeffParamMax - kTargetNeffEps) {
admix.SetTargetNeffParam(kTargetNeffParamMax);
AdmixTo(q, p, admix);
} else if (r < kTargetNeffParamMin + kTargetNeffEps) {
admix.SetTargetNeffParam(kTargetNeffParamMin);
AdmixTo(q, p, admix);
} else {
p = pp;
}
return admix.GetTargetNeffParam();
}
} // namespace cs
#endif // CS_PSEUDOCOUNTS_INL_H_