;-
; docformat = 'IDL'
;+
; GLS routines to calculate linear fit
;-
;;-
;; docformat = 'IDL'
;;+
;; GLS routines to calculate linear fit
;;-
;pro GENERATE_RAMP,time,ramp,results,SEED=SEED
;;
;;Procedure to generate a ramp with parameters specified internally;
;;SEED is the montecarlo seed that may be passed in input
;;
;;The variables time,ramp,results are transmitted in output
;;
;if KEYWORD_SET(SEED) EQ 0 THEN SEED = -6L
;;
;;make the ramp parameters available to the public
;common ramp_params,N,M,Ms,G,tf,tg,RON,rate
;;
;;set the ramp parameters
;N = 10. ;nr of groups
;M = FLOAT(4.) ;frames averaged in group
;Ms = 0. ;frames skipped between groups
;G = 0;1. ;digitization
;tf = 10. ;seconds
;tg = tf*(M+Ms); seconds
;time = indgen(N)*tf*M+tf*(M+1)/2.;timing of the samples
;time = DOUBLE(time)
;;
;;set the count rate, per second
;rate = 9.; if you want it random, add +(RANDOMU(SEED)+1)*10 ;counts/second
;;
;
;;generate the counts within the intervals between frames, Delta_t => tf, according to Poisson stats.
;counts_group = RANDOMN(seed,N*(M+Ms),POISSON=rate*tf)
;;
;;generate the ramp coadding the counts
;ramp_all = lonarr(N*(M+Ms))
;ramp_all[0] = counts_group[0]
;for i=0,N*(M+Ms)-1 do ramp_all[i]=ramp_all[i-1]+counts_group[i]; MEAN([counts_group[i*M:(i+1)*M-1]])
;;
;;add zero point/offset
;offset=10000L ;offset counts
;ramp_all=ramp_all+offset
;;
;;add readout noise, in output, per single read.
;RON=15. ;readout noise
;ramp_all+=RANDOMN(seed,N*(M+Ms))*RON
;;
;;group-average of the ramp, as we often do for JWST
;ramp = fltarr(N)
;for i=0,N-1 do ramp[i]+=MEAN([ramp_all[i*M:(i+1)*M-1]])
;;
;;I should add the rounding error, since we average 16 bit values and still store the results in 16 bit
;;neglect for the moment...
;;this should be it! we have time and ramp as output parameters
;end
; docformat = 'IDL'
;+
; GLS routines to calculate linear fit
;-
function linearize_mr,time,ramp
;this function implements the Generalized Least Square Fit to a signal ramp
;
;make the ramp parameters available to the public
common ramp_params,N,M,Ms,G,tf,tg,RON,rate
common graphics, DISPLAY
;
;define the y variables, referred to the the first read
delta_y = ramp - ramp[0];
; a0=linfit(time,ramp)
; d_y=ramp-(a0[0]+a0[1]*time)
;
;set the COVARIANCE MATRIX
SIGMA=DBLarr(N,N)
;
;to estimate the variance I need an initial estimate of b, either from the minmax...
; b = Delta_y[N-1] / ( (N-1)*tg)
;or from the OLS fit
a0=linfit(time,ramp)
b=a0[1]
;
;I calculate the first row/col of the covariance matrix out of the loop, just for convenience
SIGMA[0,0] = b*tf*(M+1)/(2.*M) + b*tf*1/(3.*M)*(M-1)*(M-2) + RON^2/M + (G*M/SQRT(12))^2 & $
SIGMA[0,1:*] = (M+1)/2.*b*tf
SIGMA[1:*,0] = (M+1)/2.*b*tf
;
;the other terms of the matrix should be under control...
for i=1,N-1 do begin & $
; b = Delta_y[i] / ((i-1)*tg + (m+1)/2.*tf)
; SIGMA[i,i] = b*(i-1)*tg + (2*M^2-3*M+7)/(6*M)*b*tf + RON^2/M + (G*M/SQRT(12))^2 & $ ;Robberto Eq. 16
SIGMA[i,i] = b*i*tg + b*tf*(M+1)/(2.*M) + b*tf*1/(3.*M)*(M-1)*(M-2) + RON^2/M + (G*M/SQRT(12))^2 & $ ;Robberto Eq. 16
IF I LT N-1 THEN BEGIN & $;diagonal terms
SIGMA[I,I+1:N-1] = REPLICATE(b*i*tg+b*(m+1)/2.*tf,N-(i+1)) & $ ;Robberto Eq.19
SIGMA[I+1:N-1,I] = REPLICATE(b*i*tg+b*(m+1)/2.*tf,N-(i+1)) & $
ENDIF & $
endfor
;stop
;
;INVERSE COVARIANCE (AKA WEIGHTS if DIAGONAL)
W_Y_1 = INVERT(SIGMA)
;
;A MATRIX
AA=fltarr(2,N)
AA[0,*]=1.
AA[1,*]=time
;
;W_A MATRIX
W_A=INVERT(TRANSPOSE(AA)##W_Y_1##AA)
;
;and here is we have the RESULTS:
eta=W_A##TRANSPOSE(AA)##W_Y_1##Delta_Y
;..eta=W_A##TRANSPOSE(AA)##W_Y_1##D_Y
;
;IN READABLE FORM
intercept = eta[0] + ramp[0]
;intercept = eta[0] + a0[0]
slope = eta[1]; no a0[1] term since I have not done a subtraction of a0[1]*time
;slope = a0[1]+eta[1]
;
;and here are the errors
delta_intercept=SQRT(W_A[0,0])
delta_slope=SQRT(W_A[1,1])
;
;if DISPLAY has been set, we check individual ellipses
IF N_ELEMENTS(DISPLAY) NE 0 THEN BEGIN
params=covar2ellipse(W_A)
plot,indgen(2),xrange=[-0.5,0.5]+rate,yrange=[-50,50]+10000.,/nodata,XTITLE='Slope', YTITLE='Intercept'
oplot,[rate],[1E4],psym=2,symsize=1.5
params=covar2ellipse(W_A)
oplot,[slope],[intercept],psym=4
tvellipse, params.major, params.minor, slope, intercept, -params.ANGLE
;NOTE: I am playing a little trick here to have the ellipse properly oriented and sized;
;should be done scaling the covariance, but this is for illustration purposes only...
;the conventional OLS fit gives
a0=linfit(time,ramp,SIGMA=da0)
oploterror,[a0[1]],[a0[0]],[da0[1]],[da0[0]],hatlen=3
stop
;
ENDIF
;
;plot ellipse
;=======================================================================
params=covar2ellipse(W_A)
plot,indgen(2),xrange=[-0.5,0.5]+rate,yrange=[-50,50]+10000.,/nodata,XTITLE='Slope', YTITLE='Intercept'
tvellipse, params.major, params.minor, slope, intercept, -params.ANGLE, Color='yellow', /FILL
oplot,[rate],[1E4],psym=2,symsize=1.5,Color='black';,symsize=0.5
params=covar2ellipse(W_A)
oplot,[slope],[intercept],psym=4,Color='black',symsize=0.5
;the conventional OLS fit gives
a0=linfit(time,ramp,SIGMA=da0)
tvellipse,da0[1],da0[0], a0[1], a0[0], 0, Color='red', /FILL
oplot,[a0[1]],[a0[0]],color='black',psym=4,symsize=0.5
; stop
; oploterror,[a0[1]],[a0[0]],[da0[1]],[da0[0]],hatlen=3,color='black'
;=======================================================================
;
;RETURN THE ARRAY WITH THE FOUR RESULTS
return,[intercept,slope,delta_intercept,delta_slope]
end
;-
; docformat = 'IDL'
;+
; GLS routines to calculate linear fit
;-
PRO run_GLSfit
;this is the main procedure to be invoked to check the results
;
;make the ramp parameters available to the public
common ramp_params,N,M,Ms,G,tf,tg,RON,rate
common graphics, DISPLAY
;
;set this parameter to 1 if you want to stop and check the results of a single fit
;...DISPLAY=0; this run the case on 10000 ramps
;...DISPLAY=1; this stops to plot one ellipse
DISPLAY=2; this stops to do Figure 2 of the report (12 ellipses)
;
;TEST RUNNING 10000 RAMPS WITH SLOPE SET IN GENERATE_RAMP
IF DISPLAY EQ 0 THEN Nramps=10000
;... or create Figure 12
IF DISPLAY EQ 2 THEN BEGIN
;...get ready for creating Fig.2
Nramps = 12
!P.MULTI = [0,3,4]
openeps,'~/FUNCTIONAL/2013/GeneralizedLeastSquares/Figure2.eps'
ENDIF
;
;set arrays storing the results
newparams=fltarr(4,Nramps)
oldparams=fltarr(4,Nramps)
SEED=randomu(5L,Nramps)
diff=fltarr(Nramps)
;
;MAIN LOOP
;-----------
for i=0,Nramps-1 do begin
;generate the ramp and get the new fit coeefficients
GENERATE_RAMP,time,ramp,results,SEED=SEED[i]*1E5
results=linearize_mr(time,ramp)
;for the same ramp do the conventional uniform weight fit
a0=linfit(time,ramp,SIGMA=da0)
;store the results for slope and interecept in vectors
newparams[*,i]=results
oldparams[*,i]=[a0,da0]
endfor
;---------------------
;
;RESULTS
;USE histogauss to find the results
print,'mean slope and sigma_slope with the GLS:'
histogauss,newparams[1,*],NP1,NOPLOT=1
print,NP1[1:2]
;
;FIND THE TYPICAL NOISE
print,'mean error on the slope and sigma_error'
histogauss,newparams[3,*],NP3,NOPLOT=1
print,NP3[1:2]
;
;let's check with a conventional OLS fit
print,'Ordinary Least Squares - mean slope and sigma_slope:'
histogauss,oldparams[1,*],NP4,NOPLOT=1
print,NP4[1:2]
;
;let's check with a conventional OLS fit
print,'Ordinary Least Squares - mean error and sigma_error:'
histogauss,oldparams[3,*],NP4,NOPLOT=1
print,NP4[1:2]
;
VAR_slope = (6/5.*(N^2+1.)/(N*(N^2-1.))*rate/tg*(1-5/3.*(M^2-1.)/(M*(N^2+1))*tf/tg)+12./(M*N*(N^2-1.))*RON^2/tg^2)
print,'theory predicts an error on the slope giveb by: ',SQRT((VAR_slope))
;
;stop
;CREATE FIGURE 1 OF THE REPORT
;openeps,'~/FUNCTIONAL/2013/GeneralizedLeastSquares/Figure1.eps'
;histogauss,newparams[1,*],NP1,CHARSIZE=1.5
;closeps
IF DISPLAY EQ 2 THEN closeps
END
;+
; NAME:
; COVAR2ELLIPSE()
;
; PURPOSE:
; Given a 2D covariance matrix, compute the parameters of the
; confidence ellipse.
;
; INPUTS:
; covar - 2D covariance matrix
;
; OPTIONAL INPUTS:
; nsigma - desired confidence interval; default is 1-sigma
;
; KEYWORD PARAMETERS:
;
; OUTPUTS:
; ellipse - data structure containing the parameters of the ellipse
;
; OPTIONAL OUTPUTS:
;
; COMMENTS:
; Based entirely on D. Coe's beautiful Fisher-matrix
; write-up, astro-ph/0906.3123.
;
; EXAMPLES:
;
; MODIFICATION HISTORY:
; J. Moustakas, 2010 Jul 09, UCSD
;
; Copyright (C) 2010, John Moustakas
;
; This program 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 2 of the License, or
; (at your option) any later version.
;
; This program 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.
;-
function covar2ellipse, covar, nsigma=nsigma
if (n_elements(nsigma) eq 0) then nsigma = 1.0
varx = covar[0,0]
vary = covar[1,1]
varxy = covar[0,1]*covar[1,0]
; (squared) semi-major and semi-minor axis lengths
aa = (varx + vary)/2.0 + sqrt(((varx - vary)^2)/4.0 + varxy)
bb = (varx + vary)/2.0 - sqrt(((varx - vary)^2)/4.0 + varxy)
; note: the angle, theta, is defined to be positive counter-clockwise
; with respect to the x-axis, such that the parameters of the ellipse
; can be passed directly to TVELLIPSE
theta = 90-!radeg*atan(2*sqrt(varxy)/(varx-vary))/2.0
; the axis lengths have to be multiplied by a coefficient that depends
; on the desired confidence level (see Table 1 in Coe's paper)
factor = sqrt(mpchilim(errorf(nsigma/sqrt(2)),2))
ell = {major: factor*sqrt(aa), minor: factor*sqrt(bb), angle: theta}
return, ell
end
;+
; NAME:
; MPCHILIM
;
; AUTHOR:
; Craig B. Markwardt, NASA/GSFC Code 662, Greenbelt, MD 20770
; craigm@lheamail.gsfc.nasa.gov
; UPDATED VERSIONs can be found on my WEB PAGE:
; http://cow.physics.wisc.edu/~craigm/idl/idl.html
;
; PURPOSE:
; Compute confidence limits for chi-square statistic
;
; MAJOR TOPICS:
; Curve and Surface Fitting, Statistics
;
; CALLING SEQUENCE:
; DELCHI = MPCHILIM(PROB, DOF, [/SIGMA, /CLEVEL, /SLEVEL ])
;
; DESCRIPTION:
;
; The function MPCHILIM() computes confidence limits of the
; chi-square statistic for a desired probability level. The returned
; values, DELCHI, are the limiting chi-squared values: a chi-squared
; value of greater than DELCHI will occur by chance with probability
; PROB:
;
; P_CHI(CHI > DELCHI; DOF) = PROB
;
; In specifying the probability level the user has three choices:
;
; * give the confidence level (default);
;
; * give the significance level (i.e., 1 - confidence level) and
; pass the /SLEVEL keyword; OR
;
; * give the "sigma" of the probability (i.e., compute the
; probability based on the normal distribution) and pass the
; /SIGMA keyword.
;
; Note that /SLEVEL, /CLEVEL and /SIGMA are mutually exclusive.
;
; INPUTS:
;
; PROB - scalar or vector number, giving the desired probability
; level as described above.
;
; DOF - scalar or vector number, giving the number of degrees of
; freedom in the chi-square distribution.
;
; RETURNS:
;
; Returns a scalar or vector of chi-square confidence limits.
;
; KEYWORD PARAMETERS:
;
; SLEVEL - if set, then PROB describes the significance level.
;
; CLEVEL - if set, then PROB describes the confidence level
; (default).
;
; SIGMA - if set, then PROB is the number of "sigma" away from the
; mean in the normal distribution.
;
; EXAMPLES:
;
; print, mpchilim(0.99d, 2d, /clevel)
;
; Print the 99% confidence limit for a chi-squared of 2 degrees of
; freedom.
;
; print, mpchilim(5d, 2d, /sigma)
;
; Print the "5 sigma" confidence limit for a chi-squared of 2
; degrees of freedom. Here "5 sigma" indicates the gaussian
; probability of a 5 sigma event or greater.
; P_GAUSS(5D) = 1D - 5.7330314e-07
;
; REFERENCES:
;
; Algorithms taken from CEPHES special function library, by Stephen
; Moshier. (http://www.netlib.org/cephes/)
;
; MODIFICATION HISTORY:
; Completed, 1999, CM
; Documented, 16 Nov 2001, CM
; Reduced obtrusiveness of common block and math error handling, 18
; Nov 2001, CM
; Convert to IDL 5 array syntax (!), 16 Jul 2006, CM
; Move STRICTARR compile option inside each function/procedure, 9
; Oct 2006
; Add usage message, 24 Nov 2006, CM
; Usage message with /CONTINUE, 23 Sep 2009, CM
;
; $Id: mpchilim.pro,v 1.8 2009/09/23 20:12:46 craigm Exp $
;-
; Copyright (C) 1997-2001, 2006, 2009, Craig Markwardt
; This software is provided as is without any warranty whatsoever.
; Permission to use, copy, modify, and distribute modified or
; unmodified copies is granted, provided this copyright and disclaimer
; are included unchanged.
;-
forward_function cephes_ndtri, cephes_igam, cephes_igamc, cephes_igami
;; Set machine constants, once for this session. Double precision
;; only.
pro cephes_setmachar
COMPILE_OPT strictarr
common cephes_machar, cephes_machar_vals
if n_elements(cephes_machar_vals) GT 0 then return
if (!version.release) LT 5 then dummy = check_math(1, 1)
mch = machar(/double)
machep = mch.eps
maxnum = mch.xmax
minnum = mch.xmin
maxlog = alog(mch.xmax)
minlog = alog(mch.xmin)
maxgam = 171.624376956302725D
cephes_machar_vals = {machep: machep, maxnum: maxnum, minnum: minnum, $
maxlog: maxlog, minlog: minlog, maxgam: maxgam}
if (!version.release) LT 5 then dummy = check_math(0, 0)
return
end
;+
; function
;-
function cephes_polevl, x, coef
COMPILE_OPT strictarr
ans = coef[0]
nc = n_elements(coef)
for i = 1L, nc-1 do ans = ans * x + coef[i]
return, ans
end
function cephes_ndtri, y0
;
; Inverse of Normal distribution function
;
;
;
; SYNOPSIS:
;
; double x, y, ndtri();
;
; x = ndtri( y );
;
;
;
; DESCRIPTION:
;
; Returns the argument, x, for which the area under the
; Gaussian probability density function (integrated from
; minus infinity to x) is equal to y.
;
;
; For small arguments 0 < y < exp(-2), the program computes
; z = sqrt( -2.0 * log(y) ); then the approximation is
; x = z - log(z)/z - (1/z) P(1/z) / Q(1/z).
; There are two rational functions P/Q, one for 0 < y < exp(-32)
; and the other for y up to exp(-2). For larger arguments,
; w = y - 0.5, and x/sqrt(2pi) = w + w**3 R(w**2)/S(w**2)).
;
;
; ACCURACY:
;
; Relative error:
; arithmetic domain # trials peak rms
; DEC 0.125, 1 5500 9.5e-17 2.1e-17
; DEC 6e-39, 0.135 3500 5.7e-17 1.3e-17
; IEEE 0.125, 1 20000 7.2e-16 1.3e-16
; IEEE 3e-308, 0.135 50000 4.6e-16 9.8e-17
;
;
; ERROR MESSAGES:
;
; message condition value returned
; ndtri domain x <= 0 -MAXNUM
; ndtri domain x >= 1 MAXNUM
COMPILE_OPT strictarr
common cephes_ndtri_data, s2pi, p0, q0, p1, q1, p2, q2
if n_elements(s2pi) EQ 0 then begin
s2pi = sqrt(2.D*!dpi)
p0 = [ -5.99633501014107895267D1, 9.80010754185999661536D1, $
-5.66762857469070293439D1, 1.39312609387279679503D1, $
-1.23916583867381258016D0 ]
q0 = [ 1.D, $
1.95448858338141759834D0, 4.67627912898881538453D0, $
8.63602421390890590575D1, -2.25462687854119370527D2, $
2.00260212380060660359D2, -8.20372256168333339912D1, $
1.59056225126211695515D1, -1.18331621121330003142D0 ]
p1 = [ 4.05544892305962419923D0, 3.15251094599893866154D1, $
5.71628192246421288162D1, 4.40805073893200834700D1, $
1.46849561928858024014D1, 2.18663306850790267539D0, $
-1.40256079171354495875D-1,-3.50424626827848203418D-2,$
-8.57456785154685413611D-4 ]
q1 = [ 1.D, $
1.57799883256466749731D1, 4.53907635128879210584D1, $
4.13172038254672030440D1, 1.50425385692907503408D1, $
2.50464946208309415979D0, -1.42182922854787788574D-1,$
-3.80806407691578277194D-2,-9.33259480895457427372D-4 ]
p2 = [ 3.23774891776946035970D0, 6.91522889068984211695D0, $
3.93881025292474443415D0, 1.33303460815807542389D0, $
2.01485389549179081538D-1, 1.23716634817820021358D-2,$
3.01581553508235416007D-4, 2.65806974686737550832D-6,$
6.23974539184983293730D-9 ]
q2 = [ 1.D, $
6.02427039364742014255D0, 3.67983563856160859403D0, $
1.37702099489081330271D0, 2.16236993594496635890D-1,$
1.34204006088543189037D-2, 3.28014464682127739104D-4,$
2.89247864745380683936D-6, 6.79019408009981274425D-9]
endif
common cephes_machar, machvals
MAXNUM = machvals.maxnum
if y0 LE 0 then begin
message, 'ERROR: domain', /info
return, -MAXNUM
endif
if y0 GE 1 then begin
message, 'ERROR: domain', /info
return, MAXNUM
endif
code = 1
y = y0
exp2 = exp(-2.D)
if y GT (1.D - exp2) then begin
y = 1.D - y
code = 0
endif
if y GT exp2 then begin
y = y - 0.5
y2 = y * y
x = y + y * y2 * cephes_polevl(y2, p0) / cephes_polevl(y2, q0)
x = x * s2pi
return, x
endif
x = sqrt( -2.D * alog(y))
x0 = x - alog(x)/x
z = 1.D/x
if x LT 8. then $
x1 = z * cephes_polevl(z, p1) / cephes_polevl(z, q1) $
else $
x1 = z * cephes_polevl(z, p2) / cephes_polevl(z, q2)
x = x0 - x1
if code NE 0 then x = -x
return, x
end
function cephes_igam, a, x
;+
; Incomplete gamma integral
;
;
;
; SYNOPSIS:
;
; double a, x, y, igam();
;
; y = igam( a, x );
;
; DESCRIPTION:
;
; The function is defined by
;
; x
; -
; 1 | | -t a-1
; igam(a,x) = ----- | e t dt.
; - | |
; | (a) -
; 0
;
;
; In this implementation both arguments must be positive.
; The integral is evaluated by either a power series or
; continued fraction expansion, depending on the relative
; values of a and x.
;
; ACCURACY:
;
; Relative error:
; arithmetic domain # trials peak rms
; IEEE 0,30 200000 3.6e-14 2.9e-15
; IEEE 0,100 300000 9.9e-14 1.5e-14
;-
COMPILE_OPT strictarr
common cephes_machar, machvals
MAXLOG = machvals.maxlog
MACHEP = machvals.machep
if x LE 0 OR a LE 0 then return, 0.D
if x GT 1. AND x GT a then return, 1.D - cephes_igamc(a, x)
ax = a * alog(x) - x - lngamma(a)
if ax LT -MAXLOG then begin
; message, 'WARNING: underflow', /info
return, 0.D
endif
ax = exp(ax)
r = a
c = 1.D
ans = 1.D
repeat begin
r = r + 1
c = c * x/r
ans = ans + c
endrep until (c/ans LE MACHEP)
return, ans*ax/a
end
function cephes_igamc, a, x
;+
; Complemented incomplete gamma integral
;
;
;
; SYNOPSIS:
;
; double a, x, y, igamc();
;
; y = igamc( a, x );
;
; DESCRIPTION:
;
; The function is defined by
;
;
; igamc(a,x) = 1 - igam(a,x)
;
; inf.
; -
; 1 | | -t a-1
; = ----- | e t dt.
; - | |
; | (a) -
; x
;
;
; In this implementation both arguments must be positive.
; The integral is evaluated by either a power series or
; continued fraction expansion, depending on the relative
; values of a and x.
;
; ACCURACY:
;
; Tested at random a, x.
; a x Relative error:
; arithmetic domain domain # trials peak rms
; IEEE 0.5,100 0,100 200000 1.9e-14 1.7e-15
; IEEE 0.01,0.5 0,100 200000 1.4e-13 1.6e-15
;-
COMPILE_OPT strictarr
common cephes_machar, machvals
MAXLOG = machvals.maxlog
MACHEP = machvals.machep
big = 4.503599627370496D15
biginv = 2.22044604925031308085D-16
if x LE 0 OR a LE 0 then return, 1.D
if x LT 1. OR x LT a then return, 1.D - cephes_igam(a, x)
ax = a * alog(x) - x - lngamma(a)
if ax LT -MAXLOG then begin
; message, 'ERROR: underflow', /info
return, 0.D
endif
ax = exp(ax)
y = 1.D - a
z = x + y + 1.D
c = 0.D
pkm2 = 1.D
qkm2 = x
pkm1 = x + 1.D
qkm1 = z * x
ans = pkm1 / qkm1
repeat begin
c = c + 1.D
y = y + 1.D
z = z + 2.D
yc = y * c
pk = pkm1 * z - pkm2 * yc
qk = qkm1 * z - qkm2 * yc
if qk NE 0 then begin
r = pk/qk
t = abs( (ans-r)/r )
ans = r
endif else begin
t = 1.D
endelse
pkm2 = pkm1
pkm1 = pk
qkm2 = qkm1
qkm1 = qk
if abs(pk) GT big then begin
pkm2 = pkm2 * biginv
pkm1 = pkm1 * biginv
qkm2 = qkm2 * biginv
qkm1 = qkm1 * biginv
endif
endrep until t LE MACHEP
return, ans * ax
end
function cephes_igami, a, y0
;+
; Inverse of complemented imcomplete gamma integral
;
;
;
; SYNOPSIS:
;
; double a, x, p, igami();
;
; x = igami( a, p );
;
; DESCRIPTION:
;
; Given p, the function finds x such that
;
; igamc( a, x ) = p.
;
; Starting with the approximate value
;
; 3
; x = a t
;
; where
;
; t = 1 - d - ndtri(p) sqrt(d)
;
; and
;
; d = 1/9a,
;
; the routine performs up to 10 Newton iterations to find the
; root of igamc(a,x) - p = 0.
;
; ACCURACY:
;
; Tested at random a, p in the intervals indicated.
;
; a p Relative error:
; arithmetic domain domain # trials peak rms
; IEEE 0.5,100 0,0.5 100000 1.0e-14 1.7e-15
; IEEE 0.01,0.5 0,0.5 100000 9.0e-14 3.4e-15
; IEEE 0.5,10000 0,0.5 20000 2.3e-13 3.8e-14
;-
COMPILE_OPT strictarr
common cephes_machar, machvals
MAXNUM = machvals.maxnum
MAXLOG = machvals.maxlog
MACHEP = machvals.machep
x0 = MAXNUM
yl = 0.D
x1 = 0.D
yh = 1.D
dithresh = 5.D * MACHEP
d = 1.D/(9.D*a)
y = (1.D - d - cephes_ndtri(y0) * sqrt(d))
x = a * y * y * y
lgm = lngamma(a)
for i=0, 9 do begin
if x GT x0 OR x LT x1 then goto, ihalve
y = cephes_igamc(a, x)
if y LT yl OR y GT yh then goto, ihalve
if y LT y0 then begin
x0 = x
yl = y
endif else begin
x1 = x
yh = y
endelse
d = (a-1.D) * alog(x) - x - lgm
if d LT -MAXLOG then goto, ihalve
d = -exp(d)
d = (y - y0)/d
if abs(d/x) LT MACHEP then goto, done
x = x - d
endfor
; Resort to interval halving if Newton iteration did not converge
IHALVE:
d = 0.0625D
if x0 EQ MAXNUM then begin
if x LE 0 then x = 1.D
while x0 EQ MAXNUM do begin
x = (1.D + d) * x
y = cephes_igamc(a, x)
if y LT y0 then begin
x0 = x
yl = y
goto, DONELOOP1
endif
d = d + d
endwhile
DONELOOP1:
endif
d = 0.5
dir = 0L
for i=0, 399 do begin
x = x1 + d * (x0-x1)
y = cephes_igamc(a, x)
lgm = (x0 - x1)/(x1 + x0)
if abs(lgm) LT dithresh then goto, DONELOOP2
lgm = (y - y0)/y0
if abs(lgm) LT dithresh then goto, DONELOOP2
if x LT 0 then goto, DONELOOP2
if y GE y0 then begin
x1 = x
yh = y
if dir LT 0 then begin
dir = 0
d = 0.5D
endif else if dir GT 1 then begin
d = 0.5 * d + 0.5
endif else begin
d = (y0 - yl)/(yh - yl)
endelse
dir = dir + 1
endif else begin
x0 = x
yl = y
if dir GT 0 then begin
dir = 0
d = 0.5
endif else if dir LT -1 then begin
d = 0.5 * d
endif else begin
d = (y0 - yl)/(yh - yl)
endelse
dir = dir - 1
endelse
endfor
DONELOOP2:
if x EQ 0 then begin
; message, 'WARNING: underflow', /info
endif
DONE:
return, x
end
;-
; docformat = 'IDL'
;+
; GLS routines to calculate linear fit
;-
function mpchilim, p, dof, sigma=sigma, clevel=clevel, slevel=slevel
COMPILE_OPT strictarr
if n_params() EQ 0 then begin
message, 'USAGE: DELCHI = MPCHILIM(PROB, DOF, [/SIGMA, /CLEVEL, /SLEVEL ])', /cont
return, !values.d_nan
endif
cephes_setmachar ;; Set machine constants
if n_elements(dof) EQ 0 then dof = 1.
;; Confidence level is the default
if n_elements(clevel) EQ 0 then clevel = 1
if keyword_set(sigma) then begin ;; Significance in terms of SIGMA
slev = 1D - errorf(p/sqrt(2.))
endif else if keyword_set(slevel) then begin ;; in terms of SIGNIFICANCE LEVEL
slev = p
endif else if keyword_set(clevel) then begin ;; in terms of CONFIDENCE LEVEL
slev = 1.D - double(p)
endif else begin
message, 'ERROR: must specify one of SIGMA, CLEVEL, SLEVEL'
endelse
;; Output will have same type as input
y = p*0
;; Loop through, computing the inverse, incomplete gamma function
;; slev is the significance level
for i = 0L, n_elements(p)-1 do begin
y[i] = 2.D * cephes_igami(0.5D*double(dof), slev[i])
end
return, y
end
;-
; docformat = 'IDL'
;+
; GLS routines to calculate linear fit
;-
pro openeps,nomefile
on_error,2
print,'out to ps on the file:', nomefile
set_plot,'ps'
device,bits=8,filename=nomefile,/ENCAPSULATED
end
;-
; docformat = 'IDL'
;+
; GLS routines to calculate linear fit
;-
pro closeps
on_error,2
device,/close
set_plot,'x'
end