[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Color question
- Subject: Re: Color question
- From: Martin Schultz <martin.schultz(at)dkrz.de>
- Date: Wed, 04 Apr 2001 09:46:17 +0200
- Newsgroups: comp.lang.idl-pvwave
- Organization: Max-Planck-Institut fuer Meteorologie, Hamburg
- References: <9adduv$avn$1@SonOfMaze.dpo.uab.edu>
- Xref: news.doit.wisc.edu comp.lang.idl-pvwave:24329
"R. Kyle Justice" wrote:
>
> I have a filled contour plot that I would like to
> display with a color bar. Everything looks fine
> on the screen but when I try to print, the colors
> on the bar are no longer correct. They appear
> washed out(dithered?). The contour colors, however,
> appear correct. If I look at the file with
> ghostscript, everything looks fine.
>
> I am generating the color bar with TV. It seems
> that the printer is treating a plot and an image
> differently.
>
> Kyle J.
If you have discrete colors in your contours and colorbar, you could
try out my colorbar (should be renamed to mgs_colorbar) routine which
you find at
http://www.mpimet.mpg.de/~schultz.martin/idl/html/libmartin_schultz.html
If you supply this routine with a levels and c_colors keyword, it will
draw filled rectangles with the same c_colors (and levels) you use in
the contour command. If that doesn't show up correctly in your
printout then I have really no idea what's going on.
Cheers,
Martin
PS: Ooops. I just recognize there was a recent bugfix. So, I attach
the new version which is now called mgs_colorbar.pro
--
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[ Dr. Martin Schultz Max-Planck-Institut fuer Meteorologie [[
[[ Bundesstr. 55, 20146 Hamburg [[
[[ phone: +49 40 41173-308 [[
[[ fax: +49 40 41173-298 [[
[[ martin.schultz@dkrz.de [[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
;+
; NAME:
; COLORBAR
;
; PURPOSE:
; Draw a colorbar (legend) with labels
;
; CATEGORY:
; Colors
;
; CALLING SEQUENCE:
; COLORBAR [,options]
;
; INPUTS:
;
; KEYWORD PARAMETERS:
; COLOR -> the drawing color for boxes and labels
; (default: !P.COLOR)
;
; BOTTOM -> first color index to use (default: 1)
;
; NCOLORS -> number of colors to use (default:
; !D.N_Colors-bottom)
;
; MIN, MAX -> range of the data (default bottom and
; bottom+ncolors-1
;
; LABEL -> array with label values (must be numeric).
; Normally, it is easier to generate labels with the
; DIVISIONS options, but this allows tighter control
; (e.g. 1,2,5,10,20 labels on logarithmic scales).
; Default (if no DIVISIONS are given): min and max
;
; DIVISIONS -> number of labels to put on the colorbar.
; Note that this keyword is overwritten by LABEL.
; The labels will be equally spaced and the /LOG option
; will be honored.
;
; FORMAT -> output format of the labels. Default is determined
; according to the range given in min and max. Label strings
; will be trimmed, so you can safely specify f14.2 for example.
;
; SCIENTIFIC -> If set, will call STRSCI to put the colorbar
; labels in scientific notation format (e.g. in the form
; A x 10^B). STRSCI will use the format string specified
; in the FORMAT keyword.
;
; /LOG -> logarithmic spacing of labels (colors are *always*
; linearily distributed)
;
; C_COLORS -> array of color indices for "discrete" color bars
; e.g. in filled contour plots. You must also use the
; C_LEVELS keyword, otherwise there will most likely be
; a mismatch between your plot colors and your colorbar
; colors. COLORBAR normally limits the number of labels
; it prints to 10. Use the SKIP keyword to force a different
; behaviour. If C_COLORS is not undefined it overrides the
; settings from NCOLORS, and BOTTOM.
;
; C_LEVELS -> array with label values for discrete colorbars.
; Use the LABEL keyword for continuous colors. C_LEVELS
; must have the same number of elements as C_COLORS and
; assigns one label to each color change (LABEL distributes
; the labels evenly). Use the SKIP keyword to skip labels.
; As default, COLORBAR limits the number of labels printed
; to 10.
; NB: In order to be consistent with the behaviour of the
; CONTOUR procedure, colorbar disregards the first entry of
; C_LEVELS.
;
; SKIP -> print only every nth discrete label. Default is computed
; so that COLORBAR will print no more than 10 labels.
;
; STARTLABEL -> for discrete colorbars: the first left box side to be
; labeled. Default is 1, i.e. between the first two boxes.
;
; /VERTICAL -> set this keyword to produce a vertical colorbar
; (default is horizontal). Note that out-of-range boxes are
; only implemented for horizontal color bars.
;
; POSITION -> a position value or 4-element vector. If POSITION
; contains only one element, it will be centered at the
; bottom or right side of the page and extend over 60% of
; the total plotting area.
;
; CHARSIZE -> character size (default !p.charsize)
;
; TITLE -> a title string (similar to XTITLE or YTITLE for PLOT)
;
; UNIT -> a unit string that will be added to the right (top) of
; the labels
;
; BotOutOfRange, TopOutOfRange -> a colorindex value for data
; that falls below or above the normal plot range. If given,
; an extra box will be drawn to the left or right of the color-
; bar, and the colorbar will shrink in size. A default label
; '<' ('>') will be placed below. Note that these options are
; only available for horizontal colorbars.
;
; BOR_Label, TOR_Label -> label values for BOTOutOfRange and
; TopOutOfRange that replace the defaults.
;
; OUTPUTS:
;
; SUBROUTINES:
;
; REQUIREMENTS:
; The user should have some knowledge about colortables and the
; use of parts of a colortable.
; This program uses STRSCI for labels in scientific notation.
;
; NOTES:
; This routine was designed after David Fanning's colorbar
; routine and enhanced. Some of the postscript
; handling of DF was removed, positioning is a little easier but
; maybe a little less flexible; out-of-range boxes have been
; added.
;
; EXAMPLE:
; ; draw a colorbar with all available colors on top of index 20
; ; will be placed at the bottom of the page
;
; colorbar,bottom=20,min=min(data),max=max(data)
;
; ; draw another colorbar above the first one, use logarithmic scale
;
; colorbar,bottom=20,min=0.1,max=10.,labels=[0.1,0.5,1.,5.10.],/log, $
; position=0.3,unit='ppt'
;
; ; (simply add keyword /vertical and you'll get it flipped)
;
; ; colorbar with out-of-range information on right side only
; ; Here we used 20 colors for the plot, the 21st is for
; ; out-of-range data
;
; colorbar,bottom=20,ncolors=20,min=0,max=100,divisions=5, $
; TopOutOfRange=40
;
; MODIFICATION HISTORY:
; mgs, 02 Jun 1998: VERSION 1.00
; mgs, 14 Nov 1998: - changed default format to f14.2 from f6.2
; mgs, 19 Nov 1998: - added cbdefaultformat function to better handle
; default labeling format.
; mgs, 28 Nov 1998: - default labelling format now exponential for
; values gt 1.e6
; mgs, 19 May 1999: - unit string placed a little further right
; in horizontal colorbars.
; mgs, 27 May 1999: - added functionality for discrete colorbars
; (C_COLORS, C_LEVELS, and SKIP keywords)
; bmy, 02 Jun 1999: - added /SCIENTIFIC keyword
; - updated comments
; mgs, 14 Sep 1999: - charsize bug fix. Needed to check for 0.
; mgs, 23 Sep 1999: - now uses !P.COLOR as default color (as it was originally)
; - BOTTOM default now 1 (because 0 is the standard beackground
; value)
; mgs, 17 Dec 1999: - fixed zero division for SKIP=0
; - added StartLabel keyword for discrete colorbars
; mgs, 20 Dec 1999: - disregard first entry of C_LEVELS
; gjb, 16 Feb 2001: - fixed bug in coordinating levels and
; colors
; mgs, 20 Feb 2001: - renamed to mgs_colorbar
;
;-
; Copyright (C) 1998, 1999, Martin Schultz and Bob Yantosca,
; Harvard University
; This software is provided as is without any warranty
; whatsoever. It may be freely used, copied or distributed
; for non-commercial purposes. This copyright notice must be
; kept with any copy of this software. If this software shall
; be used commercially or sold as part of a larger package,
; please contact the author.
; Bugs and comments should be directed to mgs@io.harvard.edu
; or bmy@io.harvard.edu with subject "IDL routine colorbar"
;-------------------------------------------------------------
function cbdefaultformat,minv,maxv,log=log
; return default format string depending on min and max value
; and log flag
res = '(f14.2)' ; general default
; determine necessary number of decimal places
ndec = fix( 2.-alog10( (maxv-minv) > 1.0E-31 ) )
ndecmin = fix( 2.-alog10( minv > 1.0E-31 ) )
if (keyword_set(log)) then ndec = max([ndec,ndecmin-1])
if (ndec gt 2) then res = '(e12.3)'
if (ndec eq 3 AND log) then res = '(f14.3)'
if (ndec le 0) then res = '(I14)'
if (ndec le -6) then res = '(e12.3)'
return,res
end
pro mgs_colorbar,color=color,bottom=bottom,ncolors=ncolors, $
min=minv,max=maxv,label=label,divisions=divisions, $
c_colors=c_colors,c_levels=c_levels,skip=skip,startlabel=startlabel, $
format=format,log=log, $
vertical=vertical,position=position,charsize=charsize, $
title=title,unit=unit, $
BotOutOfRange=BotOutOfRange,TopOutOfRange=TopOutOfRange, $
BOR_Label=BOR_Label,TOR_Label=TOR_Label,Scientific=Scientific
; Pass external functions
FORWARD_FUNCTION StrSci
;===================================================================
; set defaults and determine parameters
;===================================================================
IsDiscrete = n_elements(C_Colors) gt 0 ; discrete colorbar for
; filled contours?
if (n_elements(color) eq 0) then color = !P.COLOR
if (n_elements(bottom) eq 0) then bottom = 1
MAXCOL = !D.N_COLORS<256
if (bottom ge MAXCOL-1) then bottom = MAXCOL-1
if (n_elements(ncolors) eq 0) then ncolors = MAXCOL-bottom
if (ncolors gt MAXCOL-bottom) then ncolors = MAXCOL-bottom
if (n_elements(minv) eq 0) then minv = bottom
if (n_elements(maxv) eq 0) then maxv = ncolors
log = keyword_set(log)
if (log AND minv le 0.) then minv = 0.01
if (n_elements(format) eq 0) then $
format = cbdefaultformat(minv,maxv,log=log)
;===================================================================
; compute default labels
;===================================================================
if (IsDiscrete AND n_elements(SKIP) eq 0) then $
Skip = fix( (n_elements(C_Colors)-1)/10 ) + 1
if (n_elements(Skip) eq 0) then Skip = 1
if (n_elements(StartLabel) eq 0) then StartLabel = 0
if (n_elements(divisions) eq 0) then divisions = 2
if (IsDiscrete AND n_elements(C_Levels) eq 0) then $
Divisions = fix( (n_elements(C_Colors)-1)/(Skip>1) ) + 1
; if (IsDiscrete) then begin
; print,'#### SKIP,DIVISIONS=',skip,divisions
; print,'C_Colors=',C_Colors
; endif
if (n_elements(label) eq 0) then begin
if (divisions gt 1) then begin
if (log) then $
label = 10^(findgen(divisions)/(divisions-1)* $
(alog10(maxv/minv))+alog10(minv) ) $
else $
label = findgen(divisions)/(divisions-1)*(maxv-minv)+minv
endif else $
label = -1
endif
; Overwrite standard labels with C_Levels if given
if (IsDiscrete AND n_elements(C_Levels) gt 0) then begin
myC_Levels = C_Levels[1:*] ; omit first entry to be consistent with CONTOUR
Ind = indgen( (n_elements(myC_Levels)-1)/(Skip>1) + 1) * Skip + StartLabel
okInd = where(Ind ge 0 AND Ind lt n_elements(myC_Levels))
if (okInd[0] lt 0) then begin
message,'Invalid combination of Skip and StartLabel!',/Continue
return
endif
Ind = Ind[okInd]
Label = myC_Levels[Ind]
; print,'### C_Levels=',myC_Levels
; print,'### Ind = ',Ind,' Label = ',Label
endif
print,'# IsDiscrete = ',IsDiscrete
print,'#### LEVELS = ',myC_Levels
print,'#### LABELS = ',label
if (n_elements(charsize) eq 0) then charsize = !p.charsize
if (charsize eq 0) then charsize = 1.
if (n_elements(title) eq 0) then title = ''
if (n_elements(unit) eq 0) then unit = ''
if (n_elements(BotOutOfRange) eq 0) then BotOutOfRange = -1
if (n_elements(TopOutOfRange) eq 0) then TopOutOfRange = -1
if (n_elements(BOR_Label) eq 0) then BOR_Label = '<'
if (n_elements(TOR_Label) eq 0) then TOR_Label = '>'
vertical = keyword_set(vertical)
;===================================================================
; keep simple: out-of-range boxes only allowed for horizontal bar
; Also, these do not make sense in discrete color bars
;===================================================================
if (vertical OR IsDiscrete) then begin
BotOutOfRange = -1
TopOutOfRange = -1
endif
;===================================================================
; position: if only one element then center bar according
; to vertical keyword and give it a width of 60%
;===================================================================
if (n_elements(position) eq 0) then position = abs((vertical) - 0.10)
if (n_elements(position) ne 4) then begin
if (vertical) then $
position = [ position[0], 0.2, position[0]+0.03, 0.8 ] $
else $
position = [ 0.2, position[0], 0.8, position[0]+0.03 ]
endif
;===================================================================
; make space for extra boxes for out of range
;===================================================================
barpos = position
x10 = (position[2]-position[0])/10. > 0.03
truecharsize = float(!D.Y_CH_SIZE*charsize)
labelpos = ( position[1] * !D.Y_VSIZE - truecharsize*1.05 ) / $
!D.Y_VSIZE
;===================================================================
; draw rectangles and fill them (out of range boxes)
;===================================================================
if (BotOutOfRange ge 0) then begin
rpos = [ position[0], position[1], position[0]+x10, position[3] ]
RectAngle,rpos,px,py
; px = [ position[0], position[0]+x10,position[0]+x10, $
; position[0], position[0] ]
; py = [ position[1], position[1] ,position[3], $
; position[3], position[1] ]
polyfill,px,py,/norm,color=BotOutOfRange,/fill
plots,px,py,/norm,color=color,thick=!p.thick
; annotate
xyouts,position[0]+x10/2.,labelpos,BOR_Label,/norm, $
color=color,align=0.5,charsize=charsize
; shorten central bar
barpos = [ barpos[0]+x10+0.01, barpos[1], $
barpos[2], barpos[3] ]
endif
if (TopOutOfRange ge 0) then begin
rpos = [ position[2], position[1], position[2]-x10, position[3] ]
RectAngle,rpos,px,py
; px = [ position[2], position[2]-x10,position[2]-x10, $
; position[2], position[2] ]
; py = [ position[1], position[1] ,position[3], $
; position[3], position[1] ]
polyfill,px,py,/norm,color=TopOutOfRange,/fill
plots,px,py,/norm,color=color,thick=!p.thick
; annotate
xyouts,position[2]-x10/2.,labelpos,TOR_Label,/norm, $
color=color,align=0.5,charsize=charsize
; shorten central bar
barpos = [ barpos[0], barpos[1], $
barpos[2]-x10-0.01, barpos[3] ]
endif
; reset bar position in case of error
if (barpos[0] gt barpos[2]) then barpos = position
;===================================================================
; create (central) colorbar
;===================================================================
xstart = barpos[0] * !D.X_VSIZE
ystart = barpos[1] * !D.Y_VSIZE
xsize = (barpos[2] - barpos[0]) * !D.X_VSIZE
ysize = (barpos[3] - barpos[1]) * !D.Y_VSIZE
if (IsDiscrete) then begin
;================================================================
; discrete color bar: need to polyfill individual rectangles
; compute position for each rectangle
;================================================================
if (vertical) then begin
dx = 0.
dy = ysize/n_elements(C_Colors)
endif else begin
dx = xsize/n_elements(C_Colors)
dy = 0.
endelse
for i=0,n_elements(C_Colors)-1 do begin
if (vertical) then $
box = [ xstart, ystart+i*dy, xstart+xsize, ystart+(i+1)*dy ] $
else $
box = [ xstart+i*dx, ystart, xstart+(i+1)*dx, ystart+ysize ]
; print,'### box=',box
; print,'### xstart,xsize,ystart,ysize=',xstart,xsize,ystart,ysize
RectAngle,box,px,py
PolyFill,px,py,/DEVICE,color=C_Colors[i]
endfor
endif else begin
;================================================================
; continuous colorbar: use TV to display a smooth range of colors
;================================================================
bcol = bindgen(ncolors) + bottom
if (vertical) then $
bar = replicate(1B,5) # bcol $
else $
bar = bcol # replicate(1B,5)
IF (!D.Name eq 'PS') THEN BEGIN
TV, bar, xstart, ystart, XSIZE=xsize, YSIZE=ysize
ENDIF ELSE BEGIN
bar = CONGRID(bar, CEIL(xsize), CEIL(ysize), /INTERP)
TV, bar, xstart, ystart
ENDELSE
endelse
; Draw frame around colorbar
; px = [ barpos[0], barpos[0], barpos[2], barpos[2], barpos[0] ]
; py = [ barpos[1], barpos[3], barpos[3], barpos[1], barpos[1] ]
RectAngle,barpos,px,py
plots,px,py,/norm,color=color,thick=!p.thick
;===================================================================
; labelling : set up plot coordinates with x or y range eq to
; device size, then use position parameters for unit and title
;===================================================================
if (n_elements(label) lt 2) then return
;===================================================================
; Convert LABEL to string representation SLABEL here
; If /SCIENTIFIC is set, then call STRSCI to put the labels into
; the form A x 10^B.
;===================================================================
if ( Keyword_Set( Scientific ) ) then begin
SLabel = StrSci( Label, /Trim, Format=Format, _EXTRA=e )
endif else begin
SLabel = StrTrim( String( Label, Format=Format ), 2 )
endelse
;===================================================================
; Vertical colorbar
;===================================================================
if (vertical) then begin
if (IsDiscrete) then begin
yrange = [0,n_elements(c_colors)] ; one more!
;; bug fix gjb
ypos = 1+findgen(n_elements(Label))*Skip+StartLabel
npos = n_elements(label)+1
endif else begin
yrange = [minv,maxv]
ypos = Label
npos = n_elements(label)
endelse
plot,[0],[0],/nodata,ylog=log,xstyle=5,ystyle=5, $
xrange=[-(barpos[2]-barpos[0])*!D.X_VSIZE, 0.], $
yrange=yrange, $
position=barpos,/NOERASE
nypos = convert_coord(replicate(0,npos),ypos,/DATA,/TO_NORMAL)
print,ypos
help,slabel & print,slabel
; xyouts,replicate(truecharsize*1.05,n_elements(label)),label, $
xyouts,replicate(truecharsize*1.05,npos),ypos, $
SLabel,/data,color=color,charsize=charsize,align=0.5,orient=90
plot,[0],[0],/nodata,xstyle=5,ystyle=5, $
xrange=[-(barpos[2]-barpos[0])*!D.X_VSIZE, 0.], $
yrange=[0,1], position=position,/NOERASE
xyouts,truecharsize*1.05,1.1,unit,/data, $
color=color,charsize=charsize,align=0,orient=90
xyouts,truecharsize*2.15,0.5,title,/data, $
color=color,charsize=charsize,align=0.5,orient=90
;===================================================================
; Horizontal colorbar
;===================================================================
endif else begin
; print,'### minv,maxv = ',minv,maxv
if (IsDiscrete) then begin
xrange = [0,n_elements(c_colors)] ; one more!
;; bug fix gjb
xpos = 1+findgen(n_elements(Label))*Skip+StartLabel
npos = n_elements(label)+1
endif else begin
xrange = [minv,maxv]
xpos = Label
npos = n_elements(label)
endelse
; print,'### xpos, label=',xpos,label
; if (n_elements(myc_levels) gt 0) then print,'#### c_levels=',myc_levels
; if (n_elements(c_colors) gt 0) then print,'#### c_colors=',c_colors
plot,[0],[0],/nodata,xlog=(log AND not IsDiscrete), $
xstyle=5,ystyle=5, $
xrange=xrange, $
yrange=[0, (barpos[3]-barpos[1])*!D.Y_VSIZE], $
position=barpos,/NOERASE
; print,'#### barpos=',barpos
nxpos = convert_coord(xpos,replicate(0,npos),/DATA,/TO_NORMAL)
print,labelpos,truecharsize
; xyouts,nxpos[0,*],replicate(labelpos-truecharsize*1.05, npos), $
xyouts,xpos,replicate(-truecharsize*1.05, npos), $
slabel, /DATA,color=color,charsize=charsize,align=0.5
plot,[0],[0],/nodata,xstyle=5,ystyle=5, $
xrange=[0,1], $
yrange=[0., (barpos[3]-barpos[1])*!D.Y_VSIZE], $
position=position,/NOERASE
xyouts,1.15,-truecharsize*1.05,unit,/data, $
color=color,charsize=charsize,align=0
xyouts,0.5,-truecharsize*2.15,title,/data, $
color=color,charsize=charsize,align=0.5
endelse
return
end