[2] | 1 | ;------------------------------------------------------------ |
---|
| 2 | ;------------------------------------------------------------ |
---|
| 3 | ;------------------------------------------------------------ |
---|
| 4 | ;+ |
---|
| 5 | ; NAME: tvplus |
---|
| 6 | ; |
---|
[35] | 7 | ; PURPOSE: enhanced version of tvscl |
---|
[2] | 8 | ; |
---|
[35] | 9 | ; CATEGORY: quick exploration of 2D arrays |
---|
[2] | 10 | ; |
---|
[35] | 11 | ; CALLING SEQUENCE: tvplus,z2d [,cellsize] |
---|
[2] | 12 | ; |
---|
[35] | 13 | ; INPUTS: |
---|
[2] | 14 | ; |
---|
[35] | 15 | ; z2d: 2D array to visualize |
---|
[2] | 16 | ; |
---|
[35] | 17 | ; cellsize: (optional) this is the size (in pixel) of the square |
---|
| 18 | ; representing 1 array element. By default, this size is computed |
---|
| 19 | ; automatically in order that the size of the plotting window do |
---|
| 20 | ; not exceed the screen size. If the user specify a large value |
---|
| 21 | ; of cellsize that forces tvplus to create a window larger than |
---|
| 22 | ; the screen, a "scrolling window" will be displayed instead of a |
---|
| 23 | ; regular window. Unfortunately the nice fonctionnalities of tvplus |
---|
| 24 | ; are not coded for "scrolling window" case... |
---|
| 25 | ; |
---|
[2] | 26 | ; KEYWORD PARAMETERS: |
---|
| 27 | ; |
---|
| 28 | ; BOTTOM: The lowest color index of the colors to be loaded in |
---|
| 29 | ; the bar. default is 0. |
---|
| 30 | ; |
---|
[35] | 31 | ; C_NAN: The color number that should be used for the NaN values. |
---|
| 32 | ; default value is !d.n_colors < 255 |
---|
[2] | 33 | ; |
---|
[35] | 34 | ; C_MASK: The color number that should be used for the mask values. |
---|
| 35 | ; default value is 0 |
---|
[2] | 36 | ; |
---|
[35] | 37 | ; OFFSET: 2 elements vector used by tvplus itself when shoing zoom. |
---|
| 38 | ; It is used to shift the ranges of xaxis and yaxis. |
---|
| 39 | ; For example: tvplus,sst[x1:x2,y1:y2],offest=[x1,y1] |
---|
[2] | 40 | ; |
---|
[35] | 41 | ; MASK: The mask value. Note that if abs(mask) < 1.e6, then the |
---|
| 42 | ; exact value of the mask is used to find the maskwd point. |
---|
| 43 | ; if abs(mask) > 1.e6, the test to find the masked value is ge |
---|
| 44 | ; abs(mask)/10. This is necessary to avoid the rounding errors |
---|
[2] | 45 | ; |
---|
[35] | 46 | ; MIN and MAX: scalars used to specify the min and max values |
---|
| 47 | ; of the color bar. default is from 0 to !d.n_colors < 255 |
---|
[2] | 48 | ; |
---|
| 49 | ; NCOLORS: This is the number of colors in the color |
---|
| 50 | ; bar. default is !d.n_colors<255 -1 |
---|
| 51 | ; |
---|
[35] | 52 | ; NOINTERP: used this keyword if you don't whant that the values |
---|
| 53 | ; are interpolated between 0 (or min) and !d.n_colors < 255 (or max). |
---|
| 54 | ; This can be for example usefull when working on byte type arrays. |
---|
[2] | 55 | ; |
---|
[35] | 56 | ; NOUSEINFOS: activite to supress the printed message explaining |
---|
| 57 | ; how to use tvplus |
---|
[2] | 58 | ; |
---|
[35] | 59 | ; WINDOW: Number of the window used to display the array values. |
---|
| 60 | ; default is window number 0. |
---|
[2] | 61 | ; |
---|
[35] | 62 | ; OUTPUTS: no (except the printed finformations, see below) |
---|
[2] | 63 | ; |
---|
[35] | 64 | ; COMMON BLOCKS: no |
---|
| 65 | ; |
---|
[2] | 66 | ; SIDE EFFECTS: |
---|
| 67 | ; |
---|
[35] | 68 | ; use your mouse to scan the array values... |
---|
| 69 | ; left button : mouse position and associated array value |
---|
| 70 | ; middle button: use it twice to define a zoom box |
---|
| 71 | ; right button : quit |
---|
[2] | 72 | ; |
---|
[35] | 73 | ; RESTRICTIONS: the nice fonctionnalities of tvplus are not coded |
---|
| 74 | ; for "scrolling window" case... |
---|
[2] | 75 | ; |
---|
[35] | 76 | ; EXAMPLE: IDL> tvplus, dist(100) |
---|
[2] | 77 | ; |
---|
| 78 | ; MODIFICATION HISTORY: Sebastien Masson (smasson@lodyc.jussieu.fr) |
---|
| 79 | ; 18/12/98 |
---|
[35] | 80 | ; Aug 2005: quick cleaning + english |
---|
[2] | 81 | ;- |
---|
| 82 | ;------------------------------------------------------------ |
---|
| 83 | ;------------------------------------------------------------ |
---|
| 84 | ;------------------------------------------------------------ |
---|
[35] | 85 | PRO tvplus, z2d, cellsize, BOTTOM = bottom, C_MASK = c_mask, C_NAN = c_nan, WINDOW = window $ |
---|
| 86 | , MIN = min, MAX = max, MASK = mask, OFFSET = offset, NOUSEINFOS = NOUSEINFOS $ |
---|
[2] | 87 | , NCOLORS = ncolors, NOINTERP = nointerp, _EXTRA = ex |
---|
| 88 | ; |
---|
[114] | 89 | ; |
---|
| 90 | compile_opt idl2, strictarrsubs |
---|
| 91 | ; |
---|
[35] | 92 | IF n_elements(z2d) EQ 0 THEN return |
---|
| 93 | arr = reform(float(z2d)) |
---|
[2] | 94 | ;------------------------------------------------------------ |
---|
[35] | 95 | ; check the size of the input array |
---|
[2] | 96 | ;------------------------------------------------------------ |
---|
[35] | 97 | if (size(arr))[0] NE 2 then begin |
---|
| 98 | ras = report('Input array must have only 2 dimensions and not '+ strtrim(size(arr, /n_dimensions), 1)) |
---|
| 99 | return |
---|
| 100 | endif |
---|
[2] | 101 | ;------------------------------------------------------------ |
---|
[35] | 102 | ; def of ncolmax, bottom, topcol et ncolors |
---|
[2] | 103 | ;------------------------------------------------------------ |
---|
[35] | 104 | ncolmax = !d.n_colors < 256 |
---|
| 105 | IF N_ELEMENTS(bottom) EQ 0 THEN bottom = 0 |
---|
| 106 | if NOT keyword_set(ncolors) then ncolors = ncolmax-bottom |
---|
| 107 | topcol = (bottom+ncolors-1) < (ncolmax-1) |
---|
[2] | 108 | ;------------------------------------------------------------ |
---|
[35] | 109 | ; get default values of !x, !y, !z |
---|
[2] | 110 | ;------------------------------------------------------------ |
---|
[35] | 111 | ; xenvsauve = !x & yenvsauve = !y & penvsauve = !p |
---|
| 112 | reinitplt, /z, /invert |
---|
[2] | 113 | ;------------------------------------------------------------ |
---|
[35] | 114 | ; Do we have NaN values in arr??? |
---|
[2] | 115 | ;------------------------------------------------------------ |
---|
[35] | 116 | nan = total(finite(z2d, /nan)) < 1 |
---|
| 117 | if keyword_set(nan) then begin |
---|
| 118 | nanindex = where(finite(z2d, /nan) EQ 1) |
---|
| 119 | arr[nanindex] = min(arr, /nan) |
---|
| 120 | endif |
---|
[2] | 121 | ;------------------------------------------------------------ |
---|
[35] | 122 | ; Compute the size (in pixel) of the square representing 1 |
---|
| 123 | ; point of the input array |
---|
[2] | 124 | ;------------------------------------------------------------ |
---|
[35] | 125 | dimensions = GET_SCREEN_SIZE() |
---|
| 126 | if n_elements(cellsize) EQ 0 then BEGIN |
---|
| 127 | cellsize = min(floor(dimensions/(size(z2d))[1: 2]*.75)) |
---|
| 128 | ENDIF ELSE $ |
---|
| 129 | ; we need to use a scrolling bar window |
---|
| 130 | if cellsize GE min(floor(dimensions/(size(z2d))[1: 2]*.75)) then scrolling = 1 |
---|
| 131 | if cellsize LT 1 then begin |
---|
| 132 | cellsize = 1 |
---|
| 133 | scrolling = 1 |
---|
| 134 | endif |
---|
[2] | 135 | ;------------------------------------------------------------ |
---|
[35] | 136 | ; Change the value of the masked value for the min of the non-masked values |
---|
[2] | 137 | ;------------------------------------------------------------ |
---|
[35] | 138 | if n_elements(mask) then BEGIN |
---|
| 139 | if abs(mask) LT 1e6 then BEGIN |
---|
| 140 | masked = where(arr EQ mask) |
---|
[114] | 141 | if masked[0] NE -1 then arr[masked] = min(arr[where(arr NE mask)]) |
---|
[35] | 142 | ENDIF ELSE BEGIN |
---|
| 143 | masked = where(abs(arr) GE abs(mask)/10.) |
---|
[114] | 144 | if masked[0] NE -1 then arr[masked] = min(arr[where(abs(arr) LT abs(mask)/10.)]) |
---|
[35] | 145 | ENDELSE |
---|
| 146 | ENDIF ELSE masked = -1 |
---|
[2] | 147 | ;------------------------------------------------------------ |
---|
[35] | 148 | ; apply min/max keywords |
---|
[2] | 149 | ;------------------------------------------------------------ |
---|
[35] | 150 | if n_elements(min) NE 0 then BEGIN |
---|
| 151 | arr = min > arr |
---|
| 152 | truemin = min |
---|
| 153 | ENDIF ELSE truemin = min(arr) |
---|
| 154 | if n_elements(max) NE 0 then BEGIN |
---|
| 155 | arr = arr < max |
---|
| 156 | truemax = max |
---|
| 157 | ENDIF ELSE truemax = max(arr) |
---|
| 158 | ; |
---|
| 159 | IF truemin EQ truemax THEN BEGIN |
---|
| 160 | dummy = report('constant value everywhere: '+ strtrim(truemin, 1)) |
---|
| 161 | return |
---|
| 162 | ENDIF |
---|
[2] | 163 | ;------------------------------------------------------------ |
---|
[35] | 164 | ; apply other keywords (nointerp, c_nan, c_mask) |
---|
[2] | 165 | ;------------------------------------------------------------ |
---|
[35] | 166 | if NOT keyword_set(nointerp) then BEGIN |
---|
| 167 | ; interpolation between bottom and bottom+ncolors-1 |
---|
| 168 | m = 1.*(ncolors-1)/(truemax-truemin) |
---|
| 169 | p = bottom-1.*truemin*m |
---|
| 170 | arr = round(1.*m*arr+p) |
---|
| 171 | endif |
---|
| 172 | ; set c_nan for NaN values |
---|
| 173 | if keyword_set(nan) then begin |
---|
| 174 | if n_elements(c_nan) NE 0 THEN arr[nanindex] = c_nan < (ncolmax -1) $ |
---|
| 175 | ELSE arr[nanindex] = topcol |
---|
| 176 | endif |
---|
| 177 | ; c_mask for masked values |
---|
| 178 | if n_elements(c_mask) NE 0 AND masked[0] NE -1 THEN $ |
---|
| 179 | arr[masked] = c_mask < (ncolmax -1) |
---|
| 180 | ; use byte type to save memory |
---|
| 181 | arr = byte(arr) |
---|
| 182 | ; increase the size of the array in order to be displayed |
---|
| 183 | ; with the suitable size |
---|
| 184 | arr = congridseb(arr, (size(arr))[1]*cellsize, (size(arr))[2]*cellsize) |
---|
[2] | 185 | ;------------------------------------------------------------ |
---|
[35] | 186 | ; open a window with the correct size |
---|
[2] | 187 | ;------------------------------------------------------------ |
---|
[35] | 188 | nx = (size(arr))[1] |
---|
| 189 | ny = (size(arr))[2] |
---|
| 190 | ; margin size (in pixel) |
---|
| 191 | xyaspect = 1.*nx/ny |
---|
| 192 | if xyaspect GE 1 THEN marginpix = 1.*[25, 25, 75, 25] ELSE marginpix = 1.*[25, 100, 25, 25] |
---|
[2] | 193 | ; |
---|
[35] | 194 | if n_elements(scrolling) EQ 0 then BEGIN ; open the regular window |
---|
| 195 | if NOT keyword_set(window) then window = 0 |
---|
| 196 | window, window, xsize = nx+marginpix[0]+marginpix[1] $ |
---|
| 197 | , ysize = ny+marginpix[2]+marginpix[3] |
---|
| 198 | ; for 24 bits colors, make sure thate the background color is the good one... |
---|
| 199 | if !d.n_colors gt 256 then BEGIN |
---|
| 200 | device, decomposed = 1 |
---|
| 201 | !p.background = 'ffffff'x |
---|
| 202 | plot, [0], [0], xstyle = 5, ystyle = 5 |
---|
| 203 | device, decomposed = 0 |
---|
| 204 | endif |
---|
| 205 | tv, arr, marginpix[0], marginpix[2], _EXTRA = ex |
---|
[2] | 206 | ; |
---|
[35] | 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 | ; |
---|
[35] | 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 |
---|
| 236 | ENDIF ELSE BEGIN |
---|
[2] | 237 | ;------------------------------------------------------------ |
---|
[35] | 238 | ; scrolling bar window case... |
---|
[2] | 239 | ;------------------------------------------------------------ |
---|
[35] | 240 | ; for 24 bits colors, make sure thate the background color is the good one... |
---|
| 241 | if !d.n_colors gt 256 then begin |
---|
| 242 | window, /pixmap |
---|
| 243 | device, decomposed = 1 |
---|
| 244 | !p.background = 'ffffff'x |
---|
| 245 | plot, [0], [0] |
---|
| 246 | device, decomposed = 0 |
---|
| 247 | endif |
---|
| 248 | slide_image, arr $ ; on le dessine ds une fenetre avec une scrolling bar |
---|
| 249 | , xsize = nx, ysize = ny $ |
---|
| 250 | , xvisible = round(.7*dimensions[0]) < (size(arr))[1] $ |
---|
| 251 | , yvisible = round(.7*dimensions[1]) < (size(arr))[2], /register, congrid = 0, show_full = 0 |
---|
| 252 | return |
---|
| 253 | ENDELSE |
---|
[2] | 254 | ;------------------------------------------------------------ |
---|
[35] | 255 | ; Use the mouse to get nice functionalities |
---|
[2] | 256 | ;------------------------------------------------------------ |
---|
[35] | 257 | ; format to print the mouse position |
---|
| 258 | CASE 1 OF |
---|
| 259 | nx LT 10:fmt1 = '(i1)' |
---|
| 260 | nx LT 100:fmt1 = '(i2)' |
---|
| 261 | nx LT 1000:fmt1 = '(i3)' |
---|
| 262 | nx LT 10000:fmt1 = '(i4)' |
---|
| 263 | ELSE:fmt1 = '' |
---|
| 264 | ENDCASE |
---|
| 265 | CASE 1 OF |
---|
| 266 | ny LT 10:fmt2 = '(i1)' |
---|
| 267 | ny LT 100:fmt2 = '(i2)' |
---|
| 268 | ny LT 1000:fmt2 = '(i3)' |
---|
| 269 | ny LT 10000:fmt2 = '(i4)' |
---|
| 270 | ELSE:fmt2 = '' |
---|
| 271 | ENDCASE |
---|
| 272 | ; |
---|
| 273 | if NOT keyword_set(nouseinfos) then begin |
---|
| 274 | print, 'left button : mouse position and associated array value' |
---|
| 275 | print, 'middle button: use it twice to define a zoom box' |
---|
| 276 | print, 'right button : quit' |
---|
| 277 | endif |
---|
| 278 | cursor, x, y, /device, /down |
---|
| 279 | x = x-marginpix[0] & x = 0 > floor(x/cellsize) < ((size(arr))[1]/cellsize-1) |
---|
| 280 | y = y-marginpix[2] & y = 0 > floor(y/cellsize) < ((size(arr))[2]/cellsize-1) |
---|
| 281 | while (!mouse.button ne 4) do BEGIN |
---|
| 282 | case !mouse.button of |
---|
| 283 | 0:return |
---|
| 284 | 1:BEGIN ; get value |
---|
| 285 | if x LE nx/cellsize AND y LE ny/cellsize then begin |
---|
| 286 | print, '(x, y) = (' + string(x+offset[0], format = fmt1) $ |
---|
| 287 | + ', ' + string(y+offset[1], format = fmt2) $ |
---|
| 288 | + '), value = '+strtrim(float((reform(z2d))[x, y]), 1) |
---|
| 289 | ENDIF |
---|
| 290 | cursor, x, y, /device, /down |
---|
| 291 | x = x-marginpix[0] & x = 0 > floor(x/cellsize) < ((size(arr))[1]/cellsize-1) |
---|
| 292 | y = y-marginpix[2] & y = 0 > floor(y/cellsize) < ((size(arr))[2]/cellsize-1) |
---|
| 293 | END |
---|
| 294 | 2:BEGIN ; zoom |
---|
| 295 | cursor, x2, y2, /device, /down |
---|
| 296 | x2 = x2-marginpix[0] & x2 = 0 > floor(x2/cellsize) < ((size(arr))[1]/cellsize-1) |
---|
| 297 | y2 = y2-marginpix[2] & y2 = 0 > floor(y2/cellsize) < ((size(arr))[2]/cellsize-1) |
---|
| 298 | x = [x, x2] & x = x[sort(x)] |
---|
| 299 | y = [y, y2] & y = y[sort(y)] |
---|
| 300 | IF keyword_set(OFFSET) THEN offset = [x[0], y[0]]+offset ELSE offset = [x[0], y[0]] |
---|
| 301 | tvplus, z2d[x[0]:x[1], y[0]:y[1] ], WINDOW = window, MIN = min, MAX = max $ |
---|
| 302 | , MASK = mask, C_MASK = c_mask, C_NAN = c_nan, /NOUSEINFOS, OFFSET = OFFSET $ |
---|
| 303 | , NCOLORS = ncolors, NOINTERP = nointerp, BOTTOM = bottom, _EXTRA = ex |
---|
| 304 | return |
---|
| 305 | END |
---|
| 306 | ELSE: |
---|
| 307 | endcase |
---|
| 308 | ENDWHILE |
---|
[2] | 309 | ;------------------------------------------------------------ |
---|
[35] | 310 | !x = xenvsauve & !y = yenvsauve & !p = penvsauve |
---|
| 311 | !x.range = 1.*[0, nx]/cellsize-.5+offset[0] |
---|
| 312 | !y.range = 1.*[0, ny]/cellsize-.5+offset[1] |
---|
[2] | 313 | ;------------------------------------------------------------ |
---|
[35] | 314 | return |
---|
[2] | 315 | end |
---|