Viewing contents of file '../idllib/contrib/buie/cw_pfile.pro'
;+
; NAME:
; cw_pfile
; PURPOSE: (one line)
; Widget application for plots and profiles of an image.
; DESCRIPTION:
;
; CATEGORY:
; Compound Widgets
; CALLING SEQUENCE:
; result = cw_pfile( parent )
;
; INPUTS:
; parent : Widget id of parent.
;
; OPTIONAL INPUT PARAMETERS:
;
; KEYWORD PARAMETERS:
; HCTITLE = Title of Hard Copy.
; PLATESCALE : Plate Scale in arcseconds per pixel (used at display time).
; If supplied and non-zero, display the bottom axis in
; arcseconds and the top axis in pixels, else display the
; bottom axis in pixels.
; UVALUE = Optional user value.
;
; OUTPUTS:
;
; COMMON BLOCKS:
;
; SIDE EFFECTS:
;
; RESTRICTIONS:
;
; PROCEDURE:
; After placing this compound widget on a base, that base must then be
; realized. After realization, the image array and set-point coordinates are
; supplied via the WIDGET_CONTROL procedure and the SET_VALUE keyword.
; The 'value' of cw_pfile is a structure having three tags: image, xset,
; and yset.
;
; The following illustrates the procedure:
;
; array = some portion of a larger 2-D array.
; xset, yset = set-point of the lower portion of the extracted array.
;
; result = cw_pfile( parent )
; Realize the hierarchy of parent.
; WIDGET_CONTROL, result, SET_VALUE={image:array, xset:xset, yset:yset}
;
; MODIFICATION HISTORY:
; Written by Doug Loucks, Lowell Observatory, April, 1994.
; June, 1994, DWL, Converted to Compound Widget.
; March 1996, MWB, added print support for DOS
;-
; -----------------------------------------------------------------------------
; Procedure cw_pfile_do
; This procedure performs all processing for the draw widget and the
; hardcopy (Post Script) device.
; -----------------------------------------------------------------------------
PRO cw_pfile_do, state, HARDCOPY=hardcopy
;Save plotting structure system variable.
pmult = !p.multi
!p.multi = 0
IF state.shadesurf THEN bpp=8 ELSE bpp=4
IF KEYWORD_SET(hardcopy) THEN BEGIN
;Direct graphics to the Post Script device.
dname = !d.name
SET_PLOT,'ps'
DEVICE, FILENAME='plot.ps', /PORTRAIT, XSIZE=15.0, YSIZE=15.0, $
XOFFSET=2.5, YOFFSET=7.5, /HELVETICA, BITS_PER_PIXEL=bpp
color1 = 0
color2 = 0
ENDIF ELSE BEGIN
;Direct graphics to the draw widget.
windo = !d.window
WIDGET_CONTROL, state.dwinid, GET_VALUE=dwin
WSET, dwin
color1 = FIX( !d.n_colors * 0.9 )
color2 = FIX( !d.n_colors * 0.6 )
ENDELSE
position = STRING( 'Centroid: xpos= ', state.xpos, ' ypos= ', $
state.ypos, FORMAT='(A,F8.3,A,F8.3)' )
WIDGET_CONTROL, state.posid, SET_VALUE = position
WIDGET_CONTROL, state.dwinid, GET_UVALUE=image, /NO_COPY
;Scatter Profile section.
; The plot arrays and variables are computed once, for each incoming image
;array, and stored in the user-value of the exclusive button base.
; By incorporating these items into a structure, it is easy to determine
;if the computational steps may be skipped: If the user-value is a structure,
;no action is required.
; Setting this user-value to a scalar zero will force the computational
;steps to be performed and the new results stored to the user-value for
;later retrieval.
;
IF (state.profile AND state.scatter) THEN BEGIN
WIDGET_CONTROL, state.scatsavid, GET_UVALUE=scat
scatstat = SIZE( scat )
IF scatstat[2] NE 8 THEN BEGIN
;Need to perform computational steps.
radp, image, state.xcen, state.ycen, r, i, fwhmp, $
coeffs, /CONLY
ir = FINDGEN( 151 ) / 150.0 * MAX( r )
rcgauss_funct, ir, coeffs, ifit
rmin = MIN( r, MAX=rmax )
irmin = MIN( ir, MAX=irmax )
xmin = 0
xmax = MAX( [ rmax, irmax ] )
scat = { r:r, i:i, ir:ir, ifit:ifit, fwhmp:fwhmp, xmin:xmin, xmax:xmax }
;Save the results.
WIDGET_CONTROL, state.scatsavid, SET_UVALUE=scat
ENDIF
CASE state.pscale OF
0.0 : BEGIN
PLOT, scat.r, scat.i, PSYM=4, $
XRANGE=[scat.xmin, scat.xmax], $
XTITLE='radius (pixels)', YTITLE='counts'
OPLOT, scat.ir, scat.ifit, COLOR=color1, LINESTYLE=2
END
ELSE : BEGIN
ra = scat.r * state.pscale
PLOT, ra, scat.i, PSYM=4, XSTYLE=11, YSTYLE=3, YMARGIN=[4,3],$
XTITLE='radius (arcseconds)', YTITLE='counts', $
XRANGE=[scat.xmin*state.pscale, scat.xmax*state.pscale]
AXIS, XAXIS=1, XSTYLE=3, XRANGE=[scat.xmin, scat.xmax], $
XTITLE='radius (pixels)'
OPLOT, scat.ir*state.pscale, scat.ifit, COLOR=color1, LINESTYLE=2
END
ENDCASE
xpos = 0.85
ypos = 0.85
dy = 0.03
XYOUTS, xpos, ypos, 'FWHM(pixels): ' + STRING( scat.fwhmp, $
FORMAT='(F7.2)' ), /NORMAL, ALIGN=1.0
IF state.pscale NE 0.0 THEN BEGIN
ypos = ypos - dy
XYOUTS, xpos, ypos, 'FWHM(arcsec): ' + $
STRING( scat.fwhmp*state.pscale, FORMAT='(F7.2)'), $
/NORMAL, ALIGN=1.0
ENDIF
IF KEYWORD_SET(hardcopy) THEN BEGIN
IF state.pscale NE 0.0 THEN BEGIN
ypos = ypos - dy
XYOUTS, xpos, ypos, 'Plate Scale: ' + $
STRING( state.pscale, FORMAT='(F7.3)' ), /NORMAL, ALIGN=1.0
ENDIF
ypos = ypos - dy
XYOUTS, xpos, ypos, 'Centroid-x: ' + STRING( state.xpos, $
FORMAT='(F7.3)' ), /NORMAL, ALIGN=1.0
ypos = ypos - dy
XYOUTS, xpos, ypos, 'Centroid-y: ' + STRING( state.ypos, $
FORMAT='(F7.3)' ), /NORMAL, ALIGN=1.0
ENDIF
ENDIF
;Smooth Profile section.
; The plot arrays and variables are computed once, for each incoming image
;array, and stored in the user-value of the non-exclusive button base.
; By incorporating these items into a structure, it is easy to determine
;if the computational steps may be skipped: If the user-value is a structure,
;no action is required.
; Setting this user-value to a scalar zero will force the computational
;steps to be performed and the new results stored to the user-value for
;later retrieval.
;
IF (state.profile AND state.smooth) THEN BEGIN
WIDGET_CONTROL, state.smoosavid, GET_UVALUE=smoo
smoostat = SIZE( smoo )
IF smoostat[2] NE 8 THEN BEGIN
;Need to perform computational steps.
dr = 0.5
imsize = state.imsize
xcen = state.xcen
ycen = state.ycen
rmax = MIN( [ xcen, ycen, imsize-xcen, imsize-ycen ] )
ringprof, image, state.xcen, state.ycen, $
rmax, dr, 0.0, rout, iout
xmin = 0
xmax = MAX( rout )
smoo = { rout:rout, iout:iout, xmin:xmin, xmax:xmax }
;Save the results.
WIDGET_CONTROL, state.smoosavid, SET_UVALUE=smoo
ENDIF
CASE state.pscale OF
0.0 : BEGIN
IF state.scatter THEN BEGIN
OPLOT, smoo.rout, smoo.iout, COLOR=color2
ENDIF ELSE BEGIN
PLOT, smoo.rout, smoo.iout, $
XRANGE=[smoo.xmin, smoo.xmax], $
XTITLE='radius (pixels)', YTITLE='counts'
OPLOT, smoo.rout, smoo.iout, PSYM=5
ENDELSE
END
ELSE : BEGIN
ra = smoo.rout * state.pscale
IF state.scatter THEN BEGIN
OPLOT, ra, smoo.iout, COLOR=color2
ENDIF ELSE BEGIN
PLOT, ra, smoo.iout, XSTYLE=11, YSTYLE=3, YMARGIN=[4,3], $
XTITLE='radius (arcseconds)', YTITLE='counts', $
XRANGE=[smoo.xmin*state.pscale, smoo.xmax*state.pscale]
AXIS, XAXIS=1, XSTYLE=3, XRANGE=[smoo.xmin, smoo.xmax], $
XTITLE='radius (pixels)'
OPLOT, ra, smoo.iout, PSYM=5
ENDELSE
END
ENDCASE
ENDIF
;Histogram section.
IF state.histogram THEN BEGIN
stats, image, /ROBO
ENDIF
;Contour plot section.
IF state.contour THEN BEGIN
x = state.xset + INDGEN( state.imsize )
y = state.yset + INDGEN( state.imsize )
IF !order EQ 1 THEN $
yr=maxmin(y) $
ELSE $
yr=minmax(y)
contour, image, x, y, YRANGE=yr, XTITLE='X-pos (pixels)', $
YTITLE='Y-pos (pixels)'
ENDIF
;Shade Surface section.
IF state.shadesurf THEN BEGIN
x = state.xset + INDGEN( state.imsize )
y = state.yset + INDGEN( state.imsize )
IF !order EQ 1 THEN $
yr=maxmin(y) $
ELSE $
yr=minmax(y)
shade_surf, image, x, y, YRANGE=yr, XTITLE='X-pos (pixels)', $
YTITLE='Y-pos (pixels)', ZTITLE='Counts'
ENDIF
IF KEYWORD_SET(hardcopy) THEN BEGIN
;Add some text to the hard copy and close the Post Script device.
XYOUTS, 0.6, 1.02, state.hctitle, /NORMAL, ALIGN=0.5
XYOUTS, 0.6, -0.07, SYSTIME(), /NORMAL
DEVICE, /CLOSE
SET_PLOT, dname
IF !version.os_family EQ 'unix' THEN BEGIN
SPAWN, 'lpr -r plot.ps'
ENDIF ELSE IF !version.os_family EQ 'Windows' THEN BEGIN
SPAWN, 'copy plot.ps lpt1:'
SPAWN, 'del plot.ps'
ENDIF
ENDIF ELSE BEGIN
;Reset the draw window.
WSET, windo
ENDELSE
!p.multi = pmult
WIDGET_CONTROL, state.dwinid, SET_UVALUE=image, /NO_COPY
END
; -----------------------------------------------------------------------------
; Procedure cw_pfile_svl
; The 'set value' procedure for this compound widget.
; -----------------------------------------------------------------------------
PRO cw_pfile_svl, id, value
;Retrieve the state.
stash = WIDGET_INFO( id, /CHILD )
WIDGET_CONTROL, stash, GET_UVALUE=state, /NO_COPY
IF state.lock THEN BEGIN
;The value (display) is frozen. Ignore the request.
WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
RETURN
ENDIF
; Get input image information.
stat = SIZE( value.image )
xsize = stat[ 1 ]
ysize = stat[ 2 ]
IF xsize EQ ysize THEN BEGIN
imsize = xsize
; Find image maximum and then compute the centroid.
s = WHERE( value.image EQ MAX( value.image ), count )
s = s[ 0 ]
xmax = s MOD imsize
ymax = s / imsize
centrod, value.image, xmax, ymax, 5.0, 0.0, 0.0, 0.0, xcen, ycen, counts
state.imsize = imsize
state.xcen = xcen
state.ycen = ycen
state.xpos = value.xset + xcen
state.ypos = value.yset + ycen
state.xset = value.xset
state.yset = value.yset
;Put the profile image array into its holding area (User value of
;the draw widget).
WIDGET_CONTROL, state.dwinid, SET_UVALUE=value.image
;Set the storage area for the computed smooth profile parameters to zero.
;This forces computation when smooth profile is selected.
WIDGET_CONTROL, state.scatsavid, SET_UVALUE=0
WIDGET_CONTROL, state.smoosavid, SET_UVALUE=0
;Do the processing.
cw_pfile_do, state
ENDIF ELSE BEGIN
MESSAGE, 'Profile array must be square.' + STRING( 7B ), /INFO
ENDELSE
;Restore the state.
WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
END
; -----------------------------------------------------------------------------
; Procedure cw_pfile_eve
; Main event handler.
; -----------------------------------------------------------------------------
PRO cw_pfile_eve, event
WIDGET_CONTROL, event.id, /HOURGLASS
;Retrieve the state.
stash = WIDGET_INFO( event.handler, /CHILD )
WIDGET_CONTROL, stash, GET_UVALUE=state, /NO_COPY
CASE event.id OF
state.exitid : BEGIN
WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
WIDGET_CONTROL, event.top, /DESTROY
RETURN
END
state.hdcpyid : BEGIN
;Do the processing with the hardcopy flag set.
cw_pfile_do, state, /HARDCOPY
END
state.lockid : BEGIN
;Toggle the lock state.
state.lock = event.value
END
state.scatsavid : BEGIN
;Exclusive button events.
; These events cause state flags to be set, or cleared. The procedure
;cw_pfile_do uses them to control its processing duties.
CASE event.value OF
0 : BEGIN
;Profile.
state.profile = 1
state.histogram = 0
state.contour = 0
state.shadesurf = 0
WIDGET_CONTROL, state.scatid, SENSITIVE=1
WIDGET_CONTROL, state.smooid, SENSITIVE=1
END
1 : BEGIN
;Histogram.
state.profile = 0
state.histogram = 1
state.contour = 0
state.shadesurf = 0
WIDGET_CONTROL, state.scatid, SENSITIVE=0
WIDGET_CONTROL, state.smooid, SENSITIVE=0
END
2 : BEGIN
;Contour.
state.profile = 0
state.histogram = 0
state.contour = 1
state.shadesurf = 0
WIDGET_CONTROL, state.scatid, SENSITIVE=0
WIDGET_CONTROL, state.smooid, SENSITIVE=0
END
3 : BEGIN
;Shade Surface.
state.profile = 0
state.histogram = 0
state.contour = 0
state.shadesurf = 1
WIDGET_CONTROL, state.scatid, SENSITIVE=0
WIDGET_CONTROL, state.smooid, SENSITIVE=0
END
ELSE : BEGIN
MESSAGE, 'Unknown event.', /INFO
END
ENDCASE
cw_pfile_do, state
END
state.smoosavid : BEGIN
;Non-exclusive button events.
; State flags are set, or cleared, for each of the profile types. If an
;event would cause all flags to be set to the zero state, no action is
;taken (the remaining selected state is preserved).
ok = 1
CASE event.value OF
0 : BEGIN
;Scatter Profile.
newscatter = (state.scatter + 1) MOD 2
IF newscatter EQ 0 AND state.smooth EQ 0 THEN BEGIN
;This would set all flags to zero. Do not accept the request.
WIDGET_CONTROL, state.scatid, SET_BUTTON=1
ok = 0
ENDIF ELSE BEGIN
state.scatter = newscatter
ENDELSE
END
1 : BEGIN
;Smooth Profile.
newsmooth = (state.smooth + 1) MOD 2
IF newsmooth EQ 0 AND state.scatter EQ 0 THEN BEGIN
;This would set all flags to zero. Do not accept the request.
WIDGET_CONTROL, state.smooid, SET_BUTTON=1
ok = 0
ENDIF ELSE BEGIN
state.smooth = newsmooth
ENDELSE
END
ELSE : BEGIN
MESSAGE, 'Unknown event.', /INFO
END
ENDCASE
IF ok THEN cw_pfile_do, state
END
ELSE : BEGIN
MESSAGE, 'Outside event received. Uvalue= ' + uvalue, /INFO
HELP, event, /STRUCTURE
END
ENDCASE
;Restore the state.
WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
END
; -----------------------------------------------------------------------------
; Procedure cw_pfile
; -----------------------------------------------------------------------------
FUNCTION cw_pfile, parent, $
PLATESCALE=pscale, HCTITLE=hctitle, UVALUE=uvalue
; Check pscale keyword.
IF NOT KEYWORD_SET( pscale ) THEN pscale=0.0
;Check title keyword.
IF NOT KEYWORD_SET( hctitle ) THEN hctitle=''
;Define the state structure.
state = { $
contour:0B, $
dwinid:0L, $
exitid:0L, $
hctitle:hctitle, $
hdcpyid:0L, $
histogram:0B, $
imsize:0, $
lock:0B, lockid:0L, $
posid:0L, $
profile:1B, $
pscale:pscale, $
scatsavid:0L, smoosavid:0L, $
scatter:1B, scatid:0L, $
shadesurf:0B, $
smooth:0B, smooid:0L, $
xcen:0.0, ycen:0.0, $
xpos:0.0, ypos:0.0, $
xset:0, yset:0 }
;Define the main base.
IF KEYWORD_SET( uvalue ) THEN BEGIN
mainbase = WIDGET_BASE( parent, COLUMN=1, EVENT_PRO='cw_pfile_eve', $
PRO_SET_VALUE='cw_pfile_svl', UVALUE=uvalue )
ENDIF ELSE BEGIN
mainbase = WIDGET_BASE( parent, COLUMN=1, EVENT_PRO='cw_pfile_eve', $
PRO_SET_VALUE='cw_pfile_svl' )
ENDELSE
;Define the main buttons.
wb = WIDGET_BASE( mainbase, ROW=1 )
state.exitid = WIDGET_BUTTON( wb, VALUE='Exit' )
;Hard Copy button.
state.hdcpyid = WIDGET_BUTTON( wb, VALUE='Hard Copy' )
;Unlocked, Locked toggle buttons.
state.lockid = cw_bgroup( wb, ['Unlock Display', 'Lock Display'], $
/EXCLUSIVE, /FRAME, /NO_RELEASE, ROW=1, SET_VALUE=0 )
;Base for exclusive and non-exclusive buttons.
base = WIDGET_BASE( mainbase, /ROW )
;Define the exclusive buttons.
state.scatsavid = CW_BGROUP( base, ['Profile', 'Histogram', 'Contour', $
'Shade Surface'], COLUMN=1, /EXCLUSIVE, $
/FRAME, /NO_RELEASE, SET_VALUE=0 )
;Define the non-exclusive buttons.
state.smoosavid = CW_BGROUP( base, ['Scatter', 'Smooth'], $
COLUMN=2, /FRAME, IDS=ids, /NONEXCLUSIVE, $
SET_VALUE=[state.scatter, state.smooth] )
;Save the Scatter and Smooth button widget id's for later use.
state.scatid = ids[0]
state.smooid = ids[1]
;Define the position label widget.
position = STRING( 'Centroid: xpos= ', state.xpos, ' ypos= ', $
state.ypos, FORMAT='(A,F8.3,A,F8.3)' )
state.posid = WIDGET_LABEL( mainbase, /FRAME, VALUE=position )
;Define the draw window.
state.dwinid = WIDGET_DRAW( mainbase, XSIZE=400, YSIZE=400 )
;Set the state.
stash = WIDGET_INFO( mainbase, /CHILD )
WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
RETURN, mainbase
END