;+------------------------------------------------------------ ; NAME: ; TH_IMAGE_CONT ; PURPOSE: ; Plot contours of Images with both contour lines and colors ; CATEGORY: ; 2-D Plotting ; USAGE: ;******************** HIGH FREQUENCY RADAR DIVISION, SRL ********************** ;*************************** Ionospheric Effects ****************************** ;HELP ;1 TH_IMAGE_CONT ; Overlays an image and a contour plot and optionally adds a scale bar. ; Based on the IDL USERLIB routine IMAGE_CONT. This routine supersedes ; the USERLIB one, having far more functionality, yet capable of EXACTLY ; reproducing the effect of IMAGE_CONT. Scale bar appears on the ; right-hand-side unless /NOBAR is set. NB: the scale bar is ; automatically created by a recursive call to this routine using the ; same colour and image parameters ; ; Format: ; In its simplest form (allowing all parameters to default) ; ; IDL> TH_IMAGE_CONT, IMAGE ; ; or, ; ; IDL> TH_IMAGE_CONT, IMAGE, X, Y ; ; And in its most complex form, specifying ALL parameter ; ; IDL> TH_IMAGE_CONT, IMAGE, $ ; ASPECT=aspect, $ ; BADPTS=badpts,$ ; BAR_LABEL_LENGTH=bar_label_length, $ ; BAR_RANGE=bar_range, $ ; BAR_SEPARATION=bar_separation, $ ; BAR_TICKLEN=bar_ticklen, $ ; BAR_TICKNAME=bar_tickname, $ ; BAR_TICKS=bar_ticks, $ ; BAR_TICKV=bar_tickv,$ ; BARSZ_CHARS=barsz_chars, $ ; BOTTOMCOLOUR=bottomcolour,$ ; C_COLORS=c_colors,$ ; C_LINESTYLE=c_linestyle, $ ; C_THICK=c_thick, $ ; CONGRID=congrid, $ ; CONT=cont, $ ; CRANGE=crange, $ ; CT=ct, $ ; CUBIC=cubic, $ ; DEBUG=debug, $ ; EXACT=exact, $ ; RAISE_PTITLE=raise_ptitle ; IMAGE_WINDOW=image_window, $ ; INTERP=interp,$ ; LEVELS=levels,$ ; MAX_VALUE=max_value, $ ; NLEVELS=nlevels, $ ; NOBAR=nobar, $ ; NOCONT=nocont, $ ; NOERASE=noerase,$ ; TOPCOLOUR=topcolour,$ ; TSIZE=tsize, $ ; WINDOW_SCALE=window_scale, $ ; XRANGE=xrange, $ ; YRANGE=yrange ; ;2 IMAGE ; 2-dimensional array to display as an image. ; ;2 /ASPECT ; set to retain image's aspect ratio. Assumes square ; pixels. If /WINDOW_SCALE is set, the aspect ratio is retained. ; ;2 BADPTS ; indices into IMAGE data which define the bad points. ; These will not be contoured ; ;2 BAR_LABEL_LENGTH ; the space, in characters (default = 2), for the bar label ;2 BAR_RANGE ; set the range limits for the colour scale bar ; (same as CRANGE, defaults to autoscaling if ; BAR_TICKV not set) ; ;2 BAR_SEPARATION ; the separation, in characters (default = 2), between the scale ; bar and the image. Note that the |y-ticklength| will be added ; to this value if y-ticklength < 0. ; Both the image and the colour bar need to fit ; into the space allowed for the plot window, otherwise an ; informative message will be printed and unpredictable results ; may occur for the displayed image ; ;2 BAR_TICKS ; set the number of tick intervals for the labelling ; of the scale bar ; (defaults to !z.ticks) ; ;2 BAR_TICKV ; the values to label on the scale bar. If this is set ; then the scale bar will have AT LEAST this range ; (defaults to !z.tickv) ; ;2 BAR_TICKNAME ; the labels to use on the scale bar ; (defaults to !z.range) ; ;2 BAR_TICKLEN ; the length of the ticks on the scale bar in fractions of tick ; bar window, (defaults to !z.ticklen) ; ;2 BARSZ_CHARS ; the size of the scale bar in characters (default = 2). ; Both the image and the colour bar need to fit ; into the space allowed for the plot window, otherwise an ; informative message will be printed and unpredictable results ; may occur for the displayed image. If the value of this ; keyword is <=0 then no bar will be displayed BUT the scaling ; and window size will be calculated as those a colour bar is to ; be used. This is useful when doing multiple plots per page ; where only some scale bars are not required but you want the ; plots to all be the same size. Set BARSZ_CHARS = -#chars to ; allow room for a bar of #chars size but not to put a scale bar ; on the plot. Then set BARSZ_CHARS = +#chars to plot the bar on ; alongside another plot, to end up with images of the same ; size. Useful in collaboration with the SIDES procedure (which ; will set flags for when the plot is on the Left,Right,Top and ; Bottom of the plot window). ; ; ;2 BOTTOMCOLOUR ; Set this keyword to the colour index of the desired bottom ; colour (range from 0 to TOPCOLOUR-1). ; Note that the default value for this keyword is 1, ; which allows the colour of the image to ; be independent of the background and axes colours ; (!P.background and !P.color). If the user sets this keyword ; then allowance should be made for these colours as they are ; generally swapped for POSTSCRIPT and X-Window devices ; ;2 /CONGRID ; if the image has to be resampled then use the USERLIB CONGRID ; routine ; ;2 /CONT ; only do the contouring (no image) ; ;2 CRANGE ; set the range limits for the colour scale bar ; (same as BAR_RANGE, defaults to autoscaling if ; BAR_TICKV not set) ; ;2 CT ; load a color table (uses LOADCT via MK_COLOR) ; ;2 /CUBIC ; if the image has to be resampled AND interpolated then use the ; CUBIC interpolation rather than the bi-linear (see INTERP ; Keyword) ; ;2 /DEBUG ; write out some inforamtion as it goes ; ; ;2 /EXACT ; ; When set this will force the contour routine to fit to the ; exact positions relative to the image. ; When data is displayed as an image each datum is expanded out ; to fill a pixel of finite dimensions. The assignment of where ; the "data value" resides within this space is open to debate, ; but is most appropriately (to this author) assigned to the ; geometric centre of the pixel. Most defaults assign this ; position to be at the bottom left-hand corner of the ; pixel. Contour will fit to the 2-d plane assuming that the ; data value is associated with the bottom left-hand corner. To ; reconcile this with the notion of the value being in the ; middle of the pixel the contour call is made with the x/y ; values and ranges for the image adjusted (effectively by half ; a pixel in the x/y directions). This is the EXACT mapping. By ; default, the mapping will be the default contour one. ; ;2 RAISE_PTITLE ; Raise the plot title by this many character units above the ; plot to allow room to put a label on the top x-axis. Default ; is raise by 1 char. If not called then the default y-position ; is 1 char unit above plot (allowing room for xticks, and ; scaled by !P.charsize) ; ;2 IMAGE_WINDOW ; the position of the image window. Can be used to set ; !p.position so you can over-plot the image. ; (Only useful when the scale-bar has been used) ; ;2 /INTERP ; set to bi-linear interpolate if image is resampled. ; (see also the CUBIC keyword) ; ;2 /NOBAR ; dont put a scale bar on the right-hand-side ; ;2 /NOCONT ; only do the imaging (no contours) ; ;2 /NOERASE ; dont erase the previous plot ; /NOLOAD ; if set, do not load color table ; ;2 TOPCOLOUR ; Set this keyword to the colour index of the desired bottom ; colour (range from BOTTOMCOLOUR+1 to !D.n_colors-1). Note that ; the default value for this keyword is !D.n_colors-2, which ; allows the colour of the image to be independent of the ; background and axes colours (!P.background and !P.color). If ; the user sets this keyword then allowance should be made for ; these colours as they are generally swapped for POSTSCRIPT and ; X-Window devices ; ;2 TSIZE ; size of the plot title (default = 1) ; ;2 /WINDOW_SCALE ; set to scale the window size to the image size, ; otherwise the image size is scaled to the window size. ; Ignored when outputting to devices with scalable pixels. ; ;2 XRANGE ; will set the ranges for the x-axes labelling ; ;2 YRANGE ; will set the ranges for the y-axes labelling ; ;2 Contour ; most of the CONTOUR parameters are passed directly ; ;2 Examples ; IDL> th_image_cont, image ; ; IDL> th_image_cont, image, /nocont, /nobar ; ; IDL> !p.title = "!17 This is an example of what can be done" ; IDL> !x.title = "X Title" & !y.title = "Y Title" & !z.title = "Z Title" ; IDL> !x.ticklen = -0.02 & !y.ticklen = -0.02 & !z.ticklen = -0.02 ; IDL> !p.charsize = 1.5 ; IDL> levels = findgen(5)*2 ; IDL> image = findgen(20,20)/40. ; IDL> th_image_cont, image, crange=[0,10], /follow, level=levels, $ ; tsize=1.5*!p.charsize, bar_tickv=levels, c_char=1.5 ; ;2 Error_responses ; Returns to the calling procedure on an error ; ;2 Limitations/Assumptions ; The currently selected display is affected. ; If the device has scalable pixels then the image is written over ; the plot window. ; As with all TV style image displays, the axes range is independent of ; the image, so it is up to the user the ensure correct labelling of the ; axes. ; NOTE: if the user aborts while this routine is processing then the ; system variables (in particular !p.position) will have ; been changed, causing subsequent plots to appear different. Issue the ; command "resetplt,/all" to reset all the system variables back to the ; startup state. ; ; NOTE: if x or y does not have a constant interval, the image will be ; wrong. Instead, use contour, /fill... ;2 References ; See USERLIB IMAGE_CONT ; ;2 Keywords ; Graphics images contours ; ;2 MODIFICATIONS: ; ------------- ; 06-Jun-2006 several changes including adding x & ytickformat keywords ; 06-Apr-2006 limit max dimension of interpolated postscript plots to 2000 pixels ; 14-Mar-2006 added zrange keyword [BD] ; 25-Oct-01 Made Contours work when /ASPECT set. Made Contours work when ; XRANGE or YRANGE set. ; 18-Apr-00 Made interpolated image align with data. /EXACT does not give ; an exact representation. Warn if style=2 ; 06-Dec-99 Added another pixel to TV image size, so it fills the grid square ; 23-Aug-99 Allow Contour, Z, X, Y format. Use MK_COLOR ; 07-Jan-98 BD allow more space at the bottom and right-hand side for text ; (keyword BAR_LABEL_LENGTH added) ; 07-Aug-97 Bill Davis- v. 2.24 ; [1] added _extra call to main CONTOUR and removed ; it from those making the bar. ; (more modifications in file) ;- ;2 Amendments; ; May, 1988, DMS 1.00 ;... ;----------------------------------------------------------------- ; get a subimage from specified x & y or !x.range & !y.range function subimg, im, x_opt, y_opt ; make a subimage, if !x.range & !y.range less than full IF (!X.range[0] EQ !X.range[1] ) AND $ (!Y.range[0] EQ !Y.range[1] ) THEN RETURN, im array_info = SIZE( im ) xsize = array_info( 1 ) ysize = array_info( 2 ) if xsize le 2 or ysize le 2 then return, im if n_elements( x_opt ) GT 0 then x = x_opt $ else x = findgen( xsize ) if n_elements( y_opt ) GT 0 then y = y_opt $ else y = findgen( ysize ) ix1 = NEARESTI( x, !X.range[0]) ix2 = NEARESTI( x, !X.range[1]) iy1 = NEARESTI( y, !y.range[0]) iy2 = NEARESTI( y, !y.range[1]) return, im[ ix1>0 : ix2>(ix1+1), iy1>0 : iy2>(iy1+1) ] end ;**************************** TH_IMAGE_CONT Code ***************************** ;----------------------------------------------------------------- PRO Th_image_cont, image_in, xvalues_opt_in, yvalues_opt_in, $ WINDOW_SCALE=window_scale, $ ASPECT=aspect, $ DEBUG=debug, $ INTERP=interp, $ CONT=cont, $ NOCONT=nocont, $ IMAGE_WINDOW=image_window, $ NOERASE=noerase, $ NOBAR=nobar, $ CT=ct, $ MAX_VALUE=max_value, $ LEVELS=levels, $ C_COLORS=c_colors, $ C_LINESTYLE=c_linestyle, $ C_THICK=c_thick, $ NLEVELS=nlevels, $ XRANGE=xrange, $ YRANGE=yrange, $ ZRANGE=zrange, $ BADPTS=badpts, $ BAR_LABEL_LENGTH=bar_label_length, $ BAR_TICKS=bar_ticks, $ BAR_TICKNAME=bar_tickname, $ BAR_TICKV=bar_tickv, $ BAR_TICKLEN=bar_ticklen, $ BARSZ_CHARS=barsz_chars, $ TSIZE=tsize, $ BAR_RANGE=bar_range, $ CRANGE=crange, $ CUBIC=cubic, $ CONGRID=congrid_keyword, $ TOPCOLOUR=topc, $ BOTTOMCOLOUR=bottomc, $ BAR_SEPARATION=bar_separation, $ EXACT=exact, $ RAISE_PTITLE=raise_ptitle, $ MAX_COLORS_TO_USE=MAX_COLORS_TO_USE, $ noLoad=noLoad, $ btitle=btitle, bcharsize=bcharsize, $ xtickformat=xtickformat, ytickformat=ytickformat, $ currentTime=currentTime, $ outPos=outPos, $ _EXTRA=_extra COMMON Pset, n, lfile, encaps, colour, bppix IF (KEYWORD_SET(debug) ) THEN $ message, /INFO, ' Entered Procedure......... please wait ' IF (KEYWORD_SET(debug) ) THEN debug = 1 else debug = 0 IF debug then BEGIN print,'!x.range=', !x.range ;;; print,'xrange=', xrange print,'!y.range=', !y.range ENDIF if not debug then on_error, 2 ;Return to caller if an error occurs IF (!D.name EQ 'NULL') THEN RETURN ;no more to do if n_elements( noLoad ) eq 0 then noLoad = 0 if NOT noLoad then begin if n_elements( ct ) eq 0 then ct=3 ; hot metal if n_elements( MAX_COLORS_TO_USE ) eq 0 then MAX_COLORS_TO_USE = 128 dum=MK_COLOR(table=ct, N_NONFIXED = n_nonfixed, MAX_COLORS_TO_USE=MAX_COLORS_TO_USE) endif else begin ;;; dum=MK_COLOR( N_NONFIXED = n_nonfixed ) ; these probably don't matter when /noLoad set: if n_elements( MAX_COLORS_TO_USE ) eq 0 then MAX_COLORS_TO_USE = 256 if n_elements( N_NONFIXED ) eq 0 then N_NONFIXED=256 endelse orig_p = !P orig_x = !X orig_y = !Y orig_z = !Z IF debug then print,'!y.range=',!y.range image=reform(image_in) if n_elements( zrange ) eq 2 then image = zrange[0] > image < zrange[1] if n_elements( btitle ) gt 0 then !z.title = btitle ainfo = size( image ) IF ainfo[0] LT 2 THEN BEGIN ;;; message, '1st parameter must be 2D array' print, '1st parameter must be 2D array' return endif if n_elements( xvalues_opt_in ) eq 0 then xvalues_opt_in=findgen( ainfo[1] ) if n_elements( yvalues_opt_in ) eq 0 then yvalues_opt_in=findgen( ainfo[2] ) xvalues_opt= xvalues_opt_in yvalues_opt= yvalues_opt_in dx = xvalues_opt[1:*] - xvalues_opt[0:*] negs = where( dx lt 0, nnegs) if nnegs gt 0 and nnegs lt n_elements( dx ) then begin print, '*** X must be monotonic' return endif dy = yvalues_opt[1:*] - yvalues_opt[0:*] negs = where( dy lt 0, nnegs) if nnegs gt 0 and nnegs lt n_elements( dy ) then begin print, '*** Y must be monotonic' return endif IF N_Params(0) ge 3 THEN BEGIN Use_Args = 1 if (!X.range[0] eq !X.range[1] ) then $ !X.range = [min(xvalues_opt),max(xvalues_opt)] if (!Y.range[0] eq !Y.range[1] ) then $ !Y.range = [min(yvalues_opt),max(yvalues_opt)] ENDIF ELSE Use_Args = 0 IF (KEYWORD_SET(xrange) ) THEN BEGIN if n_elements(xrange) eq 1 then xrange=[0,0] !X.range = float(xrange) congrid_keyword = 1 ; can't get poly_2d in this case ENDIF IF (KEYWORD_SET(yrange) ) THEN BEGIN !Y.range = float(yrange) congrid_keyword = 1 ; can't get poly_2d in this case ENDIF IF (KEYWORD_SET(crange) ) THEN bar_range = crange if n_elements( bar_range ) lt 2 then begin if n_elements( zrange ) eq 2 then bar_range = zrange endif IF debug then BEGIN print,'POS 1.1 !x.range=', !x.range ;;; print,'POS 1.1 xrange=', xrange ENDIF if Use_args then begin x4lim = xvalues_opt y4lim = yvalues_opt endif else begin x4lim = indgen( aInfo[1] ) y4lim = indgen( aInfo[2] ) endelse xinds = where( x4lim ge !x.range[0] and x4lim le !x.range[1], xcount ) if xcount le 0 then begin print, ' *** x limits not allowing any data ;;; return !x.range[0]=x4lim[0] !x.range[1]=x4lim[ n_elements(x4lim)-1] endif yinds = where( y4lim ge !y.range[0] and y4lim le !y.range[1], ycount ) if ycount le 0 then begin print, ' *** y limits not allowing any data ;;;return !y.range[0]=y4lim[0] !y.range[1]=y4lim[ n_elements(y4lim)-1] endif if n_elements( xinds ) gt 1 then begin xvalues_opt= xvalues_opt[xinds] yvalues_opt= yvalues_opt[yinds] x1 = xinds[0] x2 = xinds[n_elements(xinds)-1] y1 = yinds[0] y2 = yinds[n_elements(yinds)-1] subIm = image[x1:x2, y1:y2] * 1.0 endif else begin subIm = image endelse ainfo = size( subIm ) maximage = max(subIm, MIN=minimage) if n_elements( bar_range ) eq 2 then begin maxbar = bar_range[1] minbar = bar_range[0] endif else begin maxbar = maximage minbar = minimage endelse ;; the defaults for the top and bottom colours allow the image colours to be ;; independent of the axes and background colours !P.color and !P.background ;; (normally 0 and !D.n_colors-1) ;; NB: cant use KEYWORD_SET as 0 is a valid entry !! IF N_ELEMENTS(topc) EQ 0 THEN topc = n_nonfixed-1 ;Brightest color ;(but allow room for plot and axes colours) IF N_ELEMENTS(bottomc) EQ 0 THEN bottomc = 1 ;Dullest color ;;ensure that the top colour is in the colour table topc = ((topc > 1) <(!D.n_colors -1) ) <(!D.table_size -1) ;;and the bottom colour is less than the top bottomc = (bottomc <(topc -1) ) > 0 ;;help,!d,/st sz = size( subIm ) ;Size of image IF sz[0] LT 2 THEN BEGIN message, 'Parameter not 2D' if (debug) then stop ENDIF if KEYWORD_SET(debug) then begin IF btest(!x.style,1) then message, /INFO, ' *** !x.style=2 is a problem' IF btest(!y.style,1) then message, /INFO, ' *** !y.style=2 is a problem' endif ;; NB: cant use KEYWORD_SET as 0 is a valid entry !! IF (N_ELEMENTS(bar_ticks) LE 0) THEN bar_ticks = !Z.ticks IF (NOT KEYWORD_SET(bar_tickv) ) THEN $ IF (bar_ticks GT 0) THEN bar_tickv = !Z.tickv(0:bar_ticks) IF (NOT KEYWORD_SET(bar_ticklen) ) THEN bar_ticklen = !Z.ticklen IF (NOT KEYWORD_SET(bar_tickname) ) THEN bar_tickname = !Z.tickname IF (!X.charsize GT 0) THEN xcharsize = !X.charsize ELSE xcharsize = 1.0 IF (!P.charsize GT 0) THEN pcharsize = !P.charsize ELSE pcharsize = 1.0 IF (NOT KEYWORD_SET(tsize) ) THEN tsize = pcharsize IF (N_ELEMENTS(raise_ptitle) LE 0 ) THEN raise_ptitle = 1 pposition = !P.position pmulti = !P.multi IF (KEYWORD_SET(cont) ) THEN nobar = 1 IF (KEYWORD_SET(nobar) ) THEN put_scale_bar = 0 ELSE put_scale_bar = 1 ;;use plot to set the full window dimensions IF (!X.range[0] EQ !X.range[1] ) THEN xtmp = [ 0, sz[1]-1 ] $ ;-0.5 $ 25/10/94 ELSE xtmp = !X.range IF (!Y.range[0] EQ !Y.range[1] ) THEN ytmp = [ 0, sz[2]-1 ] $ ;-0.5 $ 25/10/94 ELSE ytmp = !Y.range IF (KEYWORD_SET(debug) ) THEN BEGIN print,'pos 2 !x.range=', !x.range ;;; print,'pos 2 xrange=', xrange print,'pos 2 xtmp=', xtmp ENDIF plot, xtmp, ytmp, /NODATA, XSTYLE=5, YSTYLE=5, $ TITLE=' ', SUBTITLE=' ', XTITLE=' ', YTITLE=' ', $ xtickformat=xtickformat, ytickformat=ytickformat, $ NOERASE=KEYWORD_SET(noerase) ;;XRANGE = xtmp, YRANGE=ytmp ;get the full window dimensions xwin_sz = !X.window ywin_sz = !Y.window ;x-char size in normalised coords is: xchar_sz = float(!D.x_ch_size) /float(!D.x_vsize) ychar_sz = float(!D.y_ch_size) /float(!D.y_vsize) ;;redefine the y size to allow enough room to put a Plot Title (!P.title) on ;;the image when the x-ticks are pointing out ! (this should really be ;;handled by the IDL internal routines but isnt YET !) yshrink_for_title = 3 * tsize * xchar_sz yshrink_for_subtitle = 0 IF N_ELEMENTS(_extra) GT 0 THEN BEGIN dum = WHERE( TAG_NAMES(_extra) EQ 'SUBTITLE', nfound) IF nfound GT 0 THEN BEGIN subtitle = _extra.SUBTITLE IF STRLEN( subtitle ) GT 0 THEN $ yshrink_for_subtitle = 2. * tsize * ychar_sz ENDIF ENDIF bar_label_space = 2. * xchar_sz IF N_ELEMENTS(bar_label_length) LE 0 THEN BEGIN bar_more_space = 0 ENDIF ELSE BEGIN bar_more_space = bar_label_length * xchar_sz ENDELSE !P.position = [ xwin_sz[0], $ ywin_sz[0] + yshrink_for_subtitle, $ xwin_sz[1] - bar_more_space, $ ywin_sz[1] - yshrink_for_title] outPos = !P.position ;size of window for scale bar ;this needs to be outside put_scale_bar loop ;for the recursive call ! IF (N_ELEMENTS(barsz_chars) LE 0) THEN barsz_chars = 2. bar_sz = barsz_chars * xchar_sz IF (put_scale_bar) THEN BEGIN ;; NB: cant use KEYWORD_SET as 0 is a valid entry !! IF N_ELEMENTS(bar_separation) GT 0 THEN BEGIN bar_image_separation = bar_separation * xchar_sz ENDIF ELSE BEGIN bar_image_separation = 2. * xchar_sz ENDELSE ;;now redefine the plot window width to allow enough room for a scale bar ;;!P.position[2] = !P.position[2] - (bar_sz*4.5) - (-2.*!Y.ticklen > 0.0) !P.position[2] = !P.position[2] $ ;the user defined position of RHS - abs(bar_sz) $ ;but allow enough room for the colour bar -( -2. * !Y.ticklen > 0.0) $ ;and the ticks on both the bar and image - bar_image_separation $ ;and space between bar and image and - bar_label_space ;space for the label on the bar and the title IF !P.position[2] LT !P.position[0] THEN BEGIN IF (KEYWORD_SET(debug) ) THEN message, /INFO, ' WARNING...' message, /INFO, 'There is NOT enough room for the colour scale bar' message, /INFO, 'to fit into the plotting window !!!' !P.position[2] = !P.position[2] >(!P.position[0] +xchar_sz) ;;;stop ENDIF outPos = !P.position ENDIF ;put_scale_bar ;;if bar_tickv set then force the image to have at least this range IF (KEYWORD_SET(bar_tickv) ) THEN BEGIN maxbar = max([ bar_tickv, maximage, minimage], MIN=minbar) ;; IF (maxbar GT maximage) THEN a(sz[1]-1, sz[2]-1) = maxbar ;; IF (minbar LT minimage) THEN a(sz[1]-1, 0) = minbar ENDIF ELSE BEGIN maxbar = maximage minbar = minimage ENDELSE ;;if bar_range set then force the image to have exactly this range ;; (over-rides the bar_tickv forcing) IF (KEYWORD_SET(bar_range) ) THEN BEGIN IF (bar_range[0] NE bar_range[1] ) THEN BEGIN maxbar = bar_range[1] & minbar = bar_range[0] ;; IF (maxbar GT maximage) THEN a(sz[1]-1, sz[2]-1) = maxbar ;; IF (minbar LT minimage) THEN a(sz[1]-1, 0) = minbar ;; ;;clip the image array if necessary ;; a = a > minbar < maxbar ;; ;;the array is now clipped at the bytscl stage ;if (keyword_set(debug)) then begin IF (maxbar LT maximage) THEN BEGIN IF (KEYWORD_SET(debug) ) THEN BEGIN message, /INFO, $ " WARNING...Maximum image value out of range, Image CLIPPED" ENDIF ELSE BEGIN message, /INFO, $ "...Maximum image value out of range, Image CLIPPED" ENDELSE ENDIF IF (minbar GT minimage) THEN BEGIN IF (KEYWORD_SET(debug) ) THEN BEGIN message, /INFO, $ " WARNING...Minimum image value out of range, Image CLIPPED" ENDIF ELSE BEGIN message, /INFO, $ "...Minimum image value out of range, Image CLIPPED" ENDELSE ENDIF ENDIF ;valid bar_range ENDIF ; bar_range IF (KEYWORD_SET(debug) ) THEN BEGIN print,'POS 3 !x.range=', !x.range ;;; print,'POS 3 xrange=', xrange print,'pos 3 xtmp=', xtmp ENDIF ;;use plot to set the scaling with the new window comboStruct = ADD_STYLE( _extra, XSTYLE=5, YSTYLE=5 ) comboStruct.XSTYLE = comboStruct.XSTYLE AND 'FFFD'x ; style=2 not allowed comboStruct.YSTYLE = comboStruct.YSTYLE AND 'FFFD'x ; style=2 not allowed plot, xtmp, ytmp, /NODATA, TITLE=' ', SUBTITLE=' ', $ XTITLE=' ', YTITLE=' ', /NOERASE, $ xtickformat=xtickformat, ytickformat=ytickformat, $ _extra=comboStruct ;;;help, /str, comboStruct ;;XRANGE=xtmp, YRANGE=ytmp ;;MOVED to the bytscl code ~20 lines down ;; reverse the colour sense of the image if producing greyscale PS output ;;if (!d.name eq 'PS') then a = -a grey_scale_PS = 0b ;default is IN COLOUR for ALL devices IF (!D.name EQ 'PS') THEN BEGIN ;the output device is PostScript IF KEYWORD_SET(debug) THEN message, /INFO, 'PostScript device Detected' ;;if the PSETUP suite of routines have been used and the colour variable ;;has been set then dont worry about checking for grey-scales IF N_ELEMENTS(colour) GT 0 THEN BEGIN IF KEYWORD_SET(debug) THEN message, /INFO, '"colour" variable is defined' IF KEYWORD_SET(debug) THEN help, colour grey_scale_PS = NOT colour ENDIF ELSE BEGIN ;;decide if the default grey-scale has been loaded IF KEYWORD_SET(debug) THEN message, /INFO, 'Getting current colour table' tvlct, /GET, r, g, b ;load in the colour table grey_scale_PS = min((r AND g AND b) EQ r) ENDELSE IF KEYWORD_SET(debug) THEN help, grey_scale_PS ENDIF image_window = [ !X.window[0], !Y.window[0], !X.window[1], !Y.window[1] ] px = !X.window * !D.x_vsize ;Get size of window in device units py = !Y.window * !D.y_vsize swx = px[1] -px[0] ;Size in x in device units swx_img = swx swy = py[1] -py[0] ;Size in Y swx_offset = 0.0 if n_elements( xrange ) eq 2 then begin if xrange[1] ne xrange[0] and n_elements( xvalues_opt ) gt 0 then begin minX = MIN( xvalues_opt, max=maxX ) swx_img = swx * (maxX-minX )/(xrange[1]-xrange[0]) if minX gt xrange[0] then swx_offset = float(minX - xrange[0])/ $ (xrange[1]-xrange[0]) * $ (px[1] -px[0]) endif endif six = float(sz[1] ) ;Image sizes siy = float(sz[2] ) aspi = six / siy ;Image aspect ratio aspw = swx_img / swy ;Window aspect ratio f = aspi / aspw ;Ratio of aspect ratios IF (!D.name NE 'TEK') AND (NOT KEYWORD_SET(cont) ) THEN BEGIN ;;we can use tvscl ;;;print,'before tv' IF (KEYWORD_SET(debug) ) THEN message, /INFO, ' .......... Imaging....' IF (grey_scale_PS) THEN BEGIN IF (KEYWORD_SET(debug) ) THEN BEGIN message, /INFO, 'Grey-Scale PostScript Image...' message, /INFO, ' ... reversing colour sense of image so dark ' message, /INFO, ' backgrounds come out light' ENDIF subIm = -subIm ;reverse the colour sense of the image if ;producing postscript output so that those ;dark backgrounds come out light !! ;;rescale into the allowed colour range then shift up to the bottom ;;colour index bbb = bytscl(a, MIN=-maxbar, MAX=-minbar, TOP=topc -bottomc) + $ bottomc ENDIF ELSE BEGIN IF (KEYWORD_SET(debug) ) THEN BEGIN message, /INFO, 'Colour Image... ' ENDIF ;;rescale into the allowed colour range then shift up to the bottom ;;colour index bbb = bytscl( subIm, MIN=minbar, MAX=maxbar, TOP=topc -bottomc) + bottomc IF (KEYWORD_SET(debug) ) THEN help,topc,bottomc ;;if (!d.name eq 'PS') then bbb(where(bbb eq 1b)) = topc ENDELSE IF (KEYWORD_SET(debug) ) THEN BEGIN fstr = $ '("[",f8.2,",",f8.2,"] ==> [",f8.2,",",f8.2,"] ==> [",i3,",",i3,"]")' message, /INFO, 'byte scaled....' + $ strcompress( string( minimage, maximage, $ minbar, maxbar, min(bbb), max(bbb), $ FORM=fstr) ) ;help,/dev ENDIF IF (!D.flags AND 1) NE 0 THEN BEGIN ;Scalable pixels ---------------------> IF (KEYWORD_SET(debug) ) THEN $ message, /INFO, 'Scalable pixels detected' IF KEYWORD_SET(aspect) THEN BEGIN ;Retain aspect ratio? IF f GE 1.0 THEN swy = swy / f $ ELSE swx = swx * f ;Adjust window size ENDIF ; interpolating to the resolution of Postscript files takes 10s of sec ; and results in huge files, so limit to 2000 pixels in either directions maxRes = 2000. if swX gt maxRes or swY gt MaxRes then shrink = (maxRes/swx) < (maxRes/swy) $ else shrink = 1.0 fakeSwX = swX*shrink fakeSwY = swY*shrink newx = findgen(fakeSwX)/fakeSwX*(sz[1]-1) newy = findgen(fakeSwY)/fakeSwY*(sz[2]-1) resampled_image = INTERPOLATE(subIm, newx, newy, $ /GRID, CUBIC=KEYWORD_SET(cubic) ) bbb = bytscl( resampled_image, MIN=minbar, MAX=maxbar, TOP=topc -bottomc) $ + bottomc IF (KEYWORD_SET(debug) ) THEN help,topc,bottomc tv, bbb, px[0], py[0], XSIZE= SwX, YSIZE= SwY, /DEVICE if debug then help,swx,swy,fakeSwX,fakeSwY,newx,newy,subim,bbb ;;;stop ENDIF ELSE BEGIN ;END scalable pixels <----------------------- IF (KEYWORD_SET(debug) ) THEN $ message, /INFO, 'NON-Scalable pixels detected' IF KEYWORD_SET(window_scale) THEN BEGIN ;Scale window to image? tv, bbb, px[0], py[0] ;Output image ;;;stop swx = six ;Set window size from image swy = siy ENDIF ELSE BEGIN ;End Scale window to image IF (KEYWORD_SET(debug) ) THEN $ message, /INFO, 'Scale image to window' IF KEYWORD_SET(aspect) THEN BEGIN IF f GE 1.0 THEN swy = swy / f ELSE swx = swx * f ENDIF ;aspect ;;Have to resample image IF KEYWORD_SET(congrid_keyword) THEN BEGIN ;;; resampled_image = congrid(bbb, $ resampled_image = congrid(subim, $ /Minus_One, $ ; else will be off by 1/2 swx_img, $ swy, $ INTERP=KEYWORD_SET(interp), $ CUBIC=KEYWORD_SET(cubic) ) ENDIF ELSE BEGIN ; I couldn't get poly_2d to interpolate to the grid points! ;;; resampled_image = poly_2d(bbb, $ ; BD change 4/00 IF NOT KEYWORD_SET(interp) THEN BEGIN resampled_image = poly_2d(subIm, $ [[ 0, 0], [ six /swx_img, 0]], $ [[ 0, siy /swy], [ 0, 0]], $ KEYWORD_SET(interp), $ (swx_img>2), $ (swy>2), $ CUBIC=KEYWORD_SET(cubic) ) ENDIF ELSE BEGIN newx = findgen(swx)/swx*(sz[1]-1) newy = findgen(swy)/swy*(sz[2]-1) resampled_image = INTERPOLATE(subIm, newx, newy, $ /GRID, CUBIC=KEYWORD_SET(cubic) ) ENDELSE ENDELSE ; BD change 4/00 subIm = congrid(resampled_image,sz[1],sz[2],INTERP=KEYWORD_SET(interp)) ; so contours match colors reim_sc = bytscl(resampled_image, MIN=minbar, MAX=maxbar, $ TOP=topc -bottomc) + bottomc IF (KEYWORD_SET(debug) ) THEN help,topc,bottomc tv, reim_sc, px[0]+1+swx_offset, py[0]+1 ; BD change 12/6/99 ENDELSE ;End Scale image to window ENDELSE ;scalable pixels ENDIF ;;use contour to give the axes all the time ppmulti = !P.multi !P.multi = pmulti ; BD change 4/00 because bug if 10x10, eg., xstyle = 1 IF ((!X.style MOD 2) EQ 0) THEN xstyle = 1 +!X.style ELSE xstyle = !X.style IF (!Y.style EQ 2) THEN ystyle = 1 ; BD change 4/00 because bug if 10x10, eg., ystyle=1 IF ((!Y.style MOD 2) EQ 0) THEN ystyle = 1 +!Y.style ELSE ystyle = !Y.style c_sz = sz if (debug) then print,'pos 4 xtmp=', xtmp IF KEYWORD_SET(exact) THEN BEGIN c_x = ((indgen(c_sz[1] ) +0.5) *(xtmp[1] -xtmp[0] ) /(c_sz[1] ) ) $ +xtmp[0] c_y = ((indgen(c_sz[2] ) +0.5) *(ytmp[1] -ytmp[0] ) /(c_sz[2] ) ) $ +ytmp[0] ENDIF ELSE BEGIN c_x = (indgen(c_sz[1] ) *(xtmp[1] -xtmp[0] ) /(c_sz[1] -1 ) ) +xtmp[0] c_y = (indgen(c_sz[2] ) *(ytmp[1] -ytmp[0] ) /(c_sz[2] -1 ) ) +ytmp[0] ENDELSE IF Use_Args THEN BEGIN c_x = xvalues_opt c_y = yvalues_opt ENDIF comboStruct = ADD_STYLE( _extra, XSTYLE=xstyle, YSTYLE=ystyle ) comboStruct.XSTYLE = comboStruct.XSTYLE AND 'FFFD'x ; style=2 not allowed comboStruct.YSTYLE = comboStruct.YSTYLE AND 'FFFD'x ; style=2 not allowed IF (KEYWORD_SET(debug) ) THEN BEGIN print,'!x.crange=', !x.crange print,' ' ENDIF ;;;help, a, c_x, c_y contour, subIm, c_x, c_y, /NOERASE, /NODATA, $ XRANGE=!x.crange, YRANGE=!y.crange, $ ; not sure why needed POS=[ px[0]/!d.x_size, py[0]/!d.y_size, $ (px[0]+swx)/!d.x_size, (py[0]+swy)/!d.y_size], $ xtickformat=xtickformat, ytickformat=ytickformat, $ TITLE=' ', SUBTITLE=' ', _EXTRA=comboStruct ;;;stop ;;;print, 'c_x at contour 1=' ;;;minmax, c_x ;;find the position for the title and put it there xpos = 0.5 * total(!X.window) ;;if (!x.charsize gt 0) then xcharsize=!x.charsize else xcharsize=1.0 ;;if (!p.charsize gt 0) then pcharsize=!p.charsize else pcharsize=1.0 ;;if (not keyword_set(tsize)) then tsize = pcharsize ch_dev_to_norm = pcharsize * !D.y_ch_size /!D.y_vsize ;;ypos = !y.window[1] + (-!x.ticklen > 0.0) +2.7*xcharsize*ch_dev_to_norm ypos = !Y.window[1] +( -!X.ticklen > 0.0) $ +raise_ptitle * xcharsize * ch_dev_to_norm xyouts, xpos, ypos, !P.title, ALIGNMENT=0.5, /NORM, SIZE=tsize * 1.2 ;;find the position for the subtitle and put it there ypos = !Y.window[0] -( -!X.ticklen > 0.0) $ -(2.7 * xcharsize +tsize) * ch_dev_to_norm xyouts, xpos, ypos, !P.subtitle, ALIGNMENT=0.5, /NORM, SIZE=tsize cloop = 0 IF (NOT KEYWORD_SET(nocont) ) THEN BEGIN ;;use contour to give data contours on top of the image IF (KEYWORD_SET(debug) ) THEN message, /INFO, ' .......... Contouring....' ;;need to reset the ranges because the axis labels are independent ;;of the way contour works (plots as index numbers) save_p = !P save_x = !X save_y = !Y save_z = !Z resetplt, /ALL clearplt, /ALL !X.style = 5 !Y.style = 5 !P.multi = pmulti IF (!P.thick LE 0) THEN !P.thick = 1 ;plot contours IF (KEYWORD_SET(levels) ) THEN csz = N_ELEMENTS(levels) $ ELSE IF (KEYWORD_SET(nlevels) ) THEN csz = nlevels +1 ELSE csz = 6 IF (NOT KEYWORD_SET(max_value) ) THEN max_value = maximage +1 keyc_colors = KEYWORD_SET(c_colors) keyc_linestyle = KEYWORD_SET(c_linestyle) keyc_thick = KEYWORD_SET(c_thick) cont_image = image * 1.0 IF (KEYWORD_SET(badpts) ) THEN BEGIN IF (badpts[0] GE 0) THEN cont_image(badpts) = 10 * maximage ENDIF if (debug) then print,'pos 5 xtmp=', xtmp c_sz = size(cont_image) IF KEYWORD_SET(exact) THEN BEGIN c_x = ((indgen(c_sz[1] ) +0.5) *(xtmp[1] -xtmp[0] ) /(c_sz[1] ) ) $ +xtmp[0] c_y = ((indgen(c_sz[2] ) +0.5) *(ytmp[1] -ytmp[0] ) /(c_sz[2] ) ) $ +ytmp[0] ENDIF ELSE BEGIN c_x = (indgen(c_sz[1] ) *(xtmp[1] -xtmp[0] ) /(c_sz[1] -1 ) ) +xtmp[0] c_y = (indgen(c_sz[2] ) *(ytmp[1] -ytmp[0] ) /(c_sz[2] -1 ) ) +ytmp[0] ENDELSE IF Use_Args THEN BEGIN c_x = xvalues_opt c_y = yvalues_opt ENDIF IF (KEYWORD_SET(levels) ) THEN BEGIN cloop = 1 IF (NOT keyc_colors) THEN c_colors = $ (fix((((levels -minbar) /float(maxbar -minbar) ) * 0.5 + 0.75) $ *(topc -bottomc) ) MOD(topc -bottomc +1) ) + bottomc IF (NOT keyc_linestyle) THEN c_linestyle = levels * 0 IF (NOT keyc_thick) THEN c_thick = levels * 0 +!P.thick zero = where(levels EQ 0, count) zero = zero[0] IF (count * zero GT 0) THEN BEGIN ;; do special things to highlight the zero contour IF (NOT keyc_colors) AND (KEYWORD_SET(cont) ) THEN $ c_colors(zero) = topc IF (NOT keyc_thick) THEN BEGIN IF (KEYWORD_SET(cont) ) THEN $ c_thick(zero) = 2.5 * !P.thick $ ELSE $ c_thick(zero) = 2.0 * !P.thick ENDIF IF (NOT keyc_linestyle) AND $ (KEYWORD_SET(cont) ) THEN c_linestyle(0:zero -1) = 1 ENDIF IF (NOT keyc_colors) AND (grey_scale_PS) AND (KEYWORD_SET(cont) ) THEN $ c_colors = topc ;invert line colors if b/w postscript output IF (grey_scale_PS) THEN usec_cols = topc - c_colors + bottomc $ ELSE usec_cols = c_colors comboStruct = ADD_STYLE( _extra, XSTYLE=xstyle, YSTYLE=ystyle ) comboStruct.XSTYLE = comboStruct.XSTYLE AND 'FFFD'x ; style=2 not allowed comboStruct.YSTYLE = comboStruct.YSTYLE AND 'FFFD'x ; style=2 not allowed contour, cont_image, c_x, c_y, /overplot, $ XRANGE=!x.crange, YRANGE=!y.crange, $ ; BD add 4/00 POS=[ px[0], py[0], px[0] +swx, py[0] +swy], $ MAX_VALUE=max_value, C_COLORS=usec_cols, $ C_LINESTYLE=c_linestyle, C_THICK=c_thick, $ xtickformat=xtickformat, ytickformat=ytickformat, $ LEVELS=levels, _EXTRA=comboStruct ;;;help,cont_image, c_x, c_y ;;;print, 'c_x:' ;;;minmax,c_x ;;;stop ENDIF ELSE BEGIN cloop = 2 IF (NOT keyc_colors) THEN c_colors = $ [ replicate(topc, (csz /2 > 1) ), $ replicate(bottomc +(topc -bottomc) /4, (csz /2 +1 > 1) ) ] IF (NOT keyc_linestyle) THEN c_linestyle = replicate(0, csz) IF (NOT keyc_thick) THEN c_thick = [ !P.thick] IF (NOT KEYWORD_SET(nlevels) ) THEN nlevels = csz -1 ;invert line colors if b/w postscript output IF (grey_scale_PS) THEN usec_cols = topc - c_colors + bottomc $ ELSE usec_cols = c_colors ;;;stop comboStruct = ADD_STYLE( _extra, XSTYLE=xstyle, YSTYLE=ystyle ) comboStruct.XSTYLE = comboStruct.XSTYLE AND 'FFFD'x ; style=2 not allowed comboStruct.YSTYLE = comboStruct.YSTYLE AND 'FFFD'x ; style=2 not allowed contour, cont_image, c_x, c_y, /overplot, $ XRANGE=!x.crange, YRANGE=!y.crange, $ ; BD add 4/00 MAX_VALUE=max_value, C_COLORS=usec_cols, $ C_LINESTYLE=c_linestyle, C_THICK=c_thick, $ xtickformat=xtickformat, ytickformat=ytickformat, $ NLEVELS=nlevels, _EXTRA=comboStruct ;;;help,cont_image, c_x, c_y ;;;print, ' from way down, c_x:' ;;;minmax,c_x ;;;stop ENDELSE if n_elements( currentTime ) gt 0 then $ oplot, [currentTime,currentTime], !y.crange, line=2, thick=2 cont_image = 0 ;release some space NOW !P = save_p !X = save_x !Y = save_y !Z = save_z ENDIF if n_elements( currentTime ) gt 0 then $ oplot, [currentTime,currentTime], !y.crange, line=2, thick=2 IF put_scale_bar AND (bar_sz GT 0) THEN BEGIN ;;add a scale bar by calling this routine AGAIN IF (KEYWORD_SET(debug) ) THEN $ message, /INFO, ' .......... adding Scale Bar....' ;;do it !!! ;;now redefine the plot position for a scale bar ;;Note that the y pos must be re-enlarged for the shrinkage that took place ;;for the Plot title, as the recursive call will do the shrinkage AGAIN !! !P.position = [ !X.window[1] + $ bar_image_separation + ( -!Y.ticklen > 0.0), $ !Y.window[0], $ !X.window[1] + $ abs(bar_sz) + bar_label_space +( -!Y.ticklen > 0.0), $ !Y.window[1] + yshrink_for_title] ;use image_cont again to do scale bar save_p = !P save_x = !X save_y = !Y clearplt, /X, /Y, /P !P.multi = pmulti !P.thick = save_p.thick !P.ticklen = save_p.ticklen !X.minor = -1 & !X.ticklen = 0.000001 ;if bar_tickv set then force the image to ;have at least this range ;maxscl = max([maxbar,maximage]) ;minscl = min([minbar,minimage]) ;;bardat = (findgen(!D.n_colors) /(!D.n_colors -1) *(maxbar -minbar) ) $ ;; + minbar bar_dim = !D.n_colors < !D.table_size bardat = (findgen(bar_dim) /(bar_dim -1) *(maxbar -minbar) ) + minbar bardat = transpose([[ bardat], [ bardat]]) !X.style = 1 !Y.style = 1 !P = save_p CASE (cloop) OF 0: th_image_cont_4bar, bardat, /NOBAR, /NOERASE, $ NOCONT=KEYWORD_SET(nocont), TOPC=topc, BOTTOMC=bottomc 1: th_image_cont_4bar, bardat, /NOBAR, /NOERASE, $ NOCONT=KEYWORD_SET(nocont), TOPC=topc, BOTTOMC=bottomc, $ MAX_VALUE=max_value, C_COLORS=c_colors, $ C_LINESTYLE=c_linestyle, C_THICK=c_thick, LEVELS=levels 2: th_image_cont_4bar, bardat, /NOBAR, /NOERASE, $ NOCONT=KEYWORD_SET(nocont), TOPC=topc, BOTTOMC=bottomc, $ MAX_VALUE=max_value, C_COLORS=c_colors, $ C_LINESTYLE=c_linestyle, C_THICK=c_thick, NLEVELS=nlevels ENDCASE clearplt,/p resetplt, /Y !P.charsize = save_p.charsize !Y.charsize = save_y.charsize !Y.ticklen = save_y.ticklen IF (N_ELEMENTS(bar_ticks) GT 0) THEN !Y.ticks = bar_ticks ELSE $ IF (NOT KEYWORD_SET(bar_range) ) AND ((maxbar -minbar) LE 10.0) $ THEN !Y.ticks = 2 IF (KEYWORD_SET(bar_tickv) ) THEN BEGIN !Y.tickv = bar_tickv !Y.ticks = N_ELEMENTS(bar_tickv) -1 ENDIF !Y.range = [ minbar, maxbar] IF (KEYWORD_SET(bar_tickname) ) THEN !Y.tickname = bar_tickname IF (KEYWORD_SET(bar_ticklen) ) THEN !Y.ticklen = bar_ticklen !Y.ticklen = !Y.ticklen * $ (image_window[2] -image_window[0] ) $ /(save_p.position[2] -save_p.position[0] ) ;;; black = mk_color('black',/search) axis, /YAX, YTITLE=!Z.title, YSTYLE=1, /NOERASE, ytickformat='betterticklabels', $ color=!p.color ;;; color=black !P = save_p !X = save_x !Y = save_y ENDIF !P = orig_p !X = orig_x !Y = orig_y !Z = orig_z !P.position = pposition !P.multi = ppmulti RETURN END