; docformat = 'rst' ; ; NAME: ; redIm ; PURPOSE: ; Call a sequence of tools for data reduction: creation of master ; biases, darks, flat. Reduction of scientific frames, shift and add. ; EXPLANATION: ; This procedure is a portail to reduce imaging data, in both the ; visible and near-infrared wavelength ranges. The data is supposed ; to be organized by directories corresponding to observing nights. ; ;+ ; :Description: ; Call a sequence of tools for data reduction: creation of master ; biases, darks, flat. Reduction of scientific frames, shift and add. ; ; This procedure is a portail to reduce imaging data, in both the ; visible and near-infrared wavelength ranges. The data is supposed ; to be organized by directories corresponding to observing nights. ; ; :Categories: ; AstroIM, RedIM ; ; :Params: ; PROJECT: in, required, type=string ; Name of the project, used as root directory ; ; :Keywords: ; dates: in, optional, type=strarr ; An array of dates ('YYYY-MON-DD') to be processed ; doMedian: in, optional, type=boolean, default=0 ; Triggers the creation of median images of bias, dark & flat calibration frames ; doMask: in, optional, type=boolean, default=0 ; Triggers the creation of the bad pixel map. ; doCalibration: in, optional, type=boolean, default=0 ; Triggers the cleaning of the master calibration files (bias, dark & flat) ; doScience: in, optional, type=boolean, default=0 ; Triggers the cleaning of the scientific frames (and PSF) ; doAlign: in, optional, type=boolean, default=0 ; A boolean to trigger the "shift and add" procedure of the scientific frames (and PSF) ; ; maskINFO: in, optional, type=structure ; Contains the parameters for the creation of the Bad Pixel Mask:: ; .YN : Trigger the Cleaning of BP ; .FILE : The name of the user-supplied file with the threshold (in mask_dark_flat) ; .USER : A boolean to use default (0) or user-supplied (1) thresholds ; .SIGMA : Threshold levels (sigma unit) above noise to be considered as bad pixel ; .WIDTH : Size of the window used to clean the bad pixels (pixel) ; ; fringesINFO: in, optional, type=structure ; Contains the parameters for the Fringe of Interference Cleaning:: ; .YN : A boolean Triggering the Cleaning of Fringes in Scientific Frames ; .CP : Path to a file with the Coordinates of the Control Pairs ; ; stripeINFO: in, optional, type=structure ; Contains the parameters for the Stripes Cleaning:: ; .YN : A boolean Triggering the Cleaning of Linear Stripes in Scientific Frames ; .DIR : Direction of stripes removal: None | Hor | Vert | Both ; .MODE : Mode of level evaluation: Median | Fine ; .SAMP : Sample to consider: full | sideXXX where XXX is an integer for the number of pixels ; .COSMIC: Threshold for cosmic rejection (in unit of sky stddev) ; ; sciINFO: in, optional, type=structure ; Contains the parameters for the Scientific Frame cleaning:: ; .FILTER : Filter to analyze (ALL | J | K...) ; .FLAT : Prefered flat (SKY | DOME) ; .TARGET : Target for analyze (ALL | SCI | PSF | Name ...) ; .SKY : Sky evaluation (NoSky - Median - Fine) ; .SERIE : Number of the First Serie ; ; alignINFO: in, optional, type=structure ; Contains the parameters for the Scientific Frame Alignment and Cropping:: ; .REFID : Frame number to be used as reference ; .MODE.MAN : Alignment mode: Manual ; .MODE.STAR : Alignment mode: 2D star profile ; .MODE.CROSS : Alignment mode: Frame cross-correlation ; .GUI: .SIZE : GUI Window Size (pixel) ; .MIN : GUI Min Cut for display (ADU) ; .MAX : GUI Max Cut for display (ADU) ; .REDUC: .SIZE : Size of the Reduced Frame (pixel) ; .MARGIN: Safeguard Area around Reduc Frame (%) ; .COADD : A boolean to trigger the shifting and coadding of frames ; ; workINFO: in, optional, type=structure ; Stucture containing time, operator... information:: ; .ROOT : Root Directory of Projects ; .LOGS : Directory of Log Files ; .OBS : Observatory-Specific File ; .EPHEM: Directory for Ephemeris ; .AUTH : User Name ; .INST : User Institute ; .DATE : Current UTC Date ; ; :Uses: ; initIDL, date_conv, readcol, masterCalib, cleanCalib, cleanSci, ; setAstroName, astroSummary_read, astroSummary_write ; ; :Author: ; B.Carry (IMCCE) ; ; :History: ; Change History:: ; Original Version written in January 2008, B. Carry (ESO/LESIA) ; 2008-Aug-19: B.Carry (ESO) - Serie counting and summary tables ; 2010-Mar-04: B.Carry (ObsPM) - WCS and SkyBoT implementation ; 2010-Oct-29: B.Carry (ESA) - Basic astrometry added ; 2010-Dec-16: B.Carry (ESA) - Works with CUBE of data (NAXIS ne 1) ; 2010-Dec-20: B.Carry (ESA) - User-supplied bap pixel list input possible ; 2013-Jun-14: B.Carry (IMCCE) - Improved sky substraction in cube/nocube modes ; 2013-Jun-15: B.Carry (IMCCE) - Improved stripes removal ; 2013-Sep. : B.Carry (IMCCE) - Cleaned I/O - Finer stripes removal (sample selection...) ; 2014-Apr. : B.Carry (IMCCE) - Processing moved to sub-routines ; 2015-Jan. : B.Carry (IMCCE) - Automatic creation of BP mask threshold file ; 2015 Nov. : B.Carry (OCA) - Added compile option idl2 ;- pro redIM, project, dates=dates, doMedian=doMedian, doMask=doMask, $ doCalibration=doCalibration, doScience=doScience, doAlign=doAlign, $ maskINFO=maskINFO, fringesINFO=fringesINFO, stripeINFO=stripeINFO, $ sciINFO=sciINFO, alignINFO=alignINFO, workINFO=workINFO ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--- TAG --- I -- Initialization And Input Verification -----------------------; ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; compile_opt idl2 ;--I.1-- Set IDL to Local Working Environment ----------------------------------------- confAstroIM= initIDL() confRedim = initIDL(confAstroIM.soft.redim, /REDIM) ;--I.2-- Information for Bad Pixel Map Creation --------------------------------------- maskDefault={yn: confRedim.mask.yn, $ ;-Boolean Triggering the Cleaning of BP file: confRedim.mask.f, $ ;-User-supplied file with All the Thresholds user: confRedim.mask.u, $ ;-Boolean to Use above File sigma: confRedim.mask.s, $ ;-Default Threshold Levels for Bad Pixels Detection width: confRedim.mask.w } ;-Window Size for the Median Filter if not keyword_set(maskINFO) then maskINFO=maskDefault else maskINFO = updateStructure(maskDefault,maskINFO) ;--I.3 -- Information for Fringes Map Creation and Fringes Removal -------------------- fringeDefault={yn: confRedim.fringe.yn, $ ;-Trigger the Cleaning of Fringes in Scientific Frames cp: confRedim.fringe.cp } ;-File with the Coordinates of the Control Pairs if not keyword_set(fringeINFO) then fringeINFO=fringeDefault else fringeINFO = updateStructure(fringeDefault,fringeINFO) ;--I.4-- Information for Stripes Cleaning -------------------------------------------- stripeDefault={yn: confRedim.stripe.yn, $ ;-Trigger the Cleaning of Linear Stripes in Scientific Frames dir: confRedim.stripe.dir, $ ;-Direction of stripes removal: None | Hor | Vert | Both mode: confRedim.stripe.mode, $ ;-Level evaluation: Median - Fine samp: confRedim.stripe.samp, $ ;-Sample to consider: full | sideXXX cosmic: confRedim.stripe.cosmic} ;-Threshold for cosmic rejection (in unit of sky stddev) if not keyword_set(stripeINFO) then stripeINFO=stripeDefault else stripeINFO = updateStructure(stripeDefault,stripeINFO) ;--I.5-- Information for Science Frame Cleanning -------------------------------------- sciDefault={filter: confRedim.sci.filter, $ ;-Filter to analyze (ALL | J | K...) flat: confRedim.sci.flat, $ ;-Prefered flat (SKY | DOME) target: confRedim.sci.target, $ ;-Target for analyze (ALL | SCI | PSF | Name ...) sky: confRedim.sci.sky, $ ;-Sky evaluation (Dark - Median - Fine) serie: confRedim.sci.serie } ;-Starting Serie if not keyword_set(sciINFO) then sciINFO=sciDefault else sciINFO = updateStructure(sciDefault,sciINFO) ;--I.6-- Information for Frame Alignment ---------------------------------------------- alignDefault={refID: confRedim.align.refID, $ ;- Frame number to be used as reference mode: {man: confRedim.align.mode.man, $ ;-Alignment mode: Manual star: confRedim.align.mode.star, $ ;-Alignment mode: 2D star profile cross: confRedim.align.mode.cross},$ ;-Alignment mode: Frame cross-correlation gui: {size: confRedim.align.gui.size, $ ;-GUI Window Size min: confRedim.align.gui.min, $ ;-GUI Min Cut for display (ADU) max: confRedim.align.gui.max}, $ ;-GUI Max Cut for display (ADU) reduc: {size: confRedim.align.size, $ ;-Reduced Frame Size margin: confRedim.align.margin}, $ ;-Safeguard Area around Reduc Frame coadd: confRedim.align.coadd } ;-Do Shift & Add Frames if not keyword_set(alignINFO) then alignINFO=alignDefault else alignINFO = updateStructure(alignDefault,alignINFO) ;--I.7-- General Information: Who, When, Where... ------------------------------------- JD=systime(/UTC, /JULIAN) currentDate = strmid(date_conv( JD, 'FITS'),0,16) workDefault={root: confAstroIM.path.root, $ ;-Root Directory of Projects logs: confAstroIM.path.logs, $ ;-Directory of Log Files obs: confAstroIM.path.obs, $ ;-Observatory-Specific File ephem: confAstroIM.path.ephem, $ ;-Directory for Ephemeris auth: confAstroIM.user.name, $ ;-User Name inst: confAstroIM.user.inst, $ ;-User Institute date: currentDate } ;-Current UTC Date if not keyword_set(workINFO) then workINFO=workDefault else workINFO = updateStructure(workDefault,workINFO) ;--I.8-- Disk I/O - File suffixes & Working Directories--------------------------------- ;--I.8.1-- Place Suffixes in a Common Block common sufixes, suFITS, sufCUBE, sufCLEAN, sufREDUC, sufSnA, sufJPG suFITS = confAstroIM.ext.fits sufJPG = confAstroIM.ext.jpg sufCLEAN = confAstroIM.suffix.clean sufREDUC = confAstroIM.suffix.reduc sufSNA = confAstroIM.suffix.sna ;--I.8.2-- Definition of Logs and Observatories Directories project =strtrim(project,2)+'/' ;--I.8.2/A-- Logs Directory split = strsplit( workINFO.logs, '+', /EXTRACT, count=nbField ) if nbField eq 2 then begin case split[0] of '[root]' : workINFO.logs = workINFO.root+split[1] '[project]': workINFO.logs = workINFO.root+project+'/'+split[1] '[date]' : workINFO.logs = workINFO.root+project+'/YYYY-MON-DD/'+split[1] endcase endif ;--I.8.2/B-- Observatory Database split = strsplit( workINFO.obs, '+', /EXTRACT, count=nbField ) if nbField eq 2 then begin case split[0] of '[root]' : workINFO.obs = workINFO.root+split[1] '[project]': workINFO.obs = workINFO.root+project+'/'+split[1] '[date]' : workINFO.obs = workINFO.root+project+'/YYYY-MON-DD/'+split[1] endcase endif dirOBS = file_dirname( workINFO.obs ) ;--I.9-- Observing Dates -------------------------------------------------------------- ;--I.9/A-- Create a List of Observing Dates if ~file_test(workINFO.logs+'nights.dat') then begin ;--I.9/A.1-- List Nights spawn, 'ls -d '+workINFO.root+project+'/????-*/', dirNight subDir=strsplit(dirNight[0],'/',/extract, count=nbField) ;--I.9/A.2-- Organize nbDate=n_elements(dirNight) nightINFO=replicate({date:''}, nbDate) for kDate=0, nbDate-1 do begin subDir=strsplit(dirNight[kDate],'/',/extract, count=nbField) nightINFO[kDate].date = subDir[nbField-1] endfor ;--I.9/A.3-- Write Summary File if not file_test(workINFO.logs,/directory) then file_mkdir, workINFO.logs trash=astroSummary_write(workINFO.logs+'nights.dat',nightINFO, /NIGHT) endif ;--I.9/B-- Get Dates from Command Line if keyword_set(dates) then begin nbDate=n_elements(dates) nightINFO=replicate({date:''}, nbDate) for kDate=0, nbDate-1 do nightINFO[kDate].date = dates[kDate] ;--I.9/C-- Dates from Night List endif else begin nightINFO=astroSummary_read(workINFO.logs+'nights.dat',/NIGHT) nbDate=n_elements(nightINFO.date) endelse ;--I.10-- Check Task to Excecute ------------------------------------------------------- taskArr = [keyword_set(doMedian), $ keyword_set(doMask), $ keyword_set(doCalibration), $ keyword_set(doScience), $ keyword_set(doAlign) , $ keyword_set(doEdge) ] if total(taskArr) eq 0 then return ;--I.11-- General Constants ---------------------------------------------------------- DegToMAS = 3600000.0D MJD_to_JD = 2400000.5D ;--I.X-- Loop over Observing Nights ------------------------------------------------- for kDate=0, nbDate-1 do begin ;--I.X.1-- Directory Definition for Current Night ;--I.X.1/A-- Basename, raw data, and calibration Directories dirBASE = workINFO.root+project+'/'+nightINFO[kDate].date+'/' dirRAW = dirBASE+'data/raw/' dirRED = dirBASE+'data/reduced/' dirCAL = dirRED +'mask_dark_flat/' if not file_test( dirCAL, /DIR ) then file_mkdir, dirCAL ;--I.X.1/B-- Log Files Directory (if Incremental from Base Directory) posDate = strpos( workINFO.logs, 'YYYY-MON-DD' ) if posDate ge 0 then begin locPath = workINFO.logs strput, locPath, nightINFO[kDate].date, posDate workINFO.logs = locPath endif ;--I.X.1/C-- Observatories DB (if Incremental from Base Directory) posDate = strpos( workINFO.obs, 'YYYY-MON-DD' ) if posDate ge 0 then begin locPath = workINFO.obs strput, locPath, nightINFO[kDate].date, posDate workINFO.obs = locPath endif ;--I.X.2-- Analyze the Content of the Observations ;--I.X.2/A-- Read and Structure the Log readcol, workINFO.logs+'rawfiles-'+nightINFO[kDate].date+'.list', format='(A,A,A,I,F,I,F,A,I,I,I)', $ fileArr, typeArr, objArr, $ serieArr, expArr, nExpArr, scaleArr, filtArr, $ sizeArrX, sizeArrY, sizeArrZ, /SILENT nbFile = n_elements(fileArr) fileINFO=replicate( { name: '', type: '', target: '', serie: 0, DIT: 0., NDIT: 0, $ PS: 0., filter: '', NX: 0, NY: 0, NZ: 0 }, nbFile ) fileINFO.name = strtrim(fileArr,2) fileINFO.type = strtrim(typeArr,2) fileINFO.target= strtrim(objArr,2) fileINFO.serie = serieArr fileINFO.DIT = expArr fileINFO.NDIT = nExpArr fileINFO.PS = scaleArr fileINFO.filter= strtrim(filtArr,2) fileINFO.NX = sizeArrX fileINFO.NY = sizeArrY fileINFO.NZ = sizeArrZ ;--I.X.2/B-- On Image Cubes, Neglect the Last Slice = Cube average (ESO "cube" mode) cubeInd = where( fileINFO.NZ gt 1, nbCube ) if nbCube gt 0 then fileINFO[cubeInd].NZ-- ;--I.X.2/C-- Sort Files According to Data Types biasList = where( strcmp(typeArr,'CALIB',/fold) and strcmp(objArr,'BIAS',/fold) ) darkList = where( strcmp(typeArr,'CALIB',/fold) and strcmp(objArr,'DARK',/fold) ) skyflatList= where( strcmp(typeArr,'CALIB',/fold) and (strcmp(objArr,'FLAT-SKY',/fold) or $ strcmp(objArr,'SKY-FLAT',/fold) ) ) domflatList= where( strcmp(typeArr,'CALIB',/fold) and (strcmp(objArr,'FLAT-LAMP',/fold) or $ strcmp(objArr,'FLAT-DOME',/fold) or $ strcmp(objArr,'DOME-FLAT',/fold) ) ) sciList = where( strcmp(typeArr,'OBJECT',/fold) or $ strcmp(typeArr,'STD',/fold) or strcmp(typeArr,'PSF',/fold) ) skyList = where( strcmp(typeArr,'SKY',/fold) ) ;--I.X.3-- Counter for GUI kTask=0 ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--- TAG --- II -- Median Filtering of the Calibration Files -----------------------; ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; if keyword_set(doMEDIAN) then begin ;--II-- GUI -- Console Output --------------------------------------------------------- kTask++ print, '' print, '------------' print, '-- Task '+strtrim(string(kTask,format='(I)'),2)+' ----------------------------------------------' print, '-- '+nightINFO[kDate].date+' -- Median filtering of Calibration Cubes' print, '--------------------------------------------------------' ;--II.1-- Creation of Master Median Frames ---------------------------------------------- ;--II.1.1-- Bias Frames if biasList[0] ne -1 then begin biasINFO = masterCalib( fileINFO[biasList], {i:dirRAW, o:dirCAL}, workINFO=workINFO, /BIAS ) endif else biasINFO = -1 ;--II.1.2-- Dark Frames if darkList[0] ne -1 then begin darkINFO = masterCalib( fileINFO[darkList], {i:dirRAW, o:dirCAL}, workINFO=workINFO, /DARK ) endif else darkINFO = -1 ;--II.1.3-- Flat Frames if ( domFlatList[0] ne -1 or skyFlatList[0] ne -1 ) then begin ;--II.1.3/a-- Dome Flat only if domflatList[0] ne -1 then begin flatINFO = masterCalib( fileINFO[domFlatList], {i:dirRAW, o:dirCAL}, workINFO=workINFO, /FLAT, /DOME ) ;--II.1.3/b-- Add Sky Flats if skyflatList[0] ne -1 then $ flatINFO = masterCalib( fileINFO[skyFlatList], {i:dirRAW, o:dirCAL}, workINFO=workINFO, /FLAT, /SKY, /APPEND ) ;--II.1.3/c-- Sky Flats only endif else $ flatINFO = masterCalib( fileINFO[skyFlatList], {i:dirRAW, o:dirCAL}, workINFO=workINFO, /FLAT, /SKY ) endif else flatINFO = -1 ;--II.2-- Read Master Median Frames Information ----------------------------------------- endif else begin ;--II.2.1-- Bias Frames if biasList[0] ne -1 or file_test(dirCAL+'bias.list',/READ) then begin nameSum = setAstroName( /SUMMARY, /BIAS ) biasINFO = astroSummary_read(dirCAL+nameSum, /BIAS) endif else biasINFO = -1 ;--II.2.2-- Dark Frames if darkList[0] ne -1 or file_test(dirCAL+'dark.list',/READ) then begin nameSum = setAstroName( /SUMMARY, /DARK ) darkINFO = astroSummary_read(dirCAL+nameSum, /DARK) endif else darkINFO = -1 ;--II.2.3-- Flat Frames if ( domFlatList[0] ne -1 or skyFlatList[0] ne -1 ) ne -1 or file_test(dirCAL+'flat.list',/READ) then begin nameSum = setAstroName( /SUMMARY, /FLAT ) flatINFO = astroSummary_read(dirCAL+nameSum, /FLAT) endif else flatINFO = -1 endelse ;--II.3-- Concatenate Calibration Information ------------------------------------------- calINFO = {m: maskINFO, $ ;-Bad-Pixels b: biasINFO, $ ;-Bias d: darkINFO, $ ;-Dark f: flatINFO, $ ;-Flat sk: fileINFO[skyList], $ ;-Sky st: stripeINFO, $ ;-Linear Stripe fi: fringeINFO} ;-Fringes of Interference verbose=1 ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--- TAG --- III -- Creation of Bap Pixels Masks -----------------------; ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; if keyword_set(doMASK) then begin ;--III-- UI -- Console Output kTask++ print, '' print, '------------' print, '-- Task '+strtrim(string(kTask,format='(I)'),2)+' ----------------------------------------------' print, '-- '+nightINFO[kDate].date+' -- Bap-Pixel Maps' print, '--------------------------------------------------------' ;--III.1-- Create Basic Mask Threshold File ---------------------------------------------- if ~file_test(dirCAL+maskINFO.file,/read) then begin ;--III.1.1-- Set Defaults defSig = 2.90 ;--III.1.2-- Scan Calibration Types dimB = size(biasINFO) dimD = size(darkINFO) dimF = size(flatINFO) nameArr='' nxArr =0 nyArr =0 ;--III.1.3-- List Uniq Bias Configurations if dimB[dimB[0]+1] eq 8 then begin sBias = string(biasINFO.NX,format='('+confAstroIM.fmt.size+')')+'x'+$ string(biasINFO.NY,format='('+confAstroIM.fmt.size+')') uBias = uniq(sBias,sort(sBias)) nameArr = [nameArr, 'bias'] nxArr = [nxArr, biasINFO[uBias].NX ] nyArr = [nyArr, biasINFO[uBias].NY ] endif ;--III.1.4-- List Uniq Dark Configurations if dimD[dimD[0]+1] eq 8 then begin sDark = string(darkINFO.NX,format='('+confAstroIM.fmt.size+')')+'x'+$ string(darkINFO.NY,format='('+confAstroIM.fmt.size+')') uDark = uniq(sDark,sort(sDark)) nameArr = [nameArr, 'dark'] nxArr = [nxArr, darkINFO[uDark].NX ] nyArr = [nyArr, darkINFO[uDark].NY ] endif ;--III.1.5-- List Uniq Flat Configurations if dimF[dimF[0]+1] eq 8 then begin sFlat = strtrim(string(flatINFO.filter, format='('+confAstroIM.fmt.filter+')'),2)+'-'+$ string(flatINFO.NX,format='('+confAstroIM.fmt.size+')')+'x'+$ string(flatINFO.NY,format='('+confAstroIM.fmt.size+')') uFlat = uniq(sFlat,sort(sFlat)) nameArr = [nameArr, flatINFO[uFlat].filter] nxArr = [nxArr, flatINFO[uFlat].NX ] nyArr = [nyArr, flatINFO[uFlat].NY ] endif ;--III.1.6-- Create Dummy Mask Threshold File nUniq = n_elements(nameArr)-1 forprint, nameArr, nxArr, nyArr, replicate(defSig,nUniq+1), $ subset=indgen(nUniq)+1, textout=dirCAL+confRedim.mask.f, $ format='('+confAstroIM.fmt.filter+',2x,'+$ confAstroIM.fmt.size+',2x,'+$ confAstroIM.fmt.size+',2x,F5.2)', $ /NOCOMMENT, /SILENT endif ;--III.2-- Bad Pixel Mask from Bias Frames ----------------------------------------------- sBias = size(biasINFO) if sBias[sBias[0]+1] eq 8 then $ flag = mapBadPixels( biasINFO, {i:dirCAL,o:dirCAL}, bpINFO=maskINFO, workINFO=workINFO, verbose=verbose ) ;--III.3-- Bad Pixel Mask from Dark Frames ----------------------------------------------- sDark = size(darkINFO) if sDark[sDark[0]+1] eq 8 then $ flag = mapBadPixels( darkINFO, {i:dirCAL,o:dirCAL}, bpINFO=maskINFO, workINFO=workINFO, verbose=verbose ) ;--III.4-- Bad Pixel Mask from Flat Frames ----------------------------------------------- sFlat = size(flatINFO) if sFlat[sFlat[0]+1] eq 8 then $ flag = mapBadPixels( flatINFO, {i:dirCAL,o:dirCAL}, bpINFO=maskINFO, workINFO=workINFO, verbose=verbose ) ;-print, 'add pixel manually????' ; ;--------------------------------------------------------------------------- ; ;--III.3-- Manually added Bad Pixels -------------------------------------- ; if file_test(dirCAL+'badpixels.list',/READ) then begin ; ; ;--III.3-- UI - Console Output ; print,' Adding user-supplied list of bad pixels' ; ; ; ;--III.3-- List of Bad pixels ; readcol, dirCAL+'badpixels.list', $ ; bpFilt, bpSizeX, bpSizeY, bpPosX, bpPosY, $ ; format='(A,I,I,I,I)', /SILENT ; ; ;--III.3.1-- Look for Filters ; uniqFILT= flatINFO( uniq(flatINFO.filter, sort(flatINFO.filter)) ).filter ; for kFilt=0, n_elements( uniqFILT )-1 do begin ; ; ;--III.3.2-- For each Filter, Look for X-Sizes ; filtUniqList = where( strcmp(flatINFO.filter, uniqFILT(kFilt)) ) ; uniqSIZEX = flatINFO(filtUniqList( uniq( flatINFO(filtUniqList).NX, $ ; reverse(sort(flatINFO(filtUniqList).NX)) ) )).NX ; for kSizeX=0, n_elements( uniqSIZEX )-1 do begin ; ; ;--III.3.3--For each X-Size, Look for Y-Sizes ; sizxUniqList = where( flatINFO(filtUniqList).NX eq uniqSIZEX(kSizeX) AND $ ; flatINFO.filter eq uniqFILT(kFilt) ) ; uniqSIZEY = flatINFO(filtUniqList(sizxUniqList( uniq( flatINFO(sizxUniqList).NY, $ ; reverse(sort( flatINFO(sizxUniqList).NY)) ) ))).NY ; for kSizeY=0, n_elements( uniqSIZEY )-1 do begin ; ; ;--------------------------------------------------------------------------- ; ;--III.3.4-- Locate the Bad Pixels ---------------------------------------- ; bpList = where( bpFilt eq uniqFILT(kFilt) AND $ ; bpSizeX ge uniqSIZEX(kSizeX) AND $ ; bpSizeY ge uniqSIZEY(kSizeY), nbBP ) ; if bpList[0] eq -1 then goto, j2nextBPconfig ; ; ; ;--III.3.5-- Read current Bad Pixel Mask ; nameMask = setAstroName( MASK='BP', FILTER=uniqFILT(kFilt), NX=uniqSIZEX(kSizeX), NY=uniqSIZEY(kSizeY)) ; mask = readfits( dirCAL+nameMASK, hMask, /SILENT ) ; ; ;--III.3.6-- Add the pixel to Bad Pixel Mask ; for kBP=0, nbBP-1 do begin ; ; ;--III.3.6.1-- Mind gymnatic for smaller frame sizes ; bpX = bpPosX(bpList(kBP)) + floor(( uniqSIZEX(kSizeX)-bpSizeX(bpList[0]) )/2. ) ; bpY = bpPosY(bpList(kBP)) + floor(( uniqSIZEY(kSizeY)-bpSizeY(bpList[0]) )/2. ) ; ; ;--III.3.6.2-- Place valid pixel in the mask ; if bpX lt uniqSIZEX(kSizeX) AND $ ; bpY lt uniqSIZEY(kSizeY) then mask(bpX, bpY)=1 ; ; endfor ;--III.3.6--End of loop over bad pixels ; ; ; ;--III.3.7-- Write Updated Bap Pixel Mask on Disk ; check_fits, mask, hMask, /UPDATE, /SILENT ; writefits, dirCAL+nameMASK, mask, hMask ; ; ;j2nextBPconfig: ; endfor ;--III.3.3--End of Loop over Frame Y-Size ; ; endfor ;--III.3.2--End of Loop over Frame X-Size ; ; endfor ;--III.3.1--End of Loop over Filters ; ; endif ;--III.3--End of work on bad pixels from user-supplied list ; ; ; ; endif ;--III--End of Bad Pixel Map Creation ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--- TAG --- IV -- Reduction of Calibration Files -----------------------; ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; if keyword_set(doCALIBRATION) then begin ;--IV-- UI - Console Output kTask++ print, '' print, '------------' print, '-- Task '+strtrim(string(kTask,format='(I)'),2)+' ----------------------------------------------' print, '-- '+nightINFO[kDate].date+' -- Cleaning Calibration Files' print, '--------------------------------------------------------' ;--IV.1-- Cleaning of Bias Frames ------------------------------------------------------- sBias = size(biasINFO) if sBias[sBias[0]+1] eq 8 then $ result = cleanCalib( biasINFO, {i:dirCAL,o:dirCAL}, calINFO=calINFO, workINFO=workINFO, /BIAS ) ;--IV.2-- Cleaning of Dark Frames ------------------------------------------------------- sDark = size(darkINFO) if sDark[sDark[0]+1] eq 8 then $ result = cleanCalib( darkINFO, {i:dirCAL,o:dirCAL}, calINFO=calINFO, workINFO=workINFO, /DARK ) ;--IV.3-- Cleaning of Flat Frames ------------------------------------------------------- sFlat = size(flatINFO) if sFlat[sFlat[0]+1] eq 8 then $ result = cleanCalib( flatINFO, {i:dirCAL,o:dirCAL}, calINFO=calINFO, workINFO=workINFO, /FLAT ) endif ;--IV--End of work over Calibration Files ;--------------------------------------------------------; ;-- TAG -- Create Fringes Map based on multiple frames --; ;--------------------------------------------------------; ;if keyword_set(doFRINGES) then begin ; TBD one day ;endif ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--- TAG --- V -- Cleaning, Alignment, Cropping of Scientific Frames -------------------; ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; if keyword_set(doSCIENCE) or keyword_set(doALIGN) then begin ;--V-- UI - Console Output kTask++ print, '' print, '------------' print, '-- Task '+strtrim(string(kTask,format='(I)'),2)+' --------------------------------------------------' print, '-- '+nightINFO[kDate].date+' -- Reduction and Alignment of Science Frames ' print, '------------------------------------------------------------' result = cleanSci( fileINFO[sciList], {raw:dirRAW, red:dirRED, cal:dirCAL}, doSCIENCE=doSCIENCE, doALIGN=doALIGN, $ sciINFO=sciINFO, alignINFO=alignINFO, calINFO=calINFO, workINFO=workINFO ) endif ;--V--End of Science frame cleaning endfor ;--I.X-- End of Loop over Night end