22 from __future__
import absolute_import, division, print_function
23 from builtins
import object
32 __all__ = [
"CoaddInputRecorderTask"]
36 """Config for CoaddInputRecorderTask 38 The inputRecorder section of the various coadd tasks' configs should generally agree, 39 or the schemas created by earlier tasks (like MakeCoaddTempExpTask) will not contain 40 the fields filled by later tasks (like AssembleCoaddTask). 43 saveEmptyCcds = pexConfig.Field(
44 dtype=bool, default=
False, optional=
False,
45 doc=(
"Add records for CCDs we iterated over but did not add a coaddTempExp" 46 " due to a lack of unmasked pixels in the coadd footprint.")
48 saveErrorCcds = pexConfig.Field(
49 dtype=bool, default=
False, optional=
False,
50 doc=(
"Add records for CCDs we iterated over but did not add a coaddTempExp" 51 " due to an exception (often due to the calexp not being found on disk).")
53 saveVisitGoodPix = pexConfig.Field(
54 dtype=bool, default=
True, optional=
False,
55 doc=(
"Save the total number of good pixels in each coaddTempExp (redundant with a sum of" 56 " good pixels in associated CCDs)")
58 saveCcdWeights = pexConfig.Field(
59 dtype=bool, default=
True, optional=
False,
60 doc=(
"Save weights in the CCDs table as well as the visits table?" 61 " (This is necessary for easy construction of CoaddPsf, but otherwise duplicate information.)")
66 """A helper class for CoaddInputRecorderTask, managing the CoaddInputs object for that single 67 CoaddTempExp. This will contain a single 'visit' record for the CoaddTempExp and a number of 'ccd' 70 Should generally be created by calling CoaddInputRecorderTask.makeCoaddTempExp(). 76 @param task The CoaddInputRecorderTask that is utilising us 77 @param visitId Identifier (integer) for the visit 78 @param num Number of CCDs for this visit that overlap this 79 patch (for reserving memory) 90 """Add a 'ccd' record for a calexp just added to the CoaddTempExp 92 @param[in] calExp Calibrated exposure just added to the CoaddTempExp, or None in case of 93 failures that should nonetheless be tracked. Should be the original 94 calexp, in that it should contain the original Psf and Wcs, not the 95 warped and/or matched ones. 96 @param[in] ccdId A unique numeric ID for the Exposure. 97 @param[in] nGoodPix Number of good pixels this image will contribute to the CoaddTempExp. 98 If saveEmptyCcds is not set and this value is zero, no record will be 101 if nGoodPix == 0
and not self.
task.config.saveEmptyCcds:
107 record.setI(self.
task.ccdCcdKey, calExp.getDetector().getId())
109 self.
task.log.warn(
"Error getting detector serial number in visit %d; using -1" 111 record.setI(self.
task.ccdCcdKey, -1)
112 record.setI(self.
task.ccdGoodPixKey, nGoodPix)
113 if calExp
is not None:
115 if self.
task.config.saveCcdWeights:
116 record.setD(self.
task.ccdWeightKey, 1.0)
117 record.set(self.
task.ccdFilterKey, calExp.getFilter().getName())
119 def finish(self, coaddTempExp, nGoodPix=None):
120 """Finish creating the CoaddInputs for a CoaddTempExp. 122 @param[in,out] coaddTempExp Exposure object from which to obtain the PSF, WCS, and bounding 123 box for the entry in the 'visits' table. On return, the completed 124 CoaddInputs object will be attached to it. 125 @param[in] nGoodPix Total number of good pixels in the CoaddTempExp; ignored unless 126 saveVisitGoodPix is true. 129 if self.
task.config.saveVisitGoodPix:
131 coaddTempExp.getInfo().setCoaddInputs(self.
coaddInputs)
132 wcs = coaddTempExp.getWcs()
136 apCorrMap = makeCoaddApCorrMap(self.
coaddInputs.ccds, coaddTempExp.getBBox(afwImage.PARENT), wcs)
137 coaddTempExp.getInfo().setApCorrMap(apCorrMap)
139 def _setExposureInfoInRecord(self, exposure, record):
140 """Set exposure info and bbox in an ExposureTable record 142 @param[in] exposure exposure whose info is to be recorded 143 @param[in,out] record record of an ExposureTable to set 145 info = exposure.getInfo()
146 record.setPsf(info.getPsf())
147 record.setWcs(info.getWcs())
148 record.setCalib(info.getCalib())
149 record.setApCorrMap(info.getApCorrMap())
150 record.setValidPolygon(info.getValidPolygon())
151 record.setVisitInfo(info.getVisitInfo())
152 record.setBBox(exposure.getBBox())
153 record.setTransmissionCurve(info.getTransmissionCurve())
158 """Subtask that handles filling a CoaddInputs object for a coadd exposure, tracking the CCDs and 159 visits that went into a coadd. 161 The interface here is a little messy, but I think this is at least partly a product of a bit of 162 messiness in the coadd code it's plugged into. I hope #2590 might result in a better design. 165 ConfigClass = CoaddInputRecorderConfig
168 pipeBase.Task.__init__(self, *args, **kwargs)
170 if self.config.saveVisitGoodPix:
172 doc=
"Number of good pixels in the coaddTempExp")
174 doc=
"Weight for this visit in the coadd")
175 self.
ccdSchema = afwTable.ExposureTable.makeMinimalSchema()
176 self.
ccdCcdKey = self.
ccdSchema.addField(
"ccd", type=numpy.int32, doc=
"cameraGeom CCD serial number")
178 doc=
"Foreign key for the visits (coaddTempExp) catalog")
180 doc=
"Number of good pixels in this CCD")
181 if self.config.saveCcdWeights:
183 doc=
"Weight for this visit in the coadd")
185 doc=
"Filter associated with this visit.")
187 doc=
"Filter associated with this visit.")
190 """Return a CoaddTempExpInputRecorder instance to help with saving a CoaddTempExp's inputs. 192 The visitId may be any number that is unique for each CoaddTempExp that goes into a coadd, 193 but ideally should be something more meaningful that can be used to reconstruct a data ID. 198 """Create a CoaddInputs object with schemas defined by the task configuration""" 202 """Called by AssembleCoaddTask when adding (a subset of) a coaddTempExp to a coadd. The 203 base class impementation extracts the CoaddInputs from the coaddTempExp and appends 204 them to the given coaddInputs, filling in the weight column(s). 206 Note that the passed coaddTempExp may be a subimage, but that this method will only be 207 called for the first subimage 209 Returns the record for the visit to allow subclasses to fill in additional fields. 210 Warns and returns None if the inputRecorder catalogs for the coaddTempExp are not usable. 212 tempExpInputs = coaddTempExp.getInfo().getCoaddInputs()
213 if len(tempExpInputs.visits) != 1:
214 self.log.warn(
"CoaddInputs for coaddTempExp should have exactly one record in visits table " 215 "(found %d). CoaddInputs for this visit will not be saved." 216 % len(tempExpInputs.visits))
218 inputVisitRecord = tempExpInputs.visits[0]
219 outputVisitRecord = coaddInputs.visits.addNew()
220 outputVisitRecord.assign(inputVisitRecord)
222 outputVisitRecord.set(self.
visitFilterKey, coaddTempExp.getFilter().getName())
223 for inputCcdRecord
in tempExpInputs.ccds:
224 if inputCcdRecord.getL(self.
ccdVisitKey) != inputVisitRecord.getId():
225 self.log.warn(
"CoaddInputs for coaddTempExp with id %d contains CCDs with visit=%d. " 226 "CoaddInputs may be unreliable." 227 % (inputVisitRecord.getId(), inputCcdRecord.getL(self.
ccdVisitKey)))
228 outputCcdRecord = coaddInputs.ccds.addNew()
229 outputCcdRecord.assign(inputCcdRecord)
230 if self.config.saveCcdWeights:
232 outputCcdRecord.set(self.
ccdFilterKey, coaddTempExp.getFilter().getName())
233 return inputVisitRecord