Coverage for python/lsst/cp/pipe/ptc/measurePtcGen2Task.py: 32%
Shortcuts on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# This file is part of cp_pipe.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
21#
22import lsst.pex.config as pexConfig
23import lsst.pipe.base as pipeBase
24from lsst.cp.pipe.utils import arrangeFlatsByExpTime
26from lsst.pipe.tasks.getRepositoryData import DataRefListRunner
27from lsst.cp.pipe.ptc.cpExtractPtcTask import PhotonTransferCurveExtractTask
28from lsst.cp.pipe.ptc.cpSolvePtcTask import PhotonTransferCurveSolveTask
29from lsst.utils.timer import timeMethod
32__all__ = ['MeasurePhotonTransferCurveTask', 'MeasurePhotonTransferCurveTaskConfig']
35class MeasurePhotonTransferCurveTaskConfig(pexConfig.Config):
36 extract = pexConfig.ConfigurableField(
37 target=PhotonTransferCurveExtractTask,
38 doc="Task to measure covariances from flats.",
39 )
40 solve = pexConfig.ConfigurableField(
41 target=PhotonTransferCurveSolveTask,
42 doc="Task to fit models to the measured covariances.",
43 )
44 ccdKey = pexConfig.Field(
45 dtype=str,
46 doc="The key by which to pull a detector from a dataId, e.g. 'ccd' or 'detector'.",
47 default='ccd',
48 )
51class MeasurePhotonTransferCurveTask(pipeBase.CmdLineTask):
52 """A class to calculate, fit, and plot a PTC from a set of flat pairs.
54 The Photon Transfer Curve (var(signal) vs mean(signal)) is a standard
55 tool used in astronomical detectors characterization (e.g., Janesick 2001,
56 Janesick 2007). If ptcFitType is "EXPAPPROXIMATION" or "POLYNOMIAL",
57 this task calculates the PTC from a series of pairs of flat-field images;
58 each pair taken at identical exposure times. The difference image of each
59 pair is formed to eliminate fixed pattern noise, and then the variance
60 of the difference image and the mean of the average image
61 are used to produce the PTC. An n-degree polynomial or the approximation
62 in Equation 16 of Astier+19 ("The Shape of the Photon Transfer Curve
63 of CCD sensors", arXiv:1905.08677) can be fitted to the PTC curve. These
64 models include parameters such as the gain (e/DN) and readout noise.
66 Linearizers to correct for signal-chain non-linearity are also calculated.
67 The `Linearizer` class, in general, can support per-amp linearizers, but
68 in this task this is not supported.
70 If ptcFitType is "FULLCOVARIANCE", the covariances of the difference
71 images are calculated via the DFT methods described in Astier+19 and the
72 variances for the PTC are given by the cov[0,0] elements at each signal
73 level. The full model in Equation 20 of Astier+19 is fit to the PTC
74 to get the gain and the noise.
76 Parameters
77 ----------
78 *args: `list`
79 Positional arguments passed to the Task constructor. None used
80 at this time.
82 **kwargs: `dict`
83 Keyword arguments passed on to the Task constructor. None used
84 at this time.
85 """
87 RunnerClass = DataRefListRunner
88 ConfigClass = MeasurePhotonTransferCurveTaskConfig
89 _DefaultName = "measurePhotonTransferCurve"
91 def __init__(self, *args, **kwargs):
92 super().__init__(**kwargs)
93 self.makeSubtask("extract")
94 self.makeSubtask("solve")
96 @timeMethod
97 def runDataRef(self, dataRefList):
98 """Run the Photon Transfer Curve (PTC) measurement task.
100 For a dataRef (which is each detector here), and given a list
101 of exposure pairs (postISR) at different exposure times,
102 measure the PTC.
104 Parameters
105 ----------
106 dataRefList : `list` [`lsst.daf.peristence.ButlerDataRef`]
107 Data references for exposures.
108 """
109 if len(dataRefList) < 2:
110 raise RuntimeError("Insufficient inputs to combine.")
112 # setup necessary objects
113 dataRef = dataRefList[0]
114 camera = dataRef.get('camera')
116 if len(set([dataRef.dataId[self.config.ccdKey] for dataRef in dataRefList])) > 1:
117 raise RuntimeError("Too many detectors supplied")
118 # Get exposure list.
119 expList = []
120 for dataRef in dataRefList:
121 try:
122 tempFlat = dataRef.get("postISRCCD")
123 except RuntimeError:
124 self.log.warning("postISR exposure could not be retrieved. Ignoring flat.")
125 continue
126 expList.append(tempFlat)
127 expIds = [exp.info.getVisitInfo().id for exp in expList]
129 # Create dictionary of exposures, keyed by exposure time
130 expDict = arrangeFlatsByExpTime(expList)
131 # Call the "extract" (measure flat covariances) and "solve"
132 # (fit covariances) subtasks
133 resultsExtract = self.extract.run(inputExp=expDict, inputDims=expIds)
134 resultsSolve = self.solve.run(resultsExtract.outputCovariances, camera=camera)
136 # Get expIdPairs from one of the amps
137 expIdsPairsList = []
138 ampNames = resultsSolve.outputPtcDataset.ampNames
139 for ampName in ampNames:
140 tempAmpName = ampName
141 if ampName not in resultsSolve.outputPtcDataset.badAmps:
142 break
143 for pair in resultsSolve.outputPtcDataset.inputExpIdPairs[tempAmpName]:
144 first, second = pair[0]
145 expIdsPairsList.append((first, second))
147 self.log.info("Writing PTC data.")
148 dataRef.put(resultsSolve.outputPtcDataset, datasetType="photonTransferCurveDataset")
150 return