Dear fellow ROOTers, In performing some physics analysis I needed to compute the confidence level based on a chi-squared and number of statistical constraints (i.e. the functionality of the old cernlib routine prob). Since I couldn't find such a facility in the ROOT framework (in case there is already one, please let me know), I decided to dig into my old private fortran utilities. Below you find attached the function "conlev" which is a C++ translation of the old fortran code (the original code is also included as comment) which does the job (I tested the reproduction of the CL values as noted in the particle data book. Note : the result for 1 constraint is incorrect, but normally one doesn't encounter this situation). I know it won't win a prize in a contest for nice programming, but at least it works. Feel free to use, modifiy etc.... the code and in case the ROOT team wants to include it in the standard ROOT distribution, just go ahead with it. Curently the easiest way I found to have it always available within ROOT is to just include the C++ code in the file rootalias.C. -- Cheers, _/_/ _/ _/ _/_/_/_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/_/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/_/_/_/ _/ _/ *----------------------------------------------------------------------* Dr. Nick van Eijndhoven Department of Subatomic Physics email : nick@phys.uu.nl Utrecht University / NIKHEF tel. +31-30-2532331 (direct) P.O. Box 80.000 tel. +31-30-2531492 (secr.) NL-3508 TA Utrecht fax. +31-30-2518689 The Netherlands WWW : http://www.phys.uu.nl/~nick Office : Ornstein lab. 172 ---------------------------------------------------------------------- tel. +41-22-7679751 (direct) CERN PPE Division / ALICE exp. tel. +41-22-7675857 (secr.) CH-1211 Geneva 23 fax. +41-22-7679480 Switzerland CERN beep : 13+7294 Office : B 160 1-012 *----------------------------------------------------------------------* /////////////////////////////////////////////////////////////////////////////// // Computation of the confidence level from Chi-squared (chi2) // and number of constraints (ncons). // // Note : // for even ncons ==> same result as the Cernlib function PROB // for odd ncons ==> confidence level < result of the Cernlib function PROB // //--- Original Fortan routine copied from Lau Gatignon 1980 //--- Modified by NvE 29-sep-1980 K.U. Nijmegen //--- Modified by NvE 24-apr-1985 NIKHEF-H Amsterdam //--- Converted to C++ by Nve 06-nov-1998 UU-SAP Utrecht /////////////////////////////////////////////////////////////////////////////// float conlev(float chi2,int ncons) { const float a1=0.705230784e-1, a2=0.422820123e-1, a3=0.92705272e-2, a4=0.1520143e-3, a5=0.2765672e-3, a6=0.430638e-4; // Change to dummy variables int n=ncons; float y0=chi2; // Set CL to zero in case ncons<=0 if (n <= 0) return 0; if (y0 <= 0.) { if (y0 < 0.) { return 0; } else { return 1; } } if (n > 100) { float x=sqrt(2.*y0)-sqrt(float(n+n-1)); float t=fabs(x)/1.1412135; float denom=1.0+t*(a1+t*(a2+t*(a3+t*(a4+t*(a5+t*a6))))); float vfun=1.0/denom if (fabs(vfun) < 1.3e-5) vfun=0.; // Prevent underflow vfun=pow(vfun,16); float v=0.5*vfun; if (x < 0.) v=1.-v; if (v < 0.) v=0.; return v; } else { float y1=0.5*y0; int m=n/2; if (2*m == n) { float sum=1.; if (m > 1) { float term=1.; for (int i=2; i<=m; i++) { if (term > 1.e20) break; // Prevent overflow float fi=float(i-1); term=term*y1/fi; sum+=term; } } float rnick=y1; if (rnick >= 1.75e2) rnick=1.75e2; // Prevent underflow float v=sum*exp(-rnick); if (v < 0.) v=0.; return v; } else { float x=sqrt(y0); float t=fabs(x)/1.1412135; float denom=1.0+t*(a1+t*(a2+t*(a3+t*(a4+t*(a5+t*a6))))); float vfun=1.0/denom if (fabs(vfun) < 1.3e-5) vfun=0.; // Prevent underflow vfun=pow(vfun,16); float v=vfun; if (n < 1) return 0; if (n == 1) { if (v < 0.) v=0.; return v; } float value=v; float sum=1.; if (n >= 4) { float term=1.; int k=m-1; for (int j=1; j<=k; j++) { if (term > 1.e20) break; // Prevent overflow float fj=float(j); term=term*y0/(fj+fj+1.); sum+=term; } } if (y1 > 1.75e2) y1=1.75e2; // Prevent underflow float vi=sum*0.797846*sqrt(y0)*exp(-y1); v=vi+value; if (v < 0.) v=0.; return v; } } } /////////////////////////////////////////////////////////////////////////////// // SUBROUTINE CONLEV (CL,NCONS,CHI2) //C *** ROUTINE COPIED FROM LAU GATIGNON *** //C *** MODIFIED BY NVE 29-SEPT-1980 K.U. NIJMEGEN *** //C --- LAST MOD. NVE 24-APR-1985 NIKHEF-H AMSTERDAM --- //C //C --- THE COMPUTATION OF THE CONFIDENCE LEVEL (CL) FROM CHI-SQAURED (CHI2) --- //C --- AND NUMBER OF CONSTRAINTS (NCONS) --- //C NOTE ; //C FOR EVEN NCONS ==> SAME RESULT AS THE CERN FUNCTION PROB //C FOR ODD NCONS ==> CL < RESULT OF THE CERN FUNCTION PROB //C //* DATA A1 /0.705230784E-1/, A2 /0.422820123E-1/ //* DATA A3 /0.92705272 E-2/, A4 /0.1520143 E-3/ //* DATA A5 /0.2765672 E-3/, A6 /0.430638 E-4/ //*C //*C --- CHANGE TO DUMMY VARIABLES --- //* N=NCONS //* Y0=CHI2 //C //*C --- SET CL TO ZERO IN CASE OF NCONS .LE. 0 --- //* IF (N .GT. 0) GO TO 1 //* V=0.0 //* GO TO 130 //*C //* 1 IF (Y0 .GT. 0.0) GO TO 10 //* V=0.0 //* IF (Y0 .EQ. 0.0) V=1.0 //* GO TO 130 //*C //* 10 IF (N .LT. 101) GO TO 30 //* X=SQRT(Y0+Y0)-SQRT(FLOAT(N+N-1)) //* ASSIGN 20 TO JUMP //* GO TO 140 //*C //* 20 V=0.5*VFUN //* IF (X .LT. 0.0) V=1.0-V //* GO TO 110 //*C //* 30 Y1=0.5*Y0 //* M = N/2 //* IF (M+M .NE. N) GO TO 60 //* SUM=1.0 //* IF (M .LE. 1) GO TO 50 //* TERM=1.0 //* DO 40 I=2,M //*C //*C *** PREVENT OVERFLOW *** //* IF (TERM .GT. 1.0E20) GO TO 50 //* FI=I-1 //* TERM=TERM*Y1/FI //* 40 SUM=SUM+TERM //*C *** PREVENT UNDERFLOW *** //* 50 RNICK=Y1 //* IF (RNICK .GE. 1.75E2) RNICK=1.75E2 //* V=SUM*EXP(-RNICK) //* GO TO 110 //C //* 60 X=SQRT(Y0) //* ASSIGN 70 TO JUMP //* GO TO 140 //*C //* 70 V=VFUN //* IF (N-1) 120,110,80 //* 80 VALUE=V //* SUM=1.0 //* IF (N .LT. 4) GO TO 100 //* TERM=1.0 //* K=M-1 //* DO 90 I=1,K //* IF (TERM .GT. 1.0E20) GO TO 100 //* FI=I //* TERM=TERM*Y0/(FI+FI+1.0) //* 90 SUM=SUM+TERM //*C *** PREVENT UNDERFLOW *** //* 100 IF (Y1 .GT. 1.75E2) Y1=1.75E2 //* VI=SUM*0.797846*SQRT(Y0)*EXP(-Y1) //* V=VI+VALUE //* 110 IF (V) 120,130,130 //* 120 V=0.0 //* 130 CONTINUE //* CL=V //* RETURN //*C //* 140 T=ABS(X)/1.1412135 //* DENOM=1.0+T*(A1+T*(A2+T*(A3+T*(A4+T*(A5+T*A6))))) //* VFUN=1.0/DENOM //*C //*C *** PREVENT UNDERFLOW *** //* IF (ABS(VFUN) .LT. 1.3E-5) VFUN=0.0 //* VFUN=VFUN**16 //* GO TO JUMP,(20,70) //*C //* END //////////////////////////////////////////////////////////////////////////
This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:34:39 MET