/* t2z.cc Mark Woolrich & Mark Jenkinson, FMRIB Image Analysis Group Copyright (C) 1999-2000 University of Oxford */ /* CCOPYRIGHT */ #include #include "t2z.h" #include "newmat.h" #include "utils/tracer_plus.h" #include "libprob.h" using namespace NEWMAT; using namespace Utilities; namespace MISCMATHS { T2z* T2z::t2z = NULL; Z2t* Z2t::z2t = NULL; float Z2t::convert(float z, int dof) { float t = 0.0; if(z>8) throw Exception("z is too large to convert to t"); double p = MISCMATHS::ndtr(z); cerr << "p = " << p << endl; t = MISCMATHS::stdtri(dof,p); return t; } float T2z::larget2logp(float t, int dof) { // static float logbeta[] = { 1.144729885849, 0.693147180560, // 0.451582705289, 0.287682072452, // 0.163900632838, 0.064538521138, // -0.018420923956, -0.089612158690, // -0.151952316581, -0.207395194346 } ; //static const float pi = 3.141592653590; // static const float log2pi = log(2*pi); // Large T extrapolation routine for converting T to Z values // written by Mark Jenkinson, March 2000 // // It does T to Z via log(p) rather than p, since p becomes very // small and underflows the arithmetic // Equations were derived by using integration by parts and give the // following formulae: // (1) T to log(p) NB: n = DOF // log(p) = -1/2*log(n) - log(beta(n/2,1/2)) - (n-1)/2*log(1+t*t/n) // + log(1 - (n/(n+2))/(t*t) + 3*n*n/((n+2)*(n+4)*t*t*t*t)) // (2) Z to log(p) // log(p) = -1/2*z*z - 1/2*log(2*pi) - log(z) // + log(1 - 1/(z*z) + 3/(z*z*z*z)) // equation (2) is then solved by the recursion: // z_0 = sqrt(2*(-log(p) - 1/2*log(2*pi))) // z_{n+1} = sqrt(2*(-log(p) - 1/2*log(2*pi) - log(z_n) // + log(1 - 1/(zn*zn) + 3/(zn*zn*zn*zn)) // In practice this recursion is quite accurate in 3 to 5 iterations // Equation (1) is accurate to 1 part in 10^3 for T>7.5 (any n) // Equation (2) is accurate to 1 part in 10^3 for Z>3.12 (3 iterations) if (t<0) { return larget2logp(-t,dof); } float logp, lbeta; if (dof<=0) { cerr << "DOF cannot be zero or negative!" << endl; return 0.0; } float n = (float) dof; // complete Beta function lbeta = this->logbeta(1/2.0,n/2.0); //if (dof<=10) { //lbeta = logbeta[dof-1]; //} else { //lbeta = log2pi/2 - log(n)/2 + 1/(4*n); //} // log p from t value // logp = log( (1 - n/((n+2)*t*t) + 3*n*n/((n+2)*(n+4)*t*t*t*t))/(sqrt(n)*t)) // - ((n-1)/2)*log(1 + t*t/n) - lbeta; logp = log(( (3*n*n/((n+2)*(n+4)*t*t) - n/(n+2))/(t*t) + 1)/(sqrt(n)*t)) - ((n-1)/2)*log(1 + t*t/n) - lbeta; return logp; } bool T2z::islarget(float t, int dof, float &logp) { // aymptotic formalae are valid if // log(p) < -14.5 (derived from Z-statistic approximation error) // For dof>=15, can guarantee that log(p)>-33 (p > 1e-14) if T<7.5 // and so in this region use conventional means, not asymptotic if ((dof>=15) && (fabs(t)<7.5)) { return false; } logp=larget2logp(t,dof); if (dof>=15) return true; // force asymptotic calc for all T>=7.5, D>=15 return issmalllogp(logp); } bool T2z::issmalllogp(float logp) { // aymptotic formula accurate to 1 in 10^3 for Z>4.9 // which corresponds to log(p)=-14.5 return (logp < -14.5); } float T2z::convert(float t, int dof) { float z = 0.0, logp=0.0; if(!islarget(t,dof,logp)) { // cerr << "t = " << t << endl; double p = MISCMATHS::stdtr(dof, t); //cerr << "p = " << p << endl; z = MISCMATHS::ndtri(p); } else { z = logp2largez(logp); // cerr<