;+ ; $Id: sunloop.pro,v 1.5 2012/03/01 16:44:29 nathan Exp $ ; ; User Guide: $SSW/stereo/secchi/idl/display/sunloop/sunloop_user_guide.pdf ; ; Project: STEREO/SECCHI ; ; Name: SUNLOOP ; ; Purpose: Front-end to tiepointer and scc_triangulate programs. ; ; Category: STEREO, SECCHI, CME reconstruction, display ; ; Explanation: This IDL program provides a GUI for selecting image pairs ; by Detector, Wavelength, Date and Time. Additionally, ; images can be rotated to the stereo baseline, calibrated ; with SECCHI_PREP. Backgrounds are removed from COR and HI. ; Images are processed and passed to the tiepointer IDL program. ; The tiepointer (a separate IDL program) allows selection ; of a point on a feature in the left and right images, and ; passes that to scc_triangulate. The tiepointer program ; then passes the resulting to the line3d program for display. ; ; Syntax: sunloop ; or ; sunloop, [left_filename, right_filename, XY_FILENAME=xy_filename, /NO_SUNLOOP_GUI, /NO_SECCHI_PREP] ; ; Examples: Primary usage with GUI interface: ; (no paramaters, data is accessed from $secchi) ; ; sunloop ; ; Secondary usage for command line or scripting: ; (inputs are filenames in local directory) ; ; sunloop, '20071116_143754_d4c2A.fts', '20071116_143754_d4c2A.fts' ; ; sunloop, '20071116_143754_d4c2A.fts', '20071116_143754_d4c2A.fts', XY_FILENAME=tiepoints_20071116_143754_d4c2A.fts_saved_20080415_142136.xy ; ; Inputs: Optionally may give "A" and "B" filenames so that software ; can be used with local data files when $secchi is unavailable, ; especially useful on laptops. ; ; Outputs: All outputs are passed to the tiepointer IDL program, which generates tiepoint (xy) and xyz files. ; ; Keywords: XY_FILENAME - Name of existing tiepoint file that will be loaded in tiepointer. ; NO_SUNLOOP_GUI - Bring up tiepointer without sunloop gui. ; NO_SECCHI_PREP - Disable SECCHI_PREP (not recommended.) ; ; Calls: IS_FITS, SCCREADFITS, SCC_IMG_TRIM, EUVI_POINT, COR1_POINT, COR2_POINT, ; HI_CALIB_POINT, SCC_STEREOPAIR, SCC_ROLL_IMAGE, FITSHEAD2WCS, ; SCC_GETBKGIMG, COR1_TOTALB ; ; Common: $secchi environment variable ; ; Restrictions: Solarsoft required. ; Works for STEREO Ahead and Behind synchronized image pairs. ; ; written by: Jeffrey.R.Hall@jpl.nasa.gov ; written for: Paulett.C.Liewer@jpl.nasa.gov ; STEREO/SECCHI Project ; ; "Copyright 2012, by the California Institute of Technology. ; ALL RIGHTS RESERVED. United States Government Sponsorship ; acknowledged. Any commercial use must be negotiated with the ; Office of Technology Transfer at the California Institute of ; Technology. ; This software may be subject to U.S. export control laws. ; By accepting this software, the user agrees to comply with ; all applicable U.S. export laws and regulations. User has ; the responsibility to obtain export licenses, or other ; export authority as may be required before exporting such ; information to foreign countries or providing access to ; foreign persons." ;- @tiepointer.pro @sunloop_correct_euvi_point.pro PRO fireup_tiepointer, varstruct ;------------------------------------------------------- ; Set up task progress labels. ;------------------------------------------------------- temp_base=WIDGET_BASE(/COLUMN,GROUP_LEADER=varstruct.sunloop_tlb,TITLE='TASK LIST') temp_label0a=WIDGET_LABEL(temp_base,VALUE=STRING('n')+' x '+STRING('n'),/DYNAMIC_RESIZE) temp_label0b=WIDGET_LABEL(temp_base,VALUE=STRING('n')+' x '+STRING('n'),/DYNAMIC_RESIZE) temp_label=WIDGET_LABEL(temp_base,VALUE='') IF varstruct.calibrate EQ 'yes' THEN BEGIN temp_label1a=WIDGET_LABEL(temp_base,VALUE=' CALIBRATION',/ALIGN_LEFT,/DYNAMIC_RESIZE) ENDIF ELSE BEGIN temp_label1=WIDGET_LABEL(temp_base,VALUE=' SCCREADFITS, SCC_IMG_TRIM, and *_POINT',/ALIGN_LEFT,/DYNAMIC_RESIZE) ENDELSE IF (varstruct.rotate EQ 'to stereo baseline') THEN BEGIN IF (varstruct.detector EQ 'hi_1') OR (varstruct.detector EQ 'hi_2') THEN BEGIN temp_label3a=WIDGET_LABEL(temp_base,VALUE=' ROTATE LEFT IMAGE',/ALIGN_LEFT,/DYNAMIC_RESIZE) temp_label3b=WIDGET_LABEL(temp_base,VALUE=' ROTATE RIGHT IMAGE',/ALIGN_LEFT,/DYNAMIC_RESIZE) ENDIF ELSE BEGIN temp_label3=WIDGET_LABEL(temp_base,VALUE=' SCC_STEREOPAIR',/ALIGN_LEFT,/DYNAMIC_RESIZE) ENDELSE ENDIF temp_label5=WIDGET_LABEL(temp_base,VALUE=' START TIEPOINTER',/ALIGN_LEFT,/DYNAMIC_RESIZE) WIDGET_CONTROL,temp_base,/REALIZE IF SIZE(varstruct.stereo_b_image,/TYPE) EQ 7 THEN BEGIN ;------------------------------------------------------- ; Filenames. ;------------------------------------------------------- junk=SCCREADFITS(varstruct.stereo_b_image, left_junk_hdr, /NODATA ) junk=SCCREADFITS(varstruct.stereo_a_image,right_junk_hdr, /NODATA ) left_filename = varstruct.stereo_b_image right_filename = varstruct.stereo_a_image ENDIF ELSE BEGIN left_junk_hdr = varstruct.stereo_b_header right_junk_hdr = varstruct.stereo_a_header left_filename = left_junk_hdr.FILENAME right_filename = right_junk_hdr.FILENAME ENDELSE left_naxis1 = left_junk_hdr.NAXIS1 left_naxis2 = left_junk_hdr.NAXIS2 right_naxis1=right_junk_hdr.NAXIS1 right_naxis2=right_junk_hdr.NAXIS2 WIDGET_CONTROL,temp_label0a,SET_VALUE='left: '+STRTRIM(left_naxis1,2)+' x '+STRTRIM(left_naxis2,2) WIDGET_CONTROL,temp_label0b,SET_VALUE='right: '+STRTRIM(right_naxis1,2)+' x '+STRTRIM(right_naxis2,2) ;------------------------------------------------------- ; Initialize structure for values not in SECCHI header. ;------------------------------------------------------- left_secchistruct = { default_min:0.0d, $ default_max:0.0d, $ suncenter_xy: dblarr(2), $ mercury_xy: dblarr(2), $ venus_xy: dblarr(2), $ earth_xy: dblarr(2), $ mars_xy: dblarr(2), $ jupiter_xy: dblarr(2), $ saturn_xy: dblarr(2), $ neptune_xy: dblarr(2), $ uranus_xy: dblarr(2), $ optax_xy: dblarr(2), $ distance: 0.0d, $ solar_north_angle: 0.0d, $ focal_length_in_pixels: dblarr(2) } right_secchistruct = left_secchistruct ;------------------------------------------------------- ; Read the data. Calibrate if requested. ;------------------------------------------------------- CASE varstruct.calibrate OF 'no' : BEGIN IF WIDGET_INFO(temp_base,/VALID_ID) THEN BEGIN WIDGET_CONTROL,temp_label1,SET_VALUE='-> SCCREADFITS, SCC_IMG_TRIM, and *_POINT' ENDIF IF SIZE(varstruct.stereo_b_image,/TYPE) EQ 7 THEN BEGIN ; Input is filename. left_img = SCCREADFITS( left_filename, left_hdr,/SILENT) left_img = SCC_IMG_TRIM( left_img, left_hdr) ENDIF ELSE BEGIN ; Input is image array. left_img = varstruct.stereo_b_image left_hdr = varstruct.stereo_b_header ENDELSE CASE varstruct.detector OF 'euvi' : EUVI_POINT, left_hdr 'cor1' : COR1_POINT, left_hdr 'cor2' : COR2_POINT, left_hdr 'hi_1' : HI_CALIB_POINT, left_hdr 'hi_2' : HI_CALIB_POINT, left_hdr ENDCASE IF SIZE(varstruct.stereo_a_image,/TYPE) EQ 7 THEN BEGIN ; Input is filename. right_img = SCCREADFITS(right_filename,right_hdr,/SILENT) right_img = SCC_IMG_TRIM(right_img,right_hdr) ENDIF ELSE BEGIN ; Input is image array. right_img = varstruct.stereo_a_image right_hdr = varstruct.stereo_a_header ENDELSE CASE varstruct.detector OF 'euvi' : EUVI_POINT, right_hdr 'cor1' : COR1_POINT, right_hdr 'cor2' : COR2_POINT, right_hdr 'hi_1' : HI_CALIB_POINT,right_hdr 'hi_2' : HI_CALIB_POINT,right_hdr ENDCASE IF WIDGET_INFO(temp_base,/VALID_ID) THEN BEGIN WIDGET_CONTROL,temp_label1,SET_VALUE=' SCCREADFITS, SCC_IMG_TRIM, and *_POINT',SENSITIVE=0 ENDIF END 'yes' : BEGIN IF WIDGET_INFO(temp_base,/VALID_ID) THEN BEGIN WIDGET_CONTROL,temp_label1a,SET_VALUE='-> CALIBRATION' ENDIF ; Check varstruct.stereo_b_image is an image filename or an image array. IF SIZE(varstruct.stereo_b_image,/TYPE) NE 7 THEN BEGIN ;------------------------------------------------------- ; varstruct.stereo_b_image is an image array. ; Usually passed to sunloop on the command line as ; image array pair which allows tiepointing PNG TIF JPG ; images that have been pre-processed. Special case! ;------------------------------------------------------- left_img = varstruct.stereo_b_image left_hdr = varstruct.stereo_b_header right_img = varstruct.stereo_a_image right_hdr = varstruct.stereo_a_header ENDIF ELSE BEGIN ;------------------------------------------------------- ; varstruct.stereo_b_image is an image filename. ;------------------------------------------------------- IF STRMID(varstruct.detector,0,3) EQ 'cor' AND STRPOS(FILE_DIRNAME(varstruct.stereo_b_image),'/seq/') GE 0 THEN BEGIN ;------------------------------------------------------- ; Start time. ;------------------------------------------------------- start_time=STRMID(FILE_BASENAME(varstruct.stereo_b_image),0,15) ; Subtract one minute to ensure the start time is not skipped over. jd_start=(ANYTIM2JD(start_time)).(0) + (ANYTIM2JD(start_time)).(1) jd_start=jd_start - (1.0/60./24.) caldat,jd_start,mon,day,year,hhh,min year=STRTRIM(year,2) IF mon LT 10 THEN mon='0'+STRTRIM(mon,2) ELSE mon=STRTRIM(mon,2) IF day LT 10 THEN day='0'+STRTRIM(day,2) ELSE day=STRTRIM(day,2) IF hhh LT 10 THEN hhh='0'+STRTRIM(hhh,2) ELSE hhh=STRTRIM(hhh,2) IF min LT 10 THEN min='0'+STRTRIM(min,2) ELSE min=STRTRIM(min,2) start_time=year+mon+day+'_'+hhh+min+'00' ;------------------------------------------------------- ; End time. ;------------------------------------------------------- jd_start=(ANYTIM2JD(start_time)).(0) + (ANYTIM2JD(start_time)).(1) ; Add ten minutes to make sure that the time range in COR1_TOTALB captures at least one complete set of polarized images. jd_end=jd_start + (10.0/60./24.) caldat,jd_end,mon,day,year,hhh,min year=STRTRIM(year,2) IF mon LT 10 THEN mon='0'+STRTRIM(mon,2) ELSE mon=STRTRIM(mon,2) IF day LT 10 THEN day='0'+STRTRIM(day,2) ELSE day=STRTRIM(day,2) IF hhh LT 10 THEN hhh='0'+STRTRIM(hhh,2) ELSE hhh=STRTRIM(hhh,2) IF min LT 10 THEN min='0'+STRTRIM(min,2) ELSE min=STRTRIM(min,2) end_time=year+mon+day+'_'+hhh+min+'00' GOTO,SKIP_CHECK_COMPLETE_SERIES_PROCESS ;incorrect implementation, needs work. ;only rare cases where series is incomplete, usually most recent data where processing at NRL not yet complete. ; Error check that a complete series exists. CASE varstruct.detector OF 'cor1' : list = COR1_TOTBSERIES(date, 'combined') 'cor2' : list = COR1_TOTBSERIES(date, 'combined', /COR2) ENDCASE IF N_ELEMENTS(list) GT 1 THEN BEGIN ; 3-series FOR j=0,2 DO BEGIN ; STEREO-A, STEREO-B FOR k=0,1 DO BEGIN ; First entry (0). IF FINDFILE((list.filename)[j,0,k]) EQ '' THEN BEGIN ddddd=DIALOG_MESSAGE(['Incomplete series for this image time.',STRMID(FILE_BASENAME(varstruct.stereo_b_image),0,15),'Please select a different image time.']) IF WIDGET_INFO(temp_base,/VALID_ID) THEN BEGIN WIDGET_CONTROL,temp_base,/DESTROY ENDIF RETURN ENDIF ENDFOR ENDFOR ENDIF SKIP_CHECK_COMPLETE_SERIES_PROCESS: IF (left_naxis1 EQ right_naxis1) THEN BEGIN CASE varstruct.detector OF 'cor1' : COR1_TOTALB, [start_time, end_time], 'Combined', headers, images 'cor2' : COR1_TOTALB, [start_time, end_time], 'Combined', headers, images, /COR2 ENDCASE ENDIF ELSE BEGIN osize=MIN([left_naxis1,right_naxis1]) WIDGET_CONTROL,temp_label0a,SET_VALUE='left: '+STRTRIM( left_naxis1,2)+' x '+STRTRIM( left_naxis2,2)+' (OUTSIZE='+STRTRIM(osize,2)+')' WIDGET_CONTROL,temp_label0b,SET_VALUE='right: '+STRTRIM(right_naxis1,2)+' x '+STRTRIM(right_naxis2,2)+' (OUTSIZE='+STRTRIM(osize,2)+')' CASE varstruct.detector OF 'cor1' : COR1_TOTALB, [start_time, end_time], 'Combined', headers, images, OUTSIZE=osize 'cor2' : COR1_TOTALB, [start_time, end_time], 'Combined', headers, images, OUTSIZE=osize, /COR2 ENDCASE ENDELSE ; Error check that a complete series exists. Again. IF (SIZE(headers,/TYPE) EQ 0) THEN BEGIN ddddd=DIALOG_MESSAGE(['Incomplete series for this image time.',STRMID(FILE_BASENAME(varstruct.stereo_b_image),0,15),'Please select a different image time.']) IF WIDGET_INFO(temp_base,/VALID_ID) THEN BEGIN WIDGET_CONTROL,temp_base,/DESTROY ENDIF RETURN ENDIF ; Take the first TB image, just in case more than one set of polarized images was captured by the time range in COR1_TOTALB. left_filename=varstruct.stereo_b_image left_hdr=REFORM(headers[0,1]) left_img=REFORM(images[*,*,0,1]) right_filename=varstruct.stereo_a_image right_hdr=REFORM(headers[0,0]) right_img=REFORM(images[*,*,0,0]) ENDIF ELSE BEGIN IF (left_naxis1 EQ right_naxis1) THEN BEGIN SECCHI_PREP, left_filename, left_hdr, left_img, /NOCALFAC, /calimg_off, /update_hdr_off, _EXTRA=_extra, /EXPTIME_OFF, /SMASK, /PRECOMMCORRECT_ON SECCHI_PREP,right_filename,right_hdr,right_img, /NOCALFAC, /calimg_off, /update_hdr_off, _EXTRA=_extra, /EXPTIME_OFF, /SMASK, /PRECOMMCORRECT_ON ENDIF ELSE BEGIN osize=MIN([left_naxis1,right_naxis1]) WIDGET_CONTROL,temp_label0a,SET_VALUE='left: '+STRTRIM( left_naxis1,2)+' x '+STRTRIM( left_naxis2,2)+' (OUTSIZE='+STRTRIM(osize,2)+')' WIDGET_CONTROL,temp_label0b,SET_VALUE='right: '+STRTRIM(right_naxis1,2)+' x '+STRTRIM(right_naxis2,2)+' (OUTSIZE='+STRTRIM(osize,2)+')' SECCHI_PREP, left_filename, left_hdr, left_img, /NOCALFAC, /calimg_off, /update_hdr_off, _EXTRA=_extra, /EXPTIME_OFF, /SMASK, /PRECOMMCORRECT_ON, OUTSIZE=osize SECCHI_PREP,right_filename,right_hdr,right_img, /NOCALFAC, /calimg_off, /update_hdr_off, _EXTRA=_extra, /EXPTIME_OFF, /SMASK, /PRECOMMCORRECT_ON, OUTSIZE=osize ENDELSE ; Bill Thompson's pointing correction for EUVI. IF varstruct.detector EQ 'euvi' THEN BEGIN ; Only works with images that are 2048x2048. IF left_naxis1 EQ 2048 AND left_naxis2 EQ 2048 AND right_naxis1 EQ 2048 AND right_naxis2 EQ 2048 THEN BEGIN sunloop_correct_euvi_point, left_hdr sunloop_correct_euvi_point, right_hdr ENDIF ENDIF ENDELSE ENDELSE END ENDCASE ;------------------------------------------------------- ; Set some initial default min,max values for bytscl(). ;------------------------------------------------------- left_min = MIN( left_img) left_max = MAX( left_img) right_min = MIN(right_img) right_max = MAX(right_img) left_secchistruct.default_min = left_min left_secchistruct.default_max = left_max right_secchistruct.default_min = right_min right_secchistruct.default_max = right_max ; Cor1 Left. IF (varstruct.detector EQ 'cor1') AND (varstruct.calibrate EQ 'no' ) THEN left_secchistruct.default_min = -5.0e-10 IF (varstruct.detector EQ 'cor1') AND (varstruct.calibrate EQ 'no' ) THEN left_secchistruct.default_max = 5.0e-08 IF (varstruct.detector EQ 'cor1') AND (varstruct.calibrate EQ 'yes') THEN left_secchistruct.default_min = 0 ;-5.0e-10 IF (varstruct.detector EQ 'cor1') AND (varstruct.calibrate EQ 'yes') THEN left_secchistruct.default_max = 1.0e-07 ; Cor1 Right. IF (varstruct.detector EQ 'cor1') AND (varstruct.calibrate EQ 'no' ) THEN right_secchistruct.default_min = -5.0e-10 IF (varstruct.detector EQ 'cor1') AND (varstruct.calibrate EQ 'no' ) THEN right_secchistruct.default_max = 5.0e-08 IF (varstruct.detector EQ 'cor1') AND (varstruct.calibrate EQ 'yes') THEN right_secchistruct.default_min = 0 ;-5.0e-10 IF (varstruct.detector EQ 'cor1') AND (varstruct.calibrate EQ 'yes') THEN right_secchistruct.default_max = 1.0e-07 ;------------------------------------------------------- ; Remove background from COR2, HI-1 and HI-2 only. ; (EUVI does not need background removal.) ; This must be done PRIOR to image rotation. ;------------------------------------------------------- ; IF (varstruct.detector NE 'cor1') AND (STRPOS(FILE_DIRNAME(varstruct.stereo_b_image),'/seq/') GE 0) THEN BEGIN ; IF (STRPOS(FILE_DIRNAME(varstruct.stereo_b_image),'/img/') GE 0) THEN BEGIN IF ( (varstruct.detector EQ 'cor1') AND (STRPOS(FILE_DIRNAME(varstruct.stereo_b_image),'/img/') GE 0) ) $ OR (varstruct.detector EQ 'cor2') $ OR (varstruct.detector EQ 'hi_1') $ OR (varstruct.detector EQ 'hi_2') $ THEN BEGIN ;------------------------------------------------------- ; Find background images, if any. ;------------------------------------------------------- CASE varstruct.detector OF 'euvi' : BEGIN ; EUVI does not get background removal. Set bkg_img to all zeroes. left_bkg_img = left_img * 0 right_bkg_img = right_img * 0 END 'cor1' : BEGIN IF (STRPOS(FILE_DIRNAME(varstruct.stereo_b_image),'/seq/') GE 0) THEN BEGIN ; COR1 background removal occurs in COR1_TOTALB. Set bkg_img to all zeroes. left_bkg_img = left_img * 0 right_bkg_img = right_img * 0 ENDIF ELSE BEGIN left_bkg_img = SCC_GETBKGIMG( left_hdr,OUTHDR= left_bkg_hdr,/TOTALB,/INTERPOLATE,/MATCH ) right_bkg_img = SCC_GETBKGIMG(right_hdr,OUTHDR=right_bkg_hdr,/TOTALB,/INTERPOLATE,/MATCH ) ENDELSE END 'cor2' : BEGIN left_bkg_img = SCC_GETBKGIMG( left_hdr,OUTHDR= left_bkg_hdr,/TOTALB,/INTERPOLATE,/MATCH ) right_bkg_img = SCC_GETBKGIMG(right_hdr,OUTHDR=right_bkg_hdr,/TOTALB,/INTERPOLATE,/MATCH ) END 'hi_1' : BEGIN left_bkg_img = SCC_GETBKGIMG( left_hdr,OUTHDR= left_bkg_hdr,/INTERPOLATE,/MATCH ) right_bkg_img = SCC_GETBKGIMG(right_hdr,OUTHDR=right_bkg_hdr,/INTERPOLATE,/MATCH ) END 'hi_2' : BEGIN left_bkg_img = SCC_GETBKGIMG( left_hdr,OUTHDR= left_bkg_hdr,/INTERPOLATE,/MATCH ) right_bkg_img = SCC_GETBKGIMG(right_hdr,OUTHDR=right_bkg_hdr,/INTERPOLATE,/MATCH ) END ENDCASE ;------------------------------------------------------- ; Check to see if background images were found. ; If no background image is found, -1 is returned. ;------------------------------------------------------- IF ( left_bkg_img[0] EQ -1) AND (N_ELEMENTS( left_bkg_img) EQ 1) THEN BEGIN left_bkg_found = 0L ENDIF ELSE BEGIN left_bkg_found = 1L ENDELSE IF (right_bkg_img[0] EQ -1) AND (N_ELEMENTS(right_bkg_img) EQ 1) THEN BEGIN right_bkg_found = 0L ENDIF ELSE BEGIN right_bkg_found = 1L ENDELSE ;------------------------------------------------------- ; If either background image was not found, notify the user. ;------------------------------------------------------- CASE 1 OF (left_bkg_found EQ 0) AND (right_bkg_found EQ 0) : BEGIN answer=DIALOG_MESSAGE([ 'Background images not found.', $ 'No background removal will be performed.','','Send images to tiepointer anyway?'],/QUESTION) IF (STRLOWCASE(answer) EQ 'no') THEN BEGIN IF WIDGET_INFO(temp_base,/VALID_ID) THEN BEGIN WIDGET_CONTROL,temp_base,/DESTROY ENDIF RETURN ENDIF END (left_bkg_found EQ 1) AND (right_bkg_found EQ 0) : BEGIN answer=DIALOG_MESSAGE([ 'Background image not found for RIGHT image.', $ 'No background removal will be performed on the RIGHT image.','','Send images to tiepointer anyway?'],/QUESTION) IF (STRLOWCASE(answer) EQ 'no') THEN BEGIN IF WIDGET_INFO(temp_base,/VALID_ID) THEN BEGIN WIDGET_CONTROL,temp_base,/DESTROY ENDIF RETURN ENDIF END (left_bkg_found EQ 0) AND (right_bkg_found EQ 1) : BEGIN answer=DIALOG_MESSAGE([ 'Background image not found for LEFT image.', $ 'No background removal will be performed on the LEFT image.','','Send images to tiepointer anyway?'],/QUESTION) IF (STRLOWCASE(answer) EQ 'no') THEN BEGIN IF WIDGET_INFO(temp_base,/VALID_ID) THEN BEGIN WIDGET_CONTROL,temp_base,/DESTROY ENDIF RETURN ENDIF END ELSE : BEGIN ;------------------------------------------------------- ; Continue on with background removal. ; Print the pair of background filenames. ;------------------------------------------------------- print,' LEFT background filename = ', left_bkg_hdr.filename print,'RIGHT background filename = ',right_bkg_hdr.filename END ENDCASE ;------------------------------------------------------- ; Do LEFT background removal. ;------------------------------------------------------- IF ( left_bkg_found EQ 1) THEN BEGIN ;------------------------------------------------------- ; Remove background. (Backgroud removal for "/seq/" (totalb) is removed in SECCHI_PREP.) ;------------------------------------------------------- IF (varstruct.detector NE 'cor1') THEN BEGIN IF (varstruct.detector EQ 'cor2') THEN BEGIN left_img = left_img / left_bkg_img ENDIF ELSE BEGIN left_img = left_img - left_bkg_img ENDELSE ENDIF ;------------------------------------------------------- ; Hardcode some default min,max values for bytscl(). ;------------------------------------------------------- IF (varstruct.detector EQ 'cor2') AND (varstruct.calibrate EQ 'no' ) THEN left_secchistruct.default_min = 0.0 IF (varstruct.detector EQ 'cor2') AND (varstruct.calibrate EQ 'no' ) THEN left_secchistruct.default_max = 350.0 IF (varstruct.detector EQ 'cor2') AND (varstruct.calibrate EQ 'yes') THEN left_secchistruct.default_min = 0.45 IF (varstruct.detector EQ 'cor2') AND (varstruct.calibrate EQ 'yes') THEN left_secchistruct.default_max = 0.55 IF (STRPOS(FILE_DIRNAME(varstruct.stereo_b_image),'/seq/') GE 0) THEN BEGIN IF (varstruct.detector EQ 'cor2') AND (varstruct.calibrate EQ 'yes') THEN left_secchistruct.default_min = 0.45 IF (varstruct.detector EQ 'cor2') AND (varstruct.calibrate EQ 'yes') THEN left_secchistruct.default_max = 0.55 ENDIF ELSE BEGIN IF (varstruct.detector EQ 'cor2') AND (varstruct.calibrate EQ 'yes') THEN left_secchistruct.default_min = 0.90 IF (varstruct.detector EQ 'cor2') AND (varstruct.calibrate EQ 'yes') THEN left_secchistruct.default_max = 1.15 ENDELSE IF (varstruct.detector EQ 'hi_1') AND (varstruct.calibrate EQ 'no' ) THEN left_secchistruct.default_min = -50.0 IF (varstruct.detector EQ 'hi_1') AND (varstruct.calibrate EQ 'no' ) THEN left_secchistruct.default_max = 350.0 IF (varstruct.detector EQ 'hi_1') AND (varstruct.calibrate EQ 'yes') THEN left_secchistruct.default_min = 0 IF (varstruct.detector EQ 'hi_1') AND (varstruct.calibrate EQ 'yes') THEN left_secchistruct.default_max = 5000.0 IF (varstruct.detector EQ 'hi_2') AND (varstruct.calibrate EQ 'no' ) THEN left_secchistruct.default_min = -50.0 IF (varstruct.detector EQ 'hi_2') AND (varstruct.calibrate EQ 'no' ) THEN left_secchistruct.default_max = 350.0 IF (varstruct.detector EQ 'hi_2') AND (varstruct.calibrate EQ 'yes') THEN left_secchistruct.default_min = 0 IF (varstruct.detector EQ 'hi_2') AND (varstruct.calibrate EQ 'yes') THEN left_secchistruct.default_max = 20000.0 ; ;------------------------------------------------------- ; ; Un-hardcode default values if they're badly incorrect. ; ; (Sanity check.) ; ;------------------------------------------------------- ; left_min = MIN( left_img) ; left_max = MAX( left_img) ; IF ( left_secchistruct.default_min GT left_max) THEN BEGIN ; left_secchistruct.default_min = left_min ; left_secchistruct.default_max = left_max ; ENDIF ; IF ( left_secchistruct.default_max LT left_min) THEN BEGIN ; left_secchistruct.default_min = left_min ; left_secchistruct.default_max = left_max ; ENDIF ENDIF ;------------------------------------------------------- ; Do RIGHT background removal. ;------------------------------------------------------- IF (right_bkg_found EQ 1) THEN BEGIN ;------------------------------------------------------- ; Remove background. (COR1 is removed in SECCHI_PREP.) ;------------------------------------------------------- IF (varstruct.detector NE 'cor1') THEN BEGIN IF (varstruct.detector EQ 'cor2') THEN BEGIN right_img = right_img / right_bkg_img ENDIF ELSE BEGIN right_img = right_img - right_bkg_img ENDELSE ENDIF ;------------------------------------------------------- ; Update default min,max values for bytscl(). ;------------------------------------------------------- IF (varstruct.detector EQ 'cor2') AND (varstruct.calibrate EQ 'no' ) THEN right_secchistruct.default_min = 0.0 IF (varstruct.detector EQ 'cor2') AND (varstruct.calibrate EQ 'no' ) THEN right_secchistruct.default_max = 350.0 IF (varstruct.detector EQ 'cor2') AND (varstruct.calibrate EQ 'yes') THEN right_secchistruct.default_min = 0.45 IF (varstruct.detector EQ 'cor2') AND (varstruct.calibrate EQ 'yes') THEN right_secchistruct.default_max = 0.55 IF (STRPOS(FILE_DIRNAME(varstruct.stereo_a_image),'/seq/') GE 0) THEN BEGIN IF (varstruct.detector EQ 'cor2') AND (varstruct.calibrate EQ 'yes') THEN right_secchistruct.default_min = 0.45 IF (varstruct.detector EQ 'cor2') AND (varstruct.calibrate EQ 'yes') THEN right_secchistruct.default_max = 0.55 ENDIF ELSE BEGIN IF (varstruct.detector EQ 'cor2') AND (varstruct.calibrate EQ 'yes') THEN right_secchistruct.default_min = 0.90 IF (varstruct.detector EQ 'cor2') AND (varstruct.calibrate EQ 'yes') THEN right_secchistruct.default_max = 1.15 ENDELSE IF (varstruct.detector EQ 'hi_1') AND (varstruct.calibrate EQ 'no' ) THEN right_secchistruct.default_min = -50.0 IF (varstruct.detector EQ 'hi_1') AND (varstruct.calibrate EQ 'no' ) THEN right_secchistruct.default_max = 350.0 IF (varstruct.detector EQ 'hi_1') AND (varstruct.calibrate EQ 'yes') THEN right_secchistruct.default_min = 1 IF (varstruct.detector EQ 'hi_1') AND (varstruct.calibrate EQ 'yes') THEN right_secchistruct.default_max = 5000.0 IF (varstruct.detector EQ 'hi_2') AND (varstruct.calibrate EQ 'no' ) THEN right_secchistruct.default_min = -50.0 IF (varstruct.detector EQ 'hi_2') AND (varstruct.calibrate EQ 'no' ) THEN right_secchistruct.default_max = 350.0 IF (varstruct.detector EQ 'hi_2') AND (varstruct.calibrate EQ 'yes') THEN right_secchistruct.default_min = 0 IF (varstruct.detector EQ 'hi_2') AND (varstruct.calibrate EQ 'yes') THEN right_secchistruct.default_max = 20000.0 ; ;------------------------------------------------------- ; ; Un-hardcode default values if they're badly incorrect. ; ; (Sanity check.) ; ;------------------------------------------------------- ; right_min = MIN(right_img) ; right_max = MAX(right_img) ; IF (right_secchistruct.default_min GT right_max) THEN BEGIN ; right_secchistruct.default_min = right_min ; right_secchistruct.default_max = right_max ; ENDIF ; IF (right_secchistruct.default_max LT right_min) THEN BEGIN ; right_secchistruct.default_min = right_min ; right_secchistruct.default_max = right_max ; ENDIF ENDIF ENDIF IF WIDGET_INFO(temp_base,/VALID_ID) THEN BEGIN WIDGET_CONTROL,temp_label1a,SET_VALUE=' CALIBRATION',SENSITIVE=0 ENDIF ;------------------------------------------------------- ; Rotate if requested. ;------------------------------------------------------- IF (varstruct.rotate EQ 'to stereo baseline') THEN BEGIN ;------------------------------------------------------- ; EUVI and COR can use SCC_STEREOPAIR. ; HI must use SCC_ROLL_IMAGE. ;------------------------------------------------------- IF (varstruct.detector EQ 'hi_1') OR (varstruct.detector EQ 'hi_2') THEN BEGIN ; SCC_ROLL_IMAGE, left_hdr, left_img, SYSTEM='STPLN' ; SCC_ROLL_IMAGE,right_hdr,right_img, SYSTEM='STPLN' ; Rotate to stereo baseline and translate vertically to put sun at vertical center, without moving it horizontally (CRPIX1). ; The seemingly out-of-order sequence of these commands is crucial, but results in preserving the rolled image corners. ; Unfortunately, this sequence resamples the data twice, once during the roll and again during the translate. A seeming ; workaround of translating on integer pixels will result in sub-pixel jitter in the animation. Unknown if double resamle ; is better or worse than sub-pixel jitter. Resampling is excellent when using cubic, so double resampling is used here. ; (I was unable to find an existing routine that performs this corner-preserving rotation with a single resample. The ; rotation-translation is complicated by not knowing the translation's reference pixel until after the rotation is done.) IF WIDGET_INFO(temp_base,/VALID_ID) THEN WIDGET_CONTROL,temp_label3a,SET_VALUE='-> ROTATE LEFT IMAGE' ;------------------------------------------------------- ; Do left image. ;------------------------------------------------------- data=left_img hdr=left_hdr sz=size(data) ; Create a larger blank array that has plenty of room to preserve image corners after rotation. padded_data=make_array(3*sz[1:2],type=size(data,/type)) padded_data[sz[1]:sz[1]*2-1,sz[2]:sz[2]*2-1]=data ; Get a wcs copy of the header before the header gets updated during scc_roll_image. wcs=fitshead2wcs(hdr) ; Get the reference pixel in the padded image for rotating the padded image. xref=hdr.CRPIX1-1+sz[1] yref=hdr.CRPIX2-1+sz[2] ; ; Roll the data for the purpose of getting an updated header, but this image will be discarded. ; scc_roll_image,hdr,data,SYSTEM='STPLN',cubic=-0.5 ; Roll the data again, this time don't bother with the header which is already rolled. padded_roll = rot(padded_data, -wcs.roll_angle, 1, xref, yref, missing=0, /pivot, cubic=-0.5) ; Get a wcs copy of the header after scc_roll_image, this will match the image that gets rolled in the next couple of commands. wcs=fitshead2wcs(hdr) ; Get the sun center from the rolled header. suncenter_xy = wcs_get_pixel( wcs,[0,0],/FORCE_PROJ) + 1 ; Translate the padded image, to move the sun to the vertical center. Account for the image being embedded into a 3x3 padding. padded_trans=rot(padded_roll,0,1,hdr.CRPIX1-1+sz[1],suncenter_xy[1]-1+sz[2],missing=0,cubic=-0.5) ; padded_trans=rot(padded_roll,0,1,hdr.CRPIX1-1+sz[1],(hdr.naxis2-suncenter_xy[1])-1+sz[2],missing=0,cubic=-0.5) ; Extract the 1024x1024 rolled image from the padded image. This will have the corners preserved, and will match the rolled header. data=padded_trans[sz[1]:sz[1]*2-1,sz[2]:sz[2]*2-1] left_img=data left_hdr=hdr IF WIDGET_INFO(temp_base,/VALID_ID) THEN WIDGET_CONTROL,temp_label3a,SET_VALUE=' ROTATE LEFT IMAGE',SENSITIVE=0 IF WIDGET_INFO(temp_base,/VALID_ID) THEN WIDGET_CONTROL,temp_label3b,SET_VALUE='-> ROTATE RIGHT IMAGE' ;------------------------------------------------------- ; Do right image. ;------------------------------------------------------- data=right_img hdr=right_hdr sz=size(data) ; Create a larger blank array that has plenty of room to preserve image corners after rotation. padded_data=make_array(3*sz[1:2],type=size(data,/type)) padded_data[sz[1]:sz[1]*2-1,sz[2]:sz[2]*2-1]=data ; Get a wcs copy of the header before the header gets updated during scc_roll_image. wcs=fitshead2wcs(hdr) ; Get the reference pixel in the padded image for rotating the padded image. xref=hdr.CRPIX1-1+sz[1] yref=hdr.CRPIX2-1+sz[2] ; ; Roll the data for the purpose of getting an updated header, but this image will be discarded. ; scc_roll_image,hdr,data,SYSTEM='STPLN',cubic=-0.5 ; Roll the data again, this time don't bother with the header which is already rolled. padded_roll = rot(padded_data, -wcs.roll_angle, 1, xref, yref, missing=0, /pivot, cubic=-0.5) ; Get a wcs copy of the header after scc_roll_image, this will match the image that gets rolled in the next couple of commands. wcs=fitshead2wcs(hdr) ; Get the sun center from the rolled header. suncenter_xy = wcs_get_pixel( wcs,[0,0],/FORCE_PROJ) + 1 ; Translate the padded image, to move the sun to the vertical center. Account for the image being embedded into a 3x3 padding. padded_trans=rot(padded_roll,0,1,hdr.CRPIX1-1+sz[1],suncenter_xy[1]-1+sz[2],missing=0,cubic=-0.5) ; padded_trans=rot(padded_roll,0,1,hdr.CRPIX1-1+sz[1],(hdr.naxis2-suncenter_xy[1])-1+sz[2],missing=0,cubic=-0.5) ; Extract the 1024x1024 rolled image from the padded image. This will have the corners preserved, and will match the rolled header. data=padded_trans[sz[1]:sz[1]*2-1,sz[2]:sz[2]*2-1] right_img=data right_hdr=hdr ; Free memory. padded_data=0 padded_roll=0 padded_trans=0 IF WIDGET_INFO(temp_base,/VALID_ID) THEN WIDGET_CONTROL,temp_label3b,SET_VALUE=' ROTATE RIGHT IMAGE',SENSITIVE=0 ENDIF ELSE BEGIN IF WIDGET_INFO(temp_base,/VALID_ID) THEN WIDGET_CONTROL,temp_label3,SET_VALUE='-> SCC_STEREOPAIR' IF SIZE(varstruct.stereo_a_image,/TYPE) EQ 7 THEN BEGIN imgarr=SCC_STEREOPAIR(right_img,left_img,right_hdr,left_hdr,/CUBIC,SECCHIPREP=0) ;APPEARS TO BE UNECESSARY. ; ;------------------------------------------------------- ; ; Run scc_stereopair again with filenames instead of ; ; images. This mode returns corrected headers. (For ; ; historical reasons in sunloop.pro code, this is much ; ; simpler than restructuring the logic to only call ; ; scc_stereopair just once.) ; ;------------------------------------------------------- ;; junk=SCC_STEREOPAIR(right_filename,left_filename,right_hdr,left_hdr,/CUBIC,SECCHIPREP=0) ; IF (left_naxis1 EQ right_naxis1) THEN BEGIN ; junk=SCC_STEREOPAIR(right_filename,left_filename,right_hdr,left_hdr,/CUBIC,SECCHIPREP=0) ; ENDIF ELSE BEGIN ; osize=MIN([left_naxis1,right_naxis1]) ; junk=SCC_STEREOPAIR(right_filename,left_filename,right_hdr,left_hdr,/CUBIC,SECCHIPREP=0,_EXTRA={OUTSIZE:osize}) ; ENDELSE ENDIF ELSE BEGIN imgarr=SCC_STEREOPAIR(right_img,left_img,right_hdr,left_hdr,/CUBIC,SECCHIPREP=0) ENDELSE ;------------------------------------------------------- ; scc_stereopair reverses the pair order of ahead and ; behind. It ingests them with ahead(right) first, and ; returns them with behind(left) first. ;------------------------------------------------------- left_img = REFORM(imgarr[0,*,*]) right_img = REFORM(imgarr[1,*,*]) IF WIDGET_INFO(temp_base,/VALID_ID) THEN WIDGET_CONTROL,temp_label3,SET_VALUE=' SCC_STEREOPAIR',SENSITIVE=0 ENDELSE ENDIF ;------------------------------------------------------- ; Check for NaN values. Set any to zero. ;------------------------------------------------------- ndx = WHERE( left_img EQ !VALUES.F_NAN,count) IF (count GT 0) THEN left_img[ndx] = 0 ndx = WHERE(right_img EQ !VALUES.F_NAN,count) IF (count GT 0) THEN right_img[ndx] = 0 ;------------------------------------------------------- ; Check for infinite values. Set any to zero. ;------------------------------------------------------- ndx = WHERE(FINITE( left_img) EQ 0,count) IF (count GT 0) THEN left_img[ndx] = 0 ndx = WHERE(FINITE(right_img) EQ 0,count) IF (count GT 0) THEN right_img[ndx] = 0 ;------------------------------------------------------- ; Convert header to WCS structure. ;------------------------------------------------------- left_wcs = FITSHEAD2WCS( left_hdr) right_wcs = FITSHEAD2WCS(right_hdr) ;------------------------------------------------------- ; Add suncenter XY pixel location. ;------------------------------------------------------- left_secchistruct.suncenter_xy = wcs_get_pixel( left_wcs,[0,0],/FORCE_PROJ) + 1 right_secchistruct.suncenter_xy = wcs_get_pixel(right_wcs,[0,0],/FORCE_PROJ) + 1 ;------------------------------------------------------- ; Add mercury XY pixel location. ;------------------------------------------------------- pos=get_stereo_lonlat( left_hdr.date_obs, left_hdr.obsrvtry,system='HPC',target='mercury',/degrees, corr='lt+s') pos[1:2]=pos[1:2]*MAX([1,(3600*(STRLOWCASE(STRMID(left_hdr.detector,0,2)) NE 'hi'))]) left_secchistruct.mercury_xy = wcs_get_pixel( left_wcs,pos[1:2],/FORCE_PROJ) + 1 pos=get_stereo_lonlat(right_hdr.date_obs,right_hdr.obsrvtry,system='HPC',target='mercury',/degrees, corr='lt+s') pos[1:2]=pos[1:2]*MAX([1,(3600*(STRLOWCASE(STRMID(right_hdr.detector,0,2)) NE 'hi'))]) right_secchistruct.mercury_xy = wcs_get_pixel(right_wcs,pos[1:2],/FORCE_PROJ) + 1 ;------------------------------------------------------- ; Add venus XY pixel location. ;------------------------------------------------------- pos=get_stereo_lonlat( left_hdr.date_obs, left_hdr.obsrvtry,system='HPC',target='venus',/degrees, corr='lt+s') pos[1:2]=pos[1:2]*MAX([1,(3600*(STRLOWCASE(STRMID(left_hdr.detector,0,2)) NE 'hi'))]) left_secchistruct.venus_xy = wcs_get_pixel( left_wcs,pos[1:2],/FORCE_PROJ) + 1 pos=get_stereo_lonlat(right_hdr.date_obs,right_hdr.obsrvtry,system='HPC',target='venus',/degrees, corr='lt+s') pos[1:2]=pos[1:2]*MAX([1,(3600*(STRLOWCASE(STRMID(right_hdr.detector,0,2)) NE 'hi'))]) right_secchistruct.venus_xy = wcs_get_pixel(right_wcs,pos[1:2],/FORCE_PROJ) + 1 ;------------------------------------------------------- ; Add earth XY pixel location. ;------------------------------------------------------- pos=get_stereo_lonlat( left_hdr.date_obs, left_hdr.obsrvtry,system='HPC',target='earth',/degrees, corr='lt+s') pos[1:2]=pos[1:2]*MAX([1,(3600*(STRLOWCASE(STRMID(left_hdr.detector,0,2)) NE 'hi'))]) left_secchistruct.earth_xy = wcs_get_pixel( left_wcs,pos[1:2],/FORCE_PROJ) + 1 pos=get_stereo_lonlat(right_hdr.date_obs,right_hdr.obsrvtry,system='HPC',target='earth',/degrees, corr='lt+s') pos[1:2]=pos[1:2]*MAX([1,(3600*(STRLOWCASE(STRMID(right_hdr.detector,0,2)) NE 'hi'))]) right_secchistruct.earth_xy = wcs_get_pixel(right_wcs,pos[1:2],/FORCE_PROJ) + 1 ;------------------------------------------------------- ; Add mars XY pixel location. ;------------------------------------------------------- pos=get_stereo_lonlat( left_hdr.date_obs, left_hdr.obsrvtry,system='HPC',target='mars',/degrees, corr='lt+s') pos[1:2]=pos[1:2]*MAX([1,(3600*(STRMID(left_hdr.detector,0,2) NE 'hi'))]) left_secchistruct.mars_xy = wcs_get_pixel( left_wcs,pos[1:2],/FORCE_PROJ) + 1 pos=get_stereo_lonlat(right_hdr.date_obs,right_hdr.obsrvtry,system='HPC',target='mars',/degrees, corr='lt+s') pos[1:2]=pos[1:2]*MAX([1,(3600*(STRMID(right_hdr.detector,0,2) NE 'hi'))]) right_secchistruct.mars_xy = wcs_get_pixel(right_wcs,pos[1:2],/FORCE_PROJ) + 1 ;------------------------------------------------------- ; Add jupiter XY pixel location. ;------------------------------------------------------- pos=get_stereo_lonlat( left_hdr.date_obs, left_hdr.obsrvtry,system='HPC',target='jupiter barycenter',/degrees, corr='lt+s') pos[1:2]=pos[1:2]*MAX([1,(3600*(STRMID(left_hdr.detector,0,2) NE 'hi'))]) left_secchistruct.jupiter_xy = wcs_get_pixel( left_wcs,pos[1:2],/FORCE_PROJ) + 1 pos=get_stereo_lonlat(right_hdr.date_obs,right_hdr.obsrvtry,system='HPC',target='jupiter barycenter',/degrees, corr='lt+s') pos[1:2]=pos[1:2]*MAX([1,(3600*(STRMID(right_hdr.detector,0,2) NE 'hi'))]) right_secchistruct.jupiter_xy = wcs_get_pixel(right_wcs,pos[1:2],/FORCE_PROJ) + 1 ;------------------------------------------------------- ; Add saturn XY pixel location. ;------------------------------------------------------- pos=get_stereo_lonlat( left_hdr.date_obs, left_hdr.obsrvtry,system='HPC',target='saturn barycenter',/degrees, corr='lt+s') pos[1:2]=pos[1:2]*MAX([1,(3600*(STRMID(left_hdr.detector,0,2) NE 'hi'))]) left_secchistruct.saturn_xy = wcs_get_pixel( left_wcs,pos[1:2],/FORCE_PROJ) + 1 pos=get_stereo_lonlat(right_hdr.date_obs,right_hdr.obsrvtry,system='HPC',target='saturn barycenter',/degrees, corr='lt+s') pos[1:2]=pos[1:2]*MAX([1,(3600*(STRMID(right_hdr.detector,0,2) NE 'hi'))]) right_secchistruct.saturn_xy = wcs_get_pixel(right_wcs,pos[1:2],/FORCE_PROJ) + 1 ;------------------------------------------------------- ; Add neptune XY pixel location. ;------------------------------------------------------- pos=get_stereo_lonlat( left_hdr.date_obs, left_hdr.obsrvtry,system='HPC',target='neptune barycenter',/degrees, corr='lt+s') pos[1:2]=pos[1:2]*MAX([1,(3600*(STRMID(left_hdr.detector,0,2) NE 'hi'))]) left_secchistruct.neptune_xy = wcs_get_pixel( left_wcs,pos[1:2],/FORCE_PROJ) + 1 pos=get_stereo_lonlat(right_hdr.date_obs,right_hdr.obsrvtry,system='HPC',target='neptune barycenter',/degrees, corr='lt+s') pos[1:2]=pos[1:2]*MAX([1,(3600*(STRMID(right_hdr.detector,0,2) NE 'hi'))]) right_secchistruct.neptune_xy = wcs_get_pixel(right_wcs,pos[1:2],/FORCE_PROJ) + 1 ;------------------------------------------------------- ; Add uranus XY pixel location. ;------------------------------------------------------- pos=get_stereo_lonlat( left_hdr.date_obs, left_hdr.obsrvtry,system='HPC',target='uranus barycenter',/degrees, corr='lt+s') pos[1:2]=pos[1:2]*MAX([1,(3600*(STRMID(left_hdr.detector,0,2) NE 'hi'))]) left_secchistruct.uranus_xy = wcs_get_pixel( left_wcs,pos[1:2],/FORCE_PROJ) + 1 pos=get_stereo_lonlat(right_hdr.date_obs,right_hdr.obsrvtry,system='HPC',target='uranus barycenter',/degrees, corr='lt+s') pos[1:2]=pos[1:2]*MAX([1,(3600*(STRMID(right_hdr.detector,0,2) NE 'hi'))]) right_secchistruct.uranus_xy = wcs_get_pixel(right_wcs,pos[1:2],/FORCE_PROJ) + 1 IF WIDGET_INFO(temp_base,/VALID_ID) THEN WIDGET_CONTROL,temp_label5,SET_VALUE='-> START TIEPOINTER' ;------------------------------------------------------- ; Add optical axis. ;------------------------------------------------------- left_optax_x = ( left_hdr.NAXIS1 + 1)/2.0d right_optax_x = (right_hdr.NAXIS1 + 1)/2.0d left_optax_y = ( left_hdr.NAXIS2 + 1)/2.0d right_optax_y = (right_hdr.NAXIS2 + 1)/2.0d left_secchistruct.optax_xy = [ left_optax_x, left_optax_y ] right_secchistruct.optax_xy = [ right_optax_x, right_optax_y ] ;------------------------------------------------------- ; Add solar north angle, and get cdelt for FOV calculation. ;------------------------------------------------------- ; LEFT. left_secchistruct.solar_north_angle = left_wcs.roll_angle cdelt1_left = left_hdr.cdelt1 cdelt2_left = left_hdr.cdelt2 ; RIGHT. right_secchistruct.solar_north_angle = right_wcs.roll_angle cdelt1_right = right_hdr.cdelt1 cdelt2_right = right_hdr.cdelt2 ;------------------------------------------------------- ; Add distance to sun (convert meters to kilometers). ;------------------------------------------------------- left_secchistruct.distance = left_hdr.DSUN_OBS / 1000.0d right_secchistruct.distance = right_hdr.DSUN_OBS / 1000.0d ;------------------------------------------------------- ; Add focal length. ;------------------------------------------------------- ; (arcsec/60/60)*(pi/180)=radians ; focal length = 1/tan(radians) ;------------------------------------------------------- ; Convert to degrees, unless Heliospheric Imager which is already degrees. pixel_fov_degrees_left = DOUBLE( cdelt1_left ) / (( (STRMID( left_hdr.detector,0,2) NE 'HI') * 3600 ) > 1) pixel_fov_degrees_right = DOUBLE( cdelt1_right ) / (( (STRMID(right_hdr.detector,0,2) NE 'HI') * 3600 ) > 1) left_secchistruct.focal_length_in_pixels = 1/TAN(pixel_fov_degrees_left *!DTOR) right_secchistruct.focal_length_in_pixels = 1/TAN(pixel_fov_degrees_right*!DTOR) ;------------------------------------------------------- ; Call the tiepointer. ;------------------------------------------------------- tp=OBJ_NEW('tiepointer', $ left_img,right_img, $ left_hdr,right_hdr, $ left_secchistruct,right_secchistruct, $ left_filename[0],right_filename[0], $ ;Use index 0 because COR1 filenames are triplets. varstruct.detector, $ varstruct.rotate, $ varstruct.sunloop_tlb, $ XY_FILENAME=varstruct.xy_filename ) IF WIDGET_INFO(temp_base,/VALID_ID) THEN WIDGET_CONTROL,temp_base,/DESTROY END FUNCTION find_most_recent_data,varstruct temp_base=WIDGET_BASE(/COLUMN,GROUP_LEADER=varstruct.sunloop_tlb) temp_label=WIDGET_LABEL(temp_base,VALUE='Searching For Most Recent Data...') temp_label=WIDGET_LABEL(temp_base,VALUE='---------------------------------') temp_label=WIDGET_LABEL(temp_base,VALUE='Detector: '+varstruct.detector) IF (varstruct.detector EQ 'euvi') THEN temp_label=WIDGET_LABEL(temp_base,VALUE='Wavelength: '+varstruct.wavelnth) date_label=WIDGET_LABEL(temp_base,VALUE='Date: ',/DYNAMIC_RESIZE) hour_label=WIDGET_LABEL(temp_base,VALUE='Hour: ',/DYNAMIC_RESIZE) temp_label=WIDGET_LABEL(temp_base,VALUE='---------------------------------') cancel_button=WIDGET_BUTTON(temp_base,VALUE='Cancel') WIDGET_CONTROL,temp_base,/REALIZE recent_struct={ stereo_a_list_ptr:PTR_NEW(), $ stereo_b_list_ptr:PTR_NEW(), $ datevalue:'', $ hourvalue:'' } dd_offset=1 stereo_a_list_ptr=PTR_NEW() stereo_b_list_ptr=PTR_NEW() hourvalue='' hh='23' cancel_pressed=0 WHILE (hourvalue EQ '') DO BEGIN ;------------------------------------------------------- ; Cancel button. ;------------------------------------------------------- quit=WIDGET_EVENT(cancel_button,/NOWAIT) IF quit.ID EQ cancel_button THEN cancel_pressed=1 IF cancel_pressed THEN BEGIN ;------------------------------------------------------- ; Destroy progress bar. ;------------------------------------------------------- IF WIDGET_INFO( temp_base, /VALID_ID ) THEN BEGIN WIDGET_CONTROL, temp_base, /DESTROY ENDIF WIDGET_CONTROL,varstruct.sunloop_tlb,SENSITIVE=1 WIDGET_CONTROL,varstruct.sunloop_tlb,SET_UVALUE=varstruct ;------------------------------------------------------- ; Turn off auto_update when cancel button is pressed. ;------------------------------------------------------- varstruct.most_recent_auto_update=0 RETURN,recent_struct ENDIF datevalue='' WHILE (datevalue EQ '') DO BEGIN ;------------------------------------------------------- ; Cancel button. ;------------------------------------------------------- quit=WIDGET_EVENT(cancel_button,/NOWAIT) IF quit.ID EQ cancel_button THEN cancel_pressed=1 IF cancel_pressed THEN BEGIN ;------------------------------------------------------- ; Destroy progress bar. ;------------------------------------------------------- IF WIDGET_INFO( temp_base, /VALID_ID ) THEN BEGIN WIDGET_CONTROL, temp_base, /DESTROY ENDIF WIDGET_CONTROL,varstruct.sunloop_tlb,SENSITIVE=1 WIDGET_CONTROL,varstruct.sunloop_tlb,SET_UVALUE=varstruct ;------------------------------------------------------- ; Turn off auto_update when cancel button is pressed. ;------------------------------------------------------- varstruct.most_recent_auto_update=0 RETURN,recent_struct ENDIF julian_day=SYSTIME(/JULIAN,/UTC)+dd_offset ;------------------------------------------------------- ; Don't regress past mission start date. ;------------------------------------------------------- IF (julian_day LT JULDAY(11,11,2006)) THEN BEGIN WIDGET_CONTROL,varstruct.datefield,SET_VALUE=varstruct.datevalue ; Add PATH_SEP() to value of sourcelabel for user interface display purposes only. datatype=varstruct.detector IF (datatype EQ 'euvi') THEN BEGIN datatype=datatype+' '+varstruct.wavelnth ENDIF ddddd=DIALOG_MESSAGE([datatype,'Not found.','','source_dir defined as: '+SCC_DATA_PATH('a')]) IF WIDGET_INFO(temp_base,/VALID_ID) THEN BEGIN WIDGET_CONTROL,temp_base,/DESTROY ENDIF RETURN,recent_struct ENDIF CALDAT,julian_day,mm,dd,yyyy IF (mm LT 10) THEN mm='0'+STRTRIM(mm,2) ELSE mm=STRTRIM(mm,2) IF (dd LT 10) THEN dd='0'+STRTRIM(dd,2) ELSE dd=STRTRIM(dd,2) date=STRTRIM(yyyy,2)+STRTRIM(mm,2)+STRTRIM(dd,2) WIDGET_CONTROL,date_label,SET_VALUE='Date: '+date WIDGET_CONTROL,hour_label,SET_VALUE='Hour: '+hh ;; WIDGET_CONTROL,varstruct.datefield,SET_VALUE=date CASE varstruct.detector OF 'cor1' : BEGIN source_dir_a= SCC_DATA_PATH('a', TYPE='seq', TELESCOPE=varstruct.detector, DATE=date) source_dir_b= SCC_DATA_PATH('b', TYPE='seq', TELESCOPE=varstruct.detector, DATE=date) END ELSE : BEGIN source_dir_a= SCC_DATA_PATH('a', TYPE='img', TELESCOPE=varstruct.detector, DATE=date) source_dir_b= SCC_DATA_PATH('b', TYPE='img', TELESCOPE=varstruct.detector, DATE=date) END ENDCASE yesno_a=FILE_SEARCH(source_dir_a) yesno_b=FILE_SEARCH(source_dir_b) IF (yesno_a[0] EQ '') OR (yesno_b[0] EQ '') THEN dd_offset=dd_offset-1 ELSE datevalue=date ENDWHILE WIDGET_CONTROL,date_label,SET_VALUE='Date: '+date WIDGET_CONTROL,hour_label,SET_VALUE='Hour: '+hh stereo_a_list=FILE_SEARCH(source_dir_a,date+'_'+hh+'*.fts',/FULLY_QUALIFY_PATH,COUNT=file_count) ; Weed out Space Weather. weeds=['7eu','7c1','7c2','7h1','7h2'] FOR w=0,N_ELEMENTS(weeds)-1 DO BEGIN ndx=WHERE(STRPOS(stereo_a_list,weeds[w]) EQ -1,ndx_count) IF (ndx_count GT 0) THEN stereo_a_list=stereo_a_list[ndx] ENDFOR ;------------------------------------------------------- ; Check that stereo_a_list contains something. ;------------------------------------------------------- IF (stereo_a_list[0] EQ '') THEN BEGIN hh=STRTRIM(LONG(hh)-1) IF (LONG(hh) LT 0) THEN BEGIN dd_offset=dd_offset-1 hh='23' ENDIF IF (hh LT 10) THEN hh='0'+STRTRIM(hh,2) ELSE hh=STRTRIM(hh,2) ;; WIDGET_CONTROL,varstruct.hourfield,SET_VALUE=hh ; WIDGET_CONTROL,varstruct.filelist,SET_VALUE='none found' CONTINUE ENDIF ;------------------------------------------------------- ; Create blank "b" list, same length as "a" list. ;------------------------------------------------------- stereo_b_list=STRARR(N_ELEMENTS(stereo_a_list)) ;------------------------------------------------------- ; Loop over every "a" filename. ;------------------------------------------------------- FOR i=0L,N_ELEMENTS(stereo_a_list)-1 DO BEGIN ; Look for matching STEREO-B image (with same date & time). stereo_a=stereo_a_list[i] stereo_b=FILE_SEARCH(source_dir_b,STRMID(FILE_BASENAME(stereo_a_list[i]),0,20)+'B.fts',/FULLY_QUALIFY_PATH,COUNT=file_count) stereo_b=stereo_b[0] IF (stereo_b NE '') THEN BEGIN ; If EUVI wavelength is specified then check header to see if data is of specified wavelength. IF (varstruct.detector eq 'euvi') THEN BEGIN ; Read header to check the euvi wavelength. junk=SCCREADFITS(stereo_b,hdr,/SILENT,/NODATA) IF (hdr.wavelnth NE varstruct.wavelnth) THEN BEGIN stereo_b='' ENDIF ENDIF stereo_b_list[i]=stereo_b IF stereo_b_list[i] NE '' THEN BREAK ENDIF ENDFOR ;------------------------------------------------------- ; Check that at least 1 matching a/b pair was found. ;------------------------------------------------------- ndx=WHERE(stereo_b_list NE '',count) IF (count GT 0) THEN BEGIN hourvalue=hh ENDIF ELSE BEGIN hh=STRTRIM(LONG(hh)-1) IF (LONG(hh) LT 0) THEN BEGIN dd_offset=dd_offset-1 hh='23' ENDIF IF (hh LT 10) THEN hh='0'+STRTRIM(hh,2) ELSE hh=STRTRIM(hh,2) ENDELSE ENDWHILE recent_struct.stereo_a_list_ptr = stereo_a_list_ptr recent_struct.stereo_b_list_ptr = stereo_b_list_ptr recent_struct.datevalue = datevalue IF (varstruct.hourvalue NE 'fullday') THEN recent_struct.hourvalue=hourvalue WIDGET_CONTROL,varstruct.filelist,SET_VALUE='click on Update List' WIDGET_CONTROL,varstruct.gobutton,SENSITIVE=0 varstruct.stereo_a_list_ptr=PTR_NEW('') WIDGET_CONTROL,varstruct.datefield,SET_VALUE=varstruct.datevalue WIDGET_CONTROL,varstruct.hourfield,SET_VALUE=hh IF WIDGET_INFO(temp_base,/VALID_ID) THEN BEGIN WIDGET_CONTROL,temp_base,/DESTROY ENDIF RETURN,recent_struct END PRO sunloop_event,event WIDGET_CONTROL,event.TOP,GET_UVALUE=varstruct ;------------------------------------------------------- ; Handle all radio buttons first. ;------------------------------------------------------- WIDGET_CONTROL,event.ID,GET_UVALUE=uval ;------------------------------------------------------- ; Uval will be TYPE=1 (scaler string) if a radio button is being pressed. ;------------------------------------------------------- IF SIZE(uval,/TYPE) THEN BEGIN IF (uval EQ 'field') THEN BEGIN WIDGET_CONTROL,varstruct.filelist,SET_VALUE='click on Update List' WIDGET_CONTROL,varstruct.gobutton,SENSITIVE=0 varstruct.stereo_a_list_ptr=PTR_NEW('') ;------------------------------------------------------- ; Turn off auto_update when date/time is manually adjusted. ;------------------------------------------------------- varstruct.most_recent_auto_update=0 ENDIF ELSE BEGIN ;------------------------------------------------------- ; Make sure button is being pressed, not (also) released which causes a second event to occur. ;------------------------------------------------------- IF (event.SELECT EQ 1) THEN BEGIN WIDGET_CONTROL, event.ID, GET_VALUE=val CASE uval OF 'detector' : BEGIN varstruct.detector=val WIDGET_CONTROL,varstruct.wavelnth_base,SENSITIVE=(varstruct.detector EQ 'euvi') WIDGET_CONTROL,varstruct.filelist,SET_VALUE='click on Update List' WIDGET_CONTROL,varstruct.gobutton,SENSITIVE=0 varstruct.stereo_a_list_ptr=PTR_NEW('') ;; ;------------------------------------------------------- ;; ; Trigger another event to force selection of 'one hour'. ;; ;------------------------------------------------------- ;; WIDGET_CONTROL,event.TOP,SET_UVALUE=varstruct ;; sunloop_event,{id:varstruct.hour_onehour_button,top:varstruct.sunloop_tlb,handler:varstruct.sunloop_tlb,select:1} ;; WIDGET_CONTROL,varstruct.hour_onehour_button,/SET_BUTTON ;; WIDGET_CONTROL,event.TOP,GET_UVALUE=varstruct IF (val EQ 'euvi') THEN BEGIN ; ; Turn on calibration for EUVI. ; WIDGET_CONTROL,varstruct.calibrate_button_yes,/SET_BUTTON ; varstruct.calibrate='yes' ENDIF ELSE BEGIN ; ; Turn off calibration for COR and HI. ; WIDGET_CONTROL,varstruct.calibrate_button_no,/SET_BUTTON ; varstruct.calibrate='no' IF (val EQ 'hi_1') OR (val EQ 'hi_2') THEN BEGIN ;; ;------------------------------------------------------- ;; ; Trigger another event to force selection of 'full day'. ;; ;------------------------------------------------------- ;; WIDGET_CONTROL,event.TOP,SET_UVALUE=varstruct ;; sunloop_event,{id:varstruct.hour_fullday_button,top:varstruct.sunloop_tlb,handler:varstruct.sunloop_tlb,select:1} ;; WIDGET_CONTROL,varstruct.hour_fullday_button,/SET_BUTTON ;; WIDGET_CONTROL,event.TOP,GET_UVALUE=varstruct ENDIF ENDELSE IF (varstruct.most_recent_auto_update EQ 1) THEN BEGIN ;------------------------------------------------------- ; Trigger another event to force auto_update to occur. ;------------------------------------------------------- WIDGET_CONTROL,event.TOP,SET_UVALUE=varstruct sunloop_event,{id:varstruct.most_recent_button,top:varstruct.sunloop_tlb,handler:varstruct.sunloop_tlb,select:1} WIDGET_CONTROL,event.TOP,GET_UVALUE=varstruct ENDIF END 'wavelnth' : BEGIN varstruct.wavelnth=val WIDGET_CONTROL,varstruct.filelist,SET_VALUE='click on Update List' WIDGET_CONTROL,varstruct.gobutton,SENSITIVE=0 varstruct.stereo_a_list_ptr=PTR_NEW('') IF (varstruct.most_recent_auto_update EQ 1) THEN BEGIN ;------------------------------------------------------- ; Trigger another event to force auto_update to occur. ;------------------------------------------------------- WIDGET_CONTROL,event.TOP,SET_UVALUE=varstruct sunloop_event,{id:varstruct.most_recent_button,top:varstruct.sunloop_tlb,handler:varstruct.sunloop_tlb,select:1} WIDGET_CONTROL,event.TOP,GET_UVALUE=varstruct ENDIF END 'hour' : BEGIN varstruct.hourvalue=(['','fullday'])[(val EQ 'Full Day')] WIDGET_CONTROL,varstruct.hourfield,SENSITIVE=(varstruct.hourvalue EQ '') WIDGET_CONTROL,varstruct.filelist,SET_VALUE='click on Update List' WIDGET_CONTROL,varstruct.gobutton,SENSITIVE=0 varstruct.stereo_a_list_ptr=PTR_NEW('') END 'filecopy' : BEGIN varstruct.filecopy=val END 'rotate' : BEGIN varstruct.rotate=val END 'calibrate' : BEGIN varstruct.calibrate=val END ELSE : BEGIN ; Do nothing. END ENDCASE ENDIF ENDELSE WIDGET_CONTROL,event.TOP,SET_UVALUE=varstruct RETURN ENDIF ;------------------------------------------------------- ; Handle all complicated events from here on. ;------------------------------------------------------- WIDGET_CONTROL,event.TOP,SENSITIVE=0 WIDGET_CONTROL,/HOURGLASS IF (event.ID EQ varstruct.most_recent_button) THEN BEGIN ;------------------------------------------------------- ; Turn on auto_update when button is pressed, this is because most recent available data may ; be different for different detectors and wavelengths. This ensures the user will not get ; confused into thinking that by selecting most recent available, and subsequently changing ; the detector or wavelength, that the result is still the most recent available. Leave ; auto_update turned on until the date/time is manually adjusted. ;------------------------------------------------------- varstruct.most_recent_auto_update=1 recent_struct=find_most_recent_data(varstruct) IF (recent_struct.datevalue EQ '') THEN BEGIN WIDGET_CONTROL,varstruct.sunloop_tlb,SENSITIVE=1 WIDGET_CONTROL,event.TOP,SET_UVALUE=varstruct RETURN ENDIF varstruct.stereo_a_list_ptr = recent_struct.stereo_a_list_ptr varstruct.stereo_b_list_ptr = recent_struct.stereo_b_list_ptr varstruct.datevalue = recent_struct.datevalue WIDGET_CONTROL,varstruct.datefield,SET_VALUE=varstruct.datevalue IF (varstruct.hourvalue NE 'fullday') THEN BEGIN varstruct.hourvalue=recent_struct.hourvalue WIDGET_CONTROL,varstruct.hourfield,SET_VALUE=varstruct.hourvalue ENDIF ENDIF IF (event.ID EQ varstruct.updatebutton) THEN BEGIN ;================================================================== ; Progress bar set-up vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv ;================================================================== ; Set up progress bar. therm = WIDGET_BASE( TITLE = 'Searching for simultaneous A/B pairs...', /COLUMN, GROUP_LEADER = varstruct.sunloop_tlb ) progress = WIDGET_DRAW( therm, XSIZE = 700, YSIZE = 25, RETAIN = 2 ) label = WIDGET_LABEL( therm, VALUE = '0%', /DYNAMIC_RESIZE ) cancelB = WIDGET_BUTTON( therm, VALUE = 'Cancel' ) WIDGET_CONTROL, therm, /REALIZE ; ; Display a wedge in the background. ; a=BYTARR(!D.X_SIZE,!D.Y_SIZE) ; FOR i=0,N_ELEMENTS(a[*,0])-1 DO a[i,*]=255-FIX(255/(N_ELEMENTS(a[*,0])/(i+1.))) ; LOADCT,1,/SILENT ; TV,a WIDGET_CONTROL, progress, GET_VALUE = progress_bar_window count = 0 per = 0 perPrevious = 0 cancel_pressed = 0 stop_showing = 0 ;================================================================== ; Progress bar set-up ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ;================================================================== WIDGET_CONTROL,varstruct.datefield,GET_VALUE=datevalue ; Strip any inadvertent leading or trailing blank characters. datevalue=STRTRIM(datevalue,2) WIDGET_CONTROL,varstruct.datefield,SET_VALUE=datevalue varstruct.datevalue=datevalue ;------------------------------------------------------- ; Select the two filenames for the a/b stereo pair. ;------------------------------------------------------- date=varstruct.datevalue hour=varstruct.hourvalue IF (hour EQ 'fullday') THEN BEGIN hour='' ENDIF ELSE BEGIN WIDGET_CONTROL,varstruct.hourfield,GET_VALUE=hourvalue ; Strip any inadvertent leading or trailing blank characters. hourvalue=STRTRIM(hourvalue,2) ; Strip any characters beyond hhmmss IF STRLEN(hourvalue GT 6) THEN BEGIN hourvalue=STRMID(hourvalue,0,6) ENDIF WIDGET_CONTROL,varstruct.hourfield,SET_VALUE=hourvalue varstruct.hourvalue=hourvalue IF (STRLEN(hourvalue) EQ 1) THEN hour='0'+hourvalue ELSE hour=hourvalue ENDELSE ;------------------------------------------------------- ; Generate list of STEREO-A FITS files for yyyymmdd_hh*, excluding "space weather" ("7"). ;------------------------------------------------------- ; source_dir_a= SCC_DATA_PATH('a', TYPE='img', TELESCOPE=varstruct.detector, DATE=date) ; stereo_a_list=FILE_SEARCH(source_dir_a, date+'_'+hour+'*.fts', /FULLY_QUALIFY_PATH, COUNT=file_count) stereo_a_list=SCCLISTER(date,varstruct.detector,SCID='a',IMGTYPE='img',DEST='notSW') CASE SIZE(stereo_a_list,/TYPE) OF 7 : BEGIN ; Type = String. Presumably blank '' idicating that no matching files were found. stereo_a_list='' END 8 : BEGIN ; Type = Structure. Presumably filled with relevant results. stereo_a_list=stereo_a_list.sc_a END ENDCASE IF (hour NE 'fullday') THEN BEGIN datehour=date+'_'+hour ndx=WHERE(STRPOS(stereo_a_list,datehour) GE 0,count) IF count GT 0 THEN BEGIN stereo_a_list=stereo_a_list[ndx] ENDIF ELSE BEGIN stereo_a_list='' ENDELSE ENDIF IF STRMID(varstruct.detector,0,3) EQ 'cor' THEN BEGIN ; source_dir_a_seq= SCC_DATA_PATH('a', TYPE='seq', TELESCOPE=varstruct.detector, DATE=date) ; stereo_a_seq_list=FILE_SEARCH(source_dir_a_seq, date+'_'+hour+'*.fts', /FULLY_QUALIFY_PATH, COUNT=file_count) stereo_a_seq_list=SCCLISTER(date,varstruct.detector,SCID='a',IMGTYPE='seq',POLAR='0.0',DEST='notSW') CASE SIZE(stereo_a_seq_list,/TYPE) OF 7 : BEGIN ; Type = String. Presumably blank '' idicating that no matching files were found. stereo_a_seq_list='' END 8 : BEGIN ; Type = Structure. Presumably filled with relevant results. stereo_a_seq_list=stereo_a_seq_list.sc_a END ENDCASE IF (hour NE 'fullday') THEN BEGIN datehour=date+'_'+hour ndx=WHERE(STRPOS(stereo_a_seq_list,datehour) GE 0,count) IF count GT 0 THEN BEGIN stereo_a_seq_list=stereo_a_seq_list[ndx] ENDIF ELSE BEGIN stereo_a_seq_list='' ENDELSE ENDIF stereo_a_list=[ stereo_a_list, stereo_a_seq_list ] sort_ndx=SORT(strmid(FILE_BASENAME(stereo_a_list),0,15)) stereo_a_list=stereo_a_list[sort_ndx] ; Strip out any blank lines ndx=WHERE(stereo_a_list NE '',count) IF count GT 0 THEN BEGIN stereo_a_list=stereo_a_list[ndx] ENDIF ENDIF ; Weed out Space Weather. weeds=['7eu','7c1','7c2','7h1','7h2'] FOR w=0,N_ELEMENTS(weeds)-1 DO BEGIN ndx=WHERE(STRPOS(stereo_a_list,weeds[w]) EQ -1,ndx_count) IF (ndx_count GT 0) THEN stereo_a_list=stereo_a_list[ndx] ENDFOR GOTO,SKIP_CHECK_COMPLETE_SERIES_LIST ;incorrect implementation, needs work. ;only rare cases where series is incomplete, usually most recent data where processing at NRL not yet complete. ; Error check that a complete series exists. CASE varstruct.detector OF 'cor1' : list = COR1_TOTBSERIES(date, 'combined') 'cor2' : list = COR1_TOTBSERIES(date, 'combined', /COR2) ENDCASE IF N_ELEMENTS(list) GT 1 THEN BEGIN ; 3-series FOR j=0,2 DO BEGIN ; STEREO-A, STEREO-B FOR k=0,1 DO BEGIN ; First entry (0). IF FINDFILE((list.filename)[j,0,k]) EQ '' THEN BEGIN ddddd=DIALOG_MESSAGE(['Incomplete series for that time.']) IF WIDGET_INFO(temp_base,/VALID_ID) THEN BEGIN WIDGET_CONTROL,temp_base,/DESTROY ENDIF RETURN ENDIF ENDFOR ENDFOR ENDIF SKIP_CHECK_COMPLETE_SERIES_LIST: ;------------------------------------------------------- ; Check that list contains something. ;------------------------------------------------------- IF (stereo_a_list[0] EQ '') THEN BEGIN IF STRMID(varstruct.detector,0,2) EQ 'hi' AND (varstruct.hourvalue NE 'fullday') THEN BEGIN WIDGET_CONTROL,varstruct.filelist,SET_VALUE=['none found','try selecting Full Day'] ENDIF ELSE BEGIN WIDGET_CONTROL,varstruct.filelist,SET_VALUE='none found' ENDELSE ; Destroy progress bar. IF WIDGET_INFO( therm, /VALID_ID ) THEN BEGIN WIDGET_CONTROL, therm, /DESTROY ENDIF WIDGET_CONTROL,event.TOP,SENSITIVE=1 WIDGET_CONTROL,event.TOP,SET_UVALUE=varstruct RETURN ENDIF ;------------------------------------------------------- ; Create blank "b" list, same length as "a" list. ;------------------------------------------------------- stereo_b_list=strarr(n_elements(stereo_a_list)) source_dir_b= SCC_DATA_PATH('b', TYPE='img', TELESCOPE=varstruct.detector, DATE=date) ;------------------------------------------------------- ; Loop over every "a" filename. ;------------------------------------------------------- FOR i=0L,N_ELEMENTS(stereo_a_list)-1 DO BEGIN ;================================================================== ; Progress bar update vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv ;================================================================== IF cancel_pressed THEN BEGIN ; Destroy progress bar. IF WIDGET_INFO( therm, /VALID_ID ) THEN BEGIN WIDGET_CONTROL, therm, /DESTROY ENDIF WIDGET_CONTROL,event.TOP,SENSITIVE=1 WIDGET_CONTROL,event.TOP,SET_UVALUE=varstruct RETURN ENDIF IF WIDGET_INFO( therm, /VALID_ID ) THEN BEGIN ; Update progress bar. per = i / FLOAT( n_elements(stereo_a_list) ) perCheck = per * 100 IF (perCheck GT perPrevious) THEN BEGIN curwin = !d.window WSET, progress_bar_window LOADCT,3,/SILENT ; ; Vary the color index from 0-255 over the life of the progress bar. ; POLYFILL, [0,per,per,0], [0,0,1,1], /NORMAL, COLOR = FIX(SIN(per)*255) ; Disply wedge instead of polyfill. a=BYTARR(CEIL(!D.X_SIZE*per),!D.Y_SIZE) FOR p=0,N_ELEMENTS(a[*,0])-1 DO a[p,*]=FIX(255/(N_ELEMENTS(a[*,0])/(p+1.))) TV,a LOADCT,0,/SILENT WSET, curwin WIDGET_CONTROL, label, SET_VALUE = STRCOMPRESS( CEIL( per * 100 ) )+'%' perPrevious = CEIL( per * 100 ) ENDIF IF WIDGET_INFO( cancelB, /VALID_ID ) THEN BEGIN IF WIDGET_INFO( cancelB, /VALID_ID ) THEN quit = WIDGET_EVENT( cancelB, /NOWAIT ) IF (quit.ID EQ cancelB) THEN cancel_pressed=1 WIDGET_CONTROL,/HOURGLASS ENDIF ENDIF ;================================================================== ; Progress bar update ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ;================================================================== ;------------------------------------------------------- ; Look for matching STEREO-B image (with same date & time). ;------------------------------------------------------- stereo_b=FILE_SEARCH(source_dir_b,STRMID(FILE_BASENAME(stereo_a_list[i]),0,20)+'B.fts',/FULLY_QUALIFY_PATH,COUNT=file_count) IF STRMID(varstruct.detector,0,3) EQ 'cor' THEN BEGIN source_dir_b_seq= SCC_DATA_PATH('b', TYPE='seq', TELESCOPE=varstruct.detector, DATE=date) stereo_b_seq=FILE_SEARCH(source_dir_b_seq, STRMID(FILE_BASENAME(stereo_a_list[i]),0,20)+'B.fts', /FULLY_QUALIFY_PATH, COUNT=file_count) stereo_b=[ stereo_b, stereo_b_seq ] ; Strip out any blank lines ndx=WHERE(stereo_b NE '',count) IF count GT 0 THEN BEGIN stereo_b=stereo_b[ndx] ENDIF ENDIF stereo_b=stereo_b[0] IF (stereo_b NE '') THEN BEGIN ;------------------------------------------------------- ; If EUVI wavelength is specified then check header to see if data is of specified wavelength. ;------------------------------------------------------- IF (varstruct.detector EQ 'euvi') THEN BEGIN ;------------------------------------------------------- ; Read header to check the euvi wavelength. ;------------------------------------------------------- junk=SCCREADFITS(stereo_b,hdr,/SILENT,/NODATA) IF (hdr.wavelnth NE varstruct.wavelnth) THEN stereo_b='' ENDIF stereo_b_list[i]=stereo_b ENDIF ENDFOR ; Strip out any blank lines. ndx=WHERE(stereo_b_list NE '',count) IF count GT 0 THEN BEGIN stereo_a_list=stereo_a_list[ndx] stereo_b_list=stereo_b_list[ndx] ENDIF ;------------------------------------------------------- ; Check that at least 1 matching a/b pair was found. ;------------------------------------------------------- ndx=WHERE(stereo_b_list NE '',count) IF (count GT 0) THEN BEGIN ;------------------------------------------------------- ; Reduce lists to only matching a/b pairs. ;------------------------------------------------------- stereo_a_list=stereo_a_list[ndx] stereo_b_list=stereo_b_list[ndx] varstruct.stereo_a_list_ptr=PTR_NEW(stereo_a_list) varstruct.stereo_b_list_ptr=PTR_NEW(stereo_b_list) ENDIF ELSE BEGIN WIDGET_CONTROL,varstruct.filelist,SET_VALUE='none found' ;------------------------------------------------------- ; Destroy progress bar. ;------------------------------------------------------- IF WIDGET_INFO( therm, /VALID_ID ) THEN BEGIN WIDGET_CONTROL, therm, /DESTROY ENDIF WIDGET_CONTROL,event.TOP,SENSITIVE=1 WIDGET_CONTROL,event.TOP,SET_UVALUE=varstruct RETURN ENDELSE ;================================================================== ; Progress bar destroy vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv ;================================================================== ; Destroy progress bar. IF WIDGET_INFO( therm, /VALID_ID ) THEN BEGIN WIDGET_CONTROL, therm, /DESTROY ENDIF ;================================================================== ; Progress bar destroy ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ;================================================================== ;------------------------------------------------------- ; Set directory label. ; Add PATH_SEP() to value of sourcelabel for user interface display purposes only. ;------------------------------------------------------- WIDGET_CONTROL,varstruct.sourcelabel,SET_VALUE=FILE_DIRNAME((*(varstruct.stereo_a_list_ptr))[0])+PATH_SEP() ;------------------------------------------------------- ; Put list of files into list widget. ;------------------------------------------------------- IF STRMID(varstruct.detector,0,3) EQ 'cor' THEN BEGIN list_for_widget=*(varstruct.stereo_a_list_ptr) FOR z=0,N_ELEMENTS(list_for_widget)-1 DO BEGIN ndx=(STRPOS(list_for_widget[z],'seq/cor'))[0] IF ndx EQ -1 THEN BEGIN ndx=(STRPOS(list_for_widget[z],'img/cor'))[0] ENDIF list_for_widget[z]=STRMID(list_for_widget[z],ndx,STRLEN(list_for_widget[z])-1) ENDFOR WIDGET_CONTROL,varstruct.filelist,SET_VALUE=list_for_widget ENDIF ELSE BEGIN WIDGET_CONTROL,varstruct.filelist,SET_VALUE=FILE_BASENAME(*(varstruct.stereo_a_list_ptr)) ENDELSE varstruct.filelist_ndx=0 WIDGET_CONTROL,varstruct.filelist,SET_LIST_SELECT=varstruct.filelist_ndx WIDGET_CONTROL,varstruct.gobutton,SENSITIVE=1 ENDIF IF (event.ID EQ varstruct.helpbutton) THEN BEGIN ddddd=DIALOG_MESSAGE(['Sunloop User Guide:','','$SSW/stereo/secchi/idl/display/sunloop/sunloop_user_guide.pdf'],/INFORMATION) ENDIF IF (event.ID EQ varstruct.filelist) OR (event.ID EQ varstruct.gobutton) THEN BEGIN startup_tiepointer=0 CASE 1 OF (event.ID EQ varstruct.gobutton) : BEGIN startup_tiepointer=1 END (event.ID EQ varstruct.filelist) : BEGIN varstruct.filelist_ndx=event.INDEX IF (event.CLICKS EQ 2) THEN BEGIN startup_tiepointer=1 ENDIF END ENDCASE IF startup_tiepointer THEN BEGIN IF PTR_VALID(varstruct.stereo_a_list_ptr) OR (varstruct.start_from_command_line) THEN BEGIN IF (NOT varstruct.start_from_command_line) THEN BEGIN ;------------------------------------------------------- ; Store the pair of filenames. ;------------------------------------------------------- varstruct.stereo_a_image=(*(varstruct.stereo_a_list_ptr))[varstruct.filelist_ndx] varstruct.stereo_b_image=(*(varstruct.stereo_b_list_ptr))[varstruct.filelist_ndx] ENDIF IF SIZE(varstruct.stereo_a_image,/TYPE) EQ 7 THEN BEGIN IF IS_FITS(varstruct.stereo_a_image) AND IS_FITS(varstruct.stereo_b_image) THEN BEGIN ;------------------------------------------------------- ; Print the pair of filenames. ;------------------------------------------------------- print,varstruct.stereo_a_image print,varstruct.stereo_b_image IF (varstruct.filecopy eq 'yes') THEN BEGIN CD,CURRENT=current_dir FILE_COPY,varstruct.stereo_a_image,current_dir,/ALLOW_SAME FILE_COPY,varstruct.stereo_b_image,current_dir,/ALLOW_SAME ENDIF ;------------------------------------------------------- ; Start the tiepointer. ;------------------------------------------------------- fireup_tiepointer, varstruct ENDIF ELSE BEGIN IF (varstruct.stereo_a_image NE '') THEN BEGIN ddddd=DIALOG_MESSAGE([ $ varstruct.stereo_a_image, $ 'The selected file failed the IS_FITS() test.', $ 'It is possible that the selected file is a FITS header with no image data.', $ '','Try selecting a different file.' ] ) ENDIF ENDELSE ENDIF ELSE BEGIN ;------------------------------------------------------- ; Start the tiepointer. ;------------------------------------------------------- fireup_tiepointer, varstruct ENDELSE ENDIF ENDIF ENDIF WIDGET_CONTROL,event.TOP,SET_UVALUE=varstruct WIDGET_CONTROL,event.TOP,SENSITIVE=1 END PRO sunloop, $ stereo_a_image, $ ; image array or FITS filename stereo_b_image, $ ; image array or FITS filename stereo_a_header, $ ; for image array only stereo_b_header, $ ; for image array only ROTATE=rotate, $ NO_SECCHI_PREP=no_secchi_prep, $ XY_FILENAME=xy_filename, $ NO_SUNLOOP_GUI=no_sunloop_gui IF KEYWORD_SET(ROTATE) THEN rotate='to stereo baseline' ELSE rotate='no' IF ~KEYWORD_SET(NO_SECCHI_PREP) THEN calibrate='yes' ELSE calibrate='no' a_type=SIZE(stereo_a_image,/TYPE) b_type=SIZE(stereo_b_image,/TYPE) CASE 1 OF (a_type EQ 7) AND (b_type EQ 7) : BEGIN junk = SCCREADFITS(stereo_a_image,hdr,/SILENT,/NODATA) detector = STRLOWCASE(hdr.detector) start_from_command_line = 1 END (a_type GE 1 AND b_type LE 5) AND (a_type GE 1 AND b_type LE 5) : BEGIN detector = STRLOWCASE(stereo_a_header.detector) start_from_command_line = 1 END ELSE : BEGIN detector = 'euvi' rotate = 'to stereo baseline' ;'no' calibrate = 'yes' stereo_a_image = '' stereo_b_image = '' stereo_a_header = '' stereo_b_header = '' start_from_command_line = 0 END ENDCASE IF KEYWORD_SET(xy_filename) THEN xy_filename=xy_filename ELSE xy_filename='' cd,CURRENT=localdir wavelnth = '304' datevalue = '20070831' hourvalue = '21' filecopy = 'no' stereo_a_list_ptr = PTR_NEW('') stereo_b_list_ptr = PTR_NEW('') most_recent_auto_update = 0 sunloop_tlb = WIDGET_BASE(TITLE='Sunloop',/COLUMN) selection_base = WIDGET_BASE(sunloop_tlb,/COLUMN,/FRAME) datebase = WIDGET_BASE(selection_base,/ROW) datefield = CW_FIELD(datebase,VALUE='',/STRING,TITLE='Date: yyyymmdd',/ALL_EVENTS,UVALUE='field') most_recent_button = WIDGET_BUTTON(datebase,VALUE='Most Recent') hourbase = WIDGET_BASE(selection_base,/ROW) hourfield = CW_FIELD(hourbase,VALUE='',/STRING,TITLE='Hour: h or hh ',/ALL_EVENTS,UVALUE='field') hourbase2 = WIDGET_BASE(hourbase,/ROW,/EXCLUSIVE) hour_onehour_button = WIDGET_BUTTON(hourbase2,VALUE='One Hour',UVALUE='hour') hour_fullday_button = WIDGET_BUTTON(hourbase2,VALUE='Full Day',UVALUE='hour') WIDGET_CONTROL,hour_onehour_button,/SET_BUTTON detector_base = WIDGET_BASE(selection_base,/ROW) detector_label = WIDGET_LABEL(detector_base,VALUE='Detector:') detector_buttons_base = WIDGET_BASE(detector_base,/ROW,/EXCLUSIVE) detector_button_euvi = WIDGET_BUTTON(detector_buttons_base,VALUE='euvi',UVALUE='detector') detector_button_cor1 = WIDGET_BUTTON(detector_buttons_base,VALUE='cor1',UVALUE='detector') detector_button_cor2 = WIDGET_BUTTON(detector_buttons_base,VALUE='cor2',UVALUE='detector') detector_button_hi_1 = WIDGET_BUTTON(detector_buttons_base,VALUE='hi_1',UVALUE='detector') detector_button_hi_2 = WIDGET_BUTTON(detector_buttons_base,VALUE='hi_2',UVALUE='detector') WIDGET_CONTROL,detector_button_euvi,SET_BUTTON=(detector EQ 'euvi') WIDGET_CONTROL,detector_button_cor1,SET_BUTTON=(detector EQ 'cor1') WIDGET_CONTROL,detector_button_cor2,SET_BUTTON=(detector EQ 'cor2') WIDGET_CONTROL,detector_button_hi_1,SET_BUTTON=(detector EQ 'hi_1') WIDGET_CONTROL,detector_button_hi_2,SET_BUTTON=(detector EQ 'hi_2') wavelnth_base = WIDGET_BASE(selection_base,/ROW) wavelnth_label = WIDGET_LABEL(wavelnth_base,VALUE='euvi Wavelength:') wavelnth_buttons_base = WIDGET_BASE(wavelnth_base,/ROW,/EXCLUSIVE) wavelnth_button_171 = WIDGET_BUTTON(wavelnth_buttons_base,VALUE='171',UVALUE='wavelnth') wavelnth_button_195 = WIDGET_BUTTON(wavelnth_buttons_base,VALUE='195',UVALUE='wavelnth') wavelnth_button_284 = WIDGET_BUTTON(wavelnth_buttons_base,VALUE='284',UVALUE='wavelnth') wavelnth_button_304 = WIDGET_BUTTON(wavelnth_buttons_base,VALUE='304',UVALUE='wavelnth') WIDGET_CONTROL,wavelnth_button_304,/SET_BUTTON rotate_base = WIDGET_BASE(sunloop_tlb,/ROW,/FRAME) rotate_label = WIDGET_LABEL(rotate_base,VALUE='Rotate Images:') rotate_buttons_base = WIDGET_BASE(rotate_base,/ROW,/EXCLUSIVE) rotate_button_raw = WIDGET_BUTTON(rotate_buttons_base,VALUE='no',UVALUE='rotate') rotate_button_baseline = WIDGET_BUTTON(rotate_buttons_base,VALUE='to stereo baseline',UVALUE='rotate') WIDGET_CONTROL,rotate_button_baseline,/SET_BUTTON ; calibrate_base = WIDGET_BASE(sunloop_tlb,/ROW) ; calibrate_label = WIDGET_LABEL(calibrate_base,VALUE='Calibrate Images (SECCHI_PREP):') ; calibrate_buttons_base = WIDGET_BASE(calibrate_base,/ROW,/EXCLUSIVE) ; calibrate_button_no = WIDGET_BUTTON(calibrate_buttons_base,VALUE='no',UVALUE='calibrate') ; calibrate_button_yes = WIDGET_BUTTON(calibrate_buttons_base,VALUE='yes',UVALUE='calibrate') ; WIDGET_CONTROL,calibrate_button_yes,/SET_BUTTON dirbase = WIDGET_BASE(sunloop_tlb,/COLUMN,/FRAME) locallabel_label = WIDGET_LABEL(dirbase,VALUE='Local Path:',/DYNAMIC_RESIZE) ; Add PATH_SEP() to value of locallabel for user interface display purposes only. locallabel = WIDGET_LABEL(dirbase,VALUE=localdir+PATH_SEP(),/DYNAMIC_RESIZE) sourcelabel_label = WIDGET_LABEL(dirbase,VALUE='FITS Path:',/DYNAMIC_RESIZE) ; Add PATH_SEP() to value of sourcelabel for user interface display purposes only. data_path=GETENV('secchi') IF (data_path EQ '') THEN BEGIN data_path=GETENV('SECCHI_LZ') ENDIF IF (data_path EQ '') THEN BEGIN data_path=GETENV('SECCHI_DATA_AHEAD') ENDIF IF (data_path NE '') THEN BEGIN sourcelabel = WIDGET_LABEL(dirbase,VALUE=SCC_DATA_PATH('a'),/DYNAMIC_RESIZE) ENDIF ELSE BEGIN sourcelabel = WIDGET_LABEL(dirbase,VALUE='secchi data path not found',/DYNAMIC_RESIZE) ENDELSE filecopybase1 = WIDGET_BASE(dirbase,/ROW) filecopylabel = WIDGET_label(filecopybase1,VALUE='Copy selected FITS pair to local:') filecopybase2 = WIDGET_BASE(filecopybase1,/ROW,/EXCLUSIVE) filecopy_no = WIDGET_BUTTON(filecopybase2,VALUE='no',UVALUE='filecopy') filecopy_yes = WIDGET_BUTTON(filecopybase2,VALUE='yes',UVALUE='filecopy') WIDGET_CONTROL,filecopy_no,/SET_BUTTON listbase = WIDGET_BASE(sunloop_tlb,/COLUMN,/FRAME) filelist_base = WIDGET_BASE(listbase,/COLUMN) filelist_label = WIDGET_LABEL(filelist_base,VALUE='List:') filelist = WIDGET_LIST(filelist_base,VALUE='click on Update List',YSIZE=10,XSIZE=60) gobuttonbase = WIDGET_BASE(listbase,/ROW) helpbutton = WIDGET_BUTTON(gobuttonbase,VALUE='Help') updatebutton = WIDGET_BUTTON(gobuttonbase,VALUE='Update List') gobutton = WIDGET_BUTTON(gobuttonbase,VALUE='Highlight a Filename and Click Here',SENSITIVE=0) varstruct = { sunloop_tlb:sunloop_tlb, $ start_from_command_line:start_from_command_line, $ detector:detector, $ wavelnth:wavelnth, $ wavelnth_base:wavelnth_base, $ datefield:datefield, $ datevalue:datevalue, $ most_recent_button:most_recent_button, $ most_recent_auto_update:most_recent_auto_update, $ hourfield:hourfield, $ hourvalue:hourvalue, $ hour_onehour_button:hour_onehour_button, $ hour_fullday_button:hour_fullday_button, $ updatebutton:updatebutton, $ rotate_buttons_base:rotate_buttons_base, $ rotate:rotate, $ ; calibrate_button_yes:calibrate_button_yes, $ ; calibrate_button_no:calibrate_button_no, $ calibrate:calibrate, $ filecopy:filecopy, $ localdir:localdir, $ sourcelabel:sourcelabel, $ filelist:filelist, $ filelist_ndx:0L, $ helpbutton:helpbutton, $ gobutton:gobutton, $ stereo_a_list_ptr:stereo_a_list_ptr, $ stereo_b_list_ptr:stereo_b_list_ptr, $ stereo_a_image:stereo_a_image, $ stereo_b_image:stereo_b_image, $ stereo_a_header:stereo_a_header, $ stereo_b_header:stereo_b_header, $ xy_filename:xy_filename } WIDGET_CONTROL,datefield,SET_VALUE=varstruct.datevalue WIDGET_CONTROL,hourfield,SET_VALUE=varstruct.hourvalue WIDGET_CONTROL,sunloop_tlb,SET_UVALUE=varstruct IF ~KEYWORD_SET(no_sunloop_gui) THEN BEGIN WIDGET_CONTROL,sunloop_tlb,/REALIZE XMANAGER,'Sunloop',sunloop_tlb,EVENT_HANDLER='sunloop_event',NO_BLOCK=1 ENDIF ;------------------------------------------------------- ; Trigger event to start tiepointer using filenames given at command line. ;------------------------------------------------------- sunloop_event,{id:varstruct.gobutton,top:varstruct.sunloop_tlb,handler:varstruct.sunloop_tlb,select:1} END