31 __all__ = [
"CoaddInputRecorderTask"]
34 """Config for CoaddInputRecorderTask
36 The inputRecorder section of the various coadd tasks' configs should generally agree,
37 or the schemas created by earlier tasks (like MakeCoaddTempExpTask) will not contain
38 the fields filled by later tasks (like AssembleCoaddTask).
40 saveEmptyCcds = pexConfig.Field(
41 dtype=bool, default=
False, optional=
False,
42 doc=(
"Add records for CCDs we iterated over but did not add a coaddTempExp"
43 " due to a lack of unmasked pixels in the coadd footprint.")
45 saveErrorCcds = pexConfig.Field(
46 dtype=bool, default=
False, optional=
False,
47 doc=(
"Add records for CCDs we iterated over but did not add a coaddTempExp"
48 " due to an exception (often due to the calexp not being found on disk).")
50 saveVisitGoodPix = pexConfig.Field(
51 dtype=bool, default=
True, optional=
False,
52 doc=(
"Save the total number of good pixels in each coaddTempExp (redundant with a sum of"
53 " good pixels in associated CCDs)")
55 saveCcdWeights = pexConfig.Field(
56 dtype=bool, default=
True, optional=
False,
57 doc=(
"Save weights in the CCDs table as well as the visits table?"
58 " (This is necessary for easy construction of CoaddPsf, but otherwise duplicate information.)")
62 """A helper class for CoaddInputRecorderTask, managing the CoaddInputs object for that a single
63 CoaddTempExp. This will contain single 'visit' record for the CoaddTempExp and a number of 'ccd'
66 Should generally be created by calling CoaddInputRecorderTask.makeCoaddTempExp().
73 self.visitRecord.setId(visitId)
76 """Add a 'ccd' record for a calexp just added to the CoaddTempExp
78 @param[in] calExp Calibrated exposure just added to the CoaddTempExp, or None in case of
79 failures that should nonetheless be tracked. Should be the original
80 calexp, in that it should contain the original Psf and Wcs, not the
81 warped and/or matched ones.
82 @param[in] ccdId A unique numeric ID for the Exposure.
83 @param[in] nGoodPix Number of good pixels this image will contribute to the CoaddTempExp.
84 If saveEmptyCcds is not set and this value is zero, no record will be
87 if nGoodPix == 0
and not self.task.config.saveEmptyCcds:
89 record = self.coaddInputs.ccds.addNew()
91 record.setL(self.task.ccdVisitKey, self.visitRecord.getId())
93 record.setI(self.task.ccdCcdKey, calExp.getDetector().getId())
95 self.task.log.warn(
"Error getting detector serial number in visit %d; using -1"
96 % self.visitRecord.getId())
97 record.setI(self.task.ccdCcdKey, -1)
98 record.setI(self.task.ccdGoodPixKey, nGoodPix)
99 if calExp
is not None:
100 record.setPsf(calExp.getPsf())
101 record.setWcs(calExp.getWcs())
102 record.setBBox(calExp.getBBox())
103 record.setApCorrMap(calExp.getInfo().getApCorrMap())
104 record.setValidPolygon(calExp.getInfo().getValidPolygon())
105 if self.task.config.saveCcdWeights:
106 record.setD(self.task.ccdWeightKey, 1.0)
108 def finish(self, coaddTempExp, nGoodPix=None):
109 """Finish creating the CoaddInputs for a CoaddTempExp.
111 @param[in,out] coaddTempExp Exposure object from which to obtain the PSF, WCS, and bounding
112 box for the entry in the 'visits' table. On return, the completed
113 CoaddInputs object will be attached to it.
114 @param[in] nGoodPix Total number of good pixels in the CoaddTempExp; ignored unless
115 saveVisitGoodPix is true.
117 self.visitRecord.setPsf(coaddTempExp.getPsf())
118 self.visitRecord.setWcs(coaddTempExp.getWcs())
119 self.visitRecord.setValidPolygon(coaddTempExp.getInfo().getValidPolygon())
120 self.visitRecord.setBBox(coaddTempExp.getBBox())
121 if self.task.config.saveVisitGoodPix:
122 self.visitRecord.setI(self.task.visitGoodPixKey, nGoodPix)
123 coaddTempExp.getInfo().setCoaddInputs(self.
coaddInputs)
124 wcs = coaddTempExp.getWcs()
127 coaddTempExp.setPsf(
CoaddPsf(self.coaddInputs.ccds, wcs))
128 apCorrMap =
makeCoaddApCorrMap(self.coaddInputs.ccds, coaddTempExp.getBBox(afwImage.PARENT), wcs)
129 coaddTempExp.getInfo().setApCorrMap(apCorrMap)
132 """Subtask that handles filling a CoaddInputs object for a coadd exposure, tracking the CCDs and
133 visits that went into a coadd.
135 The interface here is a little messy, but I think this is at least partly a product of a bit of
136 messiness in the coadd code it's plugged into. I hope #2590 might result in a better design.
139 ConfigClass = CoaddInputRecorderConfig
142 pipeBase.Task.__init__(self, *args, **kwargs)
144 if self.config.saveVisitGoodPix:
146 doc=
"Number of good pixels in the coaddTempExp")
148 doc=
"Weight for this visit in the coadd")
149 self.
ccdSchema = afwTable.ExposureTable.makeMinimalSchema()
150 self.
ccdCcdKey = self.ccdSchema.addField(
"ccd", type=int, doc=
"cameraGeom CCD serial number")
151 self.
ccdVisitKey = self.ccdSchema.addField(
"visit", type=numpy.int64,
152 doc=
"Foreign key for the visits (coaddTempExp) catalog")
154 doc=
"Number of good pixels in this CCD")
155 if self.config.saveCcdWeights:
157 doc=
"Weight for this visit in the coadd")
160 """Return a CoaddTempExpInputRecorder instance to help with saving a CoaddTempExp's inputs.
162 The visitId may be any number that is unique for each CoaddTempExp that goes into a coadd,
163 but ideally should be something more meaningful that can be used to reconstruct a data ID.
168 """Create a CoaddInputs object with schemas defined by the task configuration"""
172 """Called by AssembleCoaddTask when adding (a subset of) a coaddTempExp to a coadd. The
173 base class impementation extracts the CoaddInputs from the coaddTempExp and appends
174 them to the given coaddInputs, filling in the weight column(s).
176 Note that the passed coaddTempExp may be a subimage, but that this method will only be
177 called for the first subimage
179 Returns the record for the visit to allow subclasses to fill in additional fields.
180 Warns and returns None if the inputRecorder catalogs for the coaddTempExp are not usable.
182 tempExpInputs = coaddTempExp.getInfo().getCoaddInputs()
183 if len(tempExpInputs.visits) != 1:
184 self.log.warn(
"CoaddInputs for coaddTempExp should have exactly one record in visits table "
185 "(found %d). CoaddInputs for this visit will not be saved."
186 % len(tempExpInputs.visits))
188 inputVisitRecord = tempExpInputs.visits[0];
189 outputVisitRecord = coaddInputs.visits.addNew()
190 outputVisitRecord.assign(inputVisitRecord)
192 for inputCcdRecord
in tempExpInputs.ccds:
193 if inputCcdRecord.getL(self.
ccdVisitKey) != inputVisitRecord.getId():
194 self.log.warn(
"CoaddInputs for coaddTempExp with id %d contains CCDs with visit=%d. "
195 "CoaddInputs may be unreliable."
196 % (inputVisitRecord.getId(), inputCcdRecord.getL(self.
ccdVisitKey)))
197 outputCcdRecord = coaddInputs.ccds.addNew()
198 outputCcdRecord.assign(inputCcdRecord)
199 if self.config.saveCcdWeights:
201 return inputVisitRecord
CoaddPsf is the Psf derived to be used for non-PSF-matched Coadd images.