[2] | 1 | ;+ |
---|
[230] | 2 | ; |
---|
| 3 | ; @file_comments |
---|
[142] | 4 | ; Create a bar graph, or overplot on an existing one. |
---|
[2] | 5 | ; |
---|
[230] | 6 | ; @categories |
---|
[142] | 7 | ; Graphics |
---|
[2] | 8 | ; |
---|
[163] | 9 | ; @param Values {in}{required} {type=vector} |
---|
[142] | 10 | ; A vector containing the values to be represented by the bars. |
---|
| 11 | ; Each element in VALUES corresponds to a single bar in the |
---|
| 12 | ; output. |
---|
[2] | 13 | ; |
---|
[163] | 14 | ; @keyword BASELINES {type=vector} |
---|
[142] | 15 | ; A vector, the same size as VALUES, that contains the |
---|
| 16 | ; base value associated with each bar. If not specified, |
---|
| 17 | ; a base value of zero is used for all bars. |
---|
[2] | 18 | ; |
---|
[163] | 19 | ; @keyword COLORS {type=vector} |
---|
[142] | 20 | ; A vector, the same size as VALUES, containing the color index |
---|
| 21 | ; to be used for each bar. If not specified, the colors are |
---|
[163] | 22 | ; selected based on spacing the color indexes as widely as |
---|
[142] | 23 | ; possible within the available colors (specified by D.N_COLORS). |
---|
[2] | 24 | ; |
---|
[163] | 25 | ; @keyword BARNAMES {type=string} |
---|
[142] | 26 | ; A string array, containing one string label per bar. |
---|
| 27 | ; If the bars are vertical, the labels are placed beneath |
---|
| 28 | ; them. If horizontal (rotated) bars are specified, the labels |
---|
| 29 | ; are placed to the left of the bars. |
---|
[2] | 30 | ; |
---|
[163] | 31 | ; @keyword TITLE {type=string} |
---|
[142] | 32 | ; A string containing the main title to for the bar plot. |
---|
[2] | 33 | ; |
---|
[163] | 34 | ; @keyword XTITLE {type=string} |
---|
[142] | 35 | ; A string containing the title for the X axis. |
---|
[2] | 36 | ; |
---|
[163] | 37 | ; @keyword YTITLE {type=string} |
---|
[142] | 38 | ; A string containing the title for the Y axis. |
---|
[2] | 39 | ; |
---|
[163] | 40 | ; @keyword BASERANGE {type=float} |
---|
[142] | 41 | ; A floating-point scalar in the range 0.0 to 1.0, that |
---|
| 42 | ; determines the fraction of the total available plotting area |
---|
| 43 | ; (in the direction perpendicular to the bars) to be used. |
---|
| 44 | ; If not specified, the full available area is used. |
---|
[2] | 45 | ; |
---|
[163] | 46 | ; @keyword BARWIDTH {type=float} |
---|
[142] | 47 | ; A floating-point value that specifies the width of the bars |
---|
| 48 | ; in units of "nominal bar width". The nominal bar width is |
---|
| 49 | ; computed so that all the bars (and the space between them, |
---|
| 50 | ; set by default to 20% of the width of the bars) will fill the |
---|
| 51 | ; available space (optionally controlled with the BASERANGE |
---|
| 52 | ; keyword). |
---|
[2] | 53 | ; |
---|
[163] | 54 | ; @keyword BARSPACE {type=scalar} |
---|
[142] | 55 | ; A scalar that specifies, in units of "nominal bar width", |
---|
| 56 | ; the spacing between bars. For example, if BARSPACE is 1.0, |
---|
| 57 | ; then all bars will have one bar-width of space between them. |
---|
| 58 | ; If not specified, the bars are spaced apart by 20% of the bar |
---|
| 59 | ; width. |
---|
[2] | 60 | ; |
---|
[163] | 61 | ; @keyword BAROFFSET {default=BARSPACE}{type=scalar} |
---|
[142] | 62 | ; A scalar that specifies the offset to be applied to the |
---|
| 63 | ; first bar, in units of "nominal bar width". This keyword |
---|
| 64 | ; allows, for example, different groups of bars to be overplotted |
---|
[163] | 65 | ; on the same graph. |
---|
[2] | 66 | ; |
---|
[230] | 67 | ; @keyword OUTLINE |
---|
[142] | 68 | ; If set, this keyword specifies that an outline should be |
---|
| 69 | ; drawn around each bar. |
---|
[2] | 70 | ; |
---|
[230] | 71 | ; @keyword OVERPLOT |
---|
[142] | 72 | ; If set, this keyword specifies that the bar plot should be |
---|
| 73 | ; overplotted on an existing graph. |
---|
[2] | 74 | ; |
---|
[163] | 75 | ; @keyword BACKGROUND {default=The normal IDL background color is used}{type=scalar} |
---|
[142] | 76 | ; A scalar that specifies the color index to be used for |
---|
[163] | 77 | ; the background color. |
---|
[2] | 78 | ; |
---|
[230] | 79 | ; @keyword ROTATE |
---|
[142] | 80 | ; If set, this keyword indicates that horizontal rather than |
---|
| 81 | ; vertical bars should be drawn. The bases of horizontal bars |
---|
| 82 | ; are on the left, "Y" axis and the bars extend to the right. |
---|
[2] | 83 | ; |
---|
[230] | 84 | ; @examples |
---|
| 85 | ; By using the overplotting capability, it is relatively easy to create |
---|
[2] | 86 | ; stacked bar charts, or different groups of bars on the same graph. |
---|
| 87 | ; |
---|
| 88 | ; For example, if ARRAY is a two-dimensional array of 5 columns and 8 |
---|
| 89 | ; rows, it is natural to make a plot with 5 bars, each of which is a |
---|
| 90 | ; "stacked" composite of 8 sections. First, create a 2D COLORS array, |
---|
| 91 | ; equal in size to ARRAY, that has identical color index values across |
---|
| 92 | ; each row to ensure that the same item is represented by the same color |
---|
| 93 | ; in all bars. |
---|
| 94 | ; |
---|
| 95 | ; With ARRAYS and COLORS defined, the following code fragment |
---|
| 96 | ; illustrates the creation of stacked bars (note that the number of rows |
---|
| 97 | ; and columns is arbitrary): |
---|
| 98 | ; |
---|
| 99 | ; !Y.RANGE = [0,ymax] ; Scale range to accommodate the total bar lengths. |
---|
| 100 | ; BASE = INTARR(NROWS) |
---|
| 101 | ; FOR I = 0, NROWS-1 DO BEGIN |
---|
| 102 | ; BAR_PLOT, ARRAY(*,I), COLORS=COLORS(*,I), BASELINES=BASE, $ |
---|
| 103 | ; BARWIDTH=0.75, BARSPACE=0.25, OVER=(I GT 0) |
---|
| 104 | ; BASE = BASE + ARRAY(*,I) |
---|
| 105 | ; ENDFOR |
---|
| 106 | ; |
---|
| 107 | ; To plot each row of ARRAY as a clustered group of bars within the same |
---|
| 108 | ; graph, use the BASERANGE keyword to restrict the available plotting |
---|
| 109 | ; region for each set of bars. The sample code fragment below |
---|
| 110 | ; illustrates this method: |
---|
| 111 | ; |
---|
| 112 | ; FOR I = 0, NROWS-1 DO $ |
---|
| 113 | ; BAR_PLOT, ARRAY(*,I), COLORS=COLORVECT, BARWIDTH=0.8,BARSPACE=0.2, $ |
---|
| 114 | ; BAROFFSET=I*((1.0+BARSPACE)*NCOLS), OVER=(I GT 0), BASERANGE=0.19 |
---|
| 115 | ; |
---|
| 116 | ; where NCOLS is the number of columns in ARRAY, and COLORVECT is a |
---|
| 117 | ; vector containing the color indices to be used for each group of |
---|
| 118 | ; bars. (In this example, each group uses the same set of colors, but |
---|
| 119 | ; this could easily be changed.) |
---|
| 120 | ; |
---|
[230] | 121 | ; @history |
---|
| 122 | ; August 1990, T.J. Armitage, RSI, initial programming. Replacement |
---|
[2] | 123 | ; for PLOTBAR and OPLOTBAR routines written by William Thompson. |
---|
| 124 | ; |
---|
| 125 | ; September 1990, Steve Richards, RSI, changed defaults to improve the |
---|
| 126 | ; appearance of the bar plots in the default mode. Included |
---|
| 127 | ; spacing the bars slightly. |
---|
[142] | 128 | ; |
---|
[230] | 129 | ; @version |
---|
[142] | 130 | ; $Id$ |
---|
| 131 | ; |
---|
[2] | 132 | ;- |
---|
[232] | 133 | ; |
---|
[262] | 134 | PRO bar_plot, values, BASELINES=baselines, COLORS=colors, BARNAMES=barnames, $ |
---|
| 135 | TITLE=title, XTITLE=xtitle, YTITLE=ytitle, BASERANGE=baserange, $ |
---|
| 136 | BARWIDTH=barwidth, BARSPACE=barspace, BAROFFSET=baroffset, $ |
---|
| 137 | OUTLINE=outline, OVERPLOt=overplot, BACKGROUND=background, $ |
---|
| 138 | ROTATE=rotate, _EXTRA = ex |
---|
[114] | 139 | ; |
---|
| 140 | compile_opt idl2, strictarrsubs |
---|
| 141 | ; |
---|
[2] | 142 | if (n_params(d) eq 0) then begin ;Print call & return if no parameters |
---|
[240] | 143 | ras = report(['bar_test,values,baselines=baselines,colors=colors,barnames=barnames,$', $ |
---|
| 144 | ' title=title,xtitle=xtitle,ytitle=ytitle,baserange=baserange, $', $ |
---|
| 145 | ' barwidth=barwidth,barspace=barspace,baroffset=baroffset, $', $ |
---|
| 146 | ' outline=outline,overplot=overplot,background=background, $', $ |
---|
| 147 | ' rotate=rotate']) |
---|
[2] | 148 | return |
---|
| 149 | endif |
---|
| 150 | |
---|
| 151 | nbars=n_elements(values) ; Determine number of bars |
---|
| 152 | ; Baselines (bars extend from baselines through values); default=0 |
---|
| 153 | if not(keyword_set(baselines)) then baselines=intarr(nbars) |
---|
| 154 | ; Default colors spaced evenly in current color table |
---|
| 155 | if not(keyword_set(colors)) then $ |
---|
| 156 | colors=fix((!d.n_colors/float(nbars))*(indgen(nbars)+0.5)) |
---|
| 157 | ; Labels for the individual bars; none by default |
---|
| 158 | if not(keyword_set(barnames)) then barnames=strarr(nbars)+' ' |
---|
| 159 | ; Main title |
---|
| 160 | if not(keyword_set(title)) then title='' |
---|
| 161 | ; Centered title under X-axis |
---|
| 162 | if not(keyword_set(xtitle)) then xtitle='' |
---|
| 163 | ; Title for Y-axis |
---|
| 164 | if not(keyword_set(ytitle)) then ytitle='' |
---|
| 165 | ; Fraction (0-1) of full X range to use |
---|
| 166 | if not(keyword_set(baserange)) then baserange=1.0 |
---|
| 167 | ; Space betw. bars, taken from nominal bar widths; default is none |
---|
| 168 | If not(keyword_set(barspace)) then barspace=0.2 |
---|
| 169 | ; Bar width scaling factor, relative to nominal |
---|
| 170 | if not(keyword_set(barwidth)) then barwidth=1.0 - barspace - barspace / nbars |
---|
| 171 | ; Initial X offset, in scaled bar widths; default is none |
---|
| 172 | if not(keyword_set(baroffset)) then baroffset=barspace/barwidth |
---|
| 173 | ; Outline of bars; default is none |
---|
| 174 | outline = keyword_set(outline) |
---|
| 175 | ; Overplot (do not erase the existing display); default is to create new plot |
---|
| 176 | overplot = keyword_set(overplot) |
---|
| 177 | ; Background color index; defaults to 0 (usually black) if not specified |
---|
| 178 | if not(keyword_set(background)) then background=0 |
---|
| 179 | ; Rotate (make horizontal bars); default is vertical bars |
---|
| 180 | rotate = keyword_set(rotate) |
---|
| 181 | |
---|
| 182 | mnB = MIN(baselines, MAX=mxB, /NAN) |
---|
| 183 | mnV = MIN(values, MAX=mxV, /NAN) |
---|
| 184 | range=[mnB < mnV, $ ;Minimum of bases & values |
---|
| 185 | mxB > mxV] ;Maximum of bases & values |
---|
| 186 | |
---|
| 187 | if (rotate) then begin ;Horizontal bars |
---|
| 188 | if (!x.range[0] eq 0) and (!x.range[1] eq 0) $ ;Determine range for X-axis |
---|
| 189 | then xrange=range $ |
---|
| 190 | else xrange=!x.range ;Or, use range specified |
---|
| 191 | if (!y.range[0] eq 0) and (!y.range[1] eq 0) $ ;Plot will calculate |
---|
| 192 | then $ ; defaults for X, but not |
---|
| 193 | yrange = [0, n_elements(values)] $ ; for Ys, so fill in here. |
---|
| 194 | else $ |
---|
| 195 | yrange=!y.range ;Axis perpend. to bars |
---|
| 196 | yticks=1 ;Suppress ticks in plot |
---|
| 197 | ytickname=strarr(2)+' ' |
---|
| 198 | xticks=0 |
---|
| 199 | xtickname=strarr(1)+'' |
---|
| 200 | endif else begin ;Vertical bars |
---|
| 201 | if (!y.range[0] eq 0) and (!y.range[1] eq 0) $ ;Determine range for Y-axis |
---|
| 202 | then yrange=range $ |
---|
| 203 | else yrange=!y.range ;Or, use range specified |
---|
| 204 | xrange=!x.range ;Axis perpend. to bars |
---|
| 205 | xticks=1 ;Suppress ticks in plot |
---|
| 206 | xtickname=strarr(2)+' ' |
---|
| 207 | yticks=0 |
---|
| 208 | ytickname=strarr(1)+'' |
---|
| 209 | endelse |
---|
| 210 | if (overplot eq 0) then $ ;Create new plot, no data |
---|
| 211 | plot,[values],/nodata,title=title,xtitle=xtitle,ytitle=ytitle, $ |
---|
| 212 | noerase=overplot,xrange=xrange,yrange=yrange,xticks=xticks, $ |
---|
| 213 | xtickname=xtickname,yticks=yticks,ytickname=ytickname, $ |
---|
| 214 | xstyle=1,ystyle=1,/data,background=background, _EXTRA = ex |
---|
| 215 | if (rotate) then begin ;Horizontal bars |
---|
| 216 | base_win=!y.window ;Window range in Y |
---|
| 217 | scal_fact=!x.s ;Scaling factors |
---|
| 218 | tick_scal_fact=!y.s ;Tick scaling factors |
---|
| 219 | endif else begin ;Vertical bars |
---|
| 220 | base_win=!x.window ;Window range in X |
---|
| 221 | scal_fact=!y.s ;Scaling factors |
---|
| 222 | tick_scal_fact=!x.s ;Tick scaling factors |
---|
| 223 | endelse |
---|
| 224 | winrange=baserange*(base_win[1]-base_win[0]) ;Normal. window range |
---|
| 225 | barsize=barwidth*winrange/nbars ;Normal. bar width |
---|
| 226 | winoffset=base_win[0]+(baroffset*barsize) ;Normal. first offset |
---|
| 227 | bases=scal_fact[0]+(scal_fact[1]*baselines) ;Baselines, in normal coor. |
---|
| 228 | normal=scal_fact[0]+(scal_fact[1]*values) ;Values, in normal coor. |
---|
| 229 | barstart=indgen(nbars)*(barsize+barspace*(winrange/nbars)) ;Coor. at left edges |
---|
| 230 | tickv=winoffset+barstart+(0.5*barsize) ;Tick coor. (centered) |
---|
| 231 | for i=0,nbars-1 do begin ;Draw the bars |
---|
| 232 | width=winoffset+[barstart[i],barstart[i], $ ;Compute bar width |
---|
| 233 | (barstart[i]+barsize),(barstart[i]+barsize)] |
---|
| 234 | length=[bases[i],normal[i],normal[i],bases[i]] ;Compute bar length |
---|
| 235 | if (rotate) then begin ;Horizontal bars |
---|
| 236 | x=length ;X-axis is "length" axis |
---|
| 237 | y=width ;Y-axis is "width" axis |
---|
| 238 | endif else begin ;Vertical bars |
---|
| 239 | x=width ;X-axis is "width" axis |
---|
| 240 | y=length ;Y-axis is "length" axis |
---|
| 241 | endelse |
---|
| 242 | polyfill,x,y,color=colors[i],/normal ;Polyfill with color |
---|
| 243 | if (outline) then plots,x,y,/normal ;Outline using !p.color |
---|
| 244 | endfor |
---|
| 245 | |
---|
| 246 | tickv=(tickv-tick_scal_fact[0])/tick_scal_fact[1] ;Locations of the ticks |
---|
| 247 | if (rotate) then $ ;Label the bars (Y-axis) |
---|
| 248 | axis,yaxis=0,ystyle=1,yticks=(nbars-1),ytickv=tickv,ytickname=barnames, $ |
---|
| 249 | yticklen=0.0 $ |
---|
| 250 | else $ ;Label the bars (X-axis) |
---|
| 251 | axis,xaxis=0,xstyle=1,xticks=(nbars-1),xtickv=tickv,xtickname=barnames, $ |
---|
| 252 | xticklen=0.0 |
---|
| 253 | return |
---|
| 254 | end |
---|