[2] | 1 | ;+ |
---|
| 2 | ; |
---|
[142] | 3 | ; @file_comments |
---|
[260] | 4 | ; Enhanced version of <proidl>TVSCL</proidl> |
---|
[2] | 5 | ; |
---|
[231] | 6 | ; @categories |
---|
| 7 | ; quick exploration of 2D arrays |
---|
[2] | 8 | ; |
---|
[142] | 9 | ; @param Z2D {in}{required} |
---|
| 10 | ; 2D array to visualize |
---|
[2] | 11 | ; |
---|
[163] | 12 | ; @param CELLSIZE {in}{optional} |
---|
[142] | 13 | ; This is the size (in pixel) of the square |
---|
| 14 | ; representing 1 array element. By default, this size is computed |
---|
| 15 | ; automatically in order that the size of the plotting window do |
---|
| 16 | ; not exceed the screen size. If the user specify a large value |
---|
| 17 | ; of cellsize that forces tvplus to create a window larger than |
---|
| 18 | ; the screen, a "scrolling window" will be displayed instead of a |
---|
[226] | 19 | ; regular window. Unfortunately the nice functionalities of tvplus |
---|
[142] | 20 | ; are not coded for "scrolling window" case... |
---|
[35] | 21 | ; |
---|
[152] | 22 | ; @keyword BOTTOM {default=1} |
---|
| 23 | ; The lowest color index of the colors to be used |
---|
[2] | 24 | ; |
---|
[152] | 25 | ; @keyword C_NAN {default=!d.n_colors < 255} |
---|
[142] | 26 | ; The color number that should be used for the NaN values. |
---|
[2] | 27 | ; |
---|
[152] | 28 | ; @keyword C_MASK {default=0} |
---|
[142] | 29 | ; The color number that should be used for the mask values. |
---|
[2] | 30 | ; |
---|
[226] | 31 | ; @keyword OFFSET |
---|
[163] | 32 | ; 2 elements vector used by tvplus itself when showing zoom. |
---|
[142] | 33 | ; It is used to shift the ranges of xaxis and yaxis. |
---|
[226] | 34 | ; For example: tvplus,sst[x1:x2,y1:y2],offset=[x1,y1] |
---|
[2] | 35 | ; |
---|
[226] | 36 | ; @keyword MASK |
---|
[142] | 37 | ; The mask value. Note that if abs(mask) < 1.e6, then the |
---|
| 38 | ; exact value of the mask is used to find the maskwd point. |
---|
| 39 | ; if abs(mask) > 1.e6, the test to find the masked value is ge |
---|
| 40 | ; abs(mask)/10. This is necessary to avoid the rounding errors |
---|
[2] | 41 | ; |
---|
[152] | 42 | ; @keyword MIN |
---|
| 43 | ; Scalar used to specify the min value to be drawn. |
---|
[2] | 44 | ; |
---|
[142] | 45 | ; @keyword MAX |
---|
[152] | 46 | ; Scalar used to specify the max value to be drawn. |
---|
[2] | 47 | ; |
---|
[152] | 48 | ; @keyword NCOLORS {default=(d.n_colors < 256) - 1 - bottom} |
---|
| 49 | ; number of colors to be used. |
---|
[2] | 50 | ; |
---|
[142] | 51 | ; @keyword NOINTERP |
---|
[163] | 52 | ; Used this keyword if you don't want that the values |
---|
[152] | 53 | ; are interpolated from BOTTOM using NCOLORS colors. |
---|
[163] | 54 | ; This can be for example useful when working on byte type arrays. |
---|
[2] | 55 | ; |
---|
[142] | 56 | ; @keyword NOUSEINFOS |
---|
[163] | 57 | ; Activate to suppress the printed message explaining how to use tvplus |
---|
[2] | 58 | ; |
---|
[142] | 59 | ; @keyword WINDOW |
---|
| 60 | ; Number of the window used to display the array values. |
---|
| 61 | ; default is window number 0. |
---|
[2] | 62 | ; |
---|
[152] | 63 | ; @keyword _EXTRA |
---|
[260] | 64 | ; Used to pass keywords to <proidl>TV</proidl>, |
---|
| 65 | ; <proidl>PLOT</proidl>, |
---|
[258] | 66 | ; <pro>colorbar</pro> |
---|
[226] | 67 | ; |
---|
| 68 | ; @restrictions |
---|
[35] | 69 | ; use your mouse to scan the array values... |
---|
| 70 | ; left button : mouse position and associated array value |
---|
| 71 | ; middle button: use it twice to define a zoom box |
---|
| 72 | ; right button : quit |
---|
[2] | 73 | ; |
---|
[226] | 74 | ; the nice functionalities of tvplus are not coded |
---|
[142] | 75 | ; for "scrolling window" case... |
---|
[2] | 76 | ; |
---|
[142] | 77 | ; @examples |
---|
[2] | 78 | ; |
---|
[371] | 79 | ; IDL> tvplus, dist(100) |
---|
| 80 | ; |
---|
[142] | 81 | ; @history |
---|
[157] | 82 | ; Sebastien Masson (smasson\@lodyc.jussieu.fr) |
---|
[2] | 83 | ; 18/12/98 |
---|
[493] | 84 | ; Aug 2005: quick cleaning + English |
---|
[142] | 85 | ; |
---|
| 86 | ; @version |
---|
| 87 | ; $Id$ |
---|
| 88 | ; |
---|
[2] | 89 | ;- |
---|
[327] | 90 | PRO tvplus, z2d, cellsize $ |
---|
| 91 | , BOTTOM=bottom, C_MASK=c_mask, C_NAN=c_nan, WINDOW=window $ |
---|
| 92 | , MIN=min, MAX=max, MASK=mask, OFFSET=offset $ |
---|
[506] | 93 | , NOUSEINFOS=NOUSEINFOS, PIXMAP = pixmap $ |
---|
[327] | 94 | , NCOLORS=ncolors, NOINTERP=nointerp, _EXTRA=ex |
---|
[2] | 95 | ; |
---|
[114] | 96 | compile_opt idl2, strictarrsubs |
---|
| 97 | ; |
---|
[35] | 98 | IF n_elements(z2d) EQ 0 THEN return |
---|
| 99 | arr = reform(float(z2d)) |
---|
[2] | 100 | ;------------------------------------------------------------ |
---|
[226] | 101 | ; check the size of the input array |
---|
[2] | 102 | ;------------------------------------------------------------ |
---|
[35] | 103 | if (size(arr))[0] NE 2 then begin |
---|
| 104 | ras = report('Input array must have only 2 dimensions and not '+ strtrim(size(arr, /n_dimensions), 1)) |
---|
| 105 | return |
---|
| 106 | endif |
---|
[2] | 107 | ;------------------------------------------------------------ |
---|
[296] | 108 | ; def of ncolmax, bottom, topcol and ncolors |
---|
[2] | 109 | ;------------------------------------------------------------ |
---|
[35] | 110 | ncolmax = !d.n_colors < 256 |
---|
[152] | 111 | IF N_ELEMENTS(bottom) EQ 0 THEN bottom = 1 |
---|
| 112 | if NOT keyword_set(ncolors) then ncolors = ncolmax - 1 - bottom |
---|
[35] | 113 | topcol = (bottom+ncolors-1) < (ncolmax-1) |
---|
[2] | 114 | ;------------------------------------------------------------ |
---|
[35] | 115 | ; get default values of !x, !y, !z |
---|
[2] | 116 | ;------------------------------------------------------------ |
---|
[35] | 117 | ; xenvsauve = !x & yenvsauve = !y & penvsauve = !p |
---|
| 118 | reinitplt, /z, /invert |
---|
[2] | 119 | ;------------------------------------------------------------ |
---|
[35] | 120 | ; Do we have NaN values in arr??? |
---|
[2] | 121 | ;------------------------------------------------------------ |
---|
[35] | 122 | nan = total(finite(z2d, /nan)) < 1 |
---|
| 123 | if keyword_set(nan) then begin |
---|
| 124 | nanindex = where(finite(z2d, /nan) EQ 1) |
---|
| 125 | arr[nanindex] = min(arr, /nan) |
---|
| 126 | endif |
---|
[2] | 127 | ;------------------------------------------------------------ |
---|
[35] | 128 | ; Compute the size (in pixel) of the square representing 1 |
---|
[226] | 129 | ; point of the input array |
---|
[2] | 130 | ;------------------------------------------------------------ |
---|
[35] | 131 | dimensions = GET_SCREEN_SIZE() |
---|
[226] | 132 | if n_elements(cellsize) EQ 0 then BEGIN |
---|
[35] | 133 | cellsize = min(floor(dimensions/(size(z2d))[1: 2]*.75)) |
---|
[226] | 134 | ENDIF ELSE $ |
---|
[35] | 135 | ; we need to use a scrolling bar window |
---|
| 136 | if cellsize GE min(floor(dimensions/(size(z2d))[1: 2]*.75)) then scrolling = 1 |
---|
| 137 | if cellsize LT 1 then begin |
---|
| 138 | cellsize = 1 |
---|
| 139 | scrolling = 1 |
---|
[506] | 140 | ENDIF |
---|
[2] | 141 | ;------------------------------------------------------------ |
---|
[35] | 142 | ; Change the value of the masked value for the min of the non-masked values |
---|
[2] | 143 | ;------------------------------------------------------------ |
---|
[226] | 144 | if n_elements(mask) then BEGIN |
---|
| 145 | if abs(mask) LT 1e6 then BEGIN |
---|
[35] | 146 | masked = where(arr EQ mask) |
---|
[114] | 147 | if masked[0] NE -1 then arr[masked] = min(arr[where(arr NE mask)]) |
---|
[226] | 148 | ENDIF ELSE BEGIN |
---|
[35] | 149 | masked = where(abs(arr) GE abs(mask)/10.) |
---|
[114] | 150 | if masked[0] NE -1 then arr[masked] = min(arr[where(abs(arr) LT abs(mask)/10.)]) |
---|
[35] | 151 | ENDELSE |
---|
| 152 | ENDIF ELSE masked = -1 |
---|
[2] | 153 | ;------------------------------------------------------------ |
---|
[35] | 154 | ; apply min/max keywords |
---|
[2] | 155 | ;------------------------------------------------------------ |
---|
[226] | 156 | if n_elements(min) NE 0 then BEGIN |
---|
[35] | 157 | arr = min > arr |
---|
| 158 | truemin = min |
---|
| 159 | ENDIF ELSE truemin = min(arr) |
---|
[226] | 160 | if n_elements(max) NE 0 then BEGIN |
---|
[35] | 161 | arr = arr < max |
---|
| 162 | truemax = max |
---|
| 163 | ENDIF ELSE truemax = max(arr) |
---|
| 164 | ; |
---|
| 165 | IF truemin EQ truemax THEN BEGIN |
---|
| 166 | dummy = report('constant value everywhere: '+ strtrim(truemin, 1)) |
---|
| 167 | return |
---|
| 168 | ENDIF |
---|
[2] | 169 | ;------------------------------------------------------------ |
---|
[226] | 170 | ; apply other keywords (nointerp, c_nan, c_mask) |
---|
[2] | 171 | ;------------------------------------------------------------ |
---|
[35] | 172 | if NOT keyword_set(nointerp) then BEGIN |
---|
| 173 | ; interpolation between bottom and bottom+ncolors-1 |
---|
| 174 | m = 1.*(ncolors-1)/(truemax-truemin) |
---|
| 175 | p = bottom-1.*truemin*m |
---|
[226] | 176 | arr = round(m*temporary(arr)+p) |
---|
[35] | 177 | endif |
---|
[226] | 178 | ; set c_nan for NaN values |
---|
[35] | 179 | if keyword_set(nan) then begin |
---|
| 180 | if n_elements(c_nan) NE 0 THEN arr[nanindex] = c_nan < (ncolmax -1) $ |
---|
| 181 | ELSE arr[nanindex] = topcol |
---|
| 182 | endif |
---|
| 183 | ; c_mask for masked values |
---|
| 184 | if n_elements(c_mask) NE 0 AND masked[0] NE -1 THEN $ |
---|
| 185 | arr[masked] = c_mask < (ncolmax -1) |
---|
| 186 | ; use byte type to save memory |
---|
[152] | 187 | arr = byte(temporary(arr)) |
---|
[35] | 188 | ; increase the size of the array in order to be displayed |
---|
[226] | 189 | ; with the suitable size |
---|
[152] | 190 | szarr = size(arr, /dimensions) |
---|
| 191 | arr = congrid(temporary(arr), szarr[0]*cellsize, szarr[1]*cellsize) |
---|
[2] | 192 | ;------------------------------------------------------------ |
---|
[35] | 193 | ; open a window with the correct size |
---|
[2] | 194 | ;------------------------------------------------------------ |
---|
[35] | 195 | nx = (size(arr))[1] |
---|
| 196 | ny = (size(arr))[2] |
---|
| 197 | ; margin size (in pixel) |
---|
| 198 | xyaspect = 1.*nx/ny |
---|
| 199 | if xyaspect GE 1 THEN marginpix = 1.*[25, 25, 75, 25] ELSE marginpix = 1.*[25, 100, 25, 25] |
---|
[2] | 200 | ; |
---|
[506] | 201 | if n_elements(scrolling) EQ 0 OR keyword_set(pixmap) then BEGIN ; open the regular window |
---|
[35] | 202 | if NOT keyword_set(window) then window = 0 |
---|
| 203 | window, window, xsize = nx+marginpix[0]+marginpix[1] $ |
---|
[506] | 204 | , ysize = ny+marginpix[2]+marginpix[3], PIXMAP = pixmap |
---|
[35] | 205 | tv, arr, marginpix[0], marginpix[2], _EXTRA = ex |
---|
[2] | 206 | ; |
---|
[226] | 207 | ; axis and plot frame |
---|
[2] | 208 | ; |
---|
[35] | 209 | ; get the normalized position of the tv (we just done above) |
---|
| 210 | ; to know where the frame should be drawn |
---|
| 211 | poscadre = fltarr(4) |
---|
| 212 | poscadre[0] = marginpix[0]/!d.x_size |
---|
| 213 | poscadre[2] = 1.-marginpix[1]/!d.x_size |
---|
| 214 | poscadre[1] = marginpix[2]/!d.y_size |
---|
| 215 | poscadre[3] = 1-marginpix[3]/!d.y_size |
---|
| 216 | ; Use plot to draw the frame |
---|
| 217 | if NOT keyword_set(offset) then offset = [0, 0] |
---|
| 218 | !p.position = poscadre |
---|
| 219 | plot, [0], [0], /nodata, /noerase, position = poscadre, color = 0 $ |
---|
| 220 | , xstyle = 1, ystyle = 1, xticklen = 1, yticklen = 1 $ |
---|
[69] | 221 | , xrange = 1.*[0, nx]/cellsize-.5+offset[0] $ |
---|
| 222 | , yrange = 1.*[0, ny]/cellsize-.5+offset[1], _extra = ex |
---|
[35] | 223 | xenvsauve = !x & yenvsauve = !y & penvsauve = !p |
---|
[2] | 224 | ; |
---|
[226] | 225 | ; draw the colorbar |
---|
[2] | 226 | ; |
---|
[35] | 227 | IF truemin ne truemax THEN BEGIN |
---|
| 228 | if xyaspect ge 1 then $ |
---|
| 229 | posbar = [25./!d.x_size, 25./!d.y_size, 1-25./!d.x_size, 50./!d.y_size] $ |
---|
| 230 | ELSE posbar = [1-75./!d.x_size, 25./!d.y_size, 1-50./!d.x_size, 1-25./!d.y_size] |
---|
| 231 | if keyword_set(nointerp) then BEGIN & truemin = 0 & truemax = ncolmax & endif |
---|
| 232 | colorbar, min = truemin, max = truemax, division = 10, cb_color = 0, position = posbar $ |
---|
| 233 | , vertical = xyaspect lt 1, /right, BOTTOM = bottom, NCOLORS = ncolors, _EXTRA = ex |
---|
| 234 | ENDIF |
---|
| 235 | ; !p.position = poscadre |
---|
[506] | 236 | IF keyword_set(pixmap) THEN return |
---|
[226] | 237 | ENDIF ELSE BEGIN |
---|
[2] | 238 | ;------------------------------------------------------------ |
---|
[35] | 239 | ; scrolling bar window case... |
---|
[2] | 240 | ;------------------------------------------------------------ |
---|
[142] | 241 | slide_image, arr $ ; We draw it in a window with a scrolling bar |
---|
[35] | 242 | , xsize = nx, ysize = ny $ |
---|
| 243 | , xvisible = round(.7*dimensions[0]) < (size(arr))[1] $ |
---|
| 244 | , yvisible = round(.7*dimensions[1]) < (size(arr))[2], /register, congrid = 0, show_full = 0 |
---|
| 245 | return |
---|
[226] | 246 | ENDELSE |
---|
[2] | 247 | ;------------------------------------------------------------ |
---|
[35] | 248 | ; Use the mouse to get nice functionalities |
---|
[2] | 249 | ;------------------------------------------------------------ |
---|
[35] | 250 | ; format to print the mouse position |
---|
| 251 | CASE 1 OF |
---|
| 252 | nx LT 10:fmt1 = '(i1)' |
---|
| 253 | nx LT 100:fmt1 = '(i2)' |
---|
| 254 | nx LT 1000:fmt1 = '(i3)' |
---|
| 255 | nx LT 10000:fmt1 = '(i4)' |
---|
| 256 | ELSE:fmt1 = '' |
---|
| 257 | ENDCASE |
---|
| 258 | CASE 1 OF |
---|
| 259 | ny LT 10:fmt2 = '(i1)' |
---|
| 260 | ny LT 100:fmt2 = '(i2)' |
---|
| 261 | ny LT 1000:fmt2 = '(i3)' |
---|
| 262 | ny LT 10000:fmt2 = '(i4)' |
---|
| 263 | ELSE:fmt2 = '' |
---|
| 264 | ENDCASE |
---|
| 265 | ; |
---|
| 266 | if NOT keyword_set(nouseinfos) then begin |
---|
| 267 | print, 'left button : mouse position and associated array value' |
---|
| 268 | print, 'middle button: use it twice to define a zoom box' |
---|
| 269 | print, 'right button : quit' |
---|
| 270 | endif |
---|
| 271 | cursor, x, y, /device, /down |
---|
| 272 | x = x-marginpix[0] & x = 0 > floor(x/cellsize) < ((size(arr))[1]/cellsize-1) |
---|
| 273 | y = y-marginpix[2] & y = 0 > floor(y/cellsize) < ((size(arr))[2]/cellsize-1) |
---|
| 274 | while (!mouse.button ne 4) do BEGIN |
---|
| 275 | case !mouse.button of |
---|
| 276 | 0:return |
---|
| 277 | 1:BEGIN ; get value |
---|
| 278 | if x LE nx/cellsize AND y LE ny/cellsize then begin |
---|
| 279 | print, '(x, y) = (' + string(x+offset[0], format = fmt1) $ |
---|
| 280 | + ', ' + string(y+offset[1], format = fmt2) $ |
---|
| 281 | + '), value = '+strtrim(float((reform(z2d))[x, y]), 1) |
---|
| 282 | ENDIF |
---|
| 283 | cursor, x, y, /device, /down |
---|
| 284 | x = x-marginpix[0] & x = 0 > floor(x/cellsize) < ((size(arr))[1]/cellsize-1) |
---|
| 285 | y = y-marginpix[2] & y = 0 > floor(y/cellsize) < ((size(arr))[2]/cellsize-1) |
---|
| 286 | END |
---|
| 287 | 2:BEGIN ; zoom |
---|
| 288 | cursor, x2, y2, /device, /down |
---|
| 289 | x2 = x2-marginpix[0] & x2 = 0 > floor(x2/cellsize) < ((size(arr))[1]/cellsize-1) |
---|
| 290 | y2 = y2-marginpix[2] & y2 = 0 > floor(y2/cellsize) < ((size(arr))[2]/cellsize-1) |
---|
| 291 | x = [x, x2] & x = x[sort(x)] |
---|
| 292 | y = [y, y2] & y = y[sort(y)] |
---|
| 293 | IF keyword_set(OFFSET) THEN offset = [x[0], y[0]]+offset ELSE offset = [x[0], y[0]] |
---|
| 294 | tvplus, z2d[x[0]:x[1], y[0]:y[1] ], WINDOW = window, MIN = min, MAX = max $ |
---|
| 295 | , MASK = mask, C_MASK = c_mask, C_NAN = c_nan, /NOUSEINFOS, OFFSET = OFFSET $ |
---|
| 296 | , NCOLORS = ncolors, NOINTERP = nointerp, BOTTOM = bottom, _EXTRA = ex |
---|
| 297 | return |
---|
| 298 | END |
---|
| 299 | ELSE: |
---|
| 300 | endcase |
---|
| 301 | ENDWHILE |
---|
[2] | 302 | ;------------------------------------------------------------ |
---|
[35] | 303 | !x = xenvsauve & !y = yenvsauve & !p = penvsauve |
---|
| 304 | !x.range = 1.*[0, nx]/cellsize-.5+offset[0] |
---|
| 305 | !y.range = 1.*[0, ny]/cellsize-.5+offset[1] |
---|
[2] | 306 | ;------------------------------------------------------------ |
---|
[35] | 307 | return |
---|
[2] | 308 | end |
---|