pro legend,labels,pos=pos,linestyle=linestyle,psym=psym,$ color=color,thick=thick,fg_color=fg_color,bg_color=bg_color,$ box=box,numsym=numsym,ystretch=ystretch,silent=silent,$ sympro=sympro ;+ ; ROUTINE: legend ; ; PURPOSE: draws a plot legend ; ; USEAGE: legend,labels,pos=pos,linestyle=linestyle,psym=psym,$ ; color=color,thick=thick,fg_color=fg_color,bg_color=bg_color,$ ; box=box,numsym=numsym,ystretch=ystretch,silent=silent,$ ; sympro=sympro ; ; ; INPUT: ; labels an array of labels (required). Elements of LABELS ; which do not begin with the characters ".l",".c", or ; ".r" are treated as legend labels. These elements are ; drawn to the right of a line or symbol of given ; LINESTYLE, PSYM, COLOR or THICK type. The total number ; of labels in LABELS (i.e., not counting legend titles) ; should correspond to the number of elements in those ; input parameters. ; ; If any of the label strings start with the characters ; ".l",".c", or ".r" that element of the LABELS array is ; treated as a legend title. Legend titles appear as ; left justified (".l"), centered (".c") or right ; justified (".r") strings in the legend box and do not ; correspond to elements of LINESTYLE, PSYM, COLOR or ; THICK. Null strings ("") or blank strings (" ") are ; also treated as legend titles. Lines or symbols are ; not drawn to the right of legend titles. ; ; If none of the keywords, LINESTYPE, PSYM, COLOR or ; THICK are set, then all elements of LABELS will be ; treated as legend titles and will be left justified ; unless prepended by ".c" or ".r". ; ; Consider, ; ; labels=['.ctitle','1','2','.lsecond title,'a','b'] ; linestyle= [1,2,3,4] ; ; In this example LABELS contains 4 legend labels and ; 2 legend titles. The correspondence with the linestyle ; input parameter is as follows: ; ; labels(1) <==> linestyle(0) ; labels(2) <==> linestyle(1) ; labels(4) <==> linestyle(2) ; labels(5) <==> linestyle(3) ; ; To simplify input, LABELS may also be specified as a single ; string with the different LABEL elements separated by ; backslashes (\) (E.g., labels='.cCloud height\\1\2\3\4\5' ; ; KEYWORD INPUT: ; ; pos position and size of legend area in normalized data ; coordinates. Format of this four element vector is ; [x0,y0,x1,y1] where x0,y0 is the position of lower ; left corner and x1,y1 is the position of the upper ; right corner. For example pos=[.5,.5,.9,.9] specifies ; a legend in the upper right quadrant of the data ; window. If the POS parameter is not set or if POS is ; set to zero, then the CURBOX procedure is called to ; set the legend position interactively. ; ; NOTE: the value of POS can be retrieved by setting POS ; to a named variable which has an initial value of zero. ; ; linestyle an array of linestyle types, one for each label in LABELS ; ; psym an array of symbol types, one for each label in LABELS ; ; color an array of color indices, one for each label in LABELS. ; Any elements of COLOR set to -1 causes the default color, ; !P.COLOR, to be used. ; ; thick an array of line thicknesses, one for each label in LABELS ; (default=!p.thick) ; ; numsym number of symbol nodes used to indicate linestyle or symbol ; type. The length of the line is measured in units of 4 ; character widths so that the length of the line ; = 4*(NUMSYM-1) * X_CHARSIZE (default=3) ; ; fg_color color of box and legend titles (default=!P.COLOR) ; ; bg_color background color. Setting BG_COLOR erases the area ; covered by the legend (filling it with color BG_COLOR) ; prior to writing the legend. If both BG_COLOR and !p.color ; are zero then the background color is reset to 255 to ; gaurantee a readability. ; ; ; box if set draw a box around the legend text ; ; ystretch factor by which to increase vertical spacing of legend ; entries. (default = 1) ; ; NOTE: the aspect ratio of the legend box can be ; modified on the fly by shoving the cursor box against ; one of the window boundaries and pressing the middle ; button. ; ; silent if not set, print box position string to the terminal ; and show popup help on the CURBOX cursor routine ; ; silent=1 don't print position string ; ; silent=2 don't print position string, don't show help widget ; ; sympro the name of a procedure which creates symbols, for example ; USERSYMBOL in esrg_local. If the this keyword is present ; SYMPRO will be called to create each symbol specified ; in PSYM. ; ; OUTPUT: none ; ; PROCEDURE: When called without the POS keyword, the legend position ; and size is set with the CURBOX routine. The legend ; is positioned by dragging the box where you want the ; legend to appear. The size of the legend area can be ; decreased/increased by the left/middle mouse buttons. ; When the right mouse button is pressed the legend is ; drawn and a numerical positioning string giving the ; current value of the POS keyword is written to the ; terminal (nothing printed if SILENT is set). You ; can run LEGEND in batch mode by pasting this value of ; POS into the LEGEND command line. The best way to get ; good-looking legends on your hardcopies is to size ; your graphics window to the approximate shape of the ; output media. For example a plot which is to be ; printed in landscape mode should be previewed on a ; window which is approximately 1.4 times as wide as it ; is tall. ; ; NOTE: The values returned for the POS keyword are based ; on a computation of the length of the text strings ; in your legend. If you change the contents of the ; legend titles or if you change the default text ; font, you must rerun LEGEND in interactive mode to ; determine new values for the POS paramter. ; ; ; ;; EXAMPLE interactive mode (put the box anywhere you want and press ;; the right mouse button) ; ; dcolors ; plot,6*randf(20,3),/nodata ; for i=1,6 do oplot,i*randf(20,3),li=i-1,color=i ; lb='.cFirst bunch\\First\Second\Third\\.cSecond bunch\\forth\fifth\sixth' ; legend,lb,li=[0,1,2,3,4,5],/box,bg=0,color=[1,2,3,4,5,6] ; ;; EXAMPLE interactive mode. retrieve the value of POS for later calls: ; ; !p.multi=[0,1,2] ; plot,[0,.4],yrange=[0,1],li=0 & oplot,[0,.6],li=2 & oplot,[0,.9],li=3 ; legpos=0 ; lb=['.cLegend Demo','','one','two','three'] ; legend,lb,pos=legpos,li=[0,2,3] ; plot,[0,.4],yrange=[0,1],li=0 & oplot,[0,.6],li=2 & oplot,[0,.9],li=3 ; legend,lb,pos=legpos,li=[0,2,3] ; !p.multi=0 ; ; ;; EXAMPLE batch mode: ; ; plot,[-50,50],[0,1.5],/nodata & x=findgen(101)-50. ; li=indgen(6) & pos=[0.66,0.54,0.91,0.89] ; for i=0,5 do oplot,x,1./(1.+(x/(i+2))^2),li=li(i) ; labels='.cPlot Key\\First\Second\Third\Fourth\Fifth\Sixth' ; legend,' ',bg=4,pos=pos+.02,/box ; legend,labels,li=li,pos=pos,bg=10,/box ; ;; EXAMPLE batch mode with SYMPRO: ; ; plot,[-50,50],[0,1.5],/nodata & x=findgen(101)-50. ; psym=['TRIANGLE','DIAMOND','PENTAGON','CIRCLE','SQUARE','SPADE'] ; pos=[0.66,0.54,0.91,0.89] ; for i=0,5 do begin &$ ; usersymbol,psym(i) &$ ; oplot,x,1./(1.+(x/(i+2))^2),psym=8,symsize=2 &$ ; endfor ; labels='.cPlot Key\\First\Second\Third\Fourth\Fifth\Sixth' ; legend,' ',bg=4,pos=pos+.02,/box ; legend,labels,psym=psym,pos=pos,bg=10,/box,sympro='usersymbol' ; ; ; AUTHOR Paul Ricchiazzi ESRG 4dec92 ; ; REVISIONS ; 15dec92: added legend titles, and CHARSIZE parameter ; 11jan93: added numsym parameter ; 20jan93: added thick parameter ; 2feb93: fixed positioning bug legend titles ; 25mar93: removed the NOBOX option, now you set BOX to get a box ; 29mar93: added the bg_color option to blank out legend area before writing ; 8apr93: use CURBOX for cursor control and LENSTR for exact string size ; 27apr93: improved alignment symbol and label (ylab=yy-.3*charsize*cnvrty) ; 9jun93: center legend labels when legend titles are longer (see dxcen) ; 17jun93: added ystretch option to increase vertical spacing ; 17jun93: default line thickness read from !p.thick ; 30sep93: .l implied when LINESTYLE, PSYM, COLOR, THICK not set. see NOLINES ; 28Jun94: LABELS is now normal input param, not a keyword. ; 28Jun94: legend "titles" don't correspond to LINESTYLE, PSYM, COLOR, THICK ; vector elements; no need to put in dummy values. see examples ; 18Aug94: added SYMPRO option ; 29Dec04; allows for both line and symbol to be plotted together ;- on_error,2 n=n_elements(labels) if n eq 0 then message,'Must specify legend labels' if n eq 1 then labls=str_sep(labels,'\') else labls=labels n=n_elements(labls) jblnks=where(labls eq ' ',nblnks) if nblnks gt 0 then labls(jblnks)='.l ' if keyword_set(silent) eq 0 then silent=0 ; nls=n_elements(linestyle) nps=n_elements(psym) ncl=n_elements(color) ntk=n_elements(thick) nolines=nls eq 0 and nps eq 0 and ncl eq 0 and ntk eq 0 ; if keyword_set(numsym) eq 0 then numsym=3 if n_elements(fg_color) eq 0 then fgc=!p.color else fgc=fg_color if n_elements(ystretch) eq 0 then ystretch=1. titles=strarr(n) just=strarr(n) ; real label length = slenmx - 2*(number of exclamation marks) nlbls=0 for i=0,n-1 do begin ss=labls(i) if strmid(ss,0,1) eq '.' then begin just(i)=strmid(ss,1,1) tlen=strlen(ss)-2 ttt=strmid(ss,2,tlen) if ttt eq '' then titles(i)=' ' else titles(i)=ttt endif else begin if nolines or ss eq '' then begin just(i)='l' if ss eq '' then titles(i)=' ' else titles(i)=ss endif else begin nlbls=nlbls+1 endelse endelse endfor if nlbls gt 0 then begin if nps eq 0 and keyword_set(sympro) then $ message,'must specify PSYM when SYMPRO is set' if nls eq 0 then begin & linestyle=intarr(nlbls) & nls=nlbls & end if nps eq 0 then begin & psym=intarr(nlbls) & nps=nlbls & end if ncl eq 0 then begin & color=replicate(-1,nlbls) & ncl=nlbls & end if ntk eq 0 then begin & thick=replicate(!p.thick,nlbls) & ntk=nlbls & end nof='Number of ' mess=' does not match number of labels' if nls ne nlbls then message,nof+'linestyles'+mess,/continue if nps ne nlbls then message,nof+'psym types'+mess,/continue if ncl ne nlbls then message,nof+'colors'+mess,/continue if ntk ne nlbls then message,nof+'thicknesses'+mess,/continue if nls ne nlbls or nps ne nlbls or ncl ne nlbls or ntk ne nlbls then return endif cnvrtx=float(!d.x_ch_size)/!d.x_vsize ; conversion factor from cnvrty=float(!d.y_ch_size)/!d.y_vsize ; characters to normalized coordinates iti=where(titles eq '',niti) ; these labels are not legend titles if niti gt 0 then $ slenmx=max(lenstr(labls(iti)))+(4*(numsym-1)+2)*cnvrtx else slenmx=0 tlenmx=max(lenstr(titles)) xsize=(slenmx > tlenmx) + 2*cnvrtx ; add two character widths dxcen=.5*(xsize-2*cnvrtx-slenmx) ; offset to center legend labels ysize=1.1*(n+1)*cnvrty if max([!x.window,!y.window],min=mn) eq mn then $ plot,[0,1],[0,1],xstyle=4,ystyle=4,/nodata sx0=!x.window(0) sx1=!x.window(1)-sx0 sy0=!y.window(0) sy1=!y.window(1)-sy0 if keyword_set(pos) eq 0 then begin xsz=xsize*!d.x_size ysz=ysize*!d.y_size*ystretch if silent le 1 then curbox,x,y,xsz,ysz,/message else $ curbox,x,y,xsz,ysz s0=convert_coord(x-xsz/2,y-ysz/2,/device,/to_normal) s1=convert_coord(x+xsz/2,y+ysz/2,/device,/to_normal) x0=s0(0) ; x1=s1(0) ; normalized coordinates of y0=s0(1) ; legend box y1=s1(1) pos=[(x0-sx0)/sx1,(y0-sy0)/sy1,(x1-sx0)/sx1,(y1-sy0)/sy1] posstring=string(form='(a,4(f10.2,a))',$ ',pos=[',pos(0),',',pos(1),',',pos(2),',',pos(3),']') if keyword_set(silent) eq 0 then print,strcompress(posstring,/remove_all) endif else begin if n_elements(pos) ne 4 then message,'Incorrect POS specification' x0=sx0+pos(0)*sx1 ; x1=sx0+pos(2)*sx1 ; normalized coordinates of y0=sy0+pos(1)*sy1 ; legend box y1=sy0+pos(3)*sy1 ; endelse ; blank out legend area if n_elements(bg_color) ne 0 then begin if !p.color eq 0 and bg_color eq 0 then bgc=255 else bgc=bg_color polyfill,[x0,x1,x1,x0],[y0,y0,y1,y1],color=bgc,/normal endif if keyword_set(box) then begin xbox=[x0,x1,x1,x0,x0] ybox=[y0,y0,y1,y1,y0] plots,xbox,ybox,color=fgc,/norm endif ; charsize=(x1-x0)/xsize symsize=charsize dx=charsize*cnvrtx dy=1.1*cnvrty*(y1-y0)/ysize ; dy=1.1*charsize*cnvrty xlab=x0+dx+dxcen+(4*(numsym-1)+2)*dx ; if numsym eq 1 then begin xb=x0+dx+dxcen xbar=[xb,xb] endif else begin xbar=x0+dx+dxcen+4*(numsym-1)*dx*findgen(numsym)/(numsym-1) endelse yy=y1-dy jlbl=0 for i=0,n-1 do begin ylab=yy-.3*charsize*cnvrty if titles(i) eq '' then begin clr=color(jlbl) if clr eq -1 then clr=!p.color ls=linestyle(jlbl) ps=psym(jlbl) if keyword_set(sympro) then begin call_procedure,sympro,ps ps=8 endif thk=thick(jlbl) ybar=replicate(yy,numsym) plots,xbar,ybar,psym=ps,linestyle=ls,color=clr,/norm,$ symsize=symsize,thick=thk if(keyword_set(linestyle) and keyword_set(psym)) then $ plots,xbar,ybar,linestyle=ls,/norm,thick=thk xyouts,xlab,ylab,labls(i),color=fgc,charsize=charsize,/norm jlbl=jlbl+1 endif else begin case just(i) of 'l':begin & align=0.0 & xtitle=x0+dx & end 'c':begin & align=0.5 & xtitle=.5*(x0+x1) & end 'r':begin & align=1.0 & xtitle=x1-dx & end endcase xyouts,xtitle,ylab,titles(i),color=fgc,charsize=charsize,$ alignment=align,/norm endelse yy=yy-dy endfor return end