8 """Wrapper for getting a value from a metadata object by key.
9 @param[in] metadata metadata object to query for value
10 @param[in] key key to use for value lookup
11 @returns value associated with key, None if key does not exist
13 mdKeys = metadata.paramNames()
15 return metadata.get(key)
20 """Wrapper for setting a value in a metadata object. Deals with case
21 where the key already exists.
22 @param[in, out] metadata metadata object ot modify in place.
23 @param[in] key key to associate with value
24 @param[in] value value to assign in the metadata object
25 @param[in] clobber Clobber the value if the key already exisists?
27 mdKeys = metadata.paramNames()
28 if key
not in mdKeys
or (key
in mdKeys
and clobber):
29 metadata.set(key, value)
32 """ Class to hold mapping of header cards to attributes"""
33 def addEntry(self, keyname, attribute_name, default=None, transform=lambda x: x):
34 """Adds an entry to the registr
35 @param[in] keyname Key used to retrieve the header record
36 @param[in] attribute_name Name of the attribute to store the value in
37 @param[jn] default Default velue to store if the header card is not available
38 @param[in] transform Transform to apply to the header value before assigning it to the
41 self.__setitem__(attribute_name, {
'keyName':keyname,
43 'transform':transform})
46 """Sets the attributes on the give object given a metadata object.
47 @param[in, out] obj Object on which to operate in place
48 @param[in] metadata Metadata object used for applying the mapping
49 @param[in] doRaise Raise exceptions on calling methods on the input object that do not exist?
51 for key, attrDict
in self.iteritems():
53 value =
getByKey(metadata, attrDict[
'keyName'])
55 self.
_applyVal(obj, value, key, attrDict[
'transform'])
59 value = attrDict[
'default']
60 self.
_applyVal(obj, value, key,
lambda x: x)
65 warnings.warn(
'WARNING: Failed to set %s attribute with %s value: %s'%
66 (key, value, e.message))
68 def _applyVal(self, obj, value, attrName, transform):
69 raise NotImplementedError(
'Must be implemented in sub-class')
72 """ Class to hold mapping of header cards to AmpInfoTable attributes
73 The amp info is stored using setters, thus calling the attribute as a function.
75 def _applyVal(self, obj, value, attrName, transform):
76 getattr(obj, attrName)(transform(value))
79 """ Class to hold mapping of header cards to Detector attributes
80 Detector information is stored as attributes on a Config object.
82 def _applyVal(self, obj, value, attrName, transform):
83 obj.__setattr__(attrName, transform(value))
86 def __init__(self, detectorFileName, ampFileNameList, inAmpCoords=True, plateScale=1.,
87 radialCoeffs=(0., 1.), clobberMetadata=
False, doRaise=
True):
88 ''' @param[in] detectorFileName FITS file containing the detector description.
89 May use [] notation to specify an extension in an MEF.
90 @param[in] ampFileNameList List of FITS file names to use in building the amps.
91 May contain duplicate entries if the raw data are assembled.
92 @param[in] inAmpCoords Boolean, True if raw data are in amp coordinates, False if raw data
93 are assembled into pseudo detector pixel arrays
94 @param[in] plateScale Nominal platescale (arcsec/mm)
95 @param[in] radialCoeffs Radial distortion coefficients for a radial polynomial in normalized
97 @param[in] clobberMetadata Clobber metadata from input files if overridden in the _sanitizeMetadata method
98 @param[in] doRaise Raise exception if not all non-defaulted keywords are defined? Default is True.
108 for fileName
in ampFileNameList:
115 """This method is called for all metadata and gives an opportunity to add/modify
116 header information for use downstream.
117 Override this method if more than the default is needed.
118 @param[in, out] metadata Metadata to read/modify
119 @param[in] clobber Clobber keys that exist with default keys?
124 """Does the default sanitization of the header metadata.
125 @param[in,out] metadata Header metadata to extend/modify
126 @param[in] clobber Override values in existing header cards?
137 if dtm1
is not None and dtm2
is not None:
138 setByKey(metadata,
'FLIPX', dtm1 < 0, clobber)
139 setByKey(metadata,
'FLIPY', dtm2 < 0, clobber)
140 setByKey(metadata,
'RDCRNR', afwTable.LL, clobber)
142 setByKey(metadata,
'FLIPX',
False, clobber)
143 setByKey(metadata,
'FLIPY',
True, clobber)
145 setByKey(metadata,
'RDCRNR',
None, clobber)
150 if xext
is not None and yext
is not None:
151 setByKey(metadata,
'RAWBBOX',
'[%i:%i,%i:%i]'%(1, xext, 1, yext), clobber)
155 if dtv1
is not None and dtv2
is not None:
156 setByKey(metadata,
'XYOFF', [dtv1, dtv2], clobber)
160 if metadata.isArray(
'BIASSEC'):
161 keylist = [
'HOSCAN',
'PRESCAN',
'VOSCAN']
162 biassecs =
getByKey(metadata,
'BIASSEC')
163 for i, biassec
in enumerate(biassecs):
164 setByKey(metadata, keylist[i], biassec, clobber)
166 biassec =
getByKey(metadata,
'BIASSEC')
167 if biassec
is not None:
168 setByKey(metadata,
'HOSCAN', biassec, clobber)
171 """Make the default map from header information to amplifier information
172 @return The HeaderAmpMap object containing the mapping
176 mapList = [(
'EXTNAME',
'setName'),
177 (
'DETSEC',
'setBBox',
None, self.
_makeBbox),
178 (
'GAIN',
'setGain', 1.),
179 (
'RDNOISE',
'setReadNoise', 0.),
180 (
'SATURATE',
'setSaturation', 2<<15),
181 (
'RDCRNR',
'setReadoutCorner', afwTable.LL),
182 (
'LINCOEFF',
'setLinearityCoeffs', [0., 1.]),
183 (
'LINTYPE',
'setLinearityType',
'POLY'),
184 (
'RAWBBOX',
'setRawBBox',
None, self.
_makeBbox),
185 (
'DATASEC',
'setRawDataBBox',
None, self.
_makeBbox),
186 (
'FLIPX',
'setRawFlipX',
False),
187 (
'FLIPY',
'setRawFlipY',
False),
189 (
'HOSCAN',
'setRawHorizontalOverscanBBox', emptyBBox, self.
_makeBbox),
190 (
'VOSCAN',
'setRawVerticalOverscanBBox', emptyBBox, self.
_makeBbox),
191 (
'PRESCAN',
'setRawPrescanBBox', emptyBBox, self.
_makeBbox),
198 """Make the default map from header information to detector information
199 @return The HeaderDetectorMap object containing the mapping
202 mapList = [(
'CCDNAME',
'name',
'ccdName'),
208 (
'OBSTYPE',
'detectorType', afwCameraGeom.SCIENCE),
209 (
'SERSTR',
'serial',
'none'),
210 (
'XPOS',
'offset_x', 0.),
211 (
'YPOS',
'offset_y', 0.),
212 (
'XPIX',
'refpos_x', 0.),
213 (
'YPIX',
'refpos_y', 0.),
214 (
'YAWDEG',
'yawDeg', 0.),
215 (
'PITCHDEG',
'pitchDeg', 0.),
216 (
'ROLLDEG',
'rollDeg', 0.),
217 (
'XPIXSIZE',
'pixelSize_x', 1.),
218 (
'YPIXSIZE',
'pixelSize_y', 1.),
219 (
'TRNSPOSE',
'transposeDetector',
False),
226 """Helper function to make an extent from an array
227 @param[in] extArr Length 2 array to use in creating the Extent object
228 @return Extent2I constructed from the input list
233 """Helper funtion to make a bounding box from a string representing a FITS style bounding box
234 @param[in] boxString String describing the bounding box
235 @return Box2I for the bounding box
238 x1, x2, y1, y2 = [int(el)
for el
in re.split(
'[:,]', boxString.strip()[1:-1])]
247 return self.
_makeBbox(boxString).getMinX()
250 return self.
_makeBbox(boxString).getMaxX()
253 return self.
_makeBbox(boxString).getMinY()
256 return self.
_makeBbox(boxString).getMaxY()
259 """Helper function to get the radial transform given the radial polynomial coefficients given in
261 @param[in] radialCoeffs List of coefficients describing a polynomial radial distortion in
263 @return RadialXYTransform object describing the radial distortion
269 """Take all the information and build a Detector object. The Detector object is necessary for doing
270 things like assembly.
271 @return Detector object
276 schema = afwTable.AmpInfoTable.makeMinimalSchema()
279 record = ampInfo.addNew()
280 self.defaultAmpMap.setAttributes(record, ampMetadata, self.
doRaise)
281 record.setHasRawInfo(
True)
283 detConfig = afwCameraGeom.DetectorConfig()
290 """PLaceholder for subclasses to implement construction of a calib to associate with the exposure.
291 @return empty afwImage.Calib object
296 """Method for constructing an exposure object from an image and the information contained in this
297 class to construct the Detector and Calib objects.
298 @param[in] im Image used to construct the exposure
299 @param[in] mask Optional mask plane as a <askU
300 @param[in] variance Optional variance plance as an image of the same type as im
301 @param[out] Exposure object
304 mask = afwImage.MaskU(im.getDimensions())
314 exp.setDetector(detector)
MaskedImage< ImagePixelT, MaskPixelT, VariancePixelT > * makeMaskedImage(typename Image< ImagePixelT >::Ptr image, typename Mask< MaskPixelT >::Ptr mask=typename Mask< MaskPixelT >::Ptr(), typename Image< VariancePixelT >::Ptr variance=typename Image< VariancePixelT >::Ptr())
A custom container class for records, based on std::vector.
def _sanitizeHeaderMetadata
An integer coordinate rectangle.
Wcs::Ptr makeWcs(coord::Coord const &crval, geom::Point2D const &crpix, double CD11, double CD12, double CD21, double CD22)
Create a Wcs object from crval, crpix, CD, using CD elements (useful from python) ...
boost::shared_ptr< daf::base::PropertySet > readMetadata(std::string const &fileName, int hdu=0, bool strip=false)
Return the metadata (header entries) from a FITS file.
Exposure< ImagePixelT, MaskPixelT, VariancePixelT >::Ptr makeExposure(MaskedImage< ImagePixelT, MaskPixelT, VariancePixelT > &mimage, boost::shared_ptr< Wcs const > wcs=boost::shared_ptr< Wcs const >())
double arcsecToRad(double x)
def _makeDefaultDetectorMap