function uly_cmp_select, cmp
ncomp = n_elements(cmp)
if ncomp eq 0 then begin
print, 'Usage: uly_cmp_select, <cmp>'
message, 'Miss argument <cmp>', /INFO
return, 0
endif
print, 'For LOSVD type: -1 '
for i = 0, ncomp-1 do $
print, 'For ', cmp[i].name, ' type: ', i, FORMAT='(3a, i1)'
comp = ' '
read, comp, prompt = 'Chose a number of component: '
if comp ne -1 then begin
npars = n_elements(*cmp[comp].para)
print, 'For fraction type: -1 '
for i = 0, npars-1 do begin
if (*cmp[comp].para)[i].name ne '' then $
print, 'For ', (*cmp[comp].para)[i].name, ' type: ', i, FORMAT='(3a, i1)'
endfor
endif else begin
losvd_name = ['velocity ', 'sigma ']
for i = 0, 1 do print, 'For ', losvd_name[i], 'type: ', i, FORMAT='(3a, i1)'
endelse
param = ' '
read, param, prompt = 'Chose a number of parameter: '
return, fix([comp, param])
end
pro uly_chimap_write, chimap, outfile
mkhdr, hdr, chimap.map
fxaddpar, hdr, 'CTYPE1', chimap.xtitle
if chimap.xunit ne '' then fxaddpar, hdr, 'CUNIT1', chimap.xunit
fxaddpar, hdr, 'CTYPE2', chimap.ytitle
if chimap.yunit ne '' then fxaddpar, hdr, 'CUNIT2', chimap.yunit
fxaddpar, hdr, 'EXTEND', 'T'
writefits, outfile, chimap.map, hdr
writefits, outfile, chimap.xnode, /append
writefits, outfile, chimap.ynode, /append
end
function range, x1, x2, n
compile_opt idl2, hidden
return, x1 + (x2-x1)*lindgen(n)/(n-1d)
end
function uly_chimap, spect, cmp, proj, $
VELSCALE=velscale, LMIN=lmin, LMAX=lmax, $
ERR_SP=err_sp, $
SG=sg, DG=dg, SNR=snr, $
KMOMENT=kmoment, KFIX=kfix, $
XNODE=xnode, YNODE=ynode, $
ADEGREE=adegree, MDEGREE=mdegree, $
PLOT=plot, PS=ps, $
CLEAN=clean, $
QUIET=quiet, FILE_OUT=file_out
if n_elements(spect) eq 0 or n_elements(cmp) eq 0 then begin
print,'Usage:'
print,'uly_chimap, <spectrum: file or structure>, <cmp>, ...'
return, 0
endif else if size(spect,/TYPE) ne size('str',/TYPE) then begin
spectrum = spect
endif else begin
testinp = file_test(spect)
if testinp eq 0 then $
message,'The file:'+spect+' does not exist. Give correct name for the input file.'
endelse
if n_elements(cmp) eq 0 or size(cmp, /TYPE) ne 8 $
then message, 'You must give a component array!'
if n_elements(proj) eq 0 then proj = 0
if not array_equal(size(proj), size([[1,2],[3,4]])) then begin
print, 'YOU DID NOT GIVE VALID PROJECTIONS, SELECT THE FIRST (X):'
proj1 = uly_cmp_select(cmp)
print, '... SELECT THE SECOND (Y) :'
proj2 = uly_cmp_select(cmp)
proj = [[proj1],[proj2]]
endif
if n_elements(spectrum) ne 0 then begin
SignalLog = uly_spect_extract(spectrum, ONED=0, STATUS=status)
if status ne 0 then message, 'Could not extract 1D spectrum'
SignalLog = uly_spect_logrebin(SignalLog, velscale, /OVER)
endif else begin
SignalLog = uly_spect_read(spect, lmin, lmax, VELSCALE=velscale, $
SG=shift_guess, ERR_SP=err_sp, $
QUIET=quiet $
)
SignalLog = uly_spect_extract(SignalLog, ONED=0, STATUS=status, /OVER)
if status ne 0 then message, 'Could not extract 1D spectrum'
if SignalLog.sampling ne 1 then $
SignalLog = uly_spect_logrebin(SignalLog, velscale, /OVER)
endelse
if not uly_spect_get(SignalLog, /VALID) then $
message, 'Input spectrum is invalid'
if n_elements(*SignalLog.goodpix) gt 0 then gp = *SignalLog.goodpix $
else gp = lindgen((size(*SignalLog.data,/DIM))[0])
if n_elements(*SignalLog.err) eq 0 then begin
if n_elements(snr) eq 0 then snr = 100
mean_error = mean((*SignalLog.data)[gp], /NAN) / snr
if not finite(mean_error) then $
message, 'Cannot compute the mean of the signal!'
*SignalLog.err = (*SignalLog.data) * 0 + mean_error
endif
negerr = where((*SignalLog.err)[gp] le 0, cnt, COMPLEM=poserr)
if cnt eq n_elements((*SignalLog.err)[gp]) then $
message, 'The noise is negative!!!'
if cnt gt 0 then $
(*SignalLog.err)[gp[negerr]] = min((*SignalLog.err)[gp[poserr]])
weight = 1D / ((*SignalLog.err)[gp])^2
large_weight = where(weight gt 100*mean(weight), cnt)
if cnt gt 0 then message, /INFO, $
'Some pixels have more than 100 times the average weight ... '+ $
'it may be an error (up to ' + strtrim(max(weight)/mean(weight),2)+')'
lamrange = uly_spect_get(SignalLog, /WAVERANGE, STATUS=status)
if status ne 0 then message, 'Could not obtain WAVERANGE for input spectrum'
velscale = SignalLog.step * 299792.458d
status = uly_fit_init(cmp, WAVERANGE=lamrange, VELSCALE=velscale, QUIET=quiet)
if status ne 0 then begin
message, 'Fit initialization failed, abort', /CONT
return, 0
endif
model_range = exp(cmp[0].start + [0.5,cmp[0].npix-1.5] * cmp[0].step)
SignalLog = uly_spect_extract(SignalLog, WAVERANGE=model_range, /OVER)
if min(cmp.npix) gt (size(*SignalLog.data))[1]+1 then begin
print, 'The number of pix in the model is greater than in Observation'
print, '* THIS IS PROBABLY A BUG IN THE PROGRAM *'
print, 'Please report it'
print, cmp.npix, ' vs. ', (size(*SignalLog.data))[1]
endif
if not keyword_set(mdegree) then mdegree = 10
if not keyword_set(adegree) then adegree = -1
if n_elements(kmoment) eq 0 then kmoment = 2
if n_elements(kfix) gt 0 then begin
if n_elements(kfix) gt kmoment then $
message, 'The number of elements of KFIX should not exceed '+$
strtrim(string(kmoment),2)
endif
if n_elements(dg) eq 0 then sigma_guess = velscale else sigma_guess = dg
kguess = [0, sigma_guess]
xx = proj[*, 0] & yy = proj[*, 1]
xname = '' & yname = ''
xunit = '' & yunit = ''
xdispf = '' & ydispf = ''
if xx[0] ne -1 then begin
if xx[1] ne -1 then begin
fixed_x = (*cmp[xx[0]].para)[xx[1]].fixed
guess_x = *(*cmp[xx[0]].para)[xx[1]].guess
(*cmp[xx[0]].para)[xx[1]].fixed = 1
if n_elements((*cmp[xx[0]].para)[xx[1]].name) gt 0 then begin
xname = (*cmp[xx[0]].para)[xx[1]].name
xunit = (*cmp[xx[0]].para)[xx[1]].unit
xdispf = (*cmp[xx[0]].para)[xx[1]].dispf
endif
if n_elements(xnode) le 1 then begin
nnode = 10
if n_elements(xnode) eq 1 then if xnode ge 2 then nnode = xnode
if n_elements((*cmp[xx[0]].para)[xx[1]].limits) eq 2 then begin
xgr0 = ((*cmp[xx[0]].para)[xx[1]].limits)[0]
xgr1 = ((*cmp[xx[0]].para)[xx[1]].limits)[1]
xgrid = xgr0 + dindgen(nnode)*(xgr1-xgr0)/(nnode-1)
xgrid[0] += (xgrid[1]-xgrid[0])*0.1
xgrid[nnode-1] -= (xgrid[1]-xgrid[0])*0.1
endif else message, 'There are no limits in the cmp, give XNODE'
endif else xgrid = xnode
endif else begin
if n_elements(xnode) le 1 then $
xgrid = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100] $
else xgrid = xnode
guess_x = cmp[xx[0]].lim_weig
endelse
endif else begin
kfix[xx[1]] = 1
nnode = 10
if n_elements(xnode) eq 1 then if xnode ge 2 then nnode = xnode
if n_elements(xnode) le 1 then xgrid = 10.+190.*dindgen(nnode)/(nnode-1) $
else xgrid = xnode
case xx[1] of
0 : xname = 'cz'
1 : xname = 'Velocity dispersion'
else : message,'Not valid LOSVD value, we can fix only v and sigma'
endcase
xunit = 'km/s'
endelse
if yy[0] ne -1 then begin
if yy[1] ne -1 then begin
fixed_y = (*cmp[yy[0]].para)[yy[1]].fixed
guess_y = *(*cmp[yy[0]].para)[yy[1]].guess
(*cmp[yy[0]].para)[yy[1]].fixed = 1
if n_elements((*cmp[yy[0]].para)[yy[1]].name) gt 0 then begin
yname = (*cmp[yy[0]].para)[yy[1]].name
yunit = (*cmp[yy[0]].para)[yy[1]].unit
ydispf = (*cmp[yy[0]].para)[yy[1]].dispf
endif
if n_elements(ynode) le 1 then begin
nnode = 10
if n_elements(ynode) eq 1 then if ynode ge 2 then nnode = ynode
if n_elements((*cmp[yy[0]].para)[yy[1]].limits) eq 2 then begin
ygr0 = ((*cmp[yy[0]].para)[yy[1]].limits)[0]
ygr1 = ((*cmp[yy[0]].para)[yy[1]].limits)[1]
ygrid = ygr0 + dindgen(nnode)*(ygr1-ygr0)/(nnode-1)
ygrid[0] += (ygrid[1]-ygrid[0])*0.1
ygrid[nnode-1] -= (ygrid[1]-ygrid[0])*0.1
endif else message, 'No limits in CMP found, give YNODES'
endif else ygrid = ynode
endif else begin
if n_elements(ynode) le 1 then $
ygrid = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100] $
else ygrid = ynode
guess_y = cmp[yy[0]].lim_weig
endelse
endif else begin
kfix[yy[1]] = 1
nnode = 10
if n_elements(ynode) eq 1 then if ynode ge 2 then nnode = ynode
if n_elements(ynode) le 1 then ygrid = 10.+190.*dindgen(nnode)/(nnode-1) $
else ygrid = ynode
case yy[1] of
0 : yname = 'cz'
1 : yname = 'Velocity dispersion'
else : message,'Not valid LOSVD value, we can fix only v and sigma'
endcase
yunit = 'km/s'
endelse
model_range = exp(cmp[0].start + [0,cmp[0].npix-1] * cmp[0].step)
SignalLog = uly_spect_extract(SignalLog, WAVERANGE=model_range, /OVER)
i_elem = n_elements(xgrid)
j_elem = n_elements(ygrid)
chimap = {xnode:xgrid, ynode:ygrid, map: dblarr(i_elem, j_elem), $
xtitle:xname, ytitle:yname, $
xunit:xunit, yunit:yunit}
undefine, xgrid & undefine, ygrid
if not keyword_set(quiet) then $
print, 'Computing Chi square map on', n_elements(chimap.xnode), $
' X', n_elements(chimap.ynode), ' elements.'
totnode = n_elements(chimap.xnode)*n_elements(chimap.ynode)
node = 0
for i = 0, i_elem - 1 do begin
for j = 0, j_elem - 1 do begin
if xx[0] ne -1 then begin
if xx[1] eq -1 then $
cmp[xx[0]].lim_weig = [chimap.xnode[i], chimap.xnode[i]] $
else $
*(*cmp[xx[0]].para)[xx[1]].guess = chimap.xnode[i]
endif else begin
kguess[xx[1]] = chimap.xnode[i]
endelse
if yy[0] ne -1 then begin
if yy[1] eq -1 then $
cmp[yy[0]].lim_weig = [chimap.ynode[j], chimap.ynode[j]] $
else $
*(*cmp[yy[0]].para)[yy[1]].guess = chimap.ynode[j]
endif else begin
kguess[yy[1]] = chimap.ynode[j]
endelse
solution = uly_fit (SignalLog, CMP=cmp, $
KMOMENT=kmoment, KGUESS=kguess, KFIX=kfix, $
MDEGREE=mdegree, ADEGREE=adegree, /QUIET, $
CLEAN=clean)
chimap.map[i,j] = solution.chisq
node = node+1
if not keyword_set(quiet) then $
print, $
FO='(%"X = %7.1f, Y = %5.2f, chisq = %7.4f (%5.1f%% done)")', $
chimap.xnode[i], chimap.ynode[j], chimap.map[i,j], 100.*node/totnode
if keyword_set(plot) then begin
uly_chimap_plot, chimap, PS=ps, /QUIET
endif
endfor
endfor
if xx[0] ne -1 then begin
if xx[1] ne -1 then begin
(*cmp[xx[0]].para)[xx[1]].fixed = fixed_x
*(*cmp[xx[0]].para)[xx[1]].guess = guess_x
endif else cmp[xx[0]].lim_weig = guess_x
endif
if yy[0] ne -1 then begin
if yy[1] ne -1 then begin
(*cmp[yy[0]].para)[yy[1]].fixed = fixed_y
*(*cmp[yy[0]].para)[yy[1]].guess = guess_y
endif else cmp[yy[0]].lim_weig = guess_y
endif
if xdispf eq 'exp' then chimap.xnode = exp(chimap.xnode)
if ydispf eq 'exp' then chimap.ynode = exp(chimap.ynode)
if keyword_set(plot) then uly_chimap_plot, chimap, PS=ps, QUIET=quiet
if n_elements(file_out) gt 0 then uly_chimap_write, chimap, file_out
return, chimap
end
Part of