;+ ; ; @file_comments ; Enhanced version of TVSCL ; ; @categories ; quick exploration of 2D arrays ; ; @param Z2D {in}{required} ; 2D array to visualize ; ; @param CELLSIZE {in}{optional} ; This is the size (in pixel) of the square ; representing 1 array element. By default, this size is computed ; automatically in order that the size of the plotting window do ; not exceed the screen size. If the user specify a large value ; of cellsize that forces tvplus to create a window larger than ; the screen, a "scrolling window" will be displayed instead of a ; regular window. Unfortunately the nice functionalities of tvplus ; are not coded for "scrolling window" case... ; ; @keyword BOTTOM {default=1} ; The lowest color index of the colors to be used ; ; @keyword C_NAN {default=!d.n_colors < 255} ; The color number that should be used for the NaN values. ; ; @keyword C_MASK {default=0} ; The color number that should be used for the mask values. ; ; @keyword OFFSET ; 2 elements vector used by tvplus itself when showing zoom. ; It is used to shift the ranges of xaxis and yaxis. ; For example: tvplus,sst[x1:x2,y1:y2],offset=[x1,y1] ; ; @keyword MASK ; The mask value. Note that if abs(mask) < 1.e6, then the ; exact value of the mask is used to find the maskwd point. ; if abs(mask) > 1.e6, the test to find the masked value is ge ; abs(mask)/10. This is necessary to avoid the rounding errors ; ; @keyword MIN ; Scalar used to specify the min value to be drawn. ; ; @keyword MAX ; Scalar used to specify the max value to be drawn. ; ; @keyword NCOLORS {default=(d.n_colors < 256) - 1 - bottom} ; number of colors to be used. ; ; @keyword NOINTERP ; Used this keyword if you don't want that the values ; are interpolated from BOTTOM using NCOLORS colors. ; This can be for example useful when working on byte type arrays. ; ; @keyword NOUSEINFOS ; Activate to suppress the printed message explaining how to use tvplus ; ; @keyword WINDOW ; Number of the window used to display the array values. ; default is window number 0. ; ; @keyword _EXTRA ; Used to pass keywords to TV, ; PLOT, ; colorbar ; ; @restrictions ; use your mouse to scan the array values... ; left button : mouse position and associated array value ; middle button: use it twice to define a zoom box ; right button : quit ; ; the nice functionalities of tvplus are not coded ; for "scrolling window" case... ; ; @examples ; ; IDL> tvplus, dist(100) ; ; @history ; Sebastien Masson (smasson\@lodyc.jussieu.fr) ; 18/12/98 ; Aug 2005: quick cleaning + english ; ; @version ; $Id$ ; ;- PRO tvplus, z2d, cellsize $ , BOTTOM=bottom, C_MASK=c_mask, C_NAN=c_nan, WINDOW=window $ , MIN=min, MAX=max, MASK=mask, OFFSET=offset $ , NOUSEINFOS=NOUSEINFOS $ , NCOLORS=ncolors, NOINTERP=nointerp, _EXTRA=ex ; compile_opt idl2, strictarrsubs ; IF n_elements(z2d) EQ 0 THEN return arr = reform(float(z2d)) ;------------------------------------------------------------ ; check the size of the input array ;------------------------------------------------------------ if (size(arr))[0] NE 2 then begin ras = report('Input array must have only 2 dimensions and not '+ strtrim(size(arr, /n_dimensions), 1)) return endif ;------------------------------------------------------------ ; def of ncolmax, bottom, topcol and ncolors ;------------------------------------------------------------ ncolmax = !d.n_colors < 256 IF N_ELEMENTS(bottom) EQ 0 THEN bottom = 1 if NOT keyword_set(ncolors) then ncolors = ncolmax - 1 - bottom topcol = (bottom+ncolors-1) < (ncolmax-1) ;------------------------------------------------------------ ; get default values of !x, !y, !z ;------------------------------------------------------------ ; xenvsauve = !x & yenvsauve = !y & penvsauve = !p reinitplt, /z, /invert ;------------------------------------------------------------ ; Do we have NaN values in arr??? ;------------------------------------------------------------ nan = total(finite(z2d, /nan)) < 1 if keyword_set(nan) then begin nanindex = where(finite(z2d, /nan) EQ 1) arr[nanindex] = min(arr, /nan) endif ;------------------------------------------------------------ ; Compute the size (in pixel) of the square representing 1 ; point of the input array ;------------------------------------------------------------ dimensions = GET_SCREEN_SIZE() if n_elements(cellsize) EQ 0 then BEGIN cellsize = min(floor(dimensions/(size(z2d))[1: 2]*.75)) ENDIF ELSE $ ; we need to use a scrolling bar window if cellsize GE min(floor(dimensions/(size(z2d))[1: 2]*.75)) then scrolling = 1 if cellsize LT 1 then begin cellsize = 1 scrolling = 1 endif ;------------------------------------------------------------ ; Change the value of the masked value for the min of the non-masked values ;------------------------------------------------------------ if n_elements(mask) then BEGIN if abs(mask) LT 1e6 then BEGIN masked = where(arr EQ mask) if masked[0] NE -1 then arr[masked] = min(arr[where(arr NE mask)]) ENDIF ELSE BEGIN masked = where(abs(arr) GE abs(mask)/10.) if masked[0] NE -1 then arr[masked] = min(arr[where(abs(arr) LT abs(mask)/10.)]) ENDELSE ENDIF ELSE masked = -1 ;------------------------------------------------------------ ; apply min/max keywords ;------------------------------------------------------------ if n_elements(min) NE 0 then BEGIN arr = min > arr truemin = min ENDIF ELSE truemin = min(arr) if n_elements(max) NE 0 then BEGIN arr = arr < max truemax = max ENDIF ELSE truemax = max(arr) ; IF truemin EQ truemax THEN BEGIN dummy = report('constant value everywhere: '+ strtrim(truemin, 1)) return ENDIF ;------------------------------------------------------------ ; apply other keywords (nointerp, c_nan, c_mask) ;------------------------------------------------------------ if NOT keyword_set(nointerp) then BEGIN ; interpolation between bottom and bottom+ncolors-1 m = 1.*(ncolors-1)/(truemax-truemin) p = bottom-1.*truemin*m arr = round(m*temporary(arr)+p) endif ; set c_nan for NaN values if keyword_set(nan) then begin if n_elements(c_nan) NE 0 THEN arr[nanindex] = c_nan < (ncolmax -1) $ ELSE arr[nanindex] = topcol endif ; c_mask for masked values if n_elements(c_mask) NE 0 AND masked[0] NE -1 THEN $ arr[masked] = c_mask < (ncolmax -1) ; use byte type to save memory arr = byte(temporary(arr)) ; increase the size of the array in order to be displayed ; with the suitable size szarr = size(arr, /dimensions) arr = congrid(temporary(arr), szarr[0]*cellsize, szarr[1]*cellsize) ;------------------------------------------------------------ ; open a window with the correct size ;------------------------------------------------------------ nx = (size(arr))[1] ny = (size(arr))[2] ; margin size (in pixel) xyaspect = 1.*nx/ny if xyaspect GE 1 THEN marginpix = 1.*[25, 25, 75, 25] ELSE marginpix = 1.*[25, 100, 25, 25] ; if n_elements(scrolling) EQ 0 then BEGIN ; open the regular window if NOT keyword_set(window) then window = 0 window, window, xsize = nx+marginpix[0]+marginpix[1] $ , ysize = ny+marginpix[2]+marginpix[3] ; for 24 bits colors, make sure that the background color is the good one... if !d.n_colors gt 256 then BEGIN device, decomposed = 1 !p.background = 'ffffff'x plot, [0], [0], xstyle = 5, ystyle = 5 device, decomposed = 0 endif tv, arr, marginpix[0], marginpix[2], _EXTRA = ex ; ; axis and plot frame ; ; get the normalized position of the tv (we just done above) ; to know where the frame should be drawn poscadre = fltarr(4) poscadre[0] = marginpix[0]/!d.x_size poscadre[2] = 1.-marginpix[1]/!d.x_size poscadre[1] = marginpix[2]/!d.y_size poscadre[3] = 1-marginpix[3]/!d.y_size ; Use plot to draw the frame if NOT keyword_set(offset) then offset = [0, 0] !p.position = poscadre plot, [0], [0], /nodata, /noerase, position = poscadre, color = 0 $ , xstyle = 1, ystyle = 1, xticklen = 1, yticklen = 1 $ , xrange = 1.*[0, nx]/cellsize-.5+offset[0] $ , yrange = 1.*[0, ny]/cellsize-.5+offset[1], _extra = ex xenvsauve = !x & yenvsauve = !y & penvsauve = !p ; ; draw the colorbar ; IF truemin ne truemax THEN BEGIN if xyaspect ge 1 then $ posbar = [25./!d.x_size, 25./!d.y_size, 1-25./!d.x_size, 50./!d.y_size] $ ELSE posbar = [1-75./!d.x_size, 25./!d.y_size, 1-50./!d.x_size, 1-25./!d.y_size] if keyword_set(nointerp) then BEGIN & truemin = 0 & truemax = ncolmax & endif colorbar, min = truemin, max = truemax, division = 10, cb_color = 0, position = posbar $ , vertical = xyaspect lt 1, /right, BOTTOM = bottom, NCOLORS = ncolors, _EXTRA = ex ENDIF ; !p.position = poscadre ENDIF ELSE BEGIN ;------------------------------------------------------------ ; scrolling bar window case... ;------------------------------------------------------------ ; for 24 bits colors, make sure that the background color is the good one... if !d.n_colors gt 256 then begin window, /pixmap device, decomposed = 1 !p.background = 'ffffff'x plot, [0], [0] device, decomposed = 0 endif slide_image, arr $ ; We draw it in a window with a scrolling bar , xsize = nx, ysize = ny $ , xvisible = round(.7*dimensions[0]) < (size(arr))[1] $ , yvisible = round(.7*dimensions[1]) < (size(arr))[2], /register, congrid = 0, show_full = 0 return ENDELSE ;------------------------------------------------------------ ; Use the mouse to get nice functionalities ;------------------------------------------------------------ ; format to print the mouse position CASE 1 OF nx LT 10:fmt1 = '(i1)' nx LT 100:fmt1 = '(i2)' nx LT 1000:fmt1 = '(i3)' nx LT 10000:fmt1 = '(i4)' ELSE:fmt1 = '' ENDCASE CASE 1 OF ny LT 10:fmt2 = '(i1)' ny LT 100:fmt2 = '(i2)' ny LT 1000:fmt2 = '(i3)' ny LT 10000:fmt2 = '(i4)' ELSE:fmt2 = '' ENDCASE ; if NOT keyword_set(nouseinfos) then begin print, 'left button : mouse position and associated array value' print, 'middle button: use it twice to define a zoom box' print, 'right button : quit' endif cursor, x, y, /device, /down x = x-marginpix[0] & x = 0 > floor(x/cellsize) < ((size(arr))[1]/cellsize-1) y = y-marginpix[2] & y = 0 > floor(y/cellsize) < ((size(arr))[2]/cellsize-1) while (!mouse.button ne 4) do BEGIN case !mouse.button of 0:return 1:BEGIN ; get value if x LE nx/cellsize AND y LE ny/cellsize then begin print, '(x, y) = (' + string(x+offset[0], format = fmt1) $ + ', ' + string(y+offset[1], format = fmt2) $ + '), value = '+strtrim(float((reform(z2d))[x, y]), 1) ENDIF cursor, x, y, /device, /down x = x-marginpix[0] & x = 0 > floor(x/cellsize) < ((size(arr))[1]/cellsize-1) y = y-marginpix[2] & y = 0 > floor(y/cellsize) < ((size(arr))[2]/cellsize-1) END 2:BEGIN ; zoom cursor, x2, y2, /device, /down x2 = x2-marginpix[0] & x2 = 0 > floor(x2/cellsize) < ((size(arr))[1]/cellsize-1) y2 = y2-marginpix[2] & y2 = 0 > floor(y2/cellsize) < ((size(arr))[2]/cellsize-1) x = [x, x2] & x = x[sort(x)] y = [y, y2] & y = y[sort(y)] IF keyword_set(OFFSET) THEN offset = [x[0], y[0]]+offset ELSE offset = [x[0], y[0]] tvplus, z2d[x[0]:x[1], y[0]:y[1] ], WINDOW = window, MIN = min, MAX = max $ , MASK = mask, C_MASK = c_mask, C_NAN = c_nan, /NOUSEINFOS, OFFSET = OFFSET $ , NCOLORS = ncolors, NOINTERP = nointerp, BOTTOM = bottom, _EXTRA = ex return END ELSE: endcase ENDWHILE ;------------------------------------------------------------ !x = xenvsauve & !y = yenvsauve & !p = penvsauve !x.range = 1.*[0, nx]/cellsize-.5+offset[0] !y.range = 1.*[0, ny]/cellsize-.5+offset[1] ;------------------------------------------------------------ return end