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