1 | ;+ |
---|
2 | ; |
---|
3 | ; @file_comments |
---|
4 | ; Create a bar graph, or overplot on an existing one. |
---|
5 | ; |
---|
6 | ; @categories |
---|
7 | ; Graphics |
---|
8 | ; |
---|
9 | ; @param Values {in}{required} {type=vector} |
---|
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. |
---|
13 | ; |
---|
14 | ; @keyword BASELINES {type=vector} |
---|
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. |
---|
18 | ; |
---|
19 | ; @keyword COLORS {type=vector} |
---|
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 |
---|
22 | ; selected based on spacing the color indexes as widely as |
---|
23 | ; possible within the available colors (specified by D.N_COLORS). |
---|
24 | ; |
---|
25 | ; @keyword BARNAMES {type=string} |
---|
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. |
---|
30 | ; |
---|
31 | ; @keyword TITLE {type=string} |
---|
32 | ; A string containing the main title to for the bar plot. |
---|
33 | ; |
---|
34 | ; @keyword XTITLE {type=string} |
---|
35 | ; A string containing the title for the X axis. |
---|
36 | ; |
---|
37 | ; @keyword YTITLE {type=string} |
---|
38 | ; A string containing the title for the Y axis. |
---|
39 | ; |
---|
40 | ; @keyword BASERANGE {type=float} |
---|
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. |
---|
45 | ; |
---|
46 | ; @keyword BARWIDTH {type=float} |
---|
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). |
---|
53 | ; |
---|
54 | ; @keyword BARSPACE {type=scalar} |
---|
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. |
---|
60 | ; |
---|
61 | ; @keyword BAROFFSET {default=BARSPACE}{type=scalar} |
---|
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 |
---|
65 | ; on the same graph. |
---|
66 | ; |
---|
67 | ; @keyword OUTLINE |
---|
68 | ; If set, this keyword specifies that an outline should be |
---|
69 | ; drawn around each bar. |
---|
70 | ; |
---|
71 | ; @keyword OVERPLOT |
---|
72 | ; If set, this keyword specifies that the bar plot should be |
---|
73 | ; overplotted on an existing graph. |
---|
74 | ; |
---|
75 | ; @keyword BACKGROUND {default=The normal IDL background color is used}{type=scalar} |
---|
76 | ; A scalar that specifies the color index to be used for |
---|
77 | ; the background color. |
---|
78 | ; |
---|
79 | ; @keyword ROTATE |
---|
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. |
---|
83 | ; |
---|
84 | ; @examples |
---|
85 | ; By using the overplotting capability, it is relatively easy to create |
---|
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 | ; |
---|
121 | ; @history |
---|
122 | ; August 1990, T.J. Armitage, RSI, initial programming. Replacement |
---|
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. |
---|
128 | ; |
---|
129 | ; @version |
---|
130 | ; $Id$ |
---|
131 | ; |
---|
132 | ;- |
---|
133 | ; |
---|
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 |
---|
139 | ; |
---|
140 | compile_opt idl2, strictarrsubs |
---|
141 | ; |
---|
142 | if (n_params(d) eq 0) then begin ;Print call & return if no parameters |
---|
143 | print,'bar_test,values,baselines=baselines,colors=colors,barnames=barnames,$' |
---|
144 | print,' title=title,xtitle=xtitle,ytitle=ytitle,baserange=baserange, $' |
---|
145 | print,' barwidth=barwidth,barspace=barspace,baroffset=baroffset, $' |
---|
146 | print,' outline=outline,overplot=overplot,background=background, $' |
---|
147 | print,' rotate=rotate' |
---|
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 |
---|