23 from .astierCovPtcFit
import CovFit
29 """A class to compute (via FFT) the nearby pixels correlation function.
31 Implements appendix of Astier+19.
36 Image where to calculate the covariances (e.g., the difference image of two flats).
39 Weight image (mask): it should consist of 1's (good pixel) and 0's (bad pixels).
42 2d-tuple with the shape of the FFT
45 Maximum range for the covariances.
48 def __init__(self, diff, w, fftShape, maxRangeCov):
51 assert(fftShape[0] > diff.shape[0]+maxRangeCov+1)
52 assert(fftShape[1] > diff.shape[1]+maxRangeCov+1)
55 if fftShape[1]%2 == 1:
56 fftShape = (fftShape[0], fftShape[1]+1)
57 tIm = np.fft.rfft2(diff*w, fftShape)
58 tMask = np.fft.rfft2(w, fftShape)
60 self.
pCov = np.fft.irfft2(tIm*tIm.conjugate())
62 self.
pMean = np.fft.irfft2(tIm*tMask.conjugate())
64 self.
pCount = np.fft.irfft2(tMask*tMask.conjugate())
66 def cov(self, dx, dy):
67 """Covariance for dx,dy averaged with dx,-dy if both non zero.
69 Implements appendix of Astier+19.
81 0.5*(cov1+cov2): `float`
82 Covariance at (dx, dy) lag
85 Number of pixels used in covariance calculation.
88 nPix1 = int(round(self.
pCount[dy, dx]))
89 cov1 = self.
pCov[dy, dx]/nPix1-self.
pMean[dy, dx]*self.
pMean[-dy, -dx]/(nPix1*nPix1)
90 if (dx == 0
or dy == 0):
92 nPix2 = int(round(self.
pCount[-dy, dx]))
93 cov2 = self.
pCov[-dy, dx]/nPix2-self.
pMean[-dy, dx]*self.
pMean[dy, -dx]/(nPix2*nPix2)
94 return 0.5*(cov1+cov2), nPix1+nPix2
97 """Produce a list of tuples with covariances.
99 Implements appendix of Astier+19.
104 Maximum range of covariances.
109 List with covariance tuples.
113 for dy
in range(maxRange+1):
114 for dx
in range(maxRange+1):
115 cov, npix = self.
cov(dx, dy)
116 if (dx == 0
and dy == 0):
118 tupleVec.append((dx, dy, var, cov, npix))
123 """Calculate the size fof one dimension for the FFT"""
124 x = int(np.log(s)/np.log(2.))
129 """Compute covariances of diffImage in real space.
131 For lags larger than ~25, it is slower than the FFT way.
132 Taken from https://github.com/PierreAstier/bfptc/
136 diffImage : `numpy.array`
137 Image to compute the covariance of.
139 weightImage : `numpy.array`
140 Weight image of diffImage (1's and 0's for good and bad pixels, respectively).
143 Last index of the covariance to be computed.
148 List with tuples of the form (dx, dy, var, cov, npix), where:
154 Variance at (dx, dy).
156 Covariance at (dx, dy).
158 Number of pixel pairs used to evaluate var and cov.
163 for dy
in range(maxRange + 1):
164 for dx
in range(0, maxRange + 1):
168 cov = 0.5*(cov1 + cov2)
172 if (dx == 0
and dy == 0):
174 outList.append((dx, dy, var, cov, nPix))
180 """Compute covariances of diffImage in real space at lag (dx, dy).
182 Taken from https://github.com/PierreAstier/bfptc/ (c.f., appendix of Astier+19).
186 diffImage : `numpy.array`
187 Image to compute the covariance of.
189 weightImage : `numpy.array`
190 Weight image of diffImage (1's and 0's for good and bad pixels, respectively).
201 Covariance at (dx, dy)
204 Number of pixel pairs used to evaluate var and cov.
206 (nCols, nRows) = diffImage.shape
210 (dx, dy) = (-dx, -dy)
214 im1 = diffImage[dy:, dx:]
215 w1 = weightImage[dy:, dx:]
216 im2 = diffImage[:nCols - dy, :nRows - dx]
217 w2 = weightImage[:nCols - dy, :nRows - dx]
219 im1 = diffImage[:nCols + dy, dx:]
220 w1 = weightImage[:nCols + dy, dx:]
221 im2 = diffImage[-dy:, :nRows - dx]
222 w2 = weightImage[-dy:, :nRows - dx]
228 s1 = im1TimesW.sum()/nPix
229 s2 = (im2*wAll).sum()/nPix
230 p = (im1TimesW*im2).sum()/nPix
238 A class to prepare covariances for the PTC fit.
243 Maximum lag considered (e.g., to eliminate data beyond a separation "r": ignored in the fit).
245 subtractDistantValue: `bool`, optional
246 Subtract a background to the measured covariances (mandatory for HSC flat pairs)?
248 start: `int`, optional
249 Distance beyond which the subtractDistant model is fitted.
252 Polynomial degree for the subtraction model.
256 params = LoadParams(). "params" drives what happens in he fit. LoadParams provides default values.
266 """ Returns a list of CovFit objects, indexed by amp number.
270 dataset : `lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset`
271 The PTC dataset containing the means, variances, and
274 params: `covAstierptcUtil.LoadParams`
275 Object with values to drive the bahaviour of fits.
280 Dictionary with amps as keys, and CovFit objects as values.
284 for ampName
in dataset.ampNames:
286 if ampName
in dataset.badAmps:
288 maskAtAmp = dataset.expIdMask[ampName]
289 muAtAmp = dataset.rawMeans[ampName]
290 covAtAmp = dataset.covariances[ampName]
291 covSqrtWeightsAtAmp = dataset.covariancesSqrtWeights[ampName]
293 if params.subtractDistantValue:
294 c =
CovFit(muAtAmp, covAtAmp, covSqrtWeightsAtAmp, params.r, maskAtAmp)
295 c.subtractDistantOffset(params.r, params.start, params.offsetDegree)
297 c =
CovFit(muAtAmp, covAtAmp, covSqrtWeightsAtAmp, params.r, maskAtAmp)
301 covFitList[ampName] = cc
307 """Fit data to models in Astier+19.
311 dataset : `lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset`
312 The dataset containing the means, variances, and exposure times.
315 Maximum lag considered (e.g., to eliminate data beyond a separation "r": ignored in the fit).
320 Dictionary of CovFit objects, with amp names as keys.
322 covFitNoBList: `dict`
323 Dictionary of CovFit objects, with amp names as keys (b=0 in Eq. 20 of Astier+19).
327 The parameters of the full model for C_ij(mu) ("C_ij" and "mu" in ADU^2 and ADU, respectively)
328 in Astier+19 (Eq. 20) are:
330 "a" coefficients (r by r matrix), units: 1/e
331 "b" coefficients (r by r matrix), units: 1/e
332 noise matrix (r by r matrix), units: e^2
335 "b" appears in Eq. 20 only through the "ab" combination, which is defined in this code as "c=ab".
339 lparams.subtractDistantValue =
False
343 for ext, c
in covFitList.items():
345 covFitNoBList[ext] = c.copy()
346 c.params[
'c'].release()
348 return covFitList, covFitNoBList
352 divideByMu=False, returnMasked=False):
353 """Get measured signal and covariance, cov model, weigths, and mask at covariance lag (i, j).
358 Lag for covariance matrix.
361 Lag for covariance matrix.
366 fullCov: `list` of `numpy.array`
367 Measured covariance matrices at each mean signal level in mu.
369 fullCovSqrtWeights: `list` of `numpy.array`
370 List of square root of measured covariances at each mean signal level in mu.
372 fullCovModel : `list` of `numpy.array`
373 List of modeled covariances at each mean signal level in mu.
375 gain : `float`, optional
376 Gain, in e-/ADU. If other than 1.0 (default), the returned quantities will be in
377 electrons or powers of electrons.
379 divideByMu: `bool`, optional
380 Divide returned covariance, model, and weights by the mean signal mu?
382 returnMasked : `bool`, optional
383 Use mask (based on weights) in returned arrays (mu, covariance, and model)?
388 list of signal values at (i, j).
390 covariance : `numpy.array`
391 Covariance at (i, j) at each mean signal mu value (fullCov[:, i, j]).
393 covarianceModel : `numpy.array`
394 Covariance model at (i, j).
396 weights : `numpy.array`
399 maskFromWeights : `numpy.array`, optional
400 Boolean mask of the covariance at (i,j), where the weights differ from 0.
404 This function is a method of the `CovFit` class.
407 fullCov = np.array(fullCov)
408 fullCovModel = np.array(fullCovModel)
409 fullCovSqrtWeights = np.array(fullCovSqrtWeights)
410 covariance = fullCov[:, i, j]*(gain**2)
411 covarianceModel = fullCovModel[:, i, j]*(gain**2)
412 weights = fullCovSqrtWeights[:, i, j]/(gain**2)
414 maskFromWeights = weights != 0
416 weights = weights[maskFromWeights]
417 covarianceModel = covarianceModel[maskFromWeights]
418 mu = mu[maskFromWeights]
419 covariance = covariance[maskFromWeights]
423 covarianceModel /= mu
425 return mu, covariance, covarianceModel, weights, maskFromWeights