;------------------------------------------------------------- ;+ ; NAME: ; CROSSI ; PURPOSE: ; Interactive cross-hair cursor on screen or plot. ; CATEGORY: ; CALLING SEQUENCE: ; crossi, [x, y, z] ; INPUTS: ; KEYWORD PARAMETERS: ; Keywords: ; /DATA Causes data coordinates to be used (default). ; /DEVICE Causes window device coordinates to be used. ; /NORMAL Causes normalized coordinates to be used. ; /ORDER Reverse device y coordinate (0 at window top). ; /PIXEL Show pixel value. ; COLOR=c Set color of line (ignored for /XOR). ; Use -2 for dotted line. ; LINESTYLE=s Line style. ; MAG=m Magnification for an optional magnified window. ; Setting MAG turns window on. /MAG gives magnification 10. ; SIZE=sz Mag window approx. size in pixels (def=200). ; XFORMAT=xfn These keywords are given names of functions ; YFORMAT=yfn that accept the numeric value of x or y ; and return a corresponding string which is displayed ; in place of the actual value. For example, Julian ; days could be displayed as a date with jd2date. ; XSIZE=xs, YSIZE=ys Coordinate display widths. ; /JS Means X axis is time in Julian seconds. Example: ; x=maken(-2e8,-1.9e8,200) & y=maken(20,30,200) ; z=bytscl(makez(200,200)) ; izoom,x,y,z,/js ; crossi,/js ; /NOSTATUS Inhibits status display widget. ; SETSTAT=st May use the same status display widget on ; each call to crossi (stays in same position). ; On first call: the status widget structure is returned. ; Following calls: send st. Must use with /KEEP. ; To delete status display widget after last box1 call: ; widget_control,st.top,/dest (or drop /KEEP) ; /KEEP Do not delete status widget or mag window on exit. ; /XMODE Means use XOR plot mode instead of tvrd mode. ; INSTRUCTIONS=t String array with exit instructions. ; Default: Press any button to exit. ; /DIALOG Means give an exit dialog box. ; MENU=m A string array with exit dialog box options. ; An option labeled Continue is always added. Def=Continue. ; DEFAULT=def Set exit menu default. ; EXITCODE=x Returns exit code. Always 0 unless a dialog ; box is requested, then is selected exit option number. ; BUTTON=b Returned button code: 1=left, 2=middle, 4=right. ; OUTPUTS: ; x = X coordinate of line. in, out ; y = Y coordinate of line. in, out ; z = optionally returned pixel value. out ; Only if /PIXEL is specified. ; COMMON BLOCKS: ; js_com ; NOTES: ; Note: data coordinates are default. ; X and Y may be set to starting position in entry. ; MODIFICATION HISTORY: ; R. Sterner, 1994 May 16 ; R. Sterner, 1994 May 19 --- Added mag window. ; R. Sterner, 1995 May 12 --- Added exit menu default. ; R. Sterner, 1995 Jun 30 --- Added /ORDER. ; R. Sterner, 1995 Oct 17 --- Added /PIXEL and RGB display. ; R. Sterner, 1995 Nov 30 --- Added color=-2 option. ; R. Sterner, 1998 Jan 15 --- Dropped the use of !d.n_colors. ; ; Copyright (C) 1994, Johns Hopkins University/Applied Physics Laboratory ; This software may be used, copied, or redistributed as long as it is not ; sold and this copyright notice is reproduced on each copy made. This ; routine is provided as is without any express or implied warranties ; whatsoever. Other limitations apply as described in the file disclaimer.txt. ;- ;------------------------------------------------------------- pro crossi, x, y, zdv, color=color, linestyle=linestyle, $ help=hlp, exitcode=exitcode, nostatus=nostat, nooptions=noop, $ device=device, normal=norm, data=data, xmode=xmode,$ setstat=st, keep=keep, xformat=xfn, yformat=yfn, button=button, $ xsize=xsize, ysize=ysize, dialog=dialog,menu=menu,default=def, $ instructions=instr, js=js, mag=mag0, size=msize0, order=order, $ pixel=pixel common js_com, jsoff if keyword_set(hlp) then begin print,' Interactive cross-hair cursor on screen or plot.' print,' crossi, [x, y, z]' print,' x = X coordinate of line. in, out' print,' y = Y coordinate of line. in, out' print,' z = optionally returned pixel value. out' print,' Only if /PIXEL is specified.' print,' Keywords:' print,' /DATA Causes data coordinates to be used (default).' print,' /DEVICE Causes window device coordinates to be used.' print,' /NORMAL Causes normalized coordinates to be used.' print,' /ORDER Reverse device y coordinate (0 at window top).' print,' /PIXEL Show pixel value.' print,' COLOR=c Set color of line (ignored for /XOR).' print,' Use -2 for dotted line.' print,' LINESTYLE=s Line style.' print,' MAG=m Magnification for an optional magnified window.' print,' Setting MAG turns window on. /MAG gives magnification 10.' print,' SIZE=sz Mag window approx. size in pixels (def=200).' print,' XFORMAT=xfn These keywords are given names of functions' print,' YFORMAT=yfn that accept the numeric value of x or y' print,' and return a corresponding string which is displayed' print,' in place of the actual value. For example, Julian' print,' days could be displayed as a date with jd2date.' print,' XSIZE=xs, YSIZE=ys Coordinate display widths.' print,' /JS Means X axis is time in Julian seconds. Example:' print,' x=maken(-2e8,-1.9e8,200) & y=maken(20,30,200)' print,' z=bytscl(makez(200,200))' print,' izoom,x,y,z,/js' print," crossi,/js" print,' /NOSTATUS Inhibits status display widget.' print,' SETSTAT=st May use the same status display widget on' print,' each call to crossi (stays in same position).' print,' On first call: the status widget structure is returned.' print,' Following calls: send st. Must use with /KEEP.' print,' To delete status display widget after last box1 call:' print,' widget_control,st.top,/dest (or drop /KEEP)' print,' /KEEP Do not delete status widget or mag window on exit.' print,' /XMODE Means use XOR plot mode instead of tvrd mode.' print,' INSTRUCTIONS=t String array with exit instructions.' print,' Default: Press any button to exit.' print,' /DIALOG Means give an exit dialog box.' print,' MENU=m A string array with exit dialog box options.' print,' An option labeled Continue is always added. Def=Continue.' print,' DEFAULT=def Set exit menu default.' print,' EXITCODE=x Returns exit code. Always 0 unless a dialog' print,' box is requested, then is selected exit option number.' print,' BUTTON=b Returned button code: 1=left, 2=middle, 4=right.' print,' Note: data coordinates are default.' print,' X and Y may be set to starting position in entry.' return endif ;------- If /JS make sure jsoff defined ---------- if keyword_set(js) then begin if n_elements(jsoff) eq 0 then begin print,' Error in crossi: cannot use /JS until a time series' print,' plot has been made (by izoom,/js,... or jsplot).' bell return endif if n_elements(xsize) eq 0 then xsize=25 if n_elements(xfn) eq 0 then xfn='dt_tm_fromjs' endif ;------- Coordinate system --------- if n_elements(device) eq 0 then device=0 if n_elements(norm) eq 0 then norm=0 if n_elements(data) eq 0 then data=0 if (device+norm) eq 0 then data=1 if (!x.s(1) eq 0) and $ (not keyword_set(device)) and $ (not keyword_set(norm)) then begin print,' Error in crossi: data coordinates not yet established.' print,' Must make a plot before calling crossi or use /DEVICE print,' or /NORMAL keyword.' return endif if device eq 1 then ctyp = 0 ; Coordinate flag. if norm eq 1 then ctyp = 1 if data eq 1 then ctyp = 2 ;--------- Set defaults ------------- if n_elements(x) eq 0 then begin case ctyp of 0: begin x = !d.x_size/2 y = !d.y_size/2 end 1: begin x = .25 y = .25 end 2: begin x = midv(!x.crange) y = midv(!y.crange) if !x.type eq 2 then begin x = !map.out(9)*!radeg y = !map.out(8)*!radeg endif end endcase endif else begin ;----- Handle y reversal -------- if (ctyp eq 0) and keyword_set(order) then y=(!d.y_size-1)-y endelse if n_elements(color) eq 0 then color=!p.color clr = color if n_elements(linestyle) eq 0 then linestyle=!p.linestyle if keyword_set(xmode) then begin device,get_graph=old,set_graph=6 ; clr = !d.table_size-1 clr = 255 endif stat = keyword_set(nostat) eq 0 top = -1L if n_elements(st) ne 0 then top=st.top if n_elements(menu) eq 0 then menu = ['Exit'] if n_elements(def) eq 0 then def = n_elements(menu) if n_elements(instr) eq 0 then instr = ['Press any button to exit.'] if n_elements(xsize) eq 0 then begin xsize=12 if strupcase(!version.os) eq 'MACOS' then xsize=6 endif if n_elements(ysize) eq 0 then begin ysize=12 if strupcase(!version.os) eq 'MACOS' then ysize=6 endif ;------- Find brightest and darkest colors -------------- tvlct,/get,r_curr,g_curr,b_curr ;----- 4 lines lifted from ct_luminance (userslib) ---- lum= (.3 * r_curr) + (.59 * g_curr) + (.11 * b_curr) bright = max(lum, min=dark) c1 = where(lum eq bright) c2 = where(lum eq dark) bright=c1(0) & dark=c2(0) ;------- Setup for color = -2 --------------- if clr eq -2 then begin hor2 = bright+((indgen(!d.x_size) mod 6) lt 3)*(dark-bright) ver2 = bright+((transpose(indgen(!d.y_size)) mod 6) lt 3)*$ (dark-bright) endif ;------- Deal with mag window -------------- win1 = !d.window ; Current window. if n_elements(mag0) eq 0 then mag0=0 ; Force defined. if (n_elements(msize0) ne 0) and (mag0 eq 0) then mag0=1 if mag0 ne 0 then begin if n_elements(msize0) eq 0 then msize0 = 200 ; Def mag win size. msize = round(msize0) ; Rounded size. mag = round(mag0) ; Rounded mag. if mag eq 1 then mag = 10 ; Def is 10. rdsz = round(float(msize)/mag) ; Read size. rdsz2 = rdsz/2 ; Offset. xmid = rdsz2*mag ; Mag win midpoint. ymid = rdsz2*mag wsz = rdsz*mag ; True mag win size. endif ;------ Find ranges and start in device coordinates ---- if keyword_set(device) then begin ;---- DEVICE ----- xxdv=[0,!d.x_size-1] ; Device range. yydv=[0,!d.y_size-1] if n_elements(x) eq 0 then x=!d.x_size/2 x = x>0<(!d.x_size-1) if n_elements(y) eq 0 then y=!d.y_size/2 y = y>0<(!d.y_size-1) endif else if keyword_set(norm) then begin ;--- NORMAL ----- xxdv=[0,!d.x_size-1] ; Normal range. yydv=[0,!d.y_size-1] if n_elements(x) eq 0 then x=.5 x = x>0<1. if n_elements(y) eq 0 then y=.5 y = y>0<1. endif else begin if !x.type eq 2 then begin ;---- MAPS ------ xxdv = [0,!d.x_size-1] yydv = [0,!d.y_size-1] if n_elements(x) eq 0 then x = !map.out(9)*!radeg if n_elements(y) eq 0 then y = !map.out(8)*!radeg endif else begin ;---- DATA ------ xx = [min(!x.crange), max(!x.crange)] ; Data range in x. if !x.type eq 1 then xx=10^xx ; Handle log x axis. yy = [min(!y.crange), max(!y.crange)] ; Data range in y. if !y.type eq 1 then yy=10^yy ; Handle log y axis. tmp = convert_coord(xx,yy,/to_dev) ; Convert to device coord. xxdv = tmp(0,0:1) ; Device coord. range. yydv = tmp(1,0:1) xxdv = xxdv(sort(xxdv)) ; Allow for reversed axes. yydv = yydv(sort(yydv)) if n_elements(x) eq 0 then x = total(xx)/2. x = x>xx(0)yy(0) xxdv(0) < xxdv(1) ; Keep in bounds. ydv = ydv > yydv(0) < yydv(1) ; Keep in bounds. xcl = xdv & ycl = ydv if not keyword_set(xmode) then begin tv, tsx, xl, 0 ; Replace last column. tv, tsy, 0, yl ; Replace last row. tsx = tvrd(xdv,0,1,!d.y_size) ; Read new column. tsy = tvrd(0,ydv,!d.x_size,1) ; Read new row. endif else begin plots, [xl,xl],yydv,color=clr,linestyle=linestyle,/dev plots, xxdv,[yl,yl],color=clr,linestyle=linestyle,/dev empty ; Flush graphics. endelse xl = xdv ; Last column. yl = ydv ; Last column. if keyword_set(pixel) then zdv=(tvrd(xdv,ydv,1,1)+0)(0) ; Read pix. ;---------- Update mag window if any -------------- if mag0 ne 0 then begin t=tvrd2(xdv-rdsz2,ydv-rdsz2,rdsz,rdsz) ; Read patch. t = rebin(t,wsz,wsz,/samp) ; Magnify. it = t(xmid,ymid) ; Mid pixel. if lum(it) lt 128 then cc=bright $ else cc=dark ; Outline color. t(xmid:xmid+mag,ymid)=cc ; Draw mid pixel outline. t(xmid:xmid+mag,ymid+mag)=cc t(xmid,ymid:ymid+mag)=cc t(xmid+mag,ymid:ymid+mag)=cc win = win2 if n_elements(st) ne 0 then win=st.win2 wset, win ; Set to mag window. tv, t ; Display mag view. wset, win1 ; Set back to original win. endif ;---------- Draw new cross-hairs ----------------------- if clr eq -2 then begin tv,ver2,xdv,0 tv,hor2,0,ydv endif else begin plots, [xdv,xdv],yydv,color=clr,linestyle=linestyle,/dev plots, xxdv,[ydv,ydv],color=clr,linestyle=linestyle,/dev endelse empty ; Flush graphics. ;------- Update status display ------------ if stat then begin tmp = convert_coord(xdv, ydv, /dev, $ to_dev=device, to_norm=norm, to_dat=data) x=tmp(0) & y=tmp(1) ;----- Handle y reversal -------- if (ctyp eq 0) and keyword_set(order) then y=(!d.y_size-1)-y if keyword_set(js) then x = x + jsoff if n_elements(xfn) eq 0 then x=strtrim(x,2) $ else x=call_function(xfn, x) if n_elements(yfn) eq 0 then y=strtrim(y,2) $ else y=call_function(yfn, y) widget_control, st.tx, set_val=x widget_control, st.ty, set_val=y if keyword_set(pixel) then begin widget_control,st.tz,set_val=strtrim(zdv,2) rgb = string(/print,form='(3I4)',rr(zdv),gg(zdv),bb(zdv)) widget_control, st.trgb, set_val=rgb endif endif ;------- Handle button press ---------- if !mouse.button ne 0 then begin button = !mouse.button if keyword_set(dialog) then begin exitcode = xoption([menu,'Continue'],def=def) if exitcode eq n_elements(menu) then begin !mouse.button = 0 tvcrs, xdv, ydv endif endif else begin exitcode = 0 endelse endif endwhile ;=========================================================== ;-------- Erase last line -------- if keyword_set(xmode) then begin plots, [xdv,xdv],yydv,color=clr,linestyle=linestyle,/dev plots, xxdv,[ydv,ydv],color=clr,linestyle=linestyle,/dev device,set_graph=old endif else begin tv, tsx, xl, 0 ; Replace last column. tv, tsy, 0, yl ; Replace last row.. endelse ;-------- return correct coordinate -------- tmp=convert_coord(xdv,ydv,/dev,to_dev=device,to_norm=norm,to_dat=data) x = tmp(0) if keyword_set(js) then x = x + jsoff y = tmp(1) ;----- Handle y reversal -------- if (ctyp eq 0) and keyword_set(order) then y=(!d.y_size-1)-y ;-------- Remove status display widget ------- if (not keyword_set(nostat)) and (not keyword_set(keep)) then begin widget_control, st.top, /dest ; if mag0 ne 0 then begin ; win = win2 ; if n_elements(st) ne 0 then win=st.win2 ; wdelete, win ; endif endif ;------- Remove mag window -------------- if not keyword_set(keep) then begin if mag0 ne 0 then begin win = win2 if n_elements(st) ne 0 then win=st.win2 wdelete, win endif endif return end