function uly_line_eval, eval_data, pars
compile_opt idl2
on_error, 2
c = 299792.458d
pos = (alog(pars[0]) - eval_data.start) / eval_data.step
if pos lt 0 or pos ge eval_data.npix then return, fltarr(eval_data.npix)
sigma_pix = pars[1] / (eval_data.step * c)
nline = ceil(10 * sigma_pix)
xborder = round(pos) + dindgen(2*nline+2) - nline - 0.5d
cumul = 0.5 * (1 + erf((xborder-pos)/sigma_pix /sqrt(2d)))
data = fltarr(eval_data.npix)
p1 = round(pos-nline)
p2 = 0
if p1 lt 0 then begin
p1 = 0
p2 = -p1
endif
n = min([n_elements(cumul)-1,eval_data.npix-p1+p2])-1
data[p1] = (shift(cumul,-1)-cumul[0:2*nline])[p2:n]
if n_elements(*eval_data.lsf_file) gt 0 then begin
spect = uly_spect_alloc(DATA=data, START=eval_data.start, STEP=eval_data.step, SAMPLING=1)
uly_spect_lsfconvol, *eval_data.lsf_file, spect
data = *spect.data
uly_spect_free, spect
endif
return, data
end
function uly_line_init, cmp, WAVERANGE=lamrange, VELSCALE=velscale, QUIET=quiet
compile_opt idl2
on_error, 2
c = 299792.498d
cmp.eval_fun = 'uly_line_eval'
cmp.start = alog(double(lamrange[0]))
cmp.step = double(velscale)/c
cmp.npix = round((alog(double(lamrange[1])) - cmp.start) / cmp.step) + 1
cmp.sampling = 1s
(*cmp.para)[0].step = *(*cmp.para)[0].guess * cmp.step * 1.1
init_data = *cmp.init_data
eval_data = {lsf_file:ptr_new(*init_data.lsf_file), $
start:cmp.start, step:cmp.step, npix:cmp.npix}
cmp.eval_data = ptr_new(eval_data)
if n_elements(*(*cmp.para)[1].guess) ne 0 then begin
sigma_pix = *(*cmp.para)[1].guess / (cmp.step * c)
if (*cmp.para)[1].limited[0] eq 0 then $
if (sigma_pix gt 0.3) ne 0 then begin
(*cmp.para)[1].limited[0] = 1
(*cmp.para)[1].limits[0] = 0.3 * cmp.step * c
endif else $
if *(*cmp.para)[1].guess lt (*cmp.para)[1].limits[0] then $
message, 'ULY_LINE_INIT: Failed for '+cmp.name+ $
' because sigma is not within the limits'
if (*cmp.para)[1].limited[1] eq 1 and $
*(*cmp.para)[1].guess gt (*cmp.para)[1].limits[1] then $
message, 'ULY_LINE_INIT: Failed for '+cmp.name+ $
' because sigma is not within the limits'
if sigma_pix le 0.3 then (*cmp.para)[1].fixed = 1S
endif else begin
if (*cmp.para)[1].limited[0] eq 0 then begin
(*cmp.para)[1].limited[0] = 1
(*cmp.para)[1].limits[0] = 0.3 * cmp.step * c
if (*cmp.para)[1].limited[1] eq 0 then $
*(*cmp.para)[1].guess = cmp.step * c $
else $
*(*cmp.para)[1].guess = min([cmp.step*c, (*cmp.para)[1].limits[1]])
endif
endelse
if *(*cmp.para)[1].guess / (cmp.step * c) ge 0.3 then (*cmp.para)[0].step /= 4.
(*cmp.para)[1].step = velscale/5.
return, cmp
end
function uly_line, wave, sigma, $
LSF=lsf_file, $
NAME=name, $
LL=lim_wave, $
SL=lim_sigm, $
WL=lim_weight
compile_opt idl2
on_error, 2
if n_elements(wave) eq 0 then begin
print, 'Usage: ULY_LINE, wave, ...'
message, 'Error, at minimum one wavelength must be passed', /INFO
return, 0
endif
s_wl = size(lim_weight)
namec = uly_cmp_name(name)
init_data = {lsf_file:ptr_new(lsf_file)}
if s_wl[0] gt 0 then if not (s_wl[0] eq 1 and s_wl[1] eq 2) then $
message, 'The weight limits have to be of the type arr(2)'
case n_elements(lim_weight) of
1: lw = [double(lim_weight), (machar(/DOUBLE)).xmax]
2: lw = double(lim_weight)
else : lw = [-(machar(/DOUBLE)).xmax, (machar(/DOUBLE)).xmax]
endcase
cmp = {name:namec, $
descr:'emission line', $
init_fun:'uly_line_init', $
init_data:ptr_new(init_data), $
eval_fun:'uly_line_eval', $
eval_data:ptr_new(), $
para:ptr_new(/ALLO), $
start:0d, $
step:0d, $
npix: 0l, $
sampling:-1s, $
mask:ptr_new(), $
weight:0d, $
e_weight:0d, $
l_weight:0d, $
lim_weig:lw $
}
dwave = double(wave)
*cmp.para = [{name:'lambda', unit:'Angstrom', guess:ptr_new(double(dwave)), $
step:1D, limits:[0d,0d], limited:[0S,0S], fixed:0S, $
value:0D, error:0D, dispf:''}, $
{name:'sigma', unit:'km/s', guess:ptr_new(double(sigma)), $
step:1D, limits:[0d,0d], limited:[0S,0S], fixed:0S, $
value:0D, error:0D, dispf:''}]
if n_elements(lim_wave) gt 0 then begin
(*cmp.para)[0].limited = [1S, 1S]
(*cmp.para)[0].limits = lim_wave
endif
if n_elements(lim_sigm) gt 0 then begin
(*cmp.para)[1].limited = [1S, 1S]
(*cmp.para)[1].limits = lim_sigm
endif
return, cmp
end
Part of