Viewing contents of file '../idllib/contrib/buie/ccdphot.pro'
;+
; NAME:
; ccdphot
; PURPOSE: (one line)
; General purpose display and processing of CCD image files (FITS).
; DESCRIPTION:
; A general purpose widget application which displays and processes CCD
; image files. This includes bias and flat field calibration and photometry
; reduction (itool).
; This procedure supports FITS files from the LCCD and LORAL instruments.
; CATEGORY:
; Widgets
; CALLING SEQUENCE:
; ccdphot[, keywords]
; INPUTS:
;
; OPTIONAL INPUT PARAMETERS:
;
; KEYWORD PARAMETERS:
; CALIBFILE= : Calibration startup file. Default is CALIBPATH/files.cal
; CALIBPATH= : Path for calibration files. Default is PATH/calib
; KEYLIST= : Name of a file containing a correspondence list. This list
; associates a set of standard names with the actual keyword
; names found in a FITS file header. If this keyword is
; omitted, a default list is used, as if a file with the
; following contents had been supplied:
; AIRMASS K AIRMASS
; DATE K DATE-OBS
; DATETMPL T DD-MM-YYYY
; EXPDELTA V 0.0
; EXPTIME K EXPTIME
; FILTER K FILTERS
; FILENAME K CCDFNAME
; OBJECT K OBJECT
; UT K UT
; The middle column is a flag. It may be K, for Keyword,
; T, for Template, or V, for Value. If it is V, the contents
; of the third field on that line should make sense for the
; name in the first field.
;
; PATH= : Optional path for image and calibration directory.
; If not specified, the current directory is used.
; PHOTPARMFILE= : Optional photometry parameter file. Passed to Itool.
; TMPLFILE= : Optional template file. Passed to Itool.
; WZOOMFACT= : Forces the cw_itool main draw window to have a specified
; zoom factor (passed to cw_itool).
;
; OUTPUTS:
;
; COMMON BLOCKS:
;
; SIDE EFFECTS:
;
; RESTRICTIONS:
;
; PROCEDURE:
;
; MODIFICATION HISTORY:
; Written by Doug Loucks, Lowell Observatory, December, 1993.
; Created by combining lccd.pro, loral.pro, and ccdphot_inst_init.pro.
; Added features include: Correspondence list for FITS header keywords
; and recognition of old format calibration environment files.
; 1/26/94, DWL, Added header date-parsing code to ldimage procedure.
; 3/2/94, DWL, Added keylist item EXPDELTA.
; 3/3/94, DWL, Improved the template and header date-parsing process.
; 3/10/94, DWL, Bug fixes.
; 4/94, DWL, Thorough validation of all environment parameters (overscan,
; cropping region, and bias/flat size compatibility).
; 3/1/95, MWB, Added support for a dark count calibrator (optional).
; 6/8/95, MWB, Changed defaults on calibration paths. Also, if file
; name begins with "+", CALIBPATH will replace the "+".
; 10/31/95, MWB, Added CATCH error handler to trap bad image file reads
; using READFITS. This prevents a crash to the IDL prompt
; when and invalid file is read.
; 3/18/96, MWB, Minor change to code that reads UT from header. Format
; requires two colons in string (HH:MM:SS) but also now
; allows SS to be a floating point number (ie., SS.sss).
; 6/25/96, MWB, implemented AUTO(-photometry) button.
; 1/22/97, MWB, fixed AUTO infinite loop if bad template positions found.
; 2/5/97, MWB, added FWHM and Mag safety shutoff in AUTO
; 6/13,97, MWB, extracted keylist to external general routines.
;-
; ------------------------------------------------------------------------------
; Internal support procedures.
; A list of the procedures in this file (in order of occurrence) are:
;
; ccdphot_fmt Format the filter list.
; ccdphot_di Display image with cw_itool.
; ccdphot_pr Performs bias and flat field correction.
; ccdphot_lf Loads a flat frame image into memory.
; ccdphot_af Adds a new filter code to the list of codes.
; ccdphot_li Loads an image into memory.
; ccdphot_lb Loads a bias frame image into memory.
; ccdphot_ld Loads a bias frame image into memory.
; ccdphot_lc Loads calibration environment files.
; ccdphot_sc Saves the current calibration environment.
; ccdphot_it_eve Event handler for cw_itool TLB.
; ccdphot_edit_eve Event handler for calibration editor TLB.
; ccdphot_eve Event handler for ccdphot.
; ccdphot
;
; ------------------------------------------------------------------------------
; Function ccdphot_fmt
; ------------------------------------------------------------------------------
FUNCTION ccdphot_fmt, flats
;The first element of the flats array represents the unity flat and is not
;available for modification.
n = N_ELEMENTS( flats )
;Find length of the longest filtercode name.
IF n GT 1 THEN BEGIN
maxlen = MAX( STRLEN( flats[1:n-1].filtercode ) )
;Set alpha format to this value
fmt = '(A' + STRTRIM( STRING( maxlen ), 2 ) + ')'
RETURN, STRING( flats[1:n-1].filtercode, FORMAT=fmt ) + ' ' + $
flats[1:n-1].filename
ENDIF ELSE BEGIN
RETURN, ''
ENDELSE
END
; ------------------------------------------------------------------------------
; Procedure ccdphot_di
; Calls itool to display the image.
; ------------------------------------------------------------------------------
PRO ccdphot_di, state, AUTOPHOT=autophot, PHOTTYPE=phottype, POSITION=position
IF state.imfile EQ '' THEN RETURN
valid = WIDGET_INFO( state.cwitoolbase, /valid_id )
IF state.new AND valid THEN BEGIN
WIDGET_CONTROL, state.cwitoolbase, TLB_GET_OFFSET=offset
WIDGET_CONTROL, state.cwitoolbase, /DESTROY
state.cwitoolbase = WIDGET_BASE( TITLE='Itool', COLUMN=1, $
GROUP_LEADER=state.mainbase )
WIDGET_CONTROL, state.cwitoolbase, TLB_SET_XOFFSET=offset[0], $
TLB_SET_YOFFSET=offset[1]
XMANAGER, '', state.cwitoolbase, /JUST_REG
state.cwitoolid = cw_itool( state.cwitoolbase, $
PHOTPARMFILE=state.photparmfile, $
TMPLFILE=state.tmplfile, $
WZOOMFACT=state.wzoomfact, $
XSIZE=state.pxsize, $
YSIZE=state.pysize )
ENDIF
IF state.cwitoolid EQ 0L THEN BEGIN
state.cwitoolbase = WIDGET_BASE( TITLE='Itool', COLUMN=1, $
GROUP_LEADER=state.mainbase )
XMANAGER, '', state.cwitoolbase, /JUST_REG
state.cwitoolid = cw_itool( state.cwitoolbase, $
PHOTPARMFILE=state.photparmfile, $
TMPLFILE=state.tmplfile, $
WZOOMFACT=state.wzoomfact, $
XSIZE=state.pxsize, $
YSIZE=state.pysize )
ENDIF
;In case cw_itool has been dismissed, or the TLB has not been realized:
WIDGET_CONTROL, state.cwitoolbase, /REALIZE, /MAP
;Get the image parameters structure (the 'value' for cw_itool).
WIDGET_CONTROL, state.imparmsptr, GET_UVALUE=im_parms
;Set the pointer and size fields.
im_parms.imageptr = state.dimgptr
im_parms.xsize = state.pxsize
im_parms.ysize = state.pysize
sz=size(autophot)
IF sz[1] EQ 7 THEN BEGIN
IF autophot EQ im_parms.object THEN BEGIN
im_parms.autophot = 1
im_parms.lasttype = phottype
im_parms.lastpos = position
ENDIF
ENDIF
;Display the new image.
WIDGET_CONTROL, state.cwitoolid, SET_VALUE=im_parms
END
; ------------------------------------------------------------------------------
; Procedure ccdphot_pr
; Performs bias and flat field corrections.
; ------------------------------------------------------------------------------
PRO ccdphot_pr, state
bel = STRING( 7B )
IF state.imfile EQ '' THEN RETURN
msg = 'Image: ' + state.imfile
IF state.processflag EQ 0 THEN BEGIN
IF (state.xsize NE state.pxsize) OR (state.ysize NE state.pysize) THEN BEGIN
state.new = 1B
state.pxsize = state.xsize
state.pysize = state.ysize
ENDIF ELSE BEGIN
state.new = 0B
ENDELSE
state.dimgptr = state.rimgptr
msg = msg + ' (raw).'
PRINT, ''
PRINT, msg
RETURN
ENDIF
state.dimgptr = state.cimgptr
;Full size of image (including overscan region).
xsize = state.xsize
ysize = state.ysize
;Calibration image size.
cxsize = state.cxsize
cysize = state.cysize
;Overscan region.
xl = state.xl
xr = state.xr
;Cropping region.
x1 = state.x1
x2 = state.x2
y1 = state.y1
y2 = state.y2
IF cxsize EQ 0 THEN BEGIN
xdim = xsize
ydim = ysize
ENDIF ELSE BEGIN
xdim = cxsize
ydim = cysize
ENDELSE
IF (x1 LT 0) AND (x2 LT 0) THEN BEGIN
IF cxsize GT 0 THEN BEGIN
xdim = cxsize
ENDIF ELSE BEGIN
xdim = xsize
ENDELSE
x1 = 0
x2 = xdim - 1
ENDIF ELSE BEGIN
xdim = x2 - x1 + 1
ENDELSE
IF (y1 LT 0) AND (y2 LT 0) THEN BEGIN
IF cysize GT 0 THEN BEGIN
ydim = cysize
ENDIF ELSE BEGIN
ydim = ysize
ENDELSE
y1 = 0
y2 = ydim - 1
ENDIF ELSE BEGIN
ydim = y2 - y1 + 1
ENDELSE
IF (xdim NE state.pxsize) OR (ydim NE state.pysize) THEN BEGIN
state.new = 1B
ENDIF ELSE BEGIN
state.new = 0B
ENDELSE
state.pxsize = xdim
state.pysize = ydim
WIDGET_CONTROL, state.imparmsptr, GET_UVALUE=im_parms, /NO_COPY
nframes = im_parms.nframes
filter = im_parms.filter
exptime = im_parms.exptime
WIDGET_CONTROL, state.imparmsptr, SET_UVALUE=im_parms, /NO_COPY
; Choose a flat
WIDGET_CONTROL, state.flatbase, GET_UVALUE=flats, /NO_COPY
findex = WHERE( flats[*].filtercode EQ filter, count )
IF count EQ 0 THEN BEGIN
findex = 0
state.fselected = 0
ENDIF
state.fselected = findex[0]
msg = msg + ' Filter: ' + flats[findex].filtercode
WIDGET_CONTROL, flats[findex].flatid, GET_UVALUE=flatframe, /NO_COPY
WIDGET_CONTROL, state.rimgptr, GET_UVALUE=rawframe, /NO_COPY
WIDGET_CONTROL, state.biasptr, GET_UVALUE=biasframe, /NO_COPY
WIDGET_CONTROL, state.darkptr, GET_UVALUE=darkframe, /NO_COPY
WIDGET_CONTROL, state.dimgptr, GET_UVALUE=image, /NO_COPY
image = FLTARR( xdim, ydim, nframes, /NOZERO )
; Process the image.
mean = 0
overscan = (xl GE 0) AND (xr GE 0)
FOR j=0, nframes-1 DO BEGIN
IF overscan THEN BEGIN
sigma = STDEV( rawframe[ xl : xr, * ], mean )
; msg = msg + ' Overscan (mean, sigma): ' + $
; STRING( mean, FORMAT='(G0.0)' ) + ', ' + $
; STRING( sigma, FORMAT='(G0.0)' )
ENDIF
image[*, *, j] = (rawframe[ x1:x2, y1:y2, j ] - mean - $
biasframe - darkframe*exptime) / flatframe
ENDFOR
WIDGET_CONTROL, flats[findex].flatid, SET_UVALUE=flatframe, /NO_COPY
WIDGET_CONTROL, state.rimgptr, SET_UVALUE=rawframe, /NO_COPY
WIDGET_CONTROL, state.biasptr, SET_UVALUE=biasframe, /NO_COPY
WIDGET_CONTROL, state.darkptr, SET_UVALUE=darkframe, /NO_COPY
WIDGET_CONTROL, state.dimgptr, SET_UVALUE=image, /NO_COPY
WIDGET_CONTROL, state.flatbase, SET_UVALUE=flats, /NO_COPY
PRINT, msg
END
; ------------------------------------------------------------------------------
; Procedure ccdphot_lf
; Loads a flat into memory. Flats are stored in the user-value of the
; base widget for each flat.
; ------------------------------------------------------------------------------
PRO ccdphot_lf, state, findex
bel = STRING( 7B )
WIDGET_CONTROL, state.flatbase, GET_UVALUE=flats, /NO_COPY
filter = 'Filter ' + flats[findex].filtercode + ' '
fname = flats[findex].filename
fullname=fname
if strmid(fullname,0,1) eq '+' then begin
fullname = state.calibpath + strmid(fname,1,strlen(fname)-1)
endif
IF NOT exists(fullname) THEN BEGIN
MESSAGE, 'Flat ' + fullname + ' not found.' + bel, /INFO
WIDGET_CONTROL, state.flatbase, SET_UVALUE=flats, /NO_COPY
RETURN
ENDIF
;Use the calibrated image storage area as a temporary place to load the
;prospective flat. This is OK because the calibrated image storage area
;is always initialized before a processed image is displayed.
WIDGET_CONTROL, state.cimgptr, GET_UVALUE=flatframe, /NO_COPY
flatframe = readfits( fullname, /SILENT )
stat = SIZE( flatframe )
frank = stat[ 0 ]
fxsize = stat[ 1 ]
fysize = stat[ 2 ]
;Put the storage pointer back.
WIDGET_CONTROL, state.cimgptr, SET_UVALUE=flatframe, /NO_COPY
IF frank NE 2 THEN BEGIN
MESSAGE, 'Flat ' + fullname + ' is rank ' + STRING(frank,FORMAT='(G0.0)' ) + $
'. Must be 2.' + bel, /INFO
RETURN
ENDIF
calval, state.xsize, fxsize, state.x1, state.x2, errflg, $
BANNER='LOAD FLAT: Error. Flat x-size is inconsistent with the ' + $
'established environment.', $
ISIZELAB='image frame x-size', $
CSIZELAB='calibration frame x-size', $
MLOWLAB='low limit of cropping region x-range', $
MHIGHLAB='high limit of cropping region x-range', $
DELTAMLAB='size of cropping region x-range'
err = errflg
calval, state.ysize, fysize, state.y1, state.y2, errflg, $
BANNER='LOAD FLAT: Error. Flat Y-size is inconsistent with the ' + $
'established environment.', $
ISIZELAB='image frame y-size', $
CSIZELAB='calibration frame y-size', $
MLOWLAB='low limit of cropping region y-range', $
MHIGHLAB='high limit of cropping region y-range', $
DELTAMLAB='size of cropping region y-range'
err = err OR errflg
IF err THEN BEGIN
MESSAGE, '...Flat ' + fullname + ' not loaded.', /INFO
WIDGET_CONTROL, state.flatbase, SET_UVALUE=flats, /NO_COPY
RETURN
ENDIF
state.cxsize = fxsize
state.cysize = fysize
;Move the flat frame over to its proper location.
WIDGET_CONTROL, state.cimgptr, GET_UVALUE=tframe, /NO_COPY
WIDGET_CONTROL, flats[findex].flatid, GET_UVALUE=flatframe, /NO_COPY
flatframe = tframe
tframe = 0
WIDGET_CONTROL, state.cimgptr, SET_UVALUE=tframe, /NO_COPY
WIDGET_CONTROL, flats[findex].flatid, SET_UVALUE=flatframe, /NO_COPY
;Store the filename.
flats[findex].filename = fname
MESSAGE, filter + fullname + ' loaded.', /INFO
WIDGET_CONTROL, state.flatbase, SET_UVALUE=flats, /NO_COPY
END
; ------------------------------------------------------------------------------
; Procedure ccdphot_af
; Add a new flat to the list of flats.
; The storage list for the flats consists of a tree of base widgets. Flat
; frame arrays are stored in the user-values of these widgets. The root (Top
; Level Base) holds a scalar 1.0 and is the selected default if a filter
; code is not found in the list at process time.
; If, upon entry, the filter code is not found in the current list, a new
; child base widget is added to the tree and a new entry is added to the
; flats list array (flats). The entries in this array are structures which
; identify the filter code, filename, and widget id of each of the flats.
; If, upon entry, the filter code is found, the filename field of the flats
; entry is set to the incoming filename parameter. Finally, if the filename
; argument is non-null, ccdphot_lf (Load Flat) is called.
; Note that, at this time, the new IDL storage mechanism called 'handles'
; has not been used. The reason is that there seems to be no 'automatic'
; method of releasing the storage in the event of a program 'crash.' The tree
; of widget bases will be destroyed, automatically, since the Top Level Base
; is always assigned a group leader (The Top Level Base of ccdphot).
; ------------------------------------------------------------------------------
PRO ccdphot_af, state, filtercode, fname
;Open access to the flats list array.
WIDGET_CONTROL, state.flatbase, GET_UVALUE=flats, /NO_COPY
;Search for the filtercode.
j = WHERE( flats[*].filtercode EQ filtercode, count )
IF count EQ 0 THEN BEGIN
;The incoming filter code is new.
;Add a new slot to the flats list array (flats) and update the list.
flats = [ flats, flats[ 0 ] ]
j = N_ELEMENTS( flats ) - 1
flats[j].filtercode = filtercode
flats[j].filename = fname
flats[j].flatid = WIDGET_BASE( flats[0].flatid, UVALUE=1.0 )
ENDIF ELSE BEGIN
;The incoming filtercode is in the list. Set the filename field.
IF fname NE '' THEN flats[j].filename = fname
ENDELSE
;Close access to the flats list array.
WIDGET_CONTROL, state.flatbase, SET_UVALUE=flats, /NO_COPY
IF fname NE '' THEN ccdphot_lf, state, j
END
; ------------------------------------------------------------------------------
; Procedure ccdphot_li
; Loads an image file into the image frame array.
; ------------------------------------------------------------------------------
PRO ccdphot_li, state, fname, $
AUTOPHOT=autophot, PHOTTYPE=phottype, POSITION=position
bel = STRING( 7B )
IF NOT exists( fname ) THEN BEGIN
MESSAGE, 'File ' + fname + ' not found.' + bel, /INFO
WIDGET_CONTROL, state.imtextid, SET_VALUE=state.imfile
RETURN
ENDIF
header = ''
;Use the calibrated image storage area as a temporary place to load the
;prospective image. This is OK because the calibrated image storage area
;is always initialized before a processed image is displayed.
CATCH, Error_status
IF Error_status NE 0 THEN BEGIN
MESSAGE, 'Error loading ' + fname + bel, /INFO
WIDGET_CONTROL, state.cimgptr, SET_UVALUE=tframe, /NO_COPY
WIDGET_CONTROL, state.imtextid, SET_VALUE=state.imfile
RETURN
ENDIF
WIDGET_CONTROL, state.cimgptr, GET_UVALUE=tframe, /NO_COPY
tframe = readfits( fname, header, /SILENT )
CATCH,/CANCEL
;Store the header in the user-value of the View Header button.
WIDGET_CONTROL, state.vheaderid, SET_UVALUE=header
;Initialize the new image parameters structure for the raw image.
it_init, tframe, im_parms
;Put the temporary storage pointer back.
WIDGET_CONTROL, state.cimgptr, SET_UVALUE=tframe, /NO_COPY
;Check for overscan error.
calval, im_parms.xsize, 0, state.xl, state.xr, errflg, $
BANNER='LOAD IMAGE: Error. Image x-size is inconsistent with the ' + $
'established overscan size or range.', $
ISIZELAB='image frame x-size', $
CSIZELAB='', $
MLOWLAB='low limit of overscan region', $
MHIGHLAB='high limit of overscan region', $
DELTAMLAB='size of overscan region'
err = errflg
;Check for x-range error.
calval, im_parms.xsize, state.cxsize, state.x1, state.x2, errflg, $
BANNER='LOAD IMAGE: Error. Image x-size is inconsistent with the ' + $
'established environment.', $
ISIZELAB='image frame x-size', $
CSIZELAB='calibration frame x-size', $
MLOWLAB='low limit of cropping region x-range', $
MHIGHLAB='high limit of cropping region x-range', $
DELTAMLAB='size of cropping region x-range'
err = err OR errflg
;Check for y-range error.
calval, im_parms.ysize, state.cysize, state.y1, state.y2, errflg, $
BANNER='LOAD IMAGE: Error. Image Y-size is inconsistent with the ' + $
'established environment.', $
ISIZELAB='image frame y-size', $
CSIZELAB='calibration frame y-size', $
MLOWLAB='low limit of cropping region y-range', $
MHIGHLAB='high limit of cropping region y-range', $
DELTAMLAB='size of cropping region y-range'
err = err OR errflg
IF err THEN BEGIN
MESSAGE, '...Image ' + fname + ' cannot be loaded.', /INFO
WIDGET_CONTROL, state.imtextid, SET_VALUE=state.imfile
RETURN
ENDIF
;Move the newly loaded image to its permanent location.
WIDGET_CONTROL, state.cimgptr, GET_UVALUE=tframe, /NO_COPY
WIDGET_CONTROL, state.rimgptr, GET_UVALUE=rawframe, /NO_COPY
rawframe = tframe
tframe = 0
WIDGET_CONTROL, state.cimgptr, SET_UVALUE=tframe, /NO_COPY
WIDGET_CONTROL, state.rimgptr, SET_UVALUE=rawframe, /NO_COPY
state.imfile = fname
WIDGET_CONTROL, state.imtextid, SET_VALUE=state.imfile
state.nframes = im_parms.nframes
state.xsize = im_parms.xsize
state.ysize = im_parms.ysize
;Extract some info from the header, using the list of header correspondence
;names.
WIDGET_CONTROL, state.hdrlistptr, GET_UVALUE=hdrlist, /NO_COPY
parsekey,header,hdrlist,hdrinfo
WIDGET_CONTROL, state.hdrlistptr, SET_UVALUE=hdrlist, /NO_COPY
;Copy the header imformation to the image parameters structure.
im_parms.airmass = hdrinfo.airmass
im_parms.date = hdrinfo.date
im_parms.expdelta = hdrinfo.expdelta
im_parms.exptime = hdrinfo.exptime
im_parms.imfile = hdrinfo.imfile
im_parms.filter = hdrinfo.filter
im_parms.object = hdrinfo.object
im_parms.ut = hdrinfo.ut
im_parms.jd = hdrinfo.jd
im_parms.autophot = 0
IF im_parms.imfile EQ '' THEN im_parms.imfile='(No name)'
;phot_parms.objnum = 0
ccdphot_af, state, im_parms.filter, ''
;Refresh the flats list widget.
WIDGET_CONTROL, state.flatbase, GET_UVALUE=flats, /NO_COPY
WIDGET_CONTROL, state.flatlistid, SET_VALUE=ccdphot_fmt(flats)
WIDGET_CONTROL, state.flatbase, SET_UVALUE=flats, /NO_COPY
;Freeze the flat filename edit widgets.
WIDGET_CONTROL, state.flatpickid, SENSITIVE=0
WIDGET_CONTROL, state.flattextid, SENSITIVE=0, SET_VALUE=''
;Put the new image parameters away.
WIDGET_CONTROL, state.imparmsptr, SET_UVALUE=im_parms
ccdphot_pr, state
ccdphot_di, state, AUTOPHOT=autophot, PHOTTYPE=phottype, POSITION=position
END
; ------------------------------------------------------------------------------
; Procedure ccdphot_lb
; Loads a bias frame into memory.
; ------------------------------------------------------------------------------
PRO ccdphot_lb, state, fname
bel = STRING( 7B )
fullname=fname
if strmid(fullname,0,1) eq '+' then begin
fullname = state.calibpath + strmid(fname,1,strlen(fname)-1)
endif
IF NOT exists( fullname ) THEN BEGIN
WIDGET_CONTROL, state.biastextid, SET_VALUE=state.biasname
MESSAGE, 'File ' + fullname + ' not found.' + bel, /INFO
RETURN
ENDIF
;Use the calibrated image storage area as a temporary place to load the
;prospective bias frame. This is OK because the calibrated image storage area
;is always initialized before a processed image is displayed.
WIDGET_CONTROL, state.cimgptr, GET_UVALUE=tframe, /NO_COPY
tframe = readfits( fullname, /SILENT )
stat = SIZE( tframe )
bxsize = stat[ 1 ]
bysize = stat[ 2 ]
;Put the temporary storage pointer back.
WIDGET_CONTROL, state.cimgptr, SET_UVALUE=tframe, /NO_COPY
calval, state.xsize, bxsize, state.x1, state.x2, errflg, $
BANNER='LOAD BIAS: Error. Bias x-size is inconsistent with the ' + $
'established environment.', $
ISIZELAB='image frame x-size', $
CSIZELAB='calibration frame x-size', $
MLOWLAB='low limit of cropping region x-range', $
MHIGHLAB='high limit of cropping region x-range', $
DELTAMLAB='size of cropping region x-range'
err = errflg
calval, state.ysize, bysize, state.y1, state.y2, errflg, $
BANNER='LOAD BIAS: Error. Bias Y-size is inconsistent with the ' + $
'established environment.', $
ISIZELAB='image frame y-size', $
CSIZELAB='calibration frame y-size', $
MLOWLAB='low limit of cropping region y-range', $
MHIGHLAB='high limit of cropping region y-range', $
DELTAMLAB='size of cropping region y-range'
err = err OR errflg
IF err THEN BEGIN
MESSAGE, '...Bias frame ' + fullname + ' cannot be loaded.', /INFO
RETURN
ENDIF
;Move the newly loaded bias frame to its permanent location.
WIDGET_CONTROL, state.cimgptr, GET_UVALUE=tframe, /NO_COPY
WIDGET_CONTROL, state.biasptr, GET_UVALUE=biasframe, /NO_COPY
biasframe = tframe
tframe = 0
WIDGET_CONTROL, state.cimgptr, SET_UVALUE=tframe, /NO_COPY
WIDGET_CONTROL, state.biasptr, SET_UVALUE=biasframe, /NO_COPY
state.biasname = fname
WIDGET_CONTROL, state.biastextid, SET_VALUE=fname
state.cxsize = bxsize
state.cysize = bysize
MESSAGE, 'Bias frame ' + fullname + ' loaded.', /INFO
END
; ------------------------------------------------------------------------------
; Procedure ccdphot_ld
; Loads a dark frame into memory.
; ------------------------------------------------------------------------------
PRO ccdphot_ld, state, fname
bel = STRING( 7B )
IF fname EQ '[none]' OR fname EQ '' THEN BEGIN
WIDGET_CONTROL, state.darkptr, GET_UVALUE=darkframe, /NO_COPY
darkframe = 0
WIDGET_CONTROL, state.darkptr, SET_UVALUE=darkframe, /NO_COPY
state.darkname = fname
WIDGET_CONTROL, state.darktextid, SET_VALUE=fname
MESSAGE, 'Dark frame calibration disabled.', /INFO
ENDIF ELSE BEGIN
fullname=fname
if strmid(fullname,0,1) eq '+' then begin
fullname = state.calibpath + strmid(fname,1,strlen(fname)-1)
endif
IF NOT exists( fullname ) THEN BEGIN
WIDGET_CONTROL, state.darktextid, SET_VALUE=state.darkname
MESSAGE, 'File ' + fullname + ' not found.' + bel, /INFO
RETURN
ENDIF
;Use the calibrated image storage area as a temporary place to load the
;prospective dark frame. This is OK because the calibrated image storage area
;is always initialized before a processed image is displayed.
WIDGET_CONTROL, state.cimgptr, GET_UVALUE=tframe, /NO_COPY
tframe = readfits( fullname, /SILENT )
stat = SIZE( tframe )
bxsize = stat[ 1 ]
bysize = stat[ 2 ]
;Put the temporary storage pointer back.
WIDGET_CONTROL, state.cimgptr, SET_UVALUE=tframe, /NO_COPY
calval, state.xsize, bxsize, state.x1, state.x2, errflg, $
BANNER='LOAD DARK: Error. Dark x-size is inconsistent with the ' + $
'established environment.', $
ISIZELAB='image frame x-size', $
CSIZELAB='calibration frame x-size', $
MLOWLAB='low limit of cropping region x-range', $
MHIGHLAB='high limit of cropping region x-range', $
DELTAMLAB='size of cropping region x-range'
err = errflg
calval, state.ysize, bysize, state.y1, state.y2, errflg, $
BANNER='LOAD DARK: Error. Dark Y-size is inconsistent with the ' + $
'established environment.', $
ISIZELAB='image frame y-size', $
CSIZELAB='calibration frame y-size', $
MLOWLAB='low limit of cropping region y-range', $
MHIGHLAB='high limit of cropping region y-range', $
DELTAMLAB='size of cropping region y-range'
err = err OR errflg
IF err THEN BEGIN
MESSAGE, '...Dark frame ' + fullname + ' cannot be loaded.', /INFO
RETURN
ENDIF
;Move the newly loaded dark frame to its permanent location.
WIDGET_CONTROL, state.cimgptr, GET_UVALUE=tframe, /NO_COPY
WIDGET_CONTROL, state.darkptr, GET_UVALUE=darkframe, /NO_COPY
darkframe = tframe
tframe = 0
WIDGET_CONTROL, state.cimgptr, SET_UVALUE=tframe, /NO_COPY
WIDGET_CONTROL, state.darkptr, SET_UVALUE=darkframe, /NO_COPY
state.darkname = fname
WIDGET_CONTROL, state.darktextid, SET_VALUE=fname
state.cxsize = bxsize
state.cysize = bysize
MESSAGE, 'Dark frame ' + fullname + ' loaded.', /INFO
ENDELSE
END
; ------------------------------------------------------------------------------
; Procedure ccdphot_lc
; Loads calibration files, based upon the contents of a calibration
; environment file.
; ------------------------------------------------------------------------------
PRO ccdphot_lc, state
bel = STRING( 7B )
IF state.calibfile EQ '' THEN RETURN
IF NOT exists( state.calibpath+state.calibfile ) THEN BEGIN
MESSAGE, 'Calibration Environment File ' + $
state.calibpath + state.calibfile + ' not found.'+bel, /INFO
WIDGET_CONTROL, state.caltextid, SET_VALUE=''
RETURN
ENDIF
; Remember the value of the calibration environment save flag.
calibflag = state.calibflag
IF state.calibflag THEN BEGIN
t = [ ' Calibration environment changes may not have been saved.', $
' If you do not wish to lose any changes, cancel this operation and', $
'save the current environment.' ]
con = qannounc( t, TITLE='Calibration Environment Save Confirmation', $
FALSE='Cancel', TRUE='Ok, continue', XSIZE=70 )
IF NOT con THEN RETURN
calibflag = 0
ENDIF
WIDGET_CONTROL, state.flatbase, GET_UVALUE=flats, /NO_COPY
flatbase1 = WIDGET_INFO( flats[0].flatid, /CHILD )
WIDGET_CONTROL, state.flatbase, SET_UVALUE=flats, /NO_COPY
IF flatbase1 NE 0L THEN BEGIN
t = [ ' You may choose to ADD to the existing list of flat fields, or', $
'to PURGE the existing list.' ]
purgelist=qannounc( t, TITLE='Calibration Environment Load Confirmation', $
FALSE='ADD to the existing list', TRUE='PURGE the existing list', XSIZE=70 )
calibflag = 1
IF purgelist THEN BEGIN
WIDGET_CONTROL, state.flatbase, GET_UVALUE=flats, /NO_COPY
WIDGET_CONTROL, flats[0].flatid, /DESTROY
flats = [flats[0]]
flats[0].flatid = WIDGET_BASE( UVALUE=1.0, GROUP_LEADER=state.mainbase )
calibflag = 0
WIDGET_CONTROL, state.flatbase, SET_UVALUE=flats, /NO_COPY
ENDIF
ENDIF
GET_LUN, lu
OPENR, lu, state.calibpath+state.calibfile, ERROR=err
IF err NE 0 THEN BEGIN
; We really have a problem.
FREE_LUN, lu
MESSAGE, !error_state.msg + bel, /INFO
RETURN
ENDIF
line = ''
READF, lu, line
linebuf = [ line ]
WHILE NOT EOF( lu ) DO BEGIN
READF, lu, line
linebuf = [ linebuf, line ]
ENDWHILE
CLOSE, lu
FREE_LUN, lu
; First line. Check for valid version.
w = WHERE( state.okver EQ linebuf[0], count )
IF count EQ 0 THEN BEGIN
MESSAGE, 'Unknown file version ' + line + bel, /INFO
RETURN
ENDIF
; ------------------------------------------------------------------------------
;Here is where the conversion from the old format takes place, if necessary.
;
IF linebuf[0] EQ state.okver[0] THEN BEGIN
n = N_ELEMENTS( linebuf )
CASE STRUPCASE( linebuf[1] ) OF
'LCCD' : BEGIN
line1 = '-1 -1'
line2 = ' -1 -1 -1 -1'
linebuf = [ state.okver[1], line1, line2, linebuf[2:n-1] ]
END
'LORAL' : BEGIN
line1 = linebuf[2]
line2 = linebuf[3]
linebuf = [ state.okver[1], line1, line2, linebuf[4:n-1] ]
END
ELSE : BEGIN
MESSAGE, 'Error. Unable to interpret old format environment file.'+ $
bel, /INFO
RETURN
END
ENDCASE
MESSAGE, 'Old format environment file successfully processed.', /INFO
ENDIF
; ------------------------------------------------------------------------------
error = 0
; Second line, overscan region.
overscan = linebuf[1]
n1 = GETTOK( overscan, ' ' )
n2 = GETTOK( overscan, ' ' )
xl = FIX( n1 )
xr = FIX( n2 )
calval, state.xsize, 0, xl, xr, errflg, $
BANNER='LOAD CALIB: Error. Specified Overscan is inconsistent with the ' + $
'established environment.', $
ISIZELAB='image frame x-size', $
CSIZELAB='', $
MLOWLAB='low limit of overscan region', $
MHIGHLAB='high limit of overscan region', $
DELTAMLAB='size of overscan region'
IF NOT errflg THEN BEGIN
state.xl = xl
state.xr = xr
overscan = STRING( xl, ':', xr, FORMAT='(G0.0,A,G0.0)' )
state.overscan = overscan
WIDGET_CONTROL, state.overscanid, SET_VALUE=overscan
ENDIF
;Third line, cropping region.
cropreg = linebuf[2]
n1 = GETTOK( cropreg, ' ' )
n2 = GETTOK( cropreg, ' ' )
n3 = GETTOK( cropreg, ' ' )
n4 = GETTOK( cropreg, ' ' )
x1 = FIX( n1 )
x2 = FIX( n2 )
calval, state.xsize, state.cxsize, x1, x2, errflg, $
BANNER='LOAD CALIB: Error. Specified X-range is inconsistent with the ' + $
'established environment.', $
ISIZELAB='image frame x-size', $
CSIZELAB='calibration frame x-size', $
MLOWLAB='low limit of cropping region x-range', $
MHIGHLAB='high limit of cropping region x-range', $
DELTAMLAB='size of cropping region x-range'
IF NOT errflg THEN BEGIN
state.x1 = x1
state.x2 = x2
xrange = STRING( x1, ':', x2, FORMAT='(G0.0,A,G0.0)' )
state.xrange = xrange
WIDGET_CONTROL, state.xrangeid, SET_VALUE=xrange
ENDIF
y1 = FIX( n3 )
y2 = FIX( n4 )
calval, state.ysize, state.cysize, y1, y2, errflg, $
BANNER='LOAD CALIB: Error. Specified Y-range is inconsistent with the ' + $
'established environment.', $
ISIZELAB='image frame y-size', $
CSIZELAB='calibration frame y-size', $
MLOWLAB='low limit of cropping region y-range', $
MHIGHLAB='high limit of cropping region y-range', $
DELTAMLAB='size of cropping region y-range'
IF NOT errflg THEN BEGIN
state.y1 = y1
state.y2 = y2
yrange = STRING( y1, ':', y2, FORMAT='(G0.0,A,G0.0)' )
state.yrange = yrange
WIDGET_CONTROL, state.yrangeid, SET_VALUE=yrange
ENDIF
;Fourth line, Bias frame.
ccdphot_lb, state, linebuf[3]
; Fifth line (maybe), Dark frame.
IF linebuf[0] EQ state.okver[1] THEN BEGIN
ccdphot_ld, state, '[none]'
nextline = 4
ENDIF ELSE BEGIN
ccdphot_ld, state, linebuf[4]
nextline = 5
ENDELSE
;Load the flat frames.
FOR j=nextline, N_ELEMENTS(linebuf)-1 DO BEGIN
flatline = linebuf[j]
filter = GETTOK( flatline, ' ' )
fname = GETTOK( flatline, ' ' )
fullname=fname
if strmid(fullname,0,1) eq '+' then begin
fullname = state.calibpath + strmid(fname,1,strlen(fname)-1)
endif
IF exists( fullname ) THEN BEGIN
ccdphot_af, state, filter, fname
ENDIF ELSE BEGIN
MESSAGE, 'File ' + fullname + ' not found.' + bel, /INFO
ENDELSE
ENDFOR
;Set calibration environment save flag.
state.calibflag = calibflag
;Update the flats list widget.
WIDGET_CONTROL, state.flatbase, GET_UVALUE=flats, /NO_COPY
WIDGET_CONTROL, state.flatlistid, SET_VALUE=ccdphot_fmt(flats)
WIDGET_CONTROL, state.flatbase, SET_UVALUE=flats, /NO_COPY
;Freeze the filename edit widgets.
WIDGET_CONTROL, state.flatpickid, SENSITIVE=0
WIDGET_CONTROL, state.flattextid, SENSITIVE=0, SET_VALUE=''
state.fselected = 0
;Process and display the image (if loaded).
ccdphot_pr, state
ccdphot_di, state
END
; ------------------------------------------------------------------------------
; Procedure ccdphot_sc
; Saves the current calibration environment to a file.
; ------------------------------------------------------------------------------
PRO ccdphot_sc, state
bel = STRING( 7B )
IF state.calibfile EQ '' THEN RETURN
WIDGET_CONTROL, state.flatbase, GET_UVALUE=flats, /NO_COPY
nflats = N_ELEMENTS( flats ) - 1
WIDGET_CONTROL, state.flatbase, SET_UVALUE=flats, /NO_COPY
notok = (state.biasname EQ '') OR (nflats EQ 0)
IF notok THEN BEGIN
MESSAGE, 'Error. Bias, and at least one flat must be loaded.' + $
bel, /INFO
RETURN
ENDIF
xl = state.xl
xr = state.xr
x1 = state.x1
x2 = state.x2
y1 = state.y1
y2 = state.y2
IF exists( state.calibpath+state.calibfile ) THEN BEGIN
t = $
[ ' Calibration environment file ' + state.calibpath+state.calibfile + ' exists.', $
' It will be overwritten, unless you choose to cancel and change', $
'the name of the file.' ]
con = qannounc( t, TITLE='File Overwrite Confirmation', $
FALSE='Cancel', TRUE='Overwrite File', XSIZE=70 )
IF NOT con THEN RETURN
ENDIF
GET_LUN, lu
OPENW, lu, state.calibpath+state.calibfile, ERROR=err
IF err NE 0 THEN BEGIN
; Something is wrong.
MESSAGE, !error_state.msg + STRING(7B), /INFO
RETURN
ENDIF
PRINTF, lu, state.okver[2]
PRINTF, lu, xl, xr, FORMAT='(2I5)'
PRINTF, lu, x1, x2, y1, y2, FORMAT='(4I5)'
PRINTF, lu, state.biasname
IF state.darkname eq '' then $
PRINTF, lu, '[none]' $
ELSE $
PRINTF, lu, state.darkname
WIDGET_CONTROL, state.flatbase, GET_UVALUE=flats, /NO_COPY
FOR j=1, N_ELEMENTS(flats)-1 DO BEGIN
PRINTF, lu, flats[j].filtercode + ' ' + flats[j].filename
ENDFOR
WIDGET_CONTROL, state.flatbase, SET_UVALUE=flats, /NO_COPY
CLOSE, lu
FREE_LUN, lu
state.calibflag = 0
MESSAGE, 'Calibration environment saved to file ' + $
state.calibpath+state.calibfile, /INFO
END
;<<<<<<<<<<<<<<<<<<<<<<<<< EVENT PROCESSING <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; ------------------------------------------------------------------------------
; Procedure ccdphot_it_eve
; Event handler for the cw_itool Top Level Base.
; This procedure follows my method for handling events from alternate Top
;Level Bases defined within a widget application. The user-value of the TLB
;contains pointers that allow the handler to access other data that are
;maintained in the host application.
; At this time, the only event arriving from this base is the exit event
;generated by cw_itool. The event has the following structure:
; {id:0L, top:0L, handler:0L, phedit:0B, tpedit:0B}
; ------------------------------------------------------------------------------
PRO ccdphot_it_eve, event
WIDGET_CONTROL, event.id, /HOURGLASS
bel = STRING( 7B )
;Get the TLB state structure.
WIDGET_CONTROL, event.top, GET_UVALUE=topstate, /NO_COPY
;Use the pointer to access the main state of ccdphot.
WIDGET_CONTROL, topstate.mainstash, GET_UVALUE=state, /NO_COPY
tmsg = [ '\\\\\\ WARNING //////' ]
IF event.phedit THEN BEGIN
tmsg = [ tmsg, $
'PHOTOMETRY parameter changes have not been saved.' ]
ENDIF
IF event.tpedit THEN BEGIN
tmsg = [ tmsg, 'TEMPLATE changes have not been saved.' ]
ENDIF
tmsg = [ tmsg, 'Do you wish to quit Itool without saving these changes?' ]
con = 1
IF event.phedit OR event.tpedit THEN BEGIN
con = qannounc( tmsg, TITLE='Itool Exit Confirmation', YSIZE=6 )
ENDIF
IF con THEN BEGIN
cwitoolid = WIDGET_INFO( state.cwitoolbase, /CHILD )
WIDGET_CONTROL, state.cwitoolbase, MAP=0
WIDGET_CONTROL, cwitoolid, /DESTROY
ENDIF
WIDGET_CONTROL, topstate.mainstash, SET_UVALUE=state, /NO_COPY
WIDGET_CONTROL, event.top, SET_UVALUE=topstate, /NO_COPY
END
; ------------------------------------------------------------------------------
; Procedure ccdphot_edit_eve
; Event handler for Calibration Environment Parameters.
; This procedure follows my method for handling events from alternate Top
;Level Bases defined within a widget application. The user-value of the TLB
;contains pointers that allow the handler to access other data that are
;maintained in the host application.
; ------------------------------------------------------------------------------
PRO ccdphot_edit_eve, event
WIDGET_CONTROL, event.id, /HOURGLASS
bel = STRING( 7B )
;Get the TLB state structure.
WIDGET_CONTROL, event.top, GET_UVALUE=topstate, /NO_COPY
;Use the pointer to access the main state of ccdphot.
WIDGET_CONTROL, topstate.mainstash, GET_UVALUE=state, /NO_COPY
CASE event.id OF
state.biaspickid : BEGIN
IF state.calibpath NE '' THEN BEGIN
f = DIALOG_PICKFILE( GROUP=event.top, TITLE='Select Bias Frame', $
PATH=state.calibpath )
ENDIF ELSE BEGIN
f = DIALOG_PICKFILE( GROUP=event.top, TITLE='Select Bias Frame' )
ENDELSE
fn = STRTRIM( f, 2 )
IF fn NE '' THEN BEGIN
ccdphot_lb, state, fn
ccdphot_pr, state
ccdphot_di, state
state.calibflag = 1
ENDIF
END
state.darkpickid : BEGIN
IF state.calibpath NE '' THEN BEGIN
f = DIALOG_PICKFILE( GROUP=event.top, TITLE='Select Dark Frame', $
PATH=state.calibpath )
ENDIF ELSE BEGIN
f = DIALOG_PICKFILE( GROUP=event.top, TITLE='Select Dark Frame' )
ENDELSE
fn = STRTRIM( f, 2 )
IF fn NE '' THEN BEGIN
ccdphot_ld, state, fn
ccdphot_pr, state
ccdphot_di, state
state.calibflag = 1
ENDIF
END
state.biastextid : BEGIN
WIDGET_CONTROL, event.id, GET_VALUE=value
fn = STRTRIM( value[0], 2 )
IF fn NE '' THEN BEGIN
ccdphot_lb, state, fn
ccdphot_pr, state
ccdphot_di, state
state.calibflag = 1
ENDIF ELSE BEGIN
state.biasname = ''
WIDGET_CONTROL, state.biasptr, GET_UVALUE=biasframe, /NO_COPY
biasframe = 0
WIDGET_CONTROL, state.biasptr, SET_UVALUE=biasframe, /NO_COPY
MESSAGE, 'Bias frame set to zero (no bias).', /INFO
ENDELSE
END
state.darktextid : BEGIN
WIDGET_CONTROL, event.id, GET_VALUE=value
fn = STRTRIM( value[0], 2 )
IF fn NE '' THEN BEGIN
ccdphot_ld, state, fn
ccdphot_pr, state
ccdphot_di, state
state.calibflag = 1
ENDIF ELSE BEGIN
state.darkname = ''
WIDGET_CONTROL, state.darkptr, GET_UVALUE=darkframe, /NO_COPY
darkframe = 0
WIDGET_CONTROL, state.darkptr, SET_UVALUE=darkframe, /NO_COPY
MESSAGE, 'Dark frame set to zero (no dark).', /INFO
ENDELSE
END
state.dismissid : BEGIN
WIDGET_CONTROL, state.editbase, MAP=0
END
state.flatlistid : BEGIN
selected = event.index + 1
state.fselected = selected
WIDGET_CONTROL, state.flatpickid, SENSITIVE=1
WIDGET_CONTROL, state.flatbase, GET_UVALUE=flats, /NO_COPY
WIDGET_CONTROL, state.flattextid, SET_VALUE=flats[selected].filename, $
SENSITIVE=1
WIDGET_CONTROL, state.flatbase, SET_UVALUE=flats, /NO_COPY
END
state.flatpickid : BEGIN
WIDGET_CONTROL, state.flatbase, GET_UVALUE=flats, /NO_COPY
title = 'Select Flat Frame for Filter ' + $
flats[state.fselected].filtercode
WIDGET_CONTROL, state.flatbase, SET_UVALUE=flats, /NO_COPY
IF state.calibpath NE '' THEN BEGIN
f = DIALOG_PICKFILE(GROUP=event.top, TITLE=title, PATH=state.calibpath)
ENDIF ELSE BEGIN
f = DIALOG_PICKFILE( GROUP=event.top, TITLE=title )
ENDELSE
fn = STRTRIM( f, 2 )
IF fn NE '' THEN BEGIN
WIDGET_CONTROL, state.flatbase, GET_UVALUE=flats, /NO_COPY
flats[state.fselected].filename = fn
WIDGET_CONTROL, state.flattextid, SET_VALUE=fn
WIDGET_CONTROL, state.flatlistid, SET_VALUE=ccdphot_fmt(flats), $
SET_LIST_SELECT=state.fselected-1
WIDGET_CONTROL, state.flatbase, SET_UVALUE=flats, /NO_COPY
ccdphot_lf, state, state.fselected
ccdphot_pr, state
ccdphot_di, state
state.calibflag = 1
ENDIF
END
state.flattextid : BEGIN
WIDGET_CONTROL, event.id, GET_VALUE=value
fn = STRTRIM( value[0], 2 )
fullname=fn
if strmid(fullname,0,1) eq '+' then begin
fullname = state.calibpath + strmid(fn,1,strlen(fn)-1)
endif
IF fullname NE '' THEN BEGIN
IF exists( fullname ) THEN BEGIN
WIDGET_CONTROL, state.flatbase, GET_UVALUE=flats, /NO_COPY
flats[state.fselected].filename = fn
WIDGET_CONTROL, state.flatlistid, SET_VALUE=ccdphot_fmt(flats), $
SET_LIST_SELECT=state.fselected-1
WIDGET_CONTROL, state.flatbase, SET_UVALUE=flats, /NO_COPY
ccdphot_lf, state, state.fselected
ccdphot_pr, state
ccdphot_di, state
state.calibflag = 1
ENDIF ELSE BEGIN
WIDGET_CONTROL, state.flatbase, GET_UVALUE=flats, /NO_COPY
MESSAGE, 'File '+fn+' does not exist.'+bel, /INFO
WIDGET_CONTROL, event.id, $
SET_VALUE=flats[state.fselected].filename
WIDGET_CONTROL, state.flatbase, SET_UVALUE=flats, /NO_COPY
ENDELSE
ENDIF
END
state.overscanid : BEGIN
WIDGET_CONTROL, event.id, GET_VALUE=value
v = STRTRIM( value[0], 2 )
overscan = v
IF v EQ '' THEN BEGIN
state.xl = -1
state.xr = -1
state.overscan = ''
state.calibflag = 1
WIDGET_CONTROL, topstate.mainstash, SET_UVALUE=state, /NO_COPY
WIDGET_CONTROL, event.top, SET_UVALUE=topstate, /NO_COPY
RETURN
ENDIF
n1 = GETTOK( v, ':' )
n2 = GETTOK( v, ' ' )
xl = FIX( n1 )
xr = FIX( n2 )
calval, state.xsize, 0, xl, xr, errflg, $
BANNER='OVERSCAN: Error. Specified overscan is inconsistent with the ' + $
'established environment.', $
ISIZELAB='image frame x-size', $
CSIZELAB='', $
MLOWLAB='low limit of overscan region', $
MHIGHLAB='high limit of overscan region', $
DELTAMLAB='size of overscan region'
IF errflg THEN BEGIN
WIDGET_CONTROL, state.overscanid, SET_VALUE=state.overscan
WIDGET_CONTROL, topstate.mainstash, SET_UVALUE=state, /NO_COPY
WIDGET_CONTROL, event.top, SET_UVALUE=topstate, /NO_COPY
RETURN
ENDIF
state.overscan = overscan
state.xl = xl
state.xr = xr
IF state.processflag THEN BEGIN
ccdphot_pr, state
ccdphot_di, state
ENDIF
state.calibflag = 1
END
state.xrangeid : BEGIN
WIDGET_CONTROL, event.id, GET_VALUE=value
xrange = STRTRIM( value[0], 2 )
IF (xrange EQ '') OR (xrange EQ '*') THEN BEGIN
xrange = '*'
x1 = -1
x2 = -1
ENDIF ELSE BEGIN
v = xrange
n1 = GETTOK( v, ':' )
n2 = GETTOK( v, ' ' )
x1 = FIX( n1 )
x2 = FIX( n2 )
ENDELSE
calval, state.xsize, state.cxsize, x1, x2, errflg, $
BANNER='X-RANGE: Error. Specified X-range is inconsistent with the ' + $
'established environment.', $
ISIZELAB='image frame x-size', $
CSIZELAB='calibration frame x-size', $
MLOWLAB='low limit of cropping region x-range', $
MHIGHLAB='high limit of cropping region x-range', $
DELTAMLAB='size of cropping region x-range'
IF errflg THEN BEGIN
WIDGET_CONTROL, state.xrangeid, SET_VALUE=state.xrange
WIDGET_CONTROL, topstate.mainstash, SET_UVALUE=state, /NO_COPY
WIDGET_CONTROL, event.top, SET_UVALUE=topstate, /NO_COPY
RETURN
ENDIF
state.x1 = x1
state.x2 = x2
state.xrange = xrange
IF state.processflag THEN BEGIN
ccdphot_pr, state
ccdphot_di, state
ENDIF
state.calibflag = 1
END
state.yrangeid : BEGIN
WIDGET_CONTROL, event.id, GET_VALUE=value
yrange = STRTRIM( value[0], 2 )
IF (yrange EQ '') OR (yrange EQ '*') THEN BEGIN
yrange = '*'
y1 = -1
y2 = -1
ENDIF ELSE BEGIN
v = yrange
n1 = GETTOK( v, ':' )
n2 = GETTOK( v, ' ' )
y1 = FIX( n1 )
y2 = FIX( n2 )
ENDELSE
calval, state.ysize, state.cysize, y1, y2, errflg, $
BANNER='Y-RANGE: Error. Specified Y-range is inconsistent with the ' + $
'established environment.', $
ISIZELAB='image frame y-size', $
CSIZELAB='calibration frame y-size', $
MLOWLAB='low limit of cropping region y-range', $
MHIGHLAB='high limit of cropping region y-range', $
DELTAMLAB='size of cropping region y-range'
IF errflg GT 0 THEN BEGIN
WIDGET_CONTROL, state.yrangeid, SET_VALUE=state.yrange
WIDGET_CONTROL, topstate.mainstash, SET_UVALUE=state, /NO_COPY
WIDGET_CONTROL, event.top, SET_UVALUE=topstate, /NO_COPY
RETURN
ENDIF
state.y1 = y1
state.y2 = y2
state.yrange = yrange
IF state.processflag THEN BEGIN
ccdphot_pr, state
ccdphot_di, state
ENDIF
state.calibflag = 1
END
ELSE : BEGIN
MESSAGE, 'Unknown event:', /INFO
HELP, event, /STRUCTURE
END
ENDCASE
WIDGET_CONTROL, topstate.mainstash, SET_UVALUE=state, /NO_COPY
WIDGET_CONTROL, event.top, SET_UVALUE=topstate, /NO_COPY
END
; ------------------------------------------------------------------------------
; Procedure ccdphot_eve
; Main event handler for ccdphot (main buttons).
; ------------------------------------------------------------------------------
PRO ccdphot_eve, event
bel = STRING( 7B )
WIDGET_CONTROL, event.id, /HOURGLASS
stash = WIDGET_INFO( event.handler, /CHILD )
WIDGET_CONTROL, stash, GET_UVALUE=state, /NO_COPY
CASE event.id OF
;Calibration environment file events.
state.calpickid : BEGIN
f = DIALOG_PICKFILE( GROUP=event.top, TITLE='Select Calibration File', $
PATH=state.calibpath )
fn = STRTRIM( f, 2 )
IF fn NE '' THEN BEGIN
state.calibfile = fn
WIDGET_CONTROL, state.caltextid, SET_VALUE=fn
ENDIF
END
state.calloadid : BEGIN
ccdphot_lc, state
END
state.calsaveid : BEGIN
ccdphot_sc, state
END
state.caltextid : BEGIN
WIDGET_CONTROL, event.id, GET_VALUE=value
f = STRTRIM( value[0], 2 )
state.calibfile = f
MESSAGE, 'Calibration file set to ' + f, /INFO
END
state.editid : BEGIN
WIDGET_CONTROL, state.editbase, /REALIZE, /MAP
END
;Main button widgets.
state.exitid : BEGIN
valid = WIDGET_INFO( state.cwitoolbase, /VALID_ID )
IF valid THEN BEGIN
WIDGET_CONTROL, state.cwitoolid, GET_VALUE=status
ENDIF ELSE BEGIN
status = {msg:''}
ENDELSE
tmsg = ['']
IF state.calibflag THEN BEGIN
tmsg = [ tmsg, $
'Calibration environment changes have not been saved.' ]
ENDIF
tmsg = [ tmsg, '****************************************', $
'Do you really wish to quit CCDPHOT?' ]
con = qannounc( [status.msg,tmsg], TITLE=' CCDPHOT Exit Confirmation', $
XSIZE=60, YSIZE=6 )
IF con THEN BEGIN
;Bye.
WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
WIDGET_CONTROL, event.top, /DESTROY
RETURN
ENDIF
END
;Image file events.
state.impickid : BEGIN
print,'CCDPHOT: ',state.impath
IF state.impath NE '' THEN BEGIN
f = DIALOG_PICKFILE( GROUP=event.top, TITLE='Select Image Frame', $
PATH=state.impath )
ENDIF ELSE BEGIN
f = DIALOG_PICKFILE( GROUP=event.top, TITLE='Select Image Frame' )
ENDELSE
fn = STRTRIM( f, 2 )
IF fn NE '' THEN BEGIN
WIDGET_CONTROL, state.imtextid, SET_VALUE=fn
ccdphot_li, state, fn
ENDIF
END
state.imtextid : BEGIN
WIDGET_CONTROL, event.id, GET_VALUE=value
fn = STRTRIM( value[0], 2 )
IF fn NE '' THEN BEGIN
ccdphot_li, state, fn
ENDIF ELSE BEGIN
IF state.imfile NE '' THEN BEGIN
WIDGET_CONTROL, state.imtextid, SET_VALUE=state.imfile
ENDIF
ENDELSE
END
state.rawproid : BEGIN
;Raw/Processed toggle event.
state.processflag = event.value
ccdphot_pr, state
ccdphot_di, state
END
state.nextid : BEGIN
IF state.imfile NE '' THEN BEGIN
f = state.imfile
l = STRLEN( f )
ext = STRMID( f, l-3, 3 )
bext = BYTE( ext )
t = WHERE( bext LT 48 AND bext GT 57, count )
IF count EQ 0 THEN BEGIN
next = STRING( FIX( ext ) + 1, FORMAT='(I3.3)' )
STRPUT, f, next, l-3
ccdphot_li, state, f
IF state.imfile EQ f THEN BEGIN
WIDGET_CONTROL, state.imtextid, SET_VALUE=f
ENDIF
ENDIF
ENDIF ELSE BEGIN
MESSAGE, 'Error. No image.' + bel, /INFO
ENDELSE
END
state.previd : BEGIN
IF state.imfile NE '' THEN BEGIN
f = state.imfile
l = STRLEN( f )
ext = STRMID( f, l-3, 3 )
bext = BYTE( ext )
t = WHERE( bext LT 48 AND bext GT 57, count )
IF count EQ 0 THEN BEGIN
newnum = FIX( ext ) - 1
IF newnum GE 0 THEN BEGIN
next = STRING( newnum, FORMAT='(I3.3)' )
STRPUT, f, next, l-3
ccdphot_li, state, f
IF state.imfile EQ f THEN BEGIN
WIDGET_CONTROL, state.imtextid, SET_VALUE=f
ENDIF
ENDIF ELSE BEGIN
MESSAGE, 'Error. Nothing before frame 0.' + bel, /INFO
ENDELSE
ENDIF
ENDIF ELSE BEGIN
MESSAGE, 'Error. No image.' + bel, /INFO
ENDELSE
END
state.autoid : BEGIN
IF state.imfile NE '' THEN BEGIN
sameobject = 0
fwhmok = 0
magok = 0
fail = 1
fileok = 0
firstpass=1
thisframe = -1
lastframe = -2
REPEAT BEGIN
WIDGET_CONTROL, state.cwitoolid, GET_VALUE=it_info
lasttype = it_info.lasttype
lastpos = it_info.lastpos
object = it_info.object
lastfwhm = it_info.lastfwhm
lastmag = it_info.lastmag
IF it_info.lasttype NE 0 THEN BEGIN
IF firstpass THEN BEGIN
ok=qannounc( GROUP=event.top, [ $
'This command will automatically proceed through the data with the same', $
'photometry extraction as done on the last frame. By default, this process', $
'will continue until the object name changes, or, there is no more data.', $
'If this is what you wish to do, then select "Stop on Last". However, you', $
'might want to stop on a certain frame number. If you do want to stop on', $
'a certain frame number, then select "Set Stop Point". If you choose the', $
'latter option, you will be asked for the desired stopping point. However,', $
'a changing object name will take precedence over a stop point. So, if you', $
'set a stop point after the object changes, it will stop earlier than you', $
'think.' $
], XSIZE=80, YSIZE=10, TITLE='Automatic Photometry Procedure', $
TRUELABEL='Stop on Last', FALSELABEL='Set Stop Point' )
if ok then $
lastframe=999 $
else $
lastframe=qinput(prompt='Frame number to stop on?',/integer)
firstpass=0
ENDIF
f = state.imfile
l = STRLEN( f )
ext = STRMID( f, l-3, 3 )
bext = BYTE( ext )
t = WHERE( bext LT 48 AND bext GT 57, count )
IF count EQ 0 THEN BEGIN
thisframe = FIX(ext)+1
next = STRING( thisframe, FORMAT='(I3.3)' )
STRPUT, f, next, l-3
ccdphot_li, state, f, AUTOPHOT=object, $
PHOTTYPE=lasttype, POSITION=lastpos
IF state.imfile EQ f THEN BEGIN
WIDGET_CONTROL, state.imtextid, SET_VALUE=f
WIDGET_CONTROL, state.cwitoolid, GET_VALUE=it_info
sameobject = (it_info.object EQ object)
magok = (abs(it_info.lastmag-lastmag) LT 10.0)
fwhmok = (abs(it_info.lastfwhm-lastfwhm)/lastfwhm LT 0.5 )
fail = 0
fileok = 1
ENDIF ELSE BEGIN
sameobject = 0
fileok = 0
magok = 0
fwhmok = 0
ENDELSE
ENDIF ELSE BEGIN
thisframe=-1
MESSAGE,' Filename cannot be incremented. Unable to run Auto-photometry.'+bel,/INFO
ENDELSE
ENDIF ELSE BEGIN
MESSAGE,'Cannot do auto-photometry.'+bel,/INFO
MESSAGE,' No position has yet been defined for this object.',/INFO
lastframe=thisframe
ENDELSE
ENDREP UNTIL NOT sameobject OR lastframe EQ thisframe OR NOT magok OR NOT fwhmok
IF NOT fail THEN BEGIN
IF NOT fileok THEN $
MESSAGE,' Auto-photometry halted. Next file incomplete or missing.' + bel, /INFO $
ELSE IF NOT sameobject THEN $
MESSAGE,' Auto-photometry halted. Object changed.' + bel, /INFO $
ELSE IF thisframe GE lastframe THEN $
MESSAGE,' Auto-photometry halted. Stopping point reached.' + bel, /INFO $
ELSE IF NOT magok THEN $
MESSAGE,' Auto-photometry halted. Magnitude of object changed too much.' + bel, /INFO $
ELSE IF NOT fwhmok THEN $
MESSAGE,' Auto-photometry halted. FWHM of object changed too much.' + bel, /INFO $
ELSE $
MESSAGE,' Unknown ending condition for Auto, this should not happen.' + bel, /INFO
ENDIF
ENDIF ELSE BEGIN
MESSAGE, 'Error. No image.' + bel, /INFO
ENDELSE
END
state.vheaderid : BEGIN
IF state.imfile NE '' THEN BEGIN
WIDGET_CONTROL, event.id, GET_UVALUE=header
t = 'Image Header' + ' - file ' + state.imfile
viewtext, header, GROUP=event.top, TITLE=t, XSIZE=81, YSIZE=40
ENDIF ELSE BEGIN
MESSAGE, 'Error. No image.' + bel, /INFO
ENDELSE
END
state.wfitsid : BEGIN
;Write the image to a FITS file( allows a calibrated image to be saved).
IF state.imfile NE '' THEN BEGIN
;There is an image loaded. Do it.
WIDGET_CONTROL, state.dimgptr, GET_UVALUE=image, /NO_COPY
WIDGET_CONTROL, state.imparmsptr, GET_UVALUE=im_parms, /NO_COPY
WIDGET_CONTROL, state.vheaderid, GET_UVALUE=header, /NO_COPY
filename = 'c_' + im_parms.imfile
writefits, filename, image, header
MESSAGE, 'Image saved to file ' + filename, /INFO
WIDGET_CONTROL, state.vheaderid, SET_UVALUE=header, /NO_COPY
WIDGET_CONTROL, state.imparmsptr, SET_UVALUE=im_parms, /NO_COPY
WIDGET_CONTROL, state.dimgptr, SET_UVALUE=image, /NO_COPY
ENDIF
END
ELSE : BEGIN
MESSAGE, 'Unknown event:', /INFO
HELP, event, /STRUCTURE
END
ENDCASE
WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
END
; ------------------------------------------------------------------------------
; Procedure ccdphot
; Where it begins.
; ------------------------------------------------------------------------------
PRO ccdphot, CALIBFILE=in_calibfile, CALIBPATH=in_calibpath, $
KEYLIST=in_keylist, $
PATH=in_path, PHOTPARMFILE=in_photparmfile, $
TMPLFILE=in_tmplfile, WZOOMFACT=wzoomfact
bel = STRING( 7B )
IF XREGISTERED( 'ccd' ) THEN RETURN
IF (!d.flags AND 256) EQ 0 THEN BEGIN
MESSAGE, 'Error. No windowing device. CCDPHOT cannot be started.', /INFO
RETURN
ENDIF
IF badpar(wzoomfact,[0,1,2,3],0, $
CALLER='CCDPHOT: (wzoomfact) ',DEFAULT=0) THEN RETURN
IF badpar(in_path,[0,7],0, $
CALLER='CCDPHOT: (path) ',DEFAULT='') THEN RETURN
if in_path ne '' then in_path=addslash(in_path)
IF badpar(in_calibpath,[0,7],0, $
CALLER='CCDPHOT: (calibpath) ',DEFAULT=in_path+'calib/') THEN RETURN
in_calibpath=addslash(in_calibpath)
IF badpar(in_calibfile,[0,7],0, $
CALLER='CCDPHOT: (calibfile) ',DEFAULT='files.cal') THEN RETURN
IF badpar(in_photparmfile,[0,7],0, $
CALLER='CCDPHOT: (photparmfile) ',DEFAULT='') THEN RETURN
IF badpar(in_tmplfile,[0,7],0, $
CALLER='CCDPHOT: (tmplfile) ',DEFAULT='') THEN RETURN
; Initialize the main state structure.
state = { $
biasname:'', $
biaspickid:0L, $
biasptr:0L, $
biastextid:0L, $
calibfile:in_calibfile, calibflag:0, calibpath:in_calibpath, $
calloadid:0L, $
calpickid:0L, $
calsaveid:0L, $
caltextid:0L, $
cimgptr:0L, $
cwitoolbase:0L, cwitoolid:0L, $
cxsize:0, cysize:0, $
darkname:'', $
darkpickid:0L, $
darkptr:0L, $
darktextid:0L, $
dimgptr:0L, $
editbase:0L, $
dismissid:0L, $
editid:0L, $
exitid:0L, $
flatbase:0L, $
flatbase1:0L, $
flathandid:0L, $
flatindex:0, $
flatlistid:0L, $
flatpickid:0L, $
flattextid:0L, $
fselected:0, $
hdrlistptr:0L, $
imfile:'', $
imparmsptr:0L, $
impath:in_path, $
impickid:0L, $
imtextid:0L, $
kill:0B, $
mainbase:0L, $
new:1B, $
previd:0L, $
nextid:0L, $
nframes:0L, $
okver:[ 'calib_file_v01', 'calib_file_v02', 'calib_file_v03' ], $
overscan:'', $
overscanid:0L, $
photparmfile:in_photparmfile, $
processflag:1, $
autoid:0L, $
pxsize:0, pysize:0, $
rawproid:0L, $
rimgptr:0L, $
tmplfile:in_tmplfile, $
vheaderid:0L, $
wfitsid:0L, $
wzoomfact:wzoomfact, $
xl:-1, xr:-1, $
x1:-1, x2:-1, y1:-1, y2:-1, $
xrange:'*', xrangeid:0L, $
yrange:'*', yrangeid:0L, $
xsize:0, $
ysize:0 }
; Get header correspondence list.
IF KEYWORD_SET( in_keylist ) THEN $
loadkeys,in_keylist,hdrlist $
ELSE $
loadkeys,'[[DEFAULT]]',hdrlist
;Define the main base.
mainbase = WIDGET_BASE( TITLE='CCDPHOT', /COLUMN, UVALUE=0 )
state.mainbase = mainbase
state.imparmsptr = mainbase
;Main button base.
b1 = WIDGET_BASE( mainbase, /ROW, /FRAME )
state.exitid = WIDGET_BUTTON( b1, VALUE='Exit' )
state.rawproid = cw_bgroup( b1, ['Raw', 'Processed'], /EXCLUSIVE, $
/NO_RELEASE, /ROW, SET_VALUE=state.processflag )
state.previd = WIDGET_BUTTON( b1, VALUE='Prev' )
state.nextid = WIDGET_BUTTON( b1, VALUE='Next' )
state.autoid = WIDGET_BUTTON( b1, VALUE='Auto' )
state.vheaderid = WIDGET_BUTTON( b1, VALUE='ViewHeader', UVALUE='' )
state.wfitsid = WIDGET_BUTTON( b1, VALUE='Write Fits' )
;Image select base.
imagebase = WIDGET_BASE( mainbase, /ROW, /FRAME, UVALUE=0 )
w1 = WIDGET_LABEL( imagebase, VALUE='IMAGE FRAME:', UVALUE=hdrlist )
state.impickid = WIDGET_BUTTON( imagebase, VALUE='Select File' )
state.imtextid = WIDGET_TEXT( imagebase, VALUE=state.imfile, /EDITABLE, $
XSIZE=40 )
;The header list is stored in the user-value of this base.
state.hdrlistptr = w1
state.rimgptr = imagebase
;
;Calibration environment file base.
calbase = WIDGET_BASE( mainbase, /COLUMN, /FRAME, UVALUE=0 )
w1 = WIDGET_LABEL( calbase, VALUE='CALIBRATION ENVIRONMENT' )
b2 = WIDGET_BASE( calbase, /ROW )
state.calloadid = WIDGET_BUTTON( b2, VALUE='Load' )
state.calsaveid = WIDGET_BUTTON( b2, VALUE='Save' )
state.editid = WIDGET_BUTTON( b2, VALUE='Edit' )
state.calpickid = WIDGET_BUTTON( b2, VALUE='Select File' )
state.caltextid = WIDGET_TEXT( b2, VALUE=state.calibfile, /EDITABLE, XSIZE=40 )
;
state.cimgptr = calbase
; -------------------------------------------------
;The remaining widgets are based on a separate Top Level Base. This base
;is used to invoke a widget hierarchy which permits the calibration
;environment parameters to be edited. A separate event handler is associated
;with this TLB and follows my method for TLB event handlers (state retrieval
;information is stored in the user-value of the TLB).
state.editbase = WIDGET_BASE( TITLE='CCDPHOT Calibration Environment Editor', $
COLUMN=1 )
XMANAGER, '', state.editbase, EVENT_HANDLER='ccdphot_edit_eve', $
GROUP_LEADER=mainbase, /JUST_REG
state.dismissid = WIDGET_BUTTON( state.editbase, VALUE='Dismiss' )
;Overscan region base.
overbase = WIDGET_BASE( state.editbase, ROW=1, FRAME=1 )
w1 = WIDGET_LABEL( overbase, VALUE='BIAS/OVERSCAN REGION:' )
state.overscanid = WIDGET_TEXT( overbase, VALUE=state.overscan, /EDITABLE, $
XSIZE=40 )
;Cropping region base.
cropbase = WIDGET_BASE( state.editbase, /ROW, /FRAME )
w1 = WIDGET_LABEL( cropbase, VALUE='CROPPING REGION: x-range' )
state.xrangeid = WIDGET_TEXT(cropbase, VALUE=state.xrange, /EDITABLE, XSIZE=9 )
w1 = WIDGET_LABEL( cropbase, VALUE=' y-range' )
state.yrangeid = WIDGET_TEXT(cropbase, VALUE=state.yrange, /EDIT, XSIZE=9 )
;Biasframe base. The bias frame array will be stored in the user-value and
;is initialized to 0.0.
biasbase = WIDGET_BASE( state.editbase, /ROW, /FRAME, UVALUE=0 )
w1 = WIDGET_LABEL( biasbase, VALUE='BIAS FRAME:' )
state.biaspickid = WIDGET_BUTTON( biasbase, VALUE='Select File' )
state.biastextid = WIDGET_TEXT( biasbase, VALUE='', /EDIT, XSIZE=40 )
state.biasptr = biasbase
;Darkframe base. The dark frame array will be stored in the user-value and
;is initialized to 0.0.
darkbase = WIDGET_BASE( state.editbase, /ROW, /FRAME, UVALUE=0 )
w1 = WIDGET_LABEL( darkbase, VALUE='DARK FRAME:' )
state.darkpickid = WIDGET_BUTTON( darkbase, VALUE='Select File' )
state.darktextid = WIDGET_TEXT( darkbase, VALUE='', /EDIT, XSIZE=40 )
state.darkptr = darkbase
;Flat frames base.
flats = {filtercode:'None', filename:'', flatid:WIDGET_BASE(UVALUE=1.0, $
GROUP_LEADER=mainbase)}
state.flatbase = WIDGET_BASE( state.editbase, /COLUMN, UVALUE=flats )
w1 = WIDGET_LABEL( state.flatbase, VALUE='LIST OF FLATS (filtercode filename)')
;Set-up the flats list widget.
state.flatlistid = WIDGET_LIST( state.flatbase, YSIZE=5 )
w1 = WIDGET_LABEL( state.flatbase, VALUE='Change Filename of Selected Flat:' )
b1 = WIDGET_BASE( state.flatbase, ROW=1 )
state.flatpickid = WIDGET_BUTTON( b1, VALUE='Select File' )
state.flattextid = WIDGET_TEXT( b1, VALUE='', /EDITABLE, XSIZE=40 )
WIDGET_CONTROL, state.flatpickid, SENSITIVE=0
WIDGET_CONTROL, state.flattextid, SENSITIVE=0
IF state.calibfile NE '' THEN BEGIN
;Call the calibration file load routine.
ccdphot_lc, state
;Display the list of flats.
WIDGET_CONTROL, state.flatbase, GET_UVALUE=flats, /NO_COPY
WIDGET_CONTROL, state.flatlistid, SET_VALUE=ccdphot_fmt(flats)
WIDGET_CONTROL, state.flatbase, SET_UVALUE=flats, /NO_COPY
ENDIF
;Stash area for the state structure.
stash = WIDGET_INFO( mainbase, /CHILD )
;Put the stash pointer into the edit TLB, so its event handler can access
;the main state.
WIDGET_CONTROL, state.editbase, SET_UVALUE={mainstash:stash}
;Stash the state structure.
WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
;Realize the main base.
WIDGET_CONTROL, mainbase, /REALIZE
; Give control to the XMANAGER.
XMANAGER, 'ccdphot', mainbase, $
EVENT_HANDLER='ccdphot_eve', $
GROUP_LEADER=mainbase
END