00001 /* @file pmShutterCorrection.h 00002 * @brief Functions to build and apply a shutter exposure-time correction. 00003 * 00004 * @author Eugene Magnier, IfA 00005 * @author Paul Price, IfA 00006 * 00007 * @version $Revision: 1.11 $ $Name: $ 00008 * @date $Date: 2007/01/24 02:54:15 $ 00009 * Copyright 2006 Institute for Astronomy, University of Hawaii 00010 */ 00011 00012 #ifndef PM_SHUTTER_CORRECTION_H 00013 #define PM_SHUTTER_CORRECTION_H 00014 00015 /// @addtogroup detrend Detrend Creation and Application 00016 /// @{ 00017 00018 /* A mechanical shutter may not yield uniform exposure times as a function of 00019 * position on the detector. The typical error consists of a constant 00020 * exposure-time offset relative to the requested value, ie exposure time is 00021 * T_o + dT(x,y). The exposure error, dT, may be measured with the following 00022 * scheme. Obtain a set of exposures with different exposures times taken of 00023 * the same flat-field source; the source must be spatially stable between the 00024 * exposures, but need not have a stable amplitude. For an illuminating flux 00025 * of intensity F(x,y) = F_o f(x,y), the signal recorded by any pixel in the 00026 * detector is given by: S(t,x,y) = F_o(t) f(x,y) (T_o + dT(x,y)) where F_o is 00027 * the F_o(t) is the (variable) overall intensity of the illuminating source 00028 * and f(x,y) is the spatial illumination patter times the flat-field response. 00029 * Choose a reference location in the image (eg, the detector center) and 00030 * divide by the value of that region (ie, mean or median): 00031 * 00032 * s(t,x,y) = S(t,x,y) / S(t,0,0) 00033 * s(t,x,y) = F_o(t) f(x,y) (T_o + dT(x,y)) / F_o(t) f(0,0) (T_o + dT(0,0)) 00034 * s(t,x,y) = f(x,y) (T_o + dT(x,y)) / f(0,0) (T_o + dT(0,0)) 00035 * 00036 * we can absorb the term f(0,0) into f(x,y) as we have no motivation for the 00037 * scale of f(x,y). For any single pixel, over the set of exposures, we thus 00038 * need to solve for dT(x,y), dT(0,0), and f'(x,y) in the equation: 00039 * s(t,x,y) = f'(x,y) (T_o + dT(x,y)) / (T_o + dT(0,0)) 00040 * 00041 * we avoid directly fitting these values as the process would be a non-linear 00042 * least-squares problem for every pixel in the image, and thus very time 00043 * consuming. There are linear options which may be used instead. 00044 * First, as T_o goes to a large value, s() approaches the value of f'(x,y). 00045 * Next, as T_o goes to a very small value, s() approaches the value of 00046 * f'(x,y)*dT(x,y)/dT(0,0). Finally, when s() has the value of 00047 * f'(x,y)*(1 + dT(x,y)/dT(0,0))/2, T_o has the value of dT(0,0). with data 00048 * points covering a reasonable dynamic range, we can solve for these three 00049 * values by interpolation and/or extrapolation. 00050 * 00051 * To take the strategy one step further, we could use the above recipe to 00052 * obtain a guess for the three parameters and then apply non-linear fitting to 00053 * solve more accurately for the parameters. If we limit this operation to a 00054 * handful of positions in the image (user defined, but the obvious choice would 00055 * be positions near the center, edges, and corners), then we may determine a 00056 * good value for dT(0,0). Since there is only one dT(0,0) for the image, we 00057 * can apply the resulting measurement to the rest of the pixels in the image. 00058 * If dT(0,0) is not a free parameter, then the fitting process is linear in 00059 * terms of dT(x,y) and f'(x,y) 00060 */ 00061 00062 #include <pslib.h> 00063 00064 /// Shutter correction parameters, applicable for a single pixel 00065 typedef struct 00066 { 00067 double scale; ///< The normalisation for an exposure, A(k) 00068 double offset; ///< The time offset, dTk 00069 double offref; ///< The reference time offset, dTo 00070 } 00071 pmShutterCorrection; 00072 00073 /// Allocator for shutter correction parameters 00074 pmShutterCorrection *pmShutterCorrectionAlloc(); 00075 00076 /// Guess a shutter correction, based on plot of counts vs exposure time 00077 /// 00078 /// This function is used before doing the full non-linear fit, to get parameters close to the true. Assumes 00079 /// exptime vector is sorted (ascending order; longest is last) prior to input. 00080 pmShutterCorrection *pmShutterCorrectionGuess(const psVector *exptime, ///< Exposure times for each exposure 00081 const psVector *counts ///< Counts for each exposure 00082 ); 00083 00084 /// Generate shutter correction based on a linear fit 00085 /// 00086 /// Performs a linear fit to counts as a function of exposure time, with the reference time offset fixed (so 00087 /// that the system is linear). Performs iterative clipping, if nIter > 1. 00088 pmShutterCorrection *pmShutterCorrectionLinFit(const psVector *exptime, ///< Exposure times for each exposure 00089 const psVector *counts, ///< Counts for each exposure 00090 const psVector *cntError, ///< Error in the counts 00091 const psVector *mask, ///< Mask for each exposure 00092 float offref, ///< Reference time offset 00093 int nIter, ///< Number of iterations 00094 float rej, ///< Rejection threshold (sigma) 00095 psMaskType maskVal ///< Mask value 00096 ); 00097 00098 /// Generate shutter correction based on a full non-linear fit 00099 /// 00100 /// Performs a full non-linear fit to counts as a function of exposure time. The main purpose is to solve for 00101 /// the reference time offset, so that future fits may be performed using linear fitting with the reference 00102 /// time offset fixed. 00103 pmShutterCorrection *pmShutterCorrectionFullFit(const psVector *exptime, ///< Exposure times for each exposure 00104 const psVector *counts, ///< Counts for each exposure 00105 const psVector *cntError, ///< Error in the counts 00106 const pmShutterCorrection *guess ///< Initial guess 00107 ); 00108 00109 /// Measure a shutter correction image from an array of images 00110 /// 00111 /// Given an array of readouts (with known exposure times from the cell concepts), this function measures the 00112 /// shutter correction (our principal concern is for the time offset, rather than the normalisation) by 00113 /// measuring the reference time offset using the full non-linear fit for a small number of representative 00114 /// regions (middle and corners), and then using that to perform a linear fit to each pixel. 00115 psImage *pmShutterCorrectionMeasure(const psArray *readouts, ///< Array of readouts 00116 int size, ///< Size of samples for statistics for non-linear fit 00117 psStatsOptions meanStat, ///< Statistic to use for mean 00118 psStatsOptions stdevStat, ///< Statistic to use for stdev 00119 int nIter, ///< Number of iterations 00120 float rej, ///< Rejection threshold (sigma) 00121 psMaskType maskVal ///< Mask value 00122 ); 00123 00124 /// Apply a shutter correction 00125 /// 00126 /// Given a shutter correction (with dT for each pixel), applies this correction to an input image. 00127 bool pmShutterCorrectionApply(pmReadout *readout, ///< Readout to which to apply shutter correction 00128 const pmReadout *shutter ///< Shutter correction readout, with dT for each pixel 00129 ); 00130 00131 /// @} 00132 #endif
1.5.1