pro lineid_plot,wave,flux,wline,text1,text2, extend=extend, $
	lcharthick = lcharthick,lcharsize=lcharsize,window=window, $
	 _EXTRA = extra
;+
; NAME:
;	LINEID_PLOT
; PURPOSE:
;	 Plot spectrum with specified line identifications annotated at the
;	 top of the plot.
;
; CALLING SEQUENCE:
;	lineid_plot, wave, flux, wline, text1, [ text2, 
;			LCHARSIZE=, LCHARTHICK=, EXTEND =, ...plotting keywords]
;
; INPUTS:
;	wave - wavelength vector for the plot
;	flux - flux vector
;	wline - wavelength vector of line identifications.  (only the lines 
;		between	the plot limits will be used)
;	text1 - string array of text to be used to annotate each line
;	text2 - (OPTIONAL) second string array of text to be used for
;		line annotation.  Since the text is written with
;		proportional spaced characters, TEXT2 can be used if
;		you want two sets of annotation to be alinged:
;
;		eg:	Cr IV  1390.009
;			Fe V   1390.049
;			Ni IV  1390.184
;			    instead of
;			Cr IV 1390.009
;			Fe V 1390.049
;			Ni IV 1390.184
;
; OPTIONAL KEYWORD INPUTS:
;	EXTEND - specifies that the annotated lines should have a dotted line 
;		extended to the spectrum to indicate the line position.  
;		EXTEND can be a scalar (applies to all lines) or a vector with
;		a different value for each line.  The value of EXTEND gives 
;		the line IDL plot line thickness for the dotted lines.
;		If EXTEND is a vector each dotted line can have a different 
;		thickness.  A value of 0 indicates that no dotted line is to 
;		be drawn. (default = scalar 0)
;	LCHARSIZE - the character size of the annotation for each line.
;		If can be a vector so that different lines are annotated with 
;		different size characters.  LCHARSIZE can be used to make 
;		stronger lines have a larger annotation. (default = scalar 1.0).
;	LCHARTHICK = the character thickness of the annotation for each line. 
;		It can be a vector so that different lines are annotated with 
;		characters of varying thickness.   LCHARTHICK can be used to 
;		make stronger lines have a bolder annotation. 
;		(default = !p.charthick)
;
;	LINEID_PLOT uses the _EXTRA facility to allow the use of any cgPLOT
;	keywords (e.g. AXISCOLOR, LINESTYLE, CHARSIZE) to be passed to the 
;       plot.
;
; SIDE EFFECTS:
;	Program uses SET_VIEWPORT to set the !P.POSITION parameter to allow
;	room for the annotation.   This system variable can be reset to the 
;	default value by setting !P.POSTION=0 or typing SET_VIEWPORT with no 
;	parameters
;
; OPERATIONAL NOTES:
;	Once the program has completed, You can use OPLOT to draw additional
;	plots on the display. 
;
;	If your annotated characters are not being rotated properly,
;	try setting !P.FONT to a non zero value.
; EXAMPLE:
;	Annotate some interstellar lines between 1240 and 1270 A.
;
;	IDL> w = 1240+ indgen(300)*0.1    ;Make a wavelength vector
;	IDL> f = randomn(seed,300)        ;Random flux vector
;	IDL> id = ['N V','Si II','Si II','Si II']   ;Line IDs
;	IDL> wl = [1242.80,1260.42,1264.74,1265.00] ;Line positions
;	IDL> lineid_plot,w,f,wl,id,wl,/ext
;
;	Note that LINEID_PLOT is smart enough not to overlap the annotation
;	for the two closely spaced lines at 1264.74 and 1265.00	
; HISTORY:
;	version 1  D. Lindler Jan, 1992
;	Sept 27, 1993  DJL  fixed bug in /extend option
;	Apr 19, 1994 DJL corrected bug in sorting of charthick (cthick)
;	Sep 1996, W. Landsman,  added _EXTRA keyword, changed keyword names
;		CHARTHICK==>LCHARTHICK, CHARSIZE==>LCHARSIZE
;       Work with !P.MULTI   W. Landsman   December 2003
;       Use Coyote graphics routines  W. Landsman February 2011
;-
;----------------------------------------------------------------------------
	On_error,2

	if n_params() lt 4 then begin
	   print,'Syntax - LINEID_PLOT, wave, flux, wline, text1 [,text2, '
	   print,'       LCHARTHICK=, EXTEND=, LCHARSIZE= ...plotting keywords]'
	   return
	end
;
; initialization
;

	setdefaultvalue, lcharsize, 1
	n = n_elements(wline)
	setdefaultvalue,text2,strarr(n)
	if n_elements(lcharsize) eq 1 then csize = replicate(lcharsize,n) $
				     else csize = lcharsize
	setdefaultvalue, extend, 0
	if n_elements(extend) eq 1 then ethick = replicate(extend,n) $
				   else ethick = extend
	if n_elements(lcharthick) eq 0 then cthick = !p.charthick $
				      else cthick = lcharthick
	if n_elements(cthick) eq 1 then cthick = replicate(cthick,n)
;
; First make a plot without any data to get the region size.    Then use
; the position keyword to assign a plot area that allows room for the 
; line annotation and plot the data
;       
        plot,wave,flux,xsty=4,ysty=4,/nodata,/noerase
        x0 = !X.region[0]
        y0 = !Y.region[0]
        xsize = !X.region[1] - x0
        ysize = !Y.region[1] - y0
        pos = [x0+xsize*0.13,y0+ysize*0.1, x0+xsize*0.95, y0+ysize*0.65]
	cgplot,wave,flux,_EXTRA=extra,pos = pos, Window=window       
        if keyword_set(window) then cgcontrol,execute=0
;
; get data ranges
;
	xmin = !x.crange[0]
	xmax = !x.crange[1]
	ymin = !y.crange[0]
	ymax = !y.crange[1]
	xrange = xmax-xmin
	yrange = ymax-ymin
;
; find lines within x range and sort them
;
	good = where((wline gt xmin) and (wline lt xmax),nlines)
	if nlines lt 1 then return
	wl = wline[good]
	csize = csize[good] & cthick = cthick[good] & ethick = ethick[good]
	txt1 = text1[good] & txt2 = text2[good] 

	sub = sort(wl)
	wl = wl[sub] & csize = csize[sub] & ethick = ethick[sub]
	cthick = cthick[sub] 
	txt1 = txt1[sub] & txt2 = txt2[sub] 
	maxids = 65/(total(csize)/nlines)   ;maximum number of identifications
	if nlines gt maxids then begin
		print,'Too many lines to mark'
		return
	endif

;
; determine character height in wavelength units
;
	char_height = abs(xrange) / 65 * csize
;
; adjust wavelengths of where to print the line ids
;
	wlp = wl		;wavelength to print text
;
; test to see if we can just equally space the annotated lines
;
	if (nlines gt maxids*0.85) and (n_elements(charsize) eq 1) then begin
		wlp = findgen(nlines) * (xrange/(nlines-1)) + xmin
		goto,print_text
	end
;
; iterate to find room to annotate each line
;
	changed = 1		;flag saying we moved a wlp position
	niter = 0
	factor = 0.35		;size of adjustments in text position
	while changed do begin	;iterate
	    changed = 0
	    for i=0,nlines-1 do begin
;
; determine the difference of the annotation from the lines on the
; left and right of it and the required separation
;
		if i gt 0 then begin
			diff1 = wlp[i]-wlp[i-1]
			separation1 = (char_height[i]+char_height[i-1])/2.0
		    end else begin
			diff1 = wlp[i] - xmin + char_height[i]*1.01
			separation1 = char_height[i]
		end

		if i lt (nlines-1) then begin
			diff2 = wlp[i+1] - wlp[i]
			separation2 = (char_height[i]+char_height[i+1])/2.0
		    end else begin
			diff2 = xmax + char_height[i]*1.01 - wlp[i]
			separation2 = char_height[i]
		end
;
; determine if line annotation should be moved
;
		if (diff1 lt separation1) or (diff2 lt separation2) then begin
		    if wlp[i] eq xmin then diff1 = 0
		    if wlp[i] eq xmax then diff2 = 0
		    if diff2 gt diff1 then $
				wlp[i] = (wlp[i] + separation2*factor) < xmax $
			   else wlp[i] = (wlp[i] - separation1*factor) > xmin
		    changed = 1
		endif

	    end

	    if niter eq 300 then $		; fine adjustment for 
			factor = factor/3	; crowded field
			

	    if niter eq 1000 then changed=0	; stop at 1000 iterations
	    niter = niter + 1

	endwhile

;
; print line id's
;
print_text:
	maxcsize = max(csize)
	start_arrow = ymax + yrange/60
	bend1 = ymax + yrange/30
	bend2 = ymax + (yrange/30)*3
	stop_arrow = ymax + (yrange/30)*4
	start_text1 = stop_arrow + yrange/50*maxcsize
	start_text2 = start_text1 +  $
			max(strlen(strtrim(txt1,1)))*yrange/50*maxcsize
	start_text3 = start_text2 +  $
			max(strlen(strtrim(txt2,1)))*yrange/50*maxcsize

	for i=0,nlines-1 do begin
		cgplots,[wl[i],wl[i],wlp[i],wlp[i]], ADDCMD=window, $
		      [start_arrow,bend1,bend2,stop_arrow]
		cgtext,wlp[i] + char_height[i]/2, start_text1, txt1[i], $
		    orientation = 90, size=csize[i], charthick = cthick[i],$
		    window = window
		cgtext,wlp[i] + char_height[i]/2, start_text2, txt2[i], $
		  orientation = 90, size=csize[i], charthick = cthick[i],$
		  window= window
	endfor
;
; extend selected lines down to the spectrum
;
	good = where((ethick gt 0) and (wl gt xmin) and (wl lt xmax),n)
	if n lt 1 then return
	ww = wl[good]
	ethick = ethick[good]
	linterp,wave,flux,ww,ff
	ymax = !y.crange[1]
	ymin = !y.crange[0]
	offset = (ymax-ymin)/20.0
	for i=0,n-1 do $
	   cgplots,[ww[i],ww[i]],[(ff[i]+offset)<ymax>ymin,ymax], $
				line=2,thick = ethick[i],ADDCMD=window
	if keyword_set(window) then cgcontrol,execute=1			

return
end
