C+ C NAME: C smei_frm_base C PURPOSE: C Calculates pedestal and dark current C CATEGORY: C ucsd/camera/for/lib C CALLING SEQUENCE: logical function smei_frm_base(cframe,nx,ny,frame,pattern, & nped,ped_val,ndark,dark_val,dark_pixs, & ped_aux,dark_aux,base_aux) C INPUTS: C cframe character*(*) fully-qualified file name of SMEI data frame C (only used to format messages; C contains time and camera number). C nx integer horizontal frame size C ny integer vertical frame size C frame (nx,ny) real frame data (usually after running it through C smei_frm_clean) C pattern(nx,ny) real dark current pattern C C ped_aux(*) real passed to href=smei_frm_ped= C Two values of ped_aux returned by smei_frm_ped C are used here: C ped_aux(SMEI__PED_VERY_LOW) (to reject frame) C ped_aux(SMEI__PED_NAIVE_MEAN) (message only) C C dark_aux(*) real passed to href=smei_frm_dark= C If a valid pedestal is returned by smei_frm_ped C then two values in dark_aux are set here before C passing it to smei_frm_dark: C dark_aux(SMEI__DRK_PEDESTAL) C pedestal value returned by smei_frm_ped C dark_aux(SMEI__DRK_RATIO) C dark current ratio of frame and pattern C C base_aux(*) real base_aux(SMEI__BAS_DARK_GUESS) C guess at dark current (with pedestal subtracted) C for this frame (usually the dark current from a C previous frame). C If set to bad, then the naive mean dark current C of the frame is used (without using the pattern). C base_aux(SMEI__BAS_PATTERN_DARK) C dark current of pattern. C Used with base_aux(SMEI__BAS_DARK_GUESS) to obtain C the dark current ratio needed by href=smei_frm_dark=. C base_aux(SMEI__BAS_DARK_MAX_RATIO ) C base_aux(SMEI__BAS_DARK_SCALE_RATIO) C Used to constrain the dark current ratio fed to C smei_frm_dark, but only if the dark current guess C base_aux(SMEI__BAS_DARK_GUESS) is bad. C base_aux(SMEI__BAS_NPED_MIN) C base_aux(SMEI__BAS_NDARK_MIN) C threshold on number of pixels contributing to C pedestal and dark current respectively. C Frames are rejected if less pixels than this C contribute. C base_aux(SMEI__BAS_PED_INIT:SMEI__BAS_PED_INIT+2) C used to reinitialize last_ped C base_aux(SMEI__BAS_NPED_BAD) C needs to be initialized to a negative number C by caller. Other parameters (including this one) C are initialized internally as a result. C OUTPUTS: C smei_frm_base logical .TRUE. if pedestal and dark current are OK C .FALSE. if pedestal and/or dark current are rejected C Note that, if smei_frm_base = .FALSE., the rejected C values are still returned. C nped integer # pixels contributing to pedestal C ped_val real pedestal C ndark integer # pixels contributing to dark current C dark_val real dark current C ped_aux(*) real as modified by smei_frm_ped C C base_aux(*) real base_aux(SMEI__BAS_NPED_BAD) C updated counter for # frames rejected because C pedestal exceeded ped_threshold C base_aux(SMEI__BAS_NBAD) C updated counter for # frames rejected because C not enough pixels contributed to the pedestal, C or because the dark current was bad. C dark_pixs(*) real dark current pixels as returned from href=smei_frm_dark=, C or all set to bad if the frame is rejected here. C CALLS: C Say, iHideLogical, smei_frm_ped, smei_frm_dark, smei_frm_mode C Int2Str, Str2Str, Flt2Str, ArrR4Bad, BadR4, smei_Time2Split C smei_frm_ratio C INCLUDE: include 'filparts.h' include 'smei_frm_layout.h' include 'smei_frm_basepar.h' C PROCEDURE: C 1. Calculate pedestal with smei_frm_ped (using values in ped_aux) C C 2. If pedestal is bad, then reject frame and return .FALSE. C C 3. If pedestal is good, then store good pedestal in dark_aux. C 4. If no guess for dark current is available, calculate it internally C (by calling smei_frm_dark without using pattern) C C 5. Store ratio of dark currents of frame and pattern in dark_aux. C 6. Calculate dark current with smei_frm_dark (using values in dark_aux). C This time make smei_frm_dark use the pattern. C C 7. Test pedestal and dark current. C The test mainly ensures that enough pixels contribute to pedestal C and dark current calculation. C C 8. If the frame is rejected then return .FALSE. C (a recovery attempt is made if more than 12 consecutive frames C are rejected this way). C MODIFICATION HISTORY: C DEC-2004, Paul Hick (UCSD/CASS) C NOV-2008, Paul Hick (UCSD/CASS; pphick@ucsd.edu) C Modified to accomodate new arg in smei_frm_ped call. C Pedestal initialization values stored in C base_aux(SMEI__BAS_PED_INIT+[0,1,2]) are not used anymore. C Instead the value returned by smei_frm_ped_mean is used. C- character cframe*(*) integer nx integer ny real frame (*) real pattern(*) integer nped real ped_val integer ndark real dark_val real dark_pixs(*) real ped_aux (*) real dark_aux (*) real base_aux (*) character cSay*8 /'frm_base'/ character cFlt2Str*14 integer smei_frm_ped integer smei_frm_dark integer smei_frm_mode integer Flt2Str integer Str2Str character cStr *(FIL__LENGTH) character cName*(FIL__LENGTH) integer nbase_bad_count_max /12/ integer tt(2) save iframe, nbase_bad_count, ped_last iStr = iSetFileSpec(cframe) iStr = iGetFileSpec(FIL__NAME,FIL__NAME,cName) iStr = iHideLogical(cframe,cStr) nped_bad = nint(base_aux(SMEI__BAS_NPED_BAD)) nbase_bad = nint(base_aux(SMEI__BAS_NBAD )) if (nped_bad .lt. 0) then ! Initialize if nped_bad is negative nped_bad = 0 ! In-/output args nbase_bad = 0 iframe = 0 ! Saved internally nbase_bad_count = 0 !ped_last = base_aux(SMEI__BAS_PED_INIT+2) ped_last = smei_frm_ped_mean(cframe) call Say(cSay,'I',cName,'initial pedestal='//cFlt2Str(ped_last,2)) end if iframe = iframe+1 bad = BadR4() nped = smei_frm_ped(cframe,nx,ny,frame,pattern,ped_val,ped_aux) smei_frm_base = ped_val .ne. bad nped_min = nint(base_aux(SMEI__BAS_NPED_MIN )) if (smei_frm_base) then dark_aux(SMEI__DRK_PEDESTAL) = ped_val dark_guess = base_aux(SMEI__BAS_DARK_GUESS ) pattern_dark = base_aux(SMEI__BAS_PATTERN_DARK ) if (dark_guess .eq. bad) then ! No dark current guess available ! Guess at dark current is the naive mean (without using ! the pattern). dark_aux(SMEI__DRK_RATIO) = bad ! Don't use pattern ndark = smei_frm_dark(.FALSE., nx, ny, frame, 0.0, dark_val, dark_pixs, dark_aux) if (ndark .eq. 0) then call Say(cSay,'W',cName,'empty frame?') else ! Calculate dark ratio using specified constraints dark_scale_ratio = base_aux(SMEI__BAS_DARK_SCALE_RATIO) if (dark_scale_ratio .eq. bad) then call smei_Time2Split(1,cframe,tt) dark_scale_ratio = smei_frm_ratio(tt) end if dark_max_ratio = base_aux(SMEI__BAS_DARK_MAX_RATIO ) dark_ratio = dark_scale_ratio*(dark_val/pattern_dark) dark_aux(SMEI__DRK_RATIO) = min(dark_ratio, dark_max_ratio) ! Get dark current from median. Use pattern to reject cosmic ray pixels. ndark = smei_frm_dark(.TRUE., nx, ny, frame, pattern, dark_val, dark_pixs, dark_aux) end if else dark_aux(SMEI__DRK_RATIO) = dark_guess/pattern_dark ! Get dark current from median. Use pattern to reject cosmic ray pixels. ndark = smei_frm_dark(.TRUE., nx, ny, frame, pattern, dark_val, dark_pixs, dark_aux) end if ! Use constraints on pedestal and dark current before accepting ! pedestal and dark current. ndark_min = nint(base_aux(SMEI__BAS_NDARK_MIN)) smei_frm_base = nped .ge. nped_min .and. ndark .ge. ndark_min .and. & ped_aux(SMEI__PED_VERY_LOW) .eq. 0.0 ! Set in smei_frm_ped if (smei_frm_base) then ped_last = ped_val ! Saved internally nbase_bad_count = 0 else ! Reject frame iStr = iStr+Str2Str('#ped=' , cStr(iStr+1:)) iStr = iStr+Flt2Str(ped_val,3 , cStr(iStr+1:))+1 iStr = iStr+Str2Str('(' , cStr(iStr+1:)) iStr = iStr+Int2Str(nped , cStr(iStr+1:)) if (nped .lt. nped_min) then iStr = iStr+Str2Str('<' , cStr(iStr+1:)) else iStr = iStr+Str2Str('>' , cStr(iStr+1:)) end if iStr = iStr+Int2Str(nped_min , cStr(iStr+1:)) iStr = iStr+Str2Str(' pix), dark=', cStr(iStr+1:)) iStr = iStr+Flt2Str(dark_val,3 , cStr(iStr+1:))+1 iStr = iStr+Str2Str('(' , cStr(iStr+1:)) iStr = iStr+Int2Str(ndark , cStr(iStr+1:)) if (ndark .lt. ndark_min) then iStr = iStr+Str2Str('<' , cStr(iStr+1:)) else iStr = iStr+Str2Str('>' , cStr(iStr+1:)) end if iStr = iStr+Int2Str(ndark_min , cStr(iStr+1:)) iStr = iStr+Str2Str(' pix)' , cStr(iStr+1:)) if (ped_aux(SMEI__PED_VERY_LOW) .ne. 0.0) & iStr = iStr+Str2Str('#first two ped pixels too low (redundant)', cStr(iStr+1:)) nbase_bad = nbase_bad+1 nbase_bad_count = nbase_bad_count+1 ! Don't lose more than nbase_bad_count_max frames consecutively if (nbase_bad_count .gt. nbase_bad_count_max) then !ped_last = base_aux(SMEI__BAS_PED_INIT+mod(iframe,2))! Vary recovery ped_last value ped_last = smei_frm_ped_mean(cframe) call Say(cSay,'W',cName,'recovered pedestal='//cFlt2Str(ped_last,2)) nbase_bad_count = 0 end if end if else ! Reject frame: bad pedestal ndark = 0 dark_val = bad dark_aux(SMEI__DRK_STDEV) = bad iStr = iStr+Str2Str('#nped=' , cStr(iStr+1:)) iStr = iStr+Int2Str( nped , cStr(iStr+1:)) iStr = iStr+Str2Str(', ped=' , cStr(iStr+1:)) iStr = iStr+Flt2Str(ped_aux(SMEI__PED_NAIVE_MEAN),2,cStr(iStr+1:)) iStr = iStr+Str2Str('>' , cStr(iStr+1:)) iStr = iStr+Flt2Str(smei_frm_ped_mean(cframe),2,cStr(iStr+1:)) iStr = iStr+Str2Str('+' , cStr(iStr+1:)) iStr = iStr+Flt2Str(ped_aux(SMEI__PED_MEAN_EXCESS),3,cStr(iStr+1:)) if (ped_aux(SMEI__PED_VERY_LOW) .ne. 0.0) then iStr = iStr+Str2Str('#first two ped pixels too low', cStr(iStr+1:)) if (nped .lt. nped_min) iStr = iStr+Str2Str(' (redundant)', cStr(iStr+1:)) end if nped_bad = nped_bad+1 end if if (.not. smei_frm_base) then if (iStr .gt. 0) call Say(cSay,'W','reject',cStr) mode = smei_frm_mode(nx, nbin) ! Mode (0,1,2) and binning factor 2^mode !ped_val = bad !dark_val = bad call ArrR4Bad(SMEI__DRK_NPIX/nbin, dark_pixs) end if base_aux(SMEI__BAS_NPED_BAD) = nped_bad base_aux(SMEI__BAS_NBAD ) = nbase_bad return end