; $Id: bar_plot.pro,v 1.10 2002/02/06 21:45:40 scottm Exp $ ; ; Copyright (c) 1990-2002, Research Systems, Inc. All rights reserved. ; Unauthorized reproduction prohibited. ; ;Modified by Ankur Desai to include nolabel keyword 2002 pro my_bar_plot,values,baselines=baselines,colors=colors,barnames=barnames, $ title=title,xtitle=xtitle,ytitle=ytitle,baserange=baserange, $ barwidth=barwidth,barspace=barspace,baroffset=baroffset, $ outline=outline,overplot=overplot,background=background, $ rotate=rotate,nolabel=nolabel,range=range ;+ ; NAME: ; BAR_PLOT ; ; PURPOSE: ; Create a bar graph, or overplot on an existing one. ; ; CATEGORY: ; Graphics. ; ; CALLING SEQUENCE: ; BAR_PLOT, Values ; ; INPUTS: ; Values: A vector containing the values to be represented by the bars. ; Each element in VALUES corresponds to a single bar in the ; output. ; ; KEYWORD PARAMETERS: ; BASELINES: A vector, the same size as VALUES, that contains the ; base value associated with each bar. If not specified, ; a base value of zero is used for all bars. ; ; COLORS: A vector, the same size as VALUES, containing the color index ; to be used for each bar. If not specified, the colors are ; selected based on spacing the color indices as widely as ; possible within the available colors (specified by D.N_COLORS). ; ; BARNAMES: A string array, containing one string label per bar. ; If the bars are vertical, the labels are placed beneath ; them. If horizontal (rotated) bars are specified, the labels ; are placed to the left of the bars. ; ; TITLE: A string containing the main title to for the bar plot. ; ; XTITLE: A string containing the title for the X axis. ; ; YTITLE: A string containing the title for the Y axis. ; ; BASERANGE: A floating-point scalar in the range 0.0 to 1.0, that ; determines the fraction of the total available plotting area ; (in the direction perpendicular to the bars) to be used. ; If not specified, the full available area is used. ; ; BARWIDTH: A floating-point value that specifies the width of the bars ; in units of "nominal bar width". The nominal bar width is ; computed so that all the bars (and the space between them, ; set by default to 20% of the width of the bars) will fill the ; available space (optionally controlled with the BASERANGE ; keyword). ; ; BARSPACE: A scalar that specifies, in units of "nominal bar width", ; the spacing between bars. For example, if BARSPACE is 1.0, ; then all bars will have one bar-width of space between them. ; If not specified, the bars are spaced apart by 20% of the bar ; width. ; ; BAROFFSET: A scalar that specifies the offset to be applied to the ; first bar, in units of "nominal bar width". This keyword ; allows, for example, different groups of bars to be overplotted ; on the same graph. If not specified, the default offset is ; equal to BARSPACE. ; ; OUTLINE: If set, this keyword specifies that an outline should be ; drawn around each bar. ; ; OVERPLOT: If set, this keyword specifies that the bar plot should be ; overplotted on an existing graph. ; ; BACKGROUND: A scalar that specifies the color index to be used for ; the background color. By default, the normal IDL background ; color is used. ; ; ROTATE: If set, this keyword indicates that horizontal rather than ; vertical bars should be drawn. The bases of horizontal bars ; are on the left, "Y" axis and the bars extend to the right. ; ; OUTPUTS: ; A bar plot is created, or an existing one is overplotted. ; ; EXAMPLE: ; By using the overplotting capability, it is relatively easy to create ; stacked bar charts, or different groups of bars on the same graph. ; ; For example, if ARRAY is a two-dimensional array of 5 columns and 8 ; rows, it is natural to make a plot with 5 bars, each of which is a ; "stacked" composite of 8 sections. First, create a 2D COLORS array, ; equal in size to ARRAY, that has identical color index values across ; each row to ensure that the same item is represented by the same color ; in all bars. ; ; With ARRAYS and COLORS defined, the following code fragment ; illustrates the creation of stacked bars (note that the number of rows ; and columns is arbitrary): ; ; !Y.RANGE = [0,ymax] ; Scale range to accommodate the total bar lengths. ; BASE = INTARR(NROWS) ; FOR I = 0, NROWS-1 DO BEGIN ; BAR_PLOT, ARRAY(*,I), COLORS=COLORS(*,I), BASELINES=BASE, $ ; BARWIDTH=0.75, BARSPACE=0.25, OVER=(I GT 0) ; BASE = BASE + ARRAY(*,I) ; ENDFOR ; ; To plot each row of ARRAY as a clustered group of bars within the same ; graph, use the BASERANGE keyword to restrict the available plotting ; region for each set of bars. The sample code fragment below ; illustrates this method: ; ; FOR I = 0, NROWS-1 DO $ ; BAR_PLOT, ARRAY(*,I), COLORS=COLORVECT, BARWIDTH=0.8,BARSPACE=0.2, $ ; BAROFFSET=I*((1.0+BARSPACE)*NCOLS), OVER=(I GT 0), BASERANGE=0.19 ; ; where NCOLS is the number of columns in ARRAY, and COLORVECT is a ; vector containing the color indices to be used for each group of ; bars. (In this example, each group uses the same set of colors, but ; this could easily be changed.) ; ; MODIFICATION HISTORY: ; August 1990, T.J. Armitage, RSI, initial programming. Replacement ; for PLOTBAR and OPLOTBAR routines written by William Thompson. ; ; September 1990, Steve Richards, RSI, changed defaults to improve the ; appearance of the bar plots in the default mode. Included ; spacing the bars slightly. ;- if (n_params(d) eq 0) then begin ;Print call & return if no parameters print,'bar_test,values,baselines=baselines,colors=colors,barnames=barnames,$' print,' title=title,xtitle=xtitle,ytitle=ytitle,baserange=baserange, $' print,' barwidth=barwidth,barspace=barspace,baroffset=baroffset, $' print,' outline=outline,overplot=overplot,background=background, $' print,' rotate=rotate' return endif nbars=n_elements(values) ; Determine number of bars ; Baselines (bars extend from baselines through values); default=0 if not(keyword_set(baselines)) then baselines=intarr(nbars) ; Default colors spaced evenly in current color table if not(keyword_set(colors)) then $ colors=fix((!d.n_colors/float(nbars))*(indgen(nbars)+0.5)) ; Labels for the individual bars; none by default if not(keyword_set(barnames)) then barnames=strarr(nbars)+' ' ; Main title if not(keyword_set(title)) then title='' ; Centered title under X-axis if not(keyword_set(xtitle)) then xtitle='' ; Title for Y-axis if not(keyword_set(ytitle)) then ytitle='' ; Fraction (0-1) of full X range to use if not(keyword_set(baserange)) then baserange=1.0 ; Space betw. bars, taken from nominal bar widths; default is none If not(keyword_set(barspace)) then barspace=0.2 ; Bar width scaling factor, relative to nominal if not(keyword_set(barwidth)) then barwidth=1.0 - barspace - barspace / nbars ; Initial X offset, in scaled bar widths; default is none if not(keyword_set(baroffset)) then baroffset=barspace/barwidth ; Outline of bars; default is none outline = keyword_set(outline) ; Overplot (do not erase the existing display); default is to create new plot overplot = keyword_set(overplot) ; Background color index; defaults to 0 (usually black) if not specified if not(keyword_set(background)) then background=0 ; Rotate (make horizontal bars); default is vertical bars rotate = keyword_set(rotate) mnB = MIN(baselines, MAX=mxB, /NAN) mnV = MIN(values, MAX=mxV, /NAN) IF n_elements(range) EQ 0 THEN range=[mnB < mnV, $ ;Minimum of bases & values mxB > mxV] ;Maximum of bases & values if (rotate) then begin ;Horizontal bars if (!x.range[0] eq 0) and (!x.range[1] eq 0) $ ;Determine range for X-axis then xrange=range $ else xrange=!x.range ;Or, use range specified if (!y.range[0] eq 0) and (!y.range[1] eq 0) $ ;Plot will calculate then $ ; defaults for X, but not yrange = [0, n_elements(values)] $ ; for Ys, so fill in here. else $ yrange=!y.range ;Axis perpend. to bars yticks=1 ;Suppress ticks in plot ytickname=strarr(2)+' ' xticks=0 xtickname=strarr(1)+'' endif else begin ;Vertical bars if (!y.range[0] eq 0) and (!y.range[1] eq 0) $ ;Determine range for Y-axis then yrange=range $ else yrange=!y.range ;Or, use range specified xrange=!x.range ;Axis perpend. to bars xticks=1 ;Suppress ticks in plot xtickname=strarr(2)+' ' yticks=0 ytickname=strarr(1)+'' endelse if (overplot eq 0) then $ ;Create new plot, no data plot,[values],/nodata,title=title,xtitle=xtitle,ytitle=ytitle, $ noerase=overplot,xrange=xrange,yrange=yrange,xticks=xticks, $ xtickname=xtickname,yticks=yticks,ytickname=ytickname, $ xstyle=1,ystyle=1,/data,background=background if (rotate) then begin ;Horizontal bars base_win=!y.window ;Window range in Y scal_fact=!x.s ;Scaling factors tick_scal_fact=!y.s ;Tick scaling factors endif else begin ;Vertical bars base_win=!x.window ;Window range in X scal_fact=!y.s ;Scaling factors tick_scal_fact=!x.s ;Tick scaling factors endelse winrange=baserange*(base_win[1]-base_win[0]) ;Normal. window range barsize=barwidth*winrange/nbars ;Normal. bar width winoffset=base_win[0]+(baroffset*barsize) ;Normal. first offset bases=scal_fact[0]+(scal_fact[1]*baselines) ;Baselines, in normal coor. normal=scal_fact[0]+(scal_fact[1]*values) ;Values, in normal coor. barstart=indgen(nbars)*(barsize+barspace*(winrange/nbars)) ;Coor. at left edges tickv=winoffset+barstart+(0.5*barsize) ;Tick coor. (centered) for i=0,nbars-1 do begin ;Draw the bars width=winoffset+[barstart[i],barstart[i], $ ;Compute bar width (barstart[i]+barsize),(barstart[i]+barsize)] length=[bases[i],normal[i],normal[i],bases[i]] ;Compute bar length if (rotate) then begin ;Horizontal bars x=length ;X-axis is "length" axis y=width ;Y-axis is "width" axis endif else begin ;Vertical bars x=width ;X-axis is "width" axis y=length ;Y-axis is "length" axis endelse polyfill,x,y,color=colors[i],/normal ;Polyfill with color if (outline) then plots,x,y,/normal ;Outline using !p.color endfor tickv=(tickv-tick_scal_fact[0])/tick_scal_fact[1] ;Locations of the ticks IF NOT keyword_set(nolabel) THEN BEGIN if (rotate) then $ ;Label the bars (Y-axis) axis,yaxis=0,ystyle=1,yticks=(nbars-1),ytickv=tickv,ytickname=barnames, $ yticklen=0.0 $ else $ ;Label the bars (X-axis) axis,xaxis=0,xstyle=1,xticks=(nbars-1),xtickv=tickv,xtickname=barnames, $ xticklen=0.0 ENDIF return end