;+ ; 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