Source code for corgidrp.bad_pixel_calibration

import numpy as np
from corgidrp.data import BadPixelMap, Dataset, DetectorNoiseMaps
from corgidrp.darks import build_synthesized_dark

[docs] def create_bad_pixel_map(dataset, master_dark, master_flat, dthresh = 5., ffrac = 0.8, fwidth = 32, dark_outputdir=None): """ Compute a fixed bad pixel map for EXCAM from a master dark and flat. Args: dataset (corgidrp.data.Dataset): A dataset that is ignored by this class. master_dark (corgidrp.data.Dark or corgidrp.data.DetectorNoiseMaps): a dark frame, or, if it is a Noise Map, a synthesized master is created using calibrated noise maps for the EM gain and exposure time used in master_flat master_flat (corgidrp.data.FlatField): A master flat field object. dthresh (float): Number of standard deviations above the mean to threshold for hot pixels. Must be >= 0. ffrac (float): Fraction of local mean value below which poorly-functioning pixels are flagged. Must be >=0 and < 1. fwidth (int): Number of pixels to include in local mean check with ffrac. Must be >0. dark_outputdir (str): if not None, a file directory to save any synthetic darks created from noise maps Returns: corgi.data.BadPixelMap: A 2-D boolean array the same size as dark and flat, with bad pixels marked as True. """ if isinstance(master_dark, DetectorNoiseMaps): noise_map = master_dark master_dark = build_synthesized_dark(Dataset([master_flat]), noise_map) if dark_outputdir is not None: master_dark.save(filedir=dark_outputdir) #Extract data dark_data = master_dark.data flat_data = master_flat.data #Calculate the hot and warm bad pixel maps hot_warm_pixels_bool = detect_hot_warm_pixels_from_dark(dark_data, dthresh) hot_warm_pixels = np.zeros_like(dark_data,dtype=np.uint8) hot_warm_pixels[hot_warm_pixels_bool] = 8 #Calculate the cold and dead pixels dead_pixels_bool = detect_dead_pixels_from_flat(flat_data, ffrac, fwidth) dead_pixels = np.zeros_like(dark_data,dtype=np.uint8) dead_pixels[dead_pixels_bool] = 4 #Combined the two maps combined_badpixels = np.bitwise_or(hot_warm_pixels,dead_pixels) dark_hdr = master_dark.pri_hdr.copy() dark_ext_hdr = master_dark.ext_hdr.copy() dark_ext_hdr['DATALVL'] = 'CAL' dark_ext_hdr['HISTORY'] = "Bad Pixel Map created using {} and {}".format(master_dark.filename,master_flat.filename) input_dataset = Dataset([master_dark,master_flat]) #Make the BadPixelMap object badpixelmap = BadPixelMap(combined_badpixels,pri_hdr=dark_hdr,ext_hdr=dark_ext_hdr,input_dataset=input_dataset) return badpixelmap
[docs] def detect_hot_warm_pixels_from_dark(dark, dthresh): """ Detects warm/hot pixels from the dark frame, flagging anything above dthresh standard deviations above the mean dark level in the frame. For example, dthresh = 5 will flag any pixel > 5 standard deviations above the mean of dark. Ported from II&T pipeline Args: dark (array_like): 2-D array containing the master dark frame. dthresh (float): Threshold for flagging hot pixels, specified as the number of standard deviations above the mean dark level. Must be >= 0. Returns: fixedbp_dark (array_like): A 2-D boolean array the same size as the input dark frame, with hot pixels marked as True. """ # Process dark frame fixedbp_dark = np.zeros(dark.shape).astype('bool') fixedbp_dark[dark > np.mean(dark) + dthresh*np.std(dark)] = True return fixedbp_dark
[docs] def detect_dead_pixels_from_flat(flat, ffrac, fwidth): """ Compute a fixed bad pixel map from a flat field. Detects low- or non-functional pixels from the flat frame, flagging any pixels less than ffrac times the local mean flat level. Flat uses local mean as flats may have low-spatial-frequency variations due to e.g. fringing or vignetting. For example, ffrac = 0.8 and fwidth = 32 will flag any pixel which is < 80% of the mean value in a 32-pixel box centered on the pixel. (Centration will use FFT rules, where odd-sized widths center on the pixel, and even-sized place the pixel to the right of center, e.g.: odd: [. x .] even: [. . x .] For boxes near the edge, only the subset of pixels within the box will be used for the calculation. Ported from II&T pipeline Args: flat (array_like): 2-D array containing the master flat field. ffrac (float): Fraction of the local mean value below which pixels are considered poorly-functioning. fwidth (int): Width of the box used to calculate the local mean, in pixels. Returns: fixedbp_flat (array_like): A 2-D boolean array the same size as the input flat frame, with dead pixels marked as True. """ # Check inputs # check.twoD_array(flat, 'flat', TypeError) # check.real_nonnegative_scalar(ffrac, 'ffrac', TypeError) # check.positive_scalar_integer(fwidth, 'fwidth', TypeError) # Process flat frame fixedbp_flat = np.zeros(flat.shape).astype('bool') nrow, ncol = flat.shape for r in range(nrow): tmpr = np.arange(fwidth) - fwidth//2 + r rind = np.logical_and(tmpr >= 0, tmpr < nrow) for c in range(ncol): tmpc = np.arange(fwidth) - fwidth//2 + c cind = np.logical_and(tmpc >= 0, tmpc < ncol) # rind/cind removes indices that fall out of flat subflat = flat[tmpr[rind], :][:, tmpc[cind]] localm = np.mean(subflat) if flat[r, c] < ffrac*localm: fixedbp_flat[r, c] = True pass pass pass return fixedbp_flat