Viewing contents of file '../idllib/jhuapls1r/usr/crossi.pro'
;-------------------------------------------------------------
;+
; 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)<xx(1)
if n_elements(y) eq 0 then y = total(yy)/2.
y = y>yy(0)<yy(1)
endelse
endelse
tmp = convert_coord(x,y,dev=device,norm=norm,data=data,/to_dev)
xdv = tmp(0)<xxdv(1) & ydv = tmp(1)<yydv(1)
;-------- Handle starting line ----------
tvcrs, xdv, ydv ; Place cursor.
if not keyword_set(xmode) then begin
tsx=tvrd(xdv,0,1,!d.y_size) ; 1st col.
tsy=tvrd(0,ydv,!d.x_size,1) ; 1st row.
endif
if clr eq -2 then begin ; Dotted lines.
tv,ver2,xdv,0
tv,hor2,0,ydv
endif else begin ; Normal lines.
plots, [xdv,xdv],yydv,color=clr,linestyle=linestyle,/dev
plots, xxdv,[ydv,ydv],color=clr,linestyle=linestyle,/dev
endelse
xl = xdv ; Last column.
yl = ydv ; Last row.
!mouse.button = 0 ; Clear button flag.
tmp=convert_coord(xdv,ydv,/dev,to_dev=device,to_norm=norm,to_dat=data)
xx0=tmp(0) & yy0=tmp(1)
if mag0 ne 0 then begin
if n_elements(st) ne 0 then begin
device,window_state=state ; Check if window exists.
if state(st.win2) eq 1 then win2=st.win2 else begin $
; win2=st.win2
window, /free, xs=msize, ys=msize, title='Mag: '+strtrim(mag,2)
win2 = !d.window ; Mag window.
endelse
endif else begin
window, /free, xs=msize, ys=msize, title='Mag: '+strtrim(mag,2)
win2 = !d.window ; Mag window.
endelse
wset,win1 ; Set back to starting window.
endif
;--------- Set up status widget -------------
if stat then begin
if not widget_info(top,/valid_id) then begin
;------- Mag window creation ------
if mag0 ne 0 then begin
; window, /free, xs=msize, ys=msize, title='Mag: '+strtrim(mag,2)
; win2 = !d.window ; Mag window.
; lum = ct_luminance(dark=dark, bright=bright) ; Center pix colors.
wset, win1 ; Return to first win.
endif else begin
; lum = 0
win2 = 0
; dark = 0
; bright = 0
endelse
;------ Widget setup ------------
top = widget_base(/column,title='Cross-hair cursor')
id_typ = widget_label(top,val= ' ')
b = widget_base(top,/row) ; Position.
id = widget_label(b,val='X')
tx = widget_text(b,xsize=xsize)
b = widget_base(top,/row) ; Position.
id = widget_label(b,val='Y')
ty = widget_text(b,xsize=ysize)
tz = 0
trgb = 0
if keyword_set(pixel) then begin
b = widget_base(top,/row) ; Pixel value.
id = widget_label(b,val='Z')
tz = widget_text(b,xsize=5)
id = widget_label(b,val='RGB')
trgb = widget_text(b,xsize=12)
tvlct,rr,gg,bb,/get ; Get color table
endif
xsz = max(strlen(instr))
ysz = n_elements(instr)
id = widget_text(top,xsize=xsz,ysize=ysz,val=instr)
;------- Save widget IDs in a structure --------
st = {top:top, typ:id_typ, tx:tx, ty:ty, tz:tz, trgb:trgb,$
win2:win2}
; st = {top:top, typ:id_typ, tx:tx, ty:ty, tz:tz, trgb:trgb,$
; lum:lum, win2:win2, dark:dark, bright:bright}
endif ; st not defined.
;-------- Initialize Stat widget -------
widget_control,st.typ,set_va=(['Device','Normalized','Data'])(ctyp)+$
' Coordinates'
widget_control, st.tx, set_val=strtrim(xx0,2)
widget_control, st.ty, set_val=strtrim(yy0,2)
if keyword_set(pixel) then begin
zdv = tvrd(xdv,ydv,1,1)+0
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
;-------- Create ---------
widget_control, st.top, /real
endif
;===========================================================
;------- Cursor loop -----------
xcl = -2 & ycl = -2
while !mouse.button eq 0 do begin
;------ Get mouse input ----------
cursor, xdv, ydv, 0, /dev ; Read cursor.
if ((xdv eq xcl) and (ydv eq ycl)) or $ ; Not moved, or
((xdv eq -1) and (ydv eq -1)) then $ ; moved out of window:
cursor,xdv,ydv,2,/device ; wait for a change.
;------ Erase old line --------------
xdv = xdv > 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