;+ THIS MODULE CONTAINS TWO SUBROUTINES
; pro mygauss() and function brl_find511()
;
;
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; evaluate gaussian + linear model for use with curvefit()
;
; model is f(x) = a[0]*exp(-((x-a[1])/a[2])^2) + a[3]x + a[4]
;
; INPUT: x is where the model is to be evaluated
; a is the current list of 5 parameter values; these
; must be initialized by the caller
;
; OUTPUT: f is evaluated as a linear+gaussian model
; pder is a list of 5 partial derivatives of f wrt a
;
; WARNING: for speed, no checks for foolish function evaluation
; requests. Caller is responsible! For instance,
; if one sets a[2]=0 or (x-a[1])/a[2]=1000 for some x,
; expect error msgs and/or nonsense output.
;-
pro mygauss, x, a, f, pder
cnt = n_elements(x)
z = (x-a[1])/a[2]
temp = exp(-z*z)
hold = (a[0]*2./a[2])*temp*z
f = a[0]*temp + a[3]*x + a[4]
pder = [[temp], [hold], [hold*z], [x], [fltarr(cnt)+1.]]
end
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;
;+ find the slow spectrum bin value of the 511 line
;
; INPUT: slo list of 256 slow spectrum count rates (counts/second)
; the slo list should not be normalized by bin widths
;
; OUTPUT: bin value for the 511 peak (usually not an integer)
; -1 on failure (511 peak not found)
;
; OPTIONS: offset=offset low bdy for 511 search region (default is 100)
; err=err 1-sigma uncertainties for each slo value;
; this should be should be a list of
; sqrt(# of counts)/(integration time in seconds)
;
; ACTION: limit the search to a reasonable part of the
; entire spectrum. Fit a line to the two endpoints
; of the search region, and subtract off the line.
; Then find the midpoint position of the list of
; values exceeding 50% of the max residual. That
; becomes a start guess for the peak location,
; modeled by a line+Gaussian. Amplitude and width are
; hard-coded typical values. Fit model to data and
; get best fit peak location. If the fit looks good,
; return its position; else return -1 to signal failure.
;
; HISTORY: first version working 31Dec2012/mm
;
; FUTURE: might need to adjust testing for valid 511 peak
;
; EXAMPLE: peak = brl_find511(spec, offset=95)
; peak = brl_find511(spec, err=sigmas)
;-
function brl_find511, slow, offset=offset, err=err
if n_elements(slow) ne 256 then return, -1
if (not keyword_set(err)) then err=fltarr(256)+1.
if (not keyword_set(offset)) then offset=100
widths=[intarr(64)+1,intarr(32)+2,intarr(32)+4,intarr(32)+8, $
intarr(32)+16,intarr(32)+32,intarr(32)+64]
x= [0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, $
11.5, 12.5, 13.5, 14.5, 15.5, 16.5, 17.5, 18.5, 19.5, 20.5, $
21.5, 22.5, 23.5, 24.5, 25.5, 26.5, 27.5, 28.5, 29.5, 30.5, $
31.5, 32.5, 33.5, 34.5, 35.5, 36.5, 37.5, 38.5, 39.5, 40.5, $
41.5, 42.5, 43.5, 44.5, 45.5, 46.5, 47.5, 48.5, 49.5, 50.5, $
51.5, 52.5, 53.5, 54.5, 55.5, 56.5, 57.5, 58.5, 59.5, 60.5, $
61.5, 62.5, 63.5, 65, 67, 69, 71, 73, 75, 77, 79, 81, $
83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, $
107, 109, 111, 113, 115, 117, 119, 121, 123, 125, $
127, 130, 134, 138, 142, 146, 150, 154, 158, 162, $
166, 170, 174, 178, 182, 186, 190, 194, 198, 202, $
206, 210, 214, 218, 222, 226, 230, 234, 238, 242, $
246, 250, 254, 260, 268, 276, 284, 292, 300, 308, $
316, 324, 332, 340, 348, 356, 364, 372, 380, 388, $
396, 404, 412, 420, 428, 436, 444, 452, 460, 468, $
476, 484, 492, 500, 508, 520, 536, 552, 568, 584, $
600, 616, 632, 648, 664, 680, 696, 712, 728, 744, $
760, 776, 792, 808, 824, 840, 856, 872, 888, 904, $
920, 936, 952, 968, 984, 1000, 1016, 1040, 1072, 1104, $
1136, 1168, 1200, 1232, 1264, 1296, 1328, 1360, 1392, $
1424, 1456, 1488, 1520, 1552, 1584, 1616, 1648, 1680, $
1712, 1744, 1776, 1808, 1840, 1872, 1904, 1936, 1968, $
2000, 2032, 2080, 2144, 2208, 2272, 2336, 2400, 2464, $
2528, 2592, 2656, 2720, 2784, 2848, 2912, 2976, 3040, $
3104, 3168, 3232, 3296, 3360, 3424, 3488, 3552, 3616, $
3680, 3744, 3808, 3872, 3936, 4000, 4064]
; nominal range for 511 line
width=25
select=indgen(width)+offset
y = slow[select]/widths[select]
x = x[select]
err = err[select]/widths[select]
usersym,[-.5,.5,.5,-.5,-.5],[-.5,-.5,.5,.5,-.5],/fill
; describe a line through endpoints of the selected range
y1 = y[0]
y2 = y[width-1]
x1 = x[0]
x2 = x[width-1]
m = (y2-y1)/(x2-x1)
b = y1 - m*x1
;
; find approximate peak location after subtracting linear bkgd
;
peakregion = y - (m * x + b)
apex=max(peakregion)
higharea=where(peakregion gt 0.5*apex,cnt)
if (cnt lt 2) then return, -1
peaklocation = x[floor(median(higharea))]
guess=[1., peaklocation, 10., m, b]
yfit=curvefit(x,y,1./err^2,guess, $
chisq=chisq,sigma,function_name='mygauss',status=stat)
if (guess[2] gt 20 or guess[0] lt 0.2) then return, -1
; some diagnostics (might need to adjust above tests)
;
; print,guess
; plot,x,y,psym=8,yrange=[0,3]
; oplot,x,yfit
; oploterr,x,y,err
return,guess[1]
end